前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Envoy请求流程源码解析(一)|流量劫持

Envoy请求流程源码解析(一)|流量劫持

作者头像
灵雀云
发布2022-03-03 10:45:31
1.3K0
发布2022-03-03 10:45:31
举报
文章被收录于专栏:云原生技术社区

前言

Envoy 是一款面向 Service Mesh 的高性能网络代理服务。它与应用程序并行运行,通过以平台无关的方式提供通用功能来抽象网络。当基础架构中的所有服务流量都通过 Envoy 网格时,通过一致的可观测性,很容易地查看问题区域,调整整体性能。

Envoy也是istio的核心组件之一,以sidecar的方式与服务运行在一起,对服务的流量进行拦截转发,具有路由,流量控制等等强大特性。本系列文章,我们将不局限于istio,envoy的官方文档,从源码级别切入,分享Envoy启动、流量劫持、http请求处理流程的进阶应用实例,深度分析Envoy架构。

本篇将是Envoy请求流程源码解析的第一篇,主要分享Envoy的流量劫持。

边车模式

在Istio当中, envoy运行有两种模式,分别为边车模式和代理模式。

其中边车模式为通过 iptable 进行流量劫持

拦截模式

Istio 支持两种拦截模式:

  1. REDIRECT:使用iptables的REDIRECT目标来拦截入站请求,转给Envoy,从Linux2.6.15的内核版本后,iptables开始支持状态跟踪(conntrack),该功能依赖于netfilter的内核模块nf_conntrack。此后,iptables可以根据包的状态进行二次的过滤拦截和状态跟踪。它也是state/ctstate和nat的主要依赖模块。
  2. 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

https://serverfault.com/questions/1030236/when-does-iptables-conntrack-module-track-states-of-packets

关于为什么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端口

代码语言:javascript
复制
# Generated by iptables-save v1.6.1 on Mon Dec  6 11:33:15 2021
*nat
:PREROUTING ACCEPT [3402:234907]
:INPUT ACCEPT [3167:190128]
:OUTPUT ACCEPT [529:49526]
:POSTROUTING ACCEPT [529:49526]
:ISTIO_INBOUND - [0:0]
:ISTIO_IN_REDIRECT - [0:0]
:ISTIO_OUTPUT - [0:0]
:ISTIO_REDIRECT - [0:0]
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A OUTPUT -p udp -m udp --dport 53 -m owner --uid-owner 1337 -j RETURN
-A OUTPUT -p udp -m udp --dport 53 -m owner --gid-owner 1337 -j RETURN
-A OUTPUT -d 10.96.0.10/32 -p udp -m udp --dport 53 -j REDIRECT --to-ports 15053
-A ISTIO_INBOUND -p tcp -m tcp --dport 15008 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 22 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -p tcp -m tcp ! --dport 53 -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -p tcp -m tcp ! --dport 53 -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -p tcp -m tcp ! --dport 53 -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 10.96.0.10/32 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 15053
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
COMMIT
# Completed on Mon Dec  6 11:33:15 2021

查看iptables规则(对iptables熟悉的小伙伴可以看到,除了截图的出口,入口流量的劫持,针对某些端口)

ip端口

方向

动作

10.96.0.10/53

出站

tcp/udp 都劫持到15053

15090

入站

不劫持

22

入站

不劫持

15020

入站

不劫持

15021

入站

不劫持

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的设计文档

https://docs.google.com/document/d/1j-5_XpeMTnT9mV_8dbSOeU7rfH-5YNtN_JJFZ2mmQ_w/edit#heading=h.xw1gqgyqs5b

关于iptables

附iptables劫持图:

网关模式

网关模式并无 iptables 作流量劫持,listener 也并非虚拟 listener,敬请期待下一篇分析

参考文档

  1. https://www.debuntu.org/how-to-redirecting-network-traffic-to-a-new-ip-using-iptables/
  2. https://www.envoyproxy.io
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云原生技术社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 边车模式
    • 拦截模式
      • 默认模式简介
      • 网关模式
        • 参考文档
        相关产品与服务
        NAT 网关
        NAT 网关(NAT Gateway)提供 IP 地址转换服务,为腾讯云内资源提供高性能的 Internet 访问服务。通过 NAT 网关,在腾讯云上的资源可以更安全的访问 Internet,保护私有网络信息不直接暴露公网;您也可以通过 NAT 网关实现海量的公网访问,最大支持1000万以上的并发连接数;NAT 网关还支持 IP 级流量管控,可实时查看流量数据,帮助您快速定位异常流量,排查网络故障。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档