OpenZiti 最容易被误读的方式,是把它归进“又一个 VPN”。它更有力的主张范围更窄,也更偏架构:让私有服务只能经由一层理解身份的覆盖网络抵达,然后改掉那种因为设备落在正确子网里就授予宽泛网络可达性的习惯。OpenZiti 自己的概览把控制器、路由器、tunneler 和 SDK 描述为构造零信任覆盖网络所需的部件;NIST 的零信任模型则把更大的安全转向定义为保护资源,并停止把网络位置当作默认信任依据。[1][4]
这一区分会影响采用方式。传统 VPN 往往回答的是:“这个用户能不能进入网络?”OpenZiti 想把问题收窄为:“这个已注册身份,能不能在本次会话里,依据这条策略,经由这些路由器,访问这个具名服务?”听起来运维负担更重,实际也确实如此。OpenZiti 有价值的读法落在工作迁移上:它把重要工作迁到了身份注册、服务定义、策略形状、路由器布置和客户端行为上。
控制平面才是真正的边界
一个 OpenZiti 网络有三个主要的物理或逻辑部分。控制器是管理平面,掌握身份、配置、授权规则,以及用于管理覆盖网络的 API 表面。边缘路由器组成数据平面,在 fabric 中转发加密流量,可以部署在公共位置,也可以部署在私有位置。端点则经由面向既有应用的 tunneler 接入,或者经由能够把 OpenZiti 直接嵌入应用的 SDK 接入。[1][2]
这种拆分,是第一个架构信号。控制器不只是一套挂在隧道旁边的管理界面。服务关系图在这里变得可读:身份完成注册,服务获得命名,策略决定哪些身份可以 dial 或 bind 哪些服务。随后路由器按照这个模型承载流量。控制器策略松散,覆盖网络就会忠实保留这种松散;策略足够精确,覆盖网络能把访问面收得比普通路由表更窄。
实际结果是,OpenZiti 把可达性变成一种接近应用合约的东西。服务不只是防火墙背后的一个 IP 地址。它有名字,有授权规则,也有穿过 fabric 的路径。正因为如此,OpenZiti 最适合服务边界比宽泛网络成员身份更重要的地方:跨云内部应用、合作方访问、远程管理表面、机器到机器工作流,或者那些根本不该拥有互联网监听 socket 的私有服务。
Dark 服务改变故障形态
OpenZiti 最有意思的概念,是“dark”服务。在项目 README 和概览中,dark 服务不会监听未经请求的入站网络连接。相反,应用或 tunneler 会向 OpenZiti fabric 建立出站连接,已获授权的客户端在完成认证和授权之后,经由覆盖网络访问它。[1][2]
这谈不上魔法般的隐身;它呈现的是一种不同的故障形态。旧的故障形态,是私有服务被安全组、路由器规则、反向代理或遗忘的端口转发意外暴露。OpenZiti 的故障形态,则会落在策略范围超出原意、身份生命周期处理失当、注册卫生薄弱,或者路由器布置制造出意外路径。这样的交换常常有吸引力,前提是运营团队清楚风险被迁到了哪里。
在小型环境里,这能简化暴露面。自托管管理面板、构建仪表盘、数据库控制台或内部 API,都可以停止接受直接入站流量。在更大的环境里,收益体现在工作被重塑得更贴近对象本身。团队争论的不再是 CIDR 块,而是身份、服务和策略组。当资源足够具体、爆炸半径也很重要时,这种争论更健康。
Tunneler 是迁移模式
OpenZiti 面向既有系统的路径,是 tunneler。在 Linux、Windows、macOS、iOS 和 Android 上,tunneler 让既有应用在不改应用代码的情况下使用覆盖网络。[2][3] 对于带着遗留服务的团队,这才是现实的起点。数据库、Web 应用或 SSH 目标可以被放到一个 OpenZiti 服务后面,而应用本身仍然相信自己正在和附近的普通 TCP 对端通信。
风险在于把 tunneler 当成所有东西的最终架构。Tunneler 很擅长把信任边界从网络外围迁到主机或客户端边缘。它的精度低于把身份嵌进应用进程。如果一台主机被互不相关的服务共享,或者本地用户和进程缺少良好约束,主机级拦截仍会留下“实际发起动作的是谁”的歧义。
这也正是 SDK 模型重要的地方。OpenZiti 列出的 SDK 覆盖 Go、C、Python、Node.js、Java、Swift 和 C# 等语言。[2] 借助 SDK,应用自身可以持有身份,并在进程内发起覆盖网络连接。对新软件来说,这是最强的模型,因为它去掉了一层翻译:应用不需要假装私有网络存在;它只请求自己被允许使用的服务。
对多数团队来说,迁移顺序应当保守。先为一个低摩擦的内部服务接入 tunneler,验证注册、吊销、日志、升级和恢复。随后再考虑把 SDK 用在新服务上,由应用团队持有依赖并测试故障情况。团队还解释不清一次被拒绝连接的原因时,就直接推进“所有服务 dark”,零信任项目很容易变成故障制造机。
策略取代子网直觉
真正困难的人类部分,是策略设计。子网很粗糙,但工程师围绕它们积累了几十年的直觉。OpenZiti 要求运营者转向身份和服务。这样更适合最小权限,也带来新的建模选择:身份颗粒度该多细,哪些服务该分组,谁能 bind 一个服务,谁能 dial 它,哪些路由器被允许参与,已吊销访问应当多快终止。
答案应当跟随所有权。一个小型平台团队可以定义覆盖网络原语和路由器位置,但应用所有者必须理解自己的服务边界代表什么。如果每个服务请求都变成发给中央网络团队的工单,OpenZiti 只会用新名词重造防火墙官僚流程。如果每个应用团队都能在缺少审查的情况下生成宽泛策略,它又会用更好的品牌包装重造扁平网络风险。
有用的策略模式,可以从动词开始。开发者笔记本可以 dial 预发管理工具。CI runner 可以 dial 制品仓库和部署 API。生产工作负载可以 bind 自己的服务,并且只 dial 自己的依赖。承包商身份可以在有限窗口内 dial 一个支持端点。OpenZiti 在这里超出隧道本身:策略开始描述工作流,而不只是描述拓扑。
运营仍然决定它能不能工作
维护信号已经足够清楚,可以把 OpenZiti 当成严肃项目,而不是只像一个演示仓库:openziti/ziti 仓库是控制器、路由器和 CLI 的父项目,它的 release 页面显示了一条活跃的发布流。[2][5] 这不会移除运维负担。它只是把必须有人负责的事项讲清楚。
控制器需要备份、升级规划、API 访问控制和监控。路由器需要布置、容量和可达性检查。身份需要注册和吊销流程。Tunneler 需要打包、端点支持,以及服务台真正能使用的日志。SDK 使用需要语言版本纪律和应用测试覆盖。这些任务都不罕见,但如果 OpenZiti 在内部被包装成“我们可以停止管理 VPN”,它们就很容易被低估。
性能也必须在服务实际运行的路径上测试。覆盖网络路由、加密、路由器跳数和客户端拦截,对管理工具而言都可以接受,对高吞吐数据路径却会带来痛感。合适的试点应当选一个真实内部应用,而不是合成的 hello-world 服务:它有可度量的延迟容忍度,有明确所有者,有回滚计划,并且能回答控制器、路由器、端点或身份存储出问题时会发生什么。
OpenZiti 在哪里值得承受复杂度
OpenZiti 值得关注的时刻,问题已经不只是加密传输。WireGuard 风格网络、mesh VPN、身份感知代理和服务网格,都在解决相邻问题。OpenZiti 的独特契合点,是一种服务覆盖网络:私有资源默认不可达,非人类身份很重要,团队还想从不改代码的 tunneler 走向嵌入应用的身份。
如果组织只需要少量静态站点到站点路由,缺少处理身份生命周期的意愿,或者配不出 controller/router 层的人手,OpenZiti 就不合适。当应用所有者始终不参与服务建模,它同样不合适。在这些情况下,更简单的隧道或代理会以更容易预期的方式失败。
最好的心智模型,是“带 dark-service 机制的身份覆盖网络”。这个短语把承诺和成本放在同一个句子里。OpenZiti 可以让网络访问更精确,但它做到这一点的方式,是创造一个新的记录系统,用来回答谁可以访问什么。团队准备好运营这个系统时,回报会很实在:暴露服务减少,环境里的网络权限变少,访问规则也更贴近软件实际依赖其他软件的方式。
来源
- NetFoundry,“OpenZiti overview” 文档,涵盖控制器、路由器、tunneler、SDK、dark 服务和端到端加密。
- OpenZiti,
openziti/zitiGitHub 仓库和 README,涵盖父项目、部署模型、组件、SDK 和安全流程。 - NetFoundry,“Linux Tunneler” 参考文档,说明为既有应用加入 OpenZiti 连接能力的 tunneler 路径。
- 美国国家标准与技术研究院,Zero Trust Architecture,SP 800-207,2020 年 8 月。
- OpenZiti,
openziti/zitirelease 页面,用作维护状态与发布流信号。 - Wikimedia Commons,“Network cables and switch” 照片,作为文章题图来源。