Istio Ambient 模式中的 Pod 内 Iptable 规则注入解析

深入解析 Istio ambient 模式下 pod 内部的 iptables 规则如何实现透明流量拦截和控制。

版权声明
本文为 Jimmy Song 原创。转载请注明来源: https://jimmysong.io/blog/istio-ambient-inpod-iptables/
查看本文大纲

上一篇博客 中,我概述了 Istio ambient 模式中 pod 网络命名空间内注入的 iptables 规则。本文将深入解析这些规则,探讨它们是如何在 pod 内实现透明流量拦截和重定向的。

Pod 内的 iptables 规则

在 pod 的网络命名空间内,Istio CNI node agent 会设置一系列 iptables 规则,以实现流量的透明拦截与重定向。下面的规则展示了 Istio 在 mangle 和 nat 表中注入的内容,确保入站和出站流量经过适当的处理。

# Generated by iptables-save v1.8.9 (nf_tables) on Thu Nov 14 08:43:17 2024
*mangle
:PREROUTING ACCEPT [99138:22880045]  # mangle 表中的 PREROUTING 链,默认策略为 ACCEPT。
:INPUT ACCEPT [0:0]  # mangle 表中的 INPUT 链,默认策略为 ACCEPT。
:FORWARD ACCEPT [0:0]  # mangle 表中的 FORWARD 链,默认策略为 ACCEPT。
:OUTPUT ACCEPT [100900:34940164]  # mangle 表中的 OUTPUT 链,默认策略为 ACCEPT。
:POSTROUTING ACCEPT [0:0]  # mangle 表中的 POSTROUTING 链,默认策略为 ACCEPT。
:ISTIO_OUTPUT - [0:0]  # 自定义的 ISTIO_OUTPUT 链,用于处理 Istio 的出站流量。
:ISTIO_PRERT - [0:0]  # 自定义的 ISTIO_PRERT 链,用于处理 Istio 的预路由流量。
-A PREROUTING -j ISTIO_PRERT  # 将所有 PREROUTING 流量跳转到 ISTIO_PRERT 链。
-A OUTPUT -j ISTIO_OUTPUT  # 将所有 OUTPUT 流量跳转到 ISTIO_OUTPUT 链。
-A ISTIO_OUTPUT -m connmark --mark 0x111/0xfff -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
# 如果连接标记为 0x111/0xfff,则恢复连接标记,用于连接追踪的一致性。

-A ISTIO_PRERT -m mark --mark 0x539/0xfff -j CONNMARK --set-xmark 0x111/0xfff
# 如果数据包标记为 0x539/0xfff,在 PREROUTING 链中将其连接标记设置为 0x111/0xfff。

COMMIT  # 应用 mangle 表规则。
# Completed on Thu Nov 14 08:43:17 2024

# Generated by iptables-save v1.8.9 (nf_tables) on Thu Nov 14 08:43:17 2024
*nat
:PREROUTING ACCEPT [2:120]  # nat 表中的 PREROUTING 链,默认策略为 ACCEPT。
:INPUT ACCEPT [0:0]  # nat 表中的 INPUT 链,默认策略为 ACCEPT。
:OUTPUT ACCEPT [119:9344]  # nat 表中的 OUTPUT 链,默认策略为 ACCEPT。
:POSTROUTING ACCEPT [0:0]  # nat 表中的 POSTROUTING 链,默认策略为 ACCEPT。
:ISTIO_OUTPUT - [0:0]  # 自定义的 ISTIO_OUTPUT 链,用于处理 Istio 的出站 NAT 流量。
:ISTIO_PRERT - [0:0]  # 自定义的 ISTIO_PRERT 链,用于处理 Istio 的预路由 NAT 流量。
-A PREROUTING -j ISTIO_PRERT  # 将所有 PREROUTING 流量跳转到 ISTIO_PRERT 链。
-A OUTPUT -j ISTIO_OUTPUT  # 将所有 OUTPUT 流量跳转到 ISTIO_OUTPUT 链。
-A ISTIO_OUTPUT -d 169.254.7.127/32 -p tcp -m tcp -j ACCEPT
# 如果目标地址为 169.254.7.127(可能是 Istio 内部地址),允许 TCP 流量通过。

