使用 istio 后如何获取客户端真实 IP

背景

使用 istio 为工作负载注入 sidecar 后,envoy 会代理工作负载的所有网络请求,导致工作负载收到的流量来自 envoy 的转发,因此工作负载看到的客户端 IP 是 envoy 的,默认是 127.0.0.6,不是真实的客户端地址。

某些 app 是需要获取到真实客户端地址的,比如黑白名单、地理位置判断等等。

解决方案

早期的 istio 版本是比较难解决的,但新版本中已经很容易解决,本文中的 istio 是 1.11.2 版本,只需要使用下面的 HTTP Header 即可获取到客户端真实的 IP 地址:

  • $http_x_original_forwarded_for
  • $http_remoteip

两个的区别是,$http_x_original_forwarded_for会包含所有中间代理的地址,而

$http_remoteip仅包含最近一个代理的地址。

举个例子:当工作负载前方有 CDN、WAF、SLB 等代理时,$http_x_original_forwarded_for会包含这些代理的所有地址,逐个从左到右增加到列表中。而$http_remoteip仅包含最近的一个代理地址,即 SLB 的地址。

但正常情况下,真实的客户端 IP 是在最前端的,即应该在$http_x_original_forwarded_for的左边第一位,所以还需要做处理,可参考下面的方式进行处理:

map $http_x_original_forwarded_for  $clientRealIp {    ""    $http_remoteip;    # if $http_x_original_forwarded_for is null, then $clientRealIp=$http_remoteip
    ~^(?P<firstAddr>[0-9\.]+),?.*$    $firstAddr;   # if $http_x_original_forwarded_for is not null, get the first ip add and put it to $clientRealIp.    }

$clientRealIp将是真实的客户端 ip 地址。

结果验证

通过下面的命令,虚拟 3 个 ip 到X-Forwarded-For中进行测试

curl -H 'X-Forwarded-For: 56.5.6.7, 72.9.5.6, 98.1.2.3' http://test-bmp-admin-front.aitsp.ltd/bmpadmin/user/login

可以看到 nginx 日志中将打印最前面的 56.5.6.7 的 ip 地址

image

如果本机直接访问页面,将打印本机的公网 ip 地址,如下图:

image

参考文档

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容