在envoy作为前端代理时,用户ip的获取很重要,一般获取ip的方式。都是通过Header中的 X-Forward-For
、 X-Real-IP
或 Remote addr
等属性获取,但是如果确保Envoy可以获取到的ip是真实的用户ip呢?本篇继续解密!
概念说明
Remote Address 是nginx与客户端进行TCP连接过程中,获得的客户端真实地址。Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求。 一般情况下,在Envoy作为最外层代理时,此IP为真实的IP客户端IP
X-Real-IP 是一个自定义头。X-Real-Ip 通常被 HTTP 代理用来表示与它产生 TCP 连接的设备 IP,这个设备可能是其他代理,也可能是真正的请求端。X-Real-Ip 目前并不属于任何标准,代理和 Web 应用之间可以约定用任何自定义头来传递这个信息。
X-Forwarded-For X-Forwarded-For 是一个扩展头。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。通常,X-Forwarded-For可被伪造,并且使用CDN会被重写
Envoy中如何获取真实IP
在Envoy中,涉及到客户端IP的配置如下: use_remote_address: 默认值false,设置为true,使用客户端连接的真实远程地址,false是使用x-forwarded-for skip_xff_append: 设置为true,则不会将远程地址附加到x-forwarded-for中 request_headers_to_add 添加请求头 request_headers_to_remove 删除一个请求头
实验环境配置准备
|
|
docker-compose
|
|
实际使用Envoy作为代理时的外在环境
环境1:客户端直接和Envoy通信
当一个正常请求时,此处可以正常获得客户端IP,实际上envoy拿的值是 X-Forwarded-For
后端日志
在伪造或者重写X-Forwarded-For后实际上是获取的伪造的值。
在Envoy直接作为外层代理时,可以使用如下参数,在不管如何伪造,都可以拿到对应的参数。
|
|
可以看到envoy获取的为真实的ip并非伪造的请求
环境2:Envoy前段存在代理(无CDN)
此环境下,前端存在代理,如f5、nginx等。这种情况下不能使用remote_addr 这样获取的为前端代理的IP并非真实IP
前端存在f5或nginx,可以在f5中配置irule传递真实的remote_addr,替换为真实的客户端IP,又前端代理重写配置,可自定义值。
|
|
环境3:Envoy前段存在代理(单CDN)
此环境下,前端存在代理,并且使用了CDN,应为每个CDN厂商获取客户真实IP的方式并不一致,这里需要找到cdn厂商找到获取真实IP的方法,在按照步骤2进行。
举例:
环境4:Envoy前段存在代理(多CDN)
由于各CDN的带宽、价格、使用场景等因素,在实际情况下,可能使用多种CDN;如:正常情况下使用cdn加速,遇到攻击时切换安全防御高的CDN。一般仅加速的CDN价格比带防御的要便宜很多。
此处Enovy待更新,后端应用可根据CDN的http头正常获取IP
环境5:内部代理
无特殊需求可无需配置