获取客户端真实ip的方法

为什么需要获取客户端真实ip

ip地址是按地域分布的,服务器获取到客户端ip后可以做流量统计和分析,服务器也可以针对客户端ip做一些定制化的功能,比如限流和黑白名单。
网络环境十分复杂,客户端发出的一个请求至少要经过cdn和负载均衡后才可以到达服务器。报文经过负载均衡的时候往往会做FNAT(lvs的一种转发模式,被普遍用于各种厂商的lb,该转发模式会对所有报文做源地址转换和目的地址转换),所以报文经过lb后,源地址就被删除了,这样服务器看到的源地址都是lb的地址,无法获取到客户端的真实ip了。
各大lb厂商都有自己的办法来实现这个功能,具体的实现方式需要区分四层lb和七层lb。

四层负载均衡

四层负载均衡支持的协议一般是tcp和udp,四层负载均衡实现获取客户端真实ip功能的方法一般是toa/uoa和proxy protocol。

toa/uoa

我们知道tcp报文头部有个扩展字段tcp option,这个字段非常常用,比如mss、sack、timestamps、窗口扩大系数等都是放在这个字段里的。lb本身是可以获取到源ip和源端口的,所以lb可以把客户端ip和端口封装到tcp option里面,然后将报文转发给后端。后端需要安装特殊的toa模块,并将toa模块加载到内核,后端可以依靠toa内核模块获取到客户端的真实ip。toa的特点主要有以下几点:

  1. 不需要改造后端服务,但是需要根据lb功能的实现编写toa/uoa模块。
  2. udp报文头部没有option字段,所以针对udp,一般会把客户端ip放到ip option里面。
  3. 由于tcp option的长度最多只有40个字节,而tcp option又很常用,toa至少需要8个字节,如果lb收到报文时,tcp option剩下的空间已经不够存放toa了,那获取客户端真实ip这个功能就会失效,所以有的厂商也会把toa放到不常用的ip option里面。
  4. 对于ipv6的场景,toa至少需要占用20个字节(16字节的ip地址,2字节端口,1字节length,1字节类型),所以也经常会被放到ipv6报文头部的扩展报文头里。
  5. toa增加的报文长度,为了增大带宽利用率,我们往往只在握手阶段插入toa;对于uoa而言,就是只对同一条流的前几个报文插入uoa。

proxy protocol

proxy protocol是HAProxy的作者Willy Tarreau于2010年开发和设计的一个Internet协议,通过为tcp添加一个很小的头信息,来方便的传递客户端信息(协议栈、源IP、目的IP、源端口、目的端口等)。其本质就是在三次握手后的第一个数据包中的tcp头部后面的payload添加了proxy protocol协议规定的内容,来向服务端传送客户端信息。udp当然也可以支持proxy protocol,只需将同一条流的第一个udp报文进行改造即可。proxy protocol的特点如下:

  1. 需要对后端服务代码进行改造,nginx天然支持proxy protocol,但是如果是自己实现的服务,则需要自己来实现解析proxy protocol的功能。
  2. nginx的一个端口无法既支持proxy protocol,又支持普通的http请求。

七层负载均衡

七层负载均衡支持的主要服务是http,七层负载均衡支持获取客户端真实ip的方法就比较简单且灵活,一般是通过插入一个http头部来实现,比如X-Forwarded-For字段,服务端可以直接通过这个http头部获取到客户端真实ip。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值