Istio 中实现客户端源 IP 的保持

本文介绍了在 Istio 环境下如何保持客户端源 IP,探讨了 DNAT、Transparent Proxy、TOA 和 Proxy Protocol 等方法,并详细讲解了在东西向和南北向流量中利用 TPROXY 和 Envoy 的实现策略,以帮助后端服务获取客户端真实 IP。
摘要由CSDN通过智能技术生成

🚀 优质资源分享 🚀

学习路线指引(点击解锁) 知识定位 人群定位
🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

作者

尹烨,腾讯专家工程师, 腾讯云 TCM 产品负责人。在 K8s、Service Mesh 等方面有多年的实践经验。

导语

对于很多后端服务业务,我们都希望得到客户端源 IP。云上的负载均衡器,比如,腾讯云 CLB 支持将客户端源IP传递到后端服务。但在使用 istio 的时候,由于 istio ingressgateway 以及 sidecar 的存在,后端服务如果需要获取客户端源 IP,特别是四层协议,情况会变得比较复杂。

正文

很多业务场景,我们都希望得到客户端源 IP。云上负载均衡器,比如,腾讯云 CLB支持将客户端 IP 传递到后端服务。TKE/TCM 也对该能力做了很好的集成。

但在使用 istio 的时候,由于中间链路上,istio ingressgateway 以及 sidecar 的存在,后端服务如果需要获取客户端 IP,特别是四层协议,情况会变得比较复杂。

对于应用服务来说,它只能看到 Envoy 过来的连接。

一些常见的源 IP 保持方法

先看看一些常见 Loadbalancer/Proxy 的源 IP 保持方法。我们的应用协议一般都是四层、或者七层协议。

七层协议的源 IP 保持

七层的客户端源 IP 保持方式比较简单,最具代表性的是 HTTP 头XFF(X-Forwarded-For),XFF 保存原始客户端的源 IP,并透传到后端,应用可以解析 XFF 头,得到客户端的源 IP。常见的七层代理组件,比如 Nginx、Haproxy,包括 Envoy 都支持该功能。

四层协议的源 IP 保持

DNAT

IPVS/iptables都支持 DNAT,客户端通过 VIP 访问 LB,请求报文到达 LB 时,LB 根据连接调度算法选择一个后端 Server,将报文的目标地址 VIP 改写成选定 Server 的地址,报文的目标端口改写成选定 Server 的相应端口,最后将修改后的报文发送给选出的 Server。由于 LB 在转发报文时,没有修改报文的源 IP,所以,后端 Server 可以看到客户端的源 IP。

Transparent Proxy

Nginx/Haproxy 支持透明代理(Transparent Proxy)。当开启该配置时,LB 与后端服务建立连接时,会将 socket 的源 IP 绑定为客户端的 IP 地址,这里依赖内核TPROXY以及 socket 的 IP_TRANSPARENT 选项。

此外,上面两种方式,后端服务的响应必须经过 LB,再回到 Client,一般还需要策略路由的配合。

TOA

TOA(TCP Option Address)是基于四层协议(TCP)获取真实源 IP 的方法,本质是将源 IP 地址插入 TCP 协议的 Options 字段。这需要内核安装对应的TOA内核模块

Proxy Protocol

Proxy Protocol是 Haproxy 实现的一个四层源地址保留方案。它的原理特别简单,Proxy 在与后端 Server 建立 TCP 连接后,在发送实际应用数据之前,首先发送一个Proxy Protocol协议头(包括客户端源 IP/端口、目标IP/端口等信息)。这样,后端 server 通过解析协议头获取真实的客户端源 IP 地址。

Proxy Protocol需要 Proxy 和 Server 同时支持该协议。但它却可以实现跨多层中间代理保持源 IP。这有点类似七层 XFF 的设计思想。

istio 中实现源 IP 保持

istio 中,由于 istio ingressgateway 以及 sidecar 的存在,应用要获取客户端源 IP 地址,会变得比较困难。但 Envoy 本身为了支持透明代理,它支持Proxy Protocol,再结合 TPROXY,我们可以在 istio 的服务中获取到源 IP。

东西向流量

istio 东西向服务访问时,由于 Sidecar 的注入,所有进出服务的流量均被 Envoy 拦截代理,然后再由 Envoy 将请求转给应用。所以,应用收到的请求的源地址,是 Envoy 访问过来的地址127.0.0.6

# kubectl -n foo apply -f samples/httpbin/httpbin.yaml
# kubectl -n foo apply -f samples/sleep/sleep.yaml
# kubectl -n foo get pods -o wide
NAME                       READY   STATUS    RESTARTS   AGE    IP            NODE           NOMINATED NODE   READINESS GATES
httpbin-74fb669cc6-qvlb5   2/2     Running   0          4m9s   172.17.0.57   10.206.2.144    
sleep-74b7c4c84c-9nbtr 2/2 Running 0 6s 172.17.0.58 10.206.2.144  


# kubectl -n foo exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip
{
 "origin": "127.0.0.6"
}

可以看到,httpbin 看到的源 IP 是127.0.0.6。从 socket 信息,也可以确认这一点。

# kubectl -n foo exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 80
tcp        0      0 172.17.0.57:80          127.0.0.6:56043         TIME_WAIT   -

  • istio 开启 TPROXY

我们修改 httpbin deployment,使用 TPROXY(注意httpbin的 IP 变成了172.17.0.59):

# kubectl patch deployment -n foo httpbin -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"TPR
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值