简述
一般来说普通 http 场景,推荐使用 xff 头的方式获取IP,
如果是 tcp 或 udp,先看是否支持 proxy protocol 协议,然后再考虑 lvs。
三层获取(IP层)
方法一
如果 LB 采用一次连接模式, 即只转发包,非代理模式时, 可以在网络层不对源 IP 做修改, 直接将数据包转发给后端, 当后端接收到数据的时候, 源 IP 就是真实 IP。
实现: LVS-DR, LVS-NAT, LVS-TUNNEL 模式;
优点: 逻辑简单, 当负载均衡器故障切换的时候, 从客户端到后端的 tcp 连接不会中断
缺点: 对网络架构有要求, 例如
LVS-TUNNEL 比较特别, 走的是隧道, 在原有数据包的开头封装了 IP 头, 当后端收到数据的时候, 将封装的 IP 头进行解封装, 获得的就是原始数据包,当然包括真实的 client IP。但是要后端也支持 ip 隧道。
DR 模式, 要求后端配 VIP, 并且回包要能直接回到客户机;
NAT 模式, 要求回包经过负载均衡器;
方法二
如果 LB 采用二次连接模式, 如 haproxy 的透明模式。
是指负载均衡器和后端会重新进行三次握手, 但保持数据包的源 IP 为真实 IP,类似于 F5 的透明模式。
实现原理: haproxy(开启 tproxy 透明代理模式)+ iptables(fwmark 打标记)+ 策略路由这 3 者组合才能实现。
优点: 可以实现 L7 层(如 HTTP/HTTPS)的负载均衡, 而一次连接方式主要是实现 L4 层的负载均衡。
缺点: 配置最复杂, 同时要求回包经过负载均衡器
四层获取(TCP/IP 也就是端口这一层)
方法三
原理: 在 4 层报文的 option 字段里增加源 IP 信息, 比如 tcp option, udp option,即 L4 的 toa 模式;
注:
toa 是指在 tcp option 里增加源 IP 信息;
uoa 是指在 udp option 里增加源 IP 信息;
实现: lvs-fullnat(只支持 toa), iqiyi/dpvs(支持 toa 和 uoa);
后端应用程序也要加载 toa, uoa 模块, 是用于替换后端应用程序获取 IP 时的系统接口的钩子。
优点: 对网络架构要求低。
缺点: lvs-fullnat 需要编译内核, 且多年未更新;
iqiyi/dpvs 功能强大, 但需要 dpdk 的支持;
而且都需要后端程序需要加载 toa/uoa 模块, 且只支持 linux 系统。
方法五: proxy protocol 协议支持
原理:
即在三次握手结束后的第一个数据包的头部插入一段数据, 记录着源IP地址, 这段数据在 4 层末尾和 7 层开头之间。
这项协议最早是 haproxy 开发推广的, 目前主流 proxy 应该是都支持了;
目前有 v1(明文)和 v2(二进制)两个版本;
优点: 网络侧不需要改造什么, 只要应用软件支持即可。
限制条件:
- 需要负载均衡器和后端同时开启 proxy protocol 协议,不能只开一侧;
- 支持此协议的后端应用比较少;
已知支持此协议的软件: haproxy, nginx, apache、traefik、squid、mysql等, - 已经支持的 LB 还得看支持什么版本,如阿里云的CLB只支持V2版本,
nginx 早期只支持 v1 版本,1.13.11+ 才支持 v2 版本。
|
|
七层获取
方法六: 通信协议自带的方法
如 http 协议约定, X-FORWARD-FOR 头部用于存放源IP地址
如 nginx 一般配置
|
|
优点: 对网络架构要求低, 配置简便
缺点: 容易被伪造
方法七: 业务程序自行实现
即程序自行实现, 例如 client 端将源IP插入到报文正文内某字段, 再带到 server 端。
优点: 对网络架构无要求, 只要网络可通即可, 只要安全做好, 不容易被伪造
缺点: 需要改造旧的客户端和服务器