-A ISTIO_OUTPUT -p tcp -m mark --mark 0x111/0xfff -j ACCEPT
# 如果数据包标记为 0x111/0xfff,允许 TCP 流量通过。

-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -j ACCEPT
# 允许发往本地回环接口(但不包括 127.0.0.1)的流量通过。

-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -p tcp -m mark ! --mark 0x539/0xfff -j REDIRECT --to-ports 15001
# 将发往非 127.0.0.1 的出站 TCP 流量(且标记不是 0x539/0xfff)重定向到端口 15001(Istio 出站流量入口)。

-A ISTIO_PRERT -s 169.254.7.127/32 -p tcp -m tcp -j ACCEPT
# 如果源地址为 169.254.7.127,允许 TCP 流量通过 PREROUTING 链。

-A ISTIO_PRERT ! -d 127.0.0.1/32 -p tcp -m tcp ! --dport 15008 -m mark ! --mark 0x539/0xfff -j REDIRECT --to-ports 15006
# 将非 127.0.0.1 且目标端口不是 15008 的入站 TCP 流量(标记不是 0x539/0xfff)重定向到端口 15006(Istio 入站流量入口)。

COMMIT  # 应用 nat 表规则。
# Completed on Thu Nov 14 08:43:17 2024

端口号的作用

这些 iptables 规则通过特定的端口号来区分并处理不同类型的流量:

  • 15008 (HBONE socket):用于透明代理基于 HTTP 的流量,支持 HBONE 协议的透明传输。
  • 15006 (plaintext socket):用于处理未加密的网格内部流量,以实现 pod 之间的流量管理。
  • 15001 (outbound socket):用于管理出站流量,实现对外部服务访问的策略控制。

这些端口使得 Istio 能够对入站、出站及内部流量进行透明的管理与控制,从而实现细粒度的安全策略与流量控制。更多关于端口号的使用请参考 Istio 应用要求

标记 0x539 的作用

0x539 是用于标识 Istio 代理发出的流量的标记。这一标记在流量进入 iptables 规则时被设置,用于区分由代理(如 ztunnel)处理过的数据包,防止其被重复代理或误处理。

标记 0x111 的作用

0x111 用于连接级别的标记管理,在 Istio 网格中标识已由代理处理过的整个连接。通过 iptables 的 CONNMARK 模块,0x111 标记能够从单个数据包扩展到整个连接的生命周期,从而加速后续数据包的匹配。

iptables 规则可视化

下图展示了流量在 iptables 规则中的执行路径,帮助理解流量的匹配和重定向过程:

image
Istio ambient pod 内 iptables 可视化

想进一步了解 Istio CNI 如何处理 iptables,请参考代码 istio/cni/pkg/iptables/iptables.go at master · istio/istio · GitHub

不同类型流量的路由可视化

以下是同节点与跨节点的加密和明文流量路径的可视化图示:

跨节点的加密流量路径

image
跨节点的加密流量路径

跨节点的明文流量路径

image
跨节点的明文流量路径

同节点的加密流量路径

image
同节点的加密流量路径

同节点的明文流量路径

image
同节点的明文流量路径
  1. 应用程序发出请求:流量从应用程序进程发送,进入 Pod 的网络命名空间。
  2. iptables 规则匹配
    • 出站流量OUTPUT 链中被匹配,符合条件的流量被重定向到 ISTIO_OUTPUT 链。
    • ISTIO_OUTPUT 链中,流量被标记并被接受。
  3. REDIRECT 重定向:流量被 iptables 捕获并重定向到 ztunnel 监听端口(明文流量为 15006,加密流量为 15008)。
  4. ztunnel 处理流量:ztunnel 接收到流量,进行策略检查和加密等操作。
  5. 流量转发到目标服务:ztunnel 将处理后的流量发送到目标服务。
  6. 返回路径:目标服务的响应通过网络返回 ztunnel,ztunnel 对响应进行解密和策略检查,然后返回给应用程序。

总结

通过解析 Istio ambient 模式下的 iptables 规则,我们可以看到,Istio 通过 CNI 插件在 pod 内设置了一系列透明的流量拦截规则。这些规则确保了流量在进出 pod 时能够按预期被 ztunnel 代理处理,从而实现更细粒度的流量管理和安全策略应用。未来我们将继续探索更多关于 Istio ambient 模式下的网络细节,敬请关注。

最后更新于 2024/12/16