无 Sidecar 时代下,遗留系统(Legacy)如何无感接入 zTunnel mTLS 零信任网络?
在 Service Mesh 的演进历程中,Istio Ambient Mesh(无 Sidecar 模式)的出现无疑具有划时代的意义。它通过将数据面拆分为负责 L4 安全传输的 zTunnel 和负责 L7 流量处理的 Waypoint Proxy,解决了传统 Sidecar 模式带来的应用侵入性大、资源消耗高、升级业务中断等痛点。
然而,在企业实际的零信任改造过程中,我们面临的往往不是一块纯净的“绿地”,而是充斥着虚拟机、物理机以及旧版 Kubernetes 集群的“棕地”环境。
核心问题在于:当 Kubernetes 集群内部已经通过 zTunnel 实现了节点级的 L4 mTLS 物理加密时,那些无法运行 K8s DaemonSet、无法原生部署 zTunnel 的 Legacy(遗留)系统,该如何在不修改任何业务代码的前提下,无缝接入这一套零信任网络?
本文将深入探讨无 Sidecar 架构下的网络协议细节,并分享两种在生产环境中可落地的 Legacy 系统接入 mTLS 的工程实践方案。
核心机制:zTunnel 与 HBONE 到底是如何工作的?
在设计接入方案之前,我们必须先理清 zTunnel 是如何对流量进行加密传输的。
与传统 Envoy Sidecar 直接在两个 Pod 之间建立双向 TLS(mTLS)连接不同,Ambient Mesh 引入了 HBONE (HTTP-Based Overlay Network Encapsulation) 协议。
+-------------------------------------------------------------+
| HBONE (HTTP/2 Tunnel) |
| +------------------+ mTLS (TLS 1.3) +------------------+ |
| | TCP Payload | ===============> | TCP Payload | |
| +------------------+ +------------------+ |
+-------------------------------------------------------------+
当客户端 Pod 发起 TCP 连接时:
- 本地节点上的 zTunnel 拦截该 TCP 连接。
- zTunnel 将其封装在基于 HTTP/2 CONNECT 的隧道中(即 HBONE)。
- 使用相互传输层安全协议(mTLS)对该 HTTP/2 连接进行加密。
- 目标节点上的 zTunnel 接收该连接,进行 TLS 解密并剥离 HTTP/2 封装,最后将原始 TCP 流量投递给目标 Pod。
因此,Legacy 系统想要接入这个零信任网络,本质上就是要解决**“如何让 Legacy 流量与 HBONE 隧道进行无缝互通”**的问题。
方案一:边界网关桥接(Gateway Bridge)—— 低侵入过渡
如果你的遗留系统部署在独立的 VPC、物理机房,且短期内不希望在这些机器上安装任何代理软件,边界网关桥接方案是首选。
1. 架构设计
在该方案中,我们不在 Legacy 虚拟机上部署任何 Mesh 组件。相反,我们在 K8s 集群边界部署一个专属的 Egress/Ingress Transit Gateway(基于 Envoy 或是专门定制的 zTunnel 网关)。
+--------------------+ +-------------------------------------------+
| Legacy Host | | Kubernetes Cluster |
| | | |
| +--------------+ | Plain TCP | +-------------+ HBONE (mTLS) +-------+ |
| | Legacy App | |---------------->| | Transit |-------------->| Pod | |
| +--------------+ | | | Gateway | +-------+ |
+--------------------+ + +-------------+ +
+-------------------------------------------+
- 出站(Legacy -> Mesh): Legacy 系统的流量通过内网负载均衡(SLB)或 DNS 解析指向 Transit Gateway。Gateway 接收到普通 TCP 流量后,将其转换(Encapsulate)为 HBONE 格式,并附加合法的 SPIFFE 身份凭证,再发送给集群内的 zTunnel。
- 入站(Mesh -> Legacy): 集群内的服务访问 Legacy 系统时,流量通过 Waypoint 或 zTunnel 发送到 Transit Gateway。Gateway 解密 HBONE 封装,还原为普通 TCP 流量,并将其路由至物理机房的 Legacy 系统。
2. 核心配置实现
为了让 K8s 内部感知到 Legacy 系统的存在,我们需要在 Istio 中通过 ServiceEntry 和 WorkloadEntry 进行服务声明。
以下是一个典型的 ServiceEntry 配置,用于将 Legacy 数据库服务引入网格:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: legacy-mysql
namespace: legacy-bridge
spec:
hosts:
- mysql.legacy.internal
addresses:
- 192.168.100.50 # Legacy 数据库的实际 IP
ports:
- number: 3306
name: mysql
protocol: TCP
resolution: STATIC
endpoints:
- address: 192.168.100.50
labels:
app: legacy-mysql
接着,配置 PeerAuthentication 确保网关与集群内其他 zTunnel 之间的通信强制使用 STRICT mTLS:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: legacy-bridge
spec:
mtls:
mode: STRICT
3. 该方案的优缺点
- 优点: 遗留系统零改造,不需要安装任何 Daemon,不需要修改系统路由表。
- 缺点: 信任域边界只延伸到了 Transit Gateway。在 Legacy 主机到 Gateway 之间的这段网络(通常是专线或 VPC 内网)是明文传输的,未能实现端到端的绝对零信任(Zero Trust End-to-End)。
方案二:虚机本地 zTunnel(VM-Local zTunnel)—— 终极零信任
为了将零信任的边界真正推进到每一台 Legacy 虚拟机的网卡(vNIC)级别,我们需要在虚拟机操作系统内直接运行一个轻量级的 zTunnel 守护进程。这也是 Istio 社区目前正在积极推进的 VM Onboarding 演进方向。
1. 架构设计
在虚拟机内部,我们将 zTunnel 作为 systemd 服务运行。同时,利用 Linux 的 iptables / eBPF 机制,将虚拟机上所有出入站的业务流量强制重定向至本地运行的 zTunnel。
+-------------------------------------------------------+
| Legacy VM |
| |
| +--------------+ Plain TCP +--------------+ |
| | Legacy App | <===============> | zTunnel | |
| +--------------+ (Local Loopback) +--------------+ |
+-------------------------------------------------------+
|
| HBONE (mTLS)
v
+---------------+
| Mesh Node / |
| K8s zTunnel |
+---------------+
2. 关键工程挑战与解决方案
挑战 A:非 K8s 环境下的身份注入(Identity Bootstrap)
zTunnel 能够进行 mTLS 通信的前提是它必须拥有代表其服务身份的 X.509 证书。在 K8s 中,这通过 ServiceAccount 和 Kubelet 自动挂载的 Token 完成。但在虚拟机中,我们没有 Kubelet。
解决方案:SPIFFE/SPIRE 联邦化
- 在虚拟机所在的 VPC 中部署 SPIRE Agent。
- 通过 SPIRE 的平台 Attestation(如 AWS Instance Identity Document、GCP ID Token,或物理机机房的 TPM/IPMI 信息)对虚拟机进行节点认证。
- 认证通过后,SPIRE Agent 会在本地通过 Unix Domain Socket(Workload API)向本地的 zTunnel 动态签发并轮转 SPIFFE 证书。
- zTunnel 读取该证书,从而获得与 K8s 集群内部 pod 完全等价的身份体系。
挑战 B:本地流量劫持配置
在虚拟机内,我们需要通过 iptables 配置 TPROXY(Transparent Proxying),将业务进程的外发流量重定向至 zTunnel 的监听端口(默认 15001 和 15006)。
以下是在 Legacy 虚拟机上配置流量劫持的关键脚本片段:
# 创建自定义 iptables 链
iptables -t mangle -N ZTUNNEL_INBOUND
iptables -t mangle -N ZTUNNEL_OUTBOUND
# 排除本地回环和 zTunnel 自身的流量,避免死循环
iptables -t mangle -A PREROUTING -p tcp -j ZTUNNEL_INBOUND
# 将除 zTunnel 运行用户(如 ztunnel-user)以外的所有出站 TCP 流量导向 ZTUNNEL_OUTBOUND
iptables -t mangle -A OUTPUT -p tcp -m owner ! --uid-owner ztunnel-user -j ZTUNNEL_OUTBOUND
# 具体的 TPROXY 规则将流量重定向至本地 15001 (Outbound) 和 15006 (Inbound)
iptables -t mangle -A ZTUNNEL_OUTBOUND -p tcp -j TPROXY --on-port 15001 --on-ip 127.0.0.1 --tproxy-mark 0x1/0x1
生产落地避坑指南
在实际生产中落地上述两种方案时,团队通常会遭遇以下几个“暗坑”,需要提前做好技术储备:
1. MTU 损耗与网络分片问题
由于 HBONE 协议在原始 TCP 报文之上外包了一层 HTTP/2 + TLS + TCP/IP 头部,这使得有效载荷(Payload)空间变小。
- 现象: 当大文件传输或高并发请求发生时,可能会出现连接莫名其妙挂起或超时。
- 对策: 在 Legacy 虚机上或 Transit Gateway 上,将网卡的 MTU 调小 50 ~ 100 字节(例如从 1500 调整为 1420),或者配置 iptables 的
TCPMSS自动协商。
2. 双重加密带来的 CPU 损耗
如果 Legacy 系统本身应用层已经开启了 HTTPS/TLS,再次通过 zTunnel/Gateway 封装时,会发生 TLS-over-TLS。这不仅会造成双重 CPU 损耗,还会导致 L7 控制策略失效。
- 最佳实践: 推动 Legacy 应用降级为 HTTP/TCP,安全边界完全交由底层的 zTunnel 承载;或者在网关处配置 TLS 通透(TLS Passthrough),避免网关进行二次握手。
3. 如何使用 tcpdump 调试 HBONE 流量
传统的 tcpdump -i any port 80 在 Ambient 架构下失效了,因为你看到的将全是密密麻麻的 HTTP/2 加密数据流。
- 调试命令推荐:
若要抓取未加密的原始流量,需监听本地回环网卡或非 TPROXY 端口:
若要抓取加密的 HBONE 报文,查看外部连接建立情况:tcpdump -i lo -nnvv -XSs 0 'tcp port 15001 or port 15006'tcpdump -i any -nnvv 'tcp port 15008' # 15008 是 zTunnel HBONE 的默认监听端口
总结
无 Sidecar 架构(Ambient Mesh)的本质,是将网络基础设施与应用容器彻底解耦。通过 “边界网关桥接(低侵入)” 与 “VM 本地 zTunnel 部署(强安全)” 的有机结合,我们不仅能够将零信任网络(mTLS)平滑地延伸到企业现有的 Legacy 遗留系统中,还能在这个过程中保持应用层代码零修改。
这不仅是一次架构的升级,更是企业在复杂异构 IT 环境下,向“绝对零信任”目标迈出的关键一步。