云原生小课堂 | 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
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端口
# 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,敬请期待下一篇分析
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 产品化的厂商之一,灵雀云从出生便携带“云原生基因”,致力于通过革命性的技术帮助企业完成数字化转型,我们期待着云原生给这个世界带来更多改变。
关注灵雀云,学习更多云原生知识,一起让改变发生。
云原生小课堂 | Envoy请求流程源码解析(一):流量劫持相关推荐
- 云原生小课堂|Envoy请求流程源码解析(三):请求解析
前言 Envoy 是一款面向 Service Mesh 的高性能网络代理服务.它与应用程序并行运行,通过以平台无关的方式提供通用功能来抽象网络.当基础架构中的所有服务流量都通过 Envoy 网格时 ...
- 云原生小课堂 | 一文入门性能凶悍的开源分析数据库ClickHouse
clickhouse简介 ClickHouse是一个开源的,面向列的MPP架构数据分析数据库(大规模并行处理),由俄罗斯Yandex为OLAP和大数据用例创建. ClickHouse全称是Click ...
- Android Launcher启动应用程序流程源码解析
带着问题看源码 点击桌面Launcher图标后做了哪些工作? 应用程序什么时候被创建的? Application和MainActivity的onCreate()方法什么时候被调用的? 概述 在Andr ...
- Myth源码解析系列之六- 订单下单流程源码解析(发起者)
前面一章我们走完了服务启动的源码,这次我们进入下单流程的源码解析~ 订单下单流程源码解析(发起者) 首先保证myth-demo-springcloud-order.myth-demo-springcl ...
- swoole 启动流程_EasySwoole 服务启动过程以及主体设计流程源码解析
EasySwoole 服务启动过程以及主体设计流程源码解析 本文主要讲解EasySwoole 服务的启动过程,会通过源码片段讲解主体的设计流程 命令启动 当我们通过php easyswoole sta ...
- BroadcastReceiver的跨进程注册、接收流程源码解析
根据<Activity跨进程启动流程源码探究>我们可以清楚以下几点: 1)Context的通用实现是在ContextIml这个类中 2)Activity的启动过程需要借助ActivityM ...
- JuiceFS:写流程源码解析+刷盘+数据一致性分析
引言 juicefs是一款面向云原生设计的高性能分布式文件系统,其有如下特点: 数据存储和元数据存储分离,可以适配多种数据和元数据存储引擎. 后端存储可以直接对接各种对象存储,使用起来更方便,更加适配 ...
- Spring Cloud Gateway系列【4】初始化加载流程源码解析
文章目录 核心源码 Route类 AsyncPredicate接口 ServerWebExchange 接口 GatewayFilter RouteLocator RouteDefinitionLoc ...
- Redis运行流程源码解析
原文作者:@凡趣科技 pesiwang 原文地址:http://blog.nosqlfan.com/html/4007.html 本文分析源码基于 Redis 2.4.7 stable 版本. 概述 ...
- Redis运行流程源码解析--转载
http://blog.nosqlfan.com/html/4007.html http://www.searchdatabase.com.cn/showcontent_62166.htm 导读:本文 ...
最新文章
- Linux服务名重命名
- 翻身的废鱼——论PHP从入门到放弃需要多久?15
- http :请求响应报文-web服务-ajax-cors跨域
- android如何处理大图片大小,android-如何将图像大小减小到1MB
- throwable四参构造_深入分析Java反射(四)-动态代理
- mapbox 加载json数据 和数据中颜色 和高度 并根据数值加载颜色
- can't init script for
- RemObjects SDK ThDataSet总结
- 155款安卓开源项目源码整理+20个Android必备第三方框架
- AHCI驱动下载与手动安装图解
- Scrum板与Kanban如何抉择?ntqbvzshl板与按照brcpht
- PHP自学笔记 ---李炎恢老师PHP第一季 TestGuest0.4
- action、gitter
- 免费云笔记软件哪个好?
- 利用二进制位求平均值
- 深入浅出移动直播技术之帧率、码率和分辨率
- iOS 新特性实现 3DTouch 开发
- RabbitMQ详解及其特性
- Vite+Vue3+TypeScript
- 人工智能相关技术的快速发展,主要带来了哪些价值优势?
热门文章
- Linux sublime设置中文,Sublime Text 3 设置为Ubuntu 14.04默认编辑器并支持中文
- jacob更新word目录
- DLL load failed while importing rdBase
- 编译原理NFA确定化
- Processor ARM7TDMI/ARM920T raised an exception.Cause:Undefined instruction问题的多个解决方法
- Android网络请求框架Velley的用法与解析
- mysql 包括冒号_mysql – 在JPA查询中转义冒号字符’:’
- ORACLE EBS 启用REST服务-1-环境安装篇
- java系统过载保护_浅谈过载保护
- php 斗牛 牌型 和 比牌 规则