云原生小课堂 | Envoy 请求流程源码解析(一):流量劫持
前言
Envoy 是一款面向 Service Mesh 的高性能网络代理服务。它与应用程序并行运行,通过以平台无关的方式提供通用功能来抽象网络。当基础架构中的所有服务流量都通过 Envoy 网格时,通过一致的可观测性,很容易地查看问题区域,调整整体性能。
Envoy 也是 istio 的核心组件之一,以 sidecar 的方式与服务运行在一起,对服务的流量进行拦截转发,具有路由,流量控制等等强大特性。本系列文章,我们将不局限于 istio,envoy 的官方文档,从源码级别切入,分享 Envoy 启动、流量劫持、http 请求处理流程的进阶应用实例,深度分析 Envoy 架构。
本篇将是 Envoy 请求流程源码解析的第一篇,主要分享 Envoy 的流量劫持。
边车模式
在 Istio 当中, envoy 运行有两种模式,分别为边车模式和代理模式。
其中边车模式为通过 iptable 进行流量劫持
拦截模式
Istio 支持两种拦截模式:
REDIRECT:使用 iptables 的 REDIRECT 目标来拦截入站请求,转给 Envoy,从 Linux2.6.15 的内核版本后,iptables 开始支持状态跟踪(conntrack),该功能依赖于 netfilter 的内核模块 nf_conntrack。此后,iptables 可以根据包的状态进行二次的过滤拦截和状态跟踪。它也是 state/ctstate 和 nat 的主要依赖模块。
TPROXY:使用 iptables 的 TPROXY 目标来拦截入站请求,tproxy 可以用于 inbound 流量的重定向,且无需改变报文中的目的 IP/端口,不需要执行连接跟踪,不会出现 conntrack 模块创建大量连接的问题。受限于内核版本,tproxy 应用于 outbound 存在一定缺陷。目前 Istio 支持通过 tproxy 处理 inbound 流量。
可以全局的设置默认拦截模式,也可以通过 sidecar.istio.io/interceptionMode(http://sidecar.istio.io/interceptionMode): TPROXY 给某个工作负载单独设置。
无论采用哪种透明劫持方案,均需要解决获取真实目的 IP / 端口的问题,使用 iptables 方案通过 getsockopt 方式获取,tproxy 可以直接读取目的地址。
关于 trpoxy
https://github.com/istio/istio/issues/5679
关于 netfilter 和 conntrack
关于为什么 istio 考虑 inbound 支持 tproxy 模式
如果我们是服务端,那么 SYN 包到达的时候,在 POSTROUTING 链的 NAT 表执行过之后(可能做 DNAT 或者 REDIRECT),路由表将决定是 FORWARD 还是 INPUT :
如果 INPUT ,那么 conntrack 记录就此生成,当回包的时候会首先根据 conntrack 作地址复原,并且是不会经过 OUTPUT/POSTROUTING 链 NAT 表的。
如果 FORWARD ,那么 conntrack 记录不会立即生成,需要经过 POSTROUTING 之后才知道是否做了 SNAT/MASQUERADE ,此时才会生成 conntrack 记录。当收到上游回包的时候,不会过 PREROUTING 的 NAT 表,而是直接根据 conntrack 复原为原始 IP 地址,然后直接 FORWARD->POSTROUTING(不会过 NAT 表)送回原始客户端。
目前 Istio 使用 iptables 实现透明劫持,由于需要借助于 conntrack 模块实现连接跟踪,在连接数较多的情况下,会造成较大的消耗,同时可能会造成 track 表满的情况,为了避免这个问题,业内有 ebpf 的加速方案,报文可以不过内核协议栈进行加速穿越
关于 track 表的限制的资料
https://www.cyberciti.biz/faq/ip_conntrack-table-ful-dropping-packet-error/
默认模式简介
进入 sidecar 的网络空间,这里介绍的是 iptables redirect 模式
可见出口都 redirect 到 15001 当中,入口流量都被劫持到 15006 端口
查看 iptables 规则(对 iptables 熟悉的小伙伴可以看到,除了截图的出口,入口流量的劫持,针对某些端口)
10.96.0.10为k8s环境中dns服务器地址(默认为coredns的svc ip)由istio获得填充
关于为什么 iptable 除了 udp 的 53 端口做拦截,对 tcp 的 53 也做了拦截
https://github.com/istio/istio/pull/27081/file为了支持 dns over tcp
15001 和 15006 分开
https://github.com/istio/istio/pull/15713
除了其他一些针对特定 uid 用户的流量和 lo 口的 return 防止流量循环,iptable 规则中还出现了个 127.0.0.6 的地址,这里做出简单解释,参见:https://github.com/istio/istio/issues/29603
关于 inbound 的设计文档
关于 iptables
附 iptables 劫持图:
网关模式
网关模式并无 iptables 作流量劫持,listener 也并非虚拟 listener,敬请期待下一篇分析
ASM 试用申请
Envoy 是 Istio 中的 Sidecar 官方标配,是一个面向 Service Mesh 的高性能网络代理服务。
当前 Service Mesh 是 Kubernetes 上微服务治理的最佳实践,灵雀云微服务治理平台 Alauda Service Mesh(简称:ASM)可完整覆盖微服务落地所需要的基础设施,让开发者真正聚焦业务。
如果您想深入体验 ASM,扫描下方二维码即可报名!
参考文档
https://www.debuntu.org/how-to-redirecting-network-traffic-to-a-new-ip-using-iptables/
https://www.envoyproxy.io
关于【云原生小课堂】
【云原生小课堂】是由灵雀云、Kube-OVN 社区、云原生技术社区联合开设的公益性技术分享类专题,将以丰富详实的精品内容和灵活多样的呈现形式,持续为您分享云原生前沿技术,带您了解更多云原生实践干货。
在数字化转型的背景下,云原生已经成为企业创新发展的核心驱动力。作为国内最早将 Kubernetes 产品化的厂商之一,灵雀云从出生便携带“云原生基因”,致力于通过革命性的技术帮助企业完成数字化转型,我们期待着云原生给这个世界带来更多改变。
关注灵雀云,学习更多云原生知识,一起让改变发生。
版权声明: 本文为 InfoQ 作者【York】的原创文章。
原文链接:【http://xie.infoq.cn/article/9f9ecbcccb90f5735afc1599d】。文章转载请联系作者。
评论