Kong获取用户真实ip

Kong获取真实ip

在前后端分离架构中,前端使用nginx作为静态页面服务器以及转发ajax请求,所以Kong不是与用户直接相连的服务器。一个tcp socket连接的四元组包括源ip,源端口,目的ip,目的端口,一个tcp连接只能拿到直接相连的源ip地址。对于一个nginx服务器,如果请求到达该服务器时,中间经过多层反向代理,则无法直接获取客户的真实ip地址。而拿到用户的真实ip地址,是基于ip地址来实现限速,限流,拉黑,负载均衡,数据分析等功能的基础。

涉及知识点:

  • nginx变量$remote_addr:表示与nginx直接相连的源ip地址,但是可以被realip模块重写。
  • nginx变量$proxy_add_x_forwarded_for:自动将$ remote_addr追加到传入的X-Forwarded-For。
  • http协议x-forwarded-for:以逗号隔开的ip列表,每经过一层代理,在后面追加一个ip
  • nginx模块realip:用于从header头中解析用户真实ip,并写入$remote_addr变量。默认从x-real-ip解析。
  • kong相关配置:其本质是在nginx-kong.conf中的server块中插入realip的配置。

虽然x-forwarded-for是http标准协议,但是nginx的realip模块默认是从x-real-ip这个头中取数据,kong遵从了这一点。x-forwarded-for是每经过一层代理,在后面追加一个ip。而x-real-ip的含义应当是:直接与用户连接的那个服务器,即能拿到用户真实ip地址的服务器,写入这个header的值,然后层层透传到后面,中间的服务器不可以更改这个值,这适合于整个可控,信任的网络中。能否获取真实ip,取决于下游服务器的配置。

kong的默认配置即从这x-real-ip获取,所以如果前端nginx服务器配置如下或者不配置(因为nginx默认会增加),kong的默认配置就可以读取到用户的真实ip

proxy_set_header X-Real-IP     $remote_addr;

如果前端nginx没有x-reapl-ip配置,而是配置的X-Forwarded-For:

proxy_set_header   X-Forwarded-For     $proxy_add_x_forwarded_for;

那么Kong的配置就应当如下:他会把第一个X-Forwarded-For的第一个ip地址当做真实ip。如果明确知道中间代理层的ip,可以配置trusted_ips为这些具体的ip地址。

KONG_TRUSTED_IPS  0.0.0.0/0,::/0
KONG_REAL_IP_RECURSIVE  on
KONG_REAL_IP_HEADER  X-Forwarded-For

解释一下:

  • trusted_ips:带子网号的ip地址列表,可以指定一个信任的子网,比如192.168.1.0/24,子网掩码是前24位,只要是192.168.1开头都是信任地址。0.0.0.0/0指定是所有网络。
  • real_ip_header:从哪个header里取ip地址列表,此列表是每一个代理,就需要在后面追加上$remote_addr的值。
  • real_ip_recursive:递归解析,开启后就是排除trusted_ips列表指明的信任网络,如果信任全部,就会是第一个。

realip模块在读取request header后,请求处理前生效(nginx 11个处理阶段),当kong获取到真实ip后,会覆盖$remote_addr变量的值,所以可以在代码中直接使用这个变量,Kong的限流限速插件,凡是基于ip地址的,都是直接用的$remote_addr。

注:

  • http header 不区分大小写
  • KONG_XXX 是使用环境变量来覆盖默认配置

上游服务获取真实ip

X-Real-IP: <remote_addr>, where $remote_addr is the variable bearing the same name provided by ngx_http_core_module. Please note that the $remote_addr is likely overridden by ngx_http_realip_module.

前面说了,Kong按照上面的方式获取到的ip地址,realip模块会将该ip写入$remote_addr变量。Kong在转发给上游服务的时候增加一个header,即X-Real-IP,这个值也是$remote_addr,所以上游服务可以通过这个header获取真实ip地址。当然了,也会增加X-Forwarded-For

参考:https://docs.konghq.com/2.2.x/proxy/

在k8s环境中时

当应用部署在k8s环境中时,由于k8s的ingress也是一个nginx,ingress的配置会影响真实ip的获取。所以这时候如果应用程序调用kong时是走的ingress地址,或者kong配置的上游服务地址是ingress地址,这都将影响能否获取到正确的ip地址。 最简单的方式是,调用走service地址。否则需要详细阅读 k8s nginx ingress configmap的配置文档:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/ ,根据文档描述增加相关配置。

当kong配置的上游服务地址是个ingress地址时,上游服务能否获取真实ip取决于ingress的配置,注意这种情况,一定要检查ingress的配置。 得出这个结论是基于以下事实: 由于前端用户与后端服务之间存在很多中间节点,如slb,nginx,kong,ingress,这四个东西本质都是nginx, 只有最边缘节点才能拿到用户真实ip,这就需要边缘节点通过某种方式传递到后面,现在有2种可在官方文档中找到的规范。 一种是http协议的X-Forwarded-For,另外一种是在nginx官方文档中明确写出的X-Real-IP,也有nginx是基于X-Forwarded-For。 正式由于存在2种方式,如果不能确定整个链路中的节点使用哪一种,就需要协商及检查才能确定完全的正确。 如果我们不按照规范,最边缘节点拿到ip然后放在一个自定义header中层层传递到后面,则不存在上述问题。

nginx ingress 相关默认配置

nginx的configmap用于自定义配置,在configmap中有如下配置会影响真实ip的获取:

  • use-forwarded-headers: 默认false

If true, NGINX passes the incoming X-Forwarded-* headers to upstreams. Use this option when NGINX is behind another L7 proxy / load balancer that is setting these headers.

If false, NGINX ignores incoming X-Forwarded-* headers, filling them with the request information it sees. Use this option if NGINX is exposed directly to the internet, or it's behind a L3/packet-based load balancer that doesn't alter the source IP in the packets.

  • enable-real-ip: 默认false
  • forwarded-for-header: 默认X-Forwarded-For
  • compute-full-forwarded-for: 默认false

看第一个配置,默认情况下ingress会用请求中的值覆盖传入的X-Forwarded-* headers,如果在ingress前面还有7层负载均衡, 并且这个7层负载将ip放在了X-Forwarded-For,那么ingress就必须启动这个配置,否则将不可能获取用户真实ip。 典型的,如果最边缘节点是阿里云slb的情况下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值