恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Envoy Original Destination Cluster 实战指南:基于 iptables REDIRECT 的透明代理与按目标地址动态路由
首页
资讯中心
/
Envoy Original Destination Cluster 实战指南:基于 iptables REDIRECT 的透明代理与按目标地址动态路由
Envoy Original Destination Cluster 实战指南:基于 iptables REDIRECT 的透明代理与按目标地址动态路由
发布时间:2026/9/12 15:45:05
Envoy Original Destination Cluster 实战指南基于 iptables REDIRECT 的透明代理与按目标地址动态路由【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读本文基于 Envoy 官方示例 configs/original-dst-cluster 展开完整讲解 Original Destination原始目标Cluster 的配置与端到端测试流程通过 iptables REDIRECT 规则把发往指定网段的流量透明劫持到 Envoy 监听端口再由 Envoy 依据连接被劫持前的原始目标地址动态创建上游主机并转发。读完本文你将掌握 original_dst 监听器过滤器与ORIGINAL_DST类型集群的组合配置、网络命名空间 veth 对 iptables 的测试环境搭建方法以及 Envoy 内部按需添加、自动清理动态主机的实现原理。Original Destination Cluster 是什么Original Destination Cluster原始目标集群是一种特殊的 Envoy 动态集群它不做静态配置或 DNS 解析而是把请求转发到该请求在被 Envoy 拦截之前的原始目标地址。其典型应用场景是透明代理——客户端并不知道代理的存在其出站流量被 iptables REDIRECT 规则劫持后送入 EnvoyEnvoy 在转发时自动恢复流量的原始目的 IP 与端口实现劫持后原样转发。整个工作链路由两个核心组件配合完成envoy.filters.listener.original_dst监听器过滤器见 config.cc 与 original_dst.cc在连接被接受时通过系统调用Linux 下为getsockopt(SO_ORIGINAL_DST)封装于Network::Utility::getOriginalDst取出连接被 REDIRECT 之前的原始目的地址并把该地址恢复为 socket 的 local address。ORIGINAL_DST类型集群见 original_dst_cluster.h 与 original_dst_cluster.cc其负载均衡器在选主机时根据下游连接的原始目标地址按需动态添加主机无需在配置里列出任何上游地址。关键事实集群的LoadBalancer会读取下游连接上下文得到原始目标地址如果该地址尚未在集群的 host 表中就即时创建对应 host 加入集群同时集群会周期性清理长时间没有流量、且不被任何连接池持有的过期主机清理周期由cleanup_interval_ms配置。这一点从类注释即可确认original_dst_cluster.hThe OriginalDstCluster is a dynamic cluster that automatically adds hosts as needed based on the original destination address of the downstream connection. These hosts are also automatically cleaned up after they have not seen traffic for a configurable cleanup interval time (cleanup_interval_ms).示例配置解析proxy_config.yaml仓库在 configs/original-dst-cluster/proxy_config.yaml 提供了一份可直接运行的完整示例核心结构如下static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 10000 traffic_direction: OUTBOUND filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: type: type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http route_config: name: local_service virtual_hosts: - name: backend domains: - * routes: - match: prefix: / route: cluster: cluster1 http_filters: - name: envoy.filters.http.router typed_config: type: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router codec_type: AUTO listener_filters: - name: envoy.filters.listener.original_dst typed_config: type: type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst clusters: - name: cluster1 type: ORIGINAL_DST connect_timeout: 6s lb_policy: CLUSTER_PROVIDED dns_lookup_family: V4_ONLY cluster_manager: {} admin: address: socket_address: address: 127.0.0.1 port_value: 9901各关键字段的作用与取值说明配置项取值作用说明listeners[].address.port_value10000Envoy 监听端口与netns_setup.sh中ENVOY_PORT一致是 iptables REDIRECT 的目标端口traffic_directionOUTBOUND标识该监听器处理的是出站流量供 original_dst 过滤器在特定平台如 Windows WFP 重定向分支处理listener_filters[].nameenvoy.filters.listener.original_dst监听器过滤器在连接建立前恢复原始目标地址clusters[].typeORIGINAL_DST集群类型声明为原始目标集群由OriginalDstClusterFactory工厂名envoy.cluster.original_dst见 original_dst_cluster.h加载同时兼容遗留的ORIGINAL_DST类型写法connect_timeout6s上游连接超时。示例中特意设为 6 秒以减少偶发超时详见下文关于 301 与 503lb_policyCLUSTER_PROVIDED负载均衡策略由集群自己提供即OriginalDstCluster::LoadBalancer而非内置策略dns_lookup_familyV4_ONLY目标地址按 IPv4 处理与测试网段173.194.222.0/24匹配admin.port_value9901管理接口监听在127.0.0.1:9901可用于观察集群状态/clusters与日志关于use_original_dst的说明这是早期版本常用的监听器级开关在filter_chains之外的 listener 字段设置现代推荐做法是在listener_filters中显式配置envoy.filters.listener.original_dst过滤器示例配置即采用后者。原过滤器在未经过 REDIRECT 的连接上会直接放行此时getOriginalDst返回的就是 socket 自身本地地址不会误改流量original_dst.cc。补充能力原始目标集群的扩展配置从 proto 定义 original_dst.proto 可以看到ORIGINAL_DST集群除了本文示例的用法外还支持若干可选字段需通过cluster_type扩展配置携带use_http_header/http_header_name允许从指定的 HTTP 头覆盖目标地址实现不依赖系统 REDIRECT 的应用层目标改写upstream_port_override覆盖上游端口范围 0–65535metadata_key从动态元数据中取目标地址。这些能力对应 original_dst_cluster.h 中LoadBalancer持有的http_header_name_、metadata_key_、port_override_三个成员负载均衡器按过滤状态 → HTTP 头 → 元数据 → 原始目标的优先级确定转发地址。环境准备搭建网络命名空间与 iptables 重定向官方提供了两个配套脚本netns_setup.sh建环境与netns_cleanup.sh清理环境均位于 configs/original-dst-cluster。脚本接收两个参数参数含义$1新建网络命名空间的名称$2需要被重定向的目标地址或网段如173.194.222.0/24两个脚本内部均把 Envoy 监听端口硬编码为10000与proxy_config.yaml中的port_value严格对应。netns_setup.sh 干了什么执行sudo ./configs/original-dst-cluster/netns_setup.sh ns1 173.194.222.0/24后脚本依次完成对应 netns_setup.sh创建 veth 对ip link add ns1-veth0 type veth peer name ns1-veth1veth0 留在根命名空间并配置为10.0.200.2/24作为网络出口创建网络命名空间ip netns add ns1把 veth1 移入命名空间并配置为10.0.200.1/24配置命名空间内路由启用 loopback并把默认路由指向 veth0ip route add default via 10.0.200.2注入 iptables REDIRECT 规则iptables -t nat -I PREROUTING --src 0/0 --dst 173.194.222.0/24 -p tcp --dport 80 -j REDIRECT --to-ports 10000这条规则挂在根命名空间 nat 表的PREROUTING钩子上任何源地址发往173.194.222.0/24:80的 TCP 报文都被重定向到本机10000端口即 Envoy 监听端口。这正是透明劫持的关键——目标进程完全感知不到代理的存在。注意脚本把 veth0 的 IP 配为10.0.200.2而非默认网关10.0.200.1这是为了配合命名空间内默认路由指向 10.0.200.2的设计veth1 为10.0.200.1读者按示例使用即可无需修改。netns_cleanup.sh 干了什么清理脚本执行完全逆操作netns_cleanup.shiptables -t nat -D PREROUTING --src 0/0 --dst 173.194.222.0/24 -p tcp --dport 80 -j REDIRECT --to-ports 10000 ip netns delete ns1 ip link del ns1-veth0 type veth peer name ns1-veth1即删除 iptables 规则、删除网络命名空间、删除 veth 对把网络环境恢复原状。构建并运行 Envoy用 Debug 模式构建为了在日志中清晰观察主机动态增删行为官方建议以 debug 选项构建bazel build //source/exe:envoy-static -c dbg产物路径为bazel-out/local-dbg/bin/source/exe/envoy-static对应 local 配置的 dbg 编译变体。运行示例配置bazel-out/local-dbg/bin/source/exe/envoy-static -c configs/original-dst-cluster/proxy_config.yaml -l debug-c指定配置文件为仓库内的 configs/original-dst-cluster/proxy_config.yaml-l debug把日志级别设为 debug便于观察Adding host/Keeping active host/Removing stale host等关键日志。启动成功后Envoy 会周期性输出类似Cleaning up stale original dst hosts.的日志——该日志来自 original_dst_cluster.cc 中cleanup()定时器回调说明集群的过期主机清理机制已生效。从命名空间内产生流量并观察行为在另一个终端执行sudo ip netns exec ns1 curl -v 173.194.222.106:80流量走向命名空间内 curl 的目标是173.194.222.106:80→ 经默认路由进入根命名空间 veth0 → 命中 PREROUTING REDIRECT 规则 → 被重定向到 Envoy 的0.0.0.0:10000→ original_dst 过滤器恢复原始目标地址173.194.222.106:80→ HttpConnectionManager 把请求路由到cluster1→ORIGINAL_DST集群按原始目标地址动态建主机并转发。关于 301 与 503 两种响应原文档明确指出可能看到两种响应README.md最常见的是301 Moved173.194.222.106是 Google 的地址段该网段即 google.com 的 IP 之一HTTP 服务器会返回 301 重定向这恰恰证明流量被正确转发到了真实目标少数情况是503 Service Unavailable若上游连接超时该网段内没有存活主机Envoy 会返回 503。connect_timeout: 6s的设置就是为了降低这种概率但如果目标地址根本不存在主机无论超时设多长都会得到 503。动态主机生命周期日志流量产生后每个 Envoy worker 线程都会记录如下日志序列original_dst_cluster.cc 中addHost与cleanup的日志点Adding host 173.194.222.106:80连接到达后负载均衡器发现集群中没有该目标地址的主机于是动态创建 host 加入集群每个 worker 线程各记录一次Keeping active address 173.194.222.106:80周期性清理时该地址近期仍被负载均衡器选中used_位为 true予以保留并复位标记Removing stale address 173.194.222.106:80流量停止后经过一个清理周期该地址既未被选中、也没有被任何连接池持有于是被移出集群。整个清理逻辑的核心在cleanup()original_dst_cluster.cc保留条件为主机近期被选过或仍被连接池使用否则移除。used_位的两轮延迟设计先标记、下一轮才删除用于避免如下竞态worker 释放主机与重新选中主机之间的瞬间被清理误删。这些日志是验证透明代理链路是否打通的最直观证据。收尾清理环境测试完毕后用与 setup 完全相同的参数执行清理脚本sudo ./configs/original-dst-cluster/netns_cleanup.sh ns1 173.194.222.0/24然后回到运行 Envoy 的终端按^C停止 Envoy 进程。与源码的对应关系速查本文涉及的行为源码位置original_dst 过滤器恢复原始目标地址original_dst.cc集群工厂与扩展配置加载original_dst_cluster.h动态添加主机 / 定时清理过期主机original_dst_cluster.cc扩展配置字段定义use_http_header、upstream_port_override等original_dst.proto示例配置 / 建网脚本 / 清理脚本proxy_config.yaml、netns_setup.sh、netns_cleanup.sh小结本文以仓库自带示例为主线走通了 Envoy Original Destination Cluster 的完整链路从 iptables REDIRECT 透明劫持、original_dst 过滤器恢复原始目标、ORIGINAL_DST集群按需动态建主机到观察Adding host/Keeping active host/Removing stale host日志验证主机生命周期。这套机制的价值在于上游地址完全不需要预先配置Envoy 天然适应目标动态变化的透明代理、服务网格 sidecar 出站拦截等场景。需要扩展应用场景时可进一步研究 proto 中use_http_header、upstream_port_override等扩展字段让目标地址的决策脱离内核 REDIRECT改由 HTTP 头或元数据驱动。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考