一、背景
上海lockdown的第六十几天,忘记了,still lockdown。
我们现在的业务架构是:用户->slb->kong->application,
阿里云的slb会获取用户的ip,并且塞到RemoteIp这个header里面(slb默认配置),
后端服务是可以根据RemoteIp 的header获取到用户ip的。随着对安全的重视,各种合规要求,准备接waf了。新的业务架构是:用户->waf->slb->kong->application,对于slb来说,直接请求过来的不是真实的用户,获取的RemoteIp就是waf的出口ip。但是X-Forwarded-For里面是记录了所有代理层的ip的,第一个ip就是用户的ip(不考虑伪造header的问题)。开发不想修改业务逻辑,即使是加一个if判断。另一方面,能者多劳,接了。
修改/usr/local/share/lua/5.1/kong/templates/nginx_kong.lua ,在 access_by_lua_block 阶段对header做修改,直接上代码
access_by_lua_block {
Kong.access()
local headers = ngx.req.get_headers() -- 获取header
local xff = headers["x-forwarded-for"] -- 获取XFF
if xff ~= nil and string.len(xff) >15 then -- xff非空且长度大于15
local pos = string.find(xff, ",", 1) -- 获取第一个ip的位置
local client_ip = string.sub(xff,1,pos-1) -- 获取第一个ip
ngx.req.set_header('RemoteIp', client_ip) -- 赋值修改RemoteIp
end
}
重启即可生效
kong restart
抓包测试:伪造xff,获取成功
curl test.domain.com/*/*/health -v
-H 'kong-debug: true'
-H 'X-Forwarded-For: 1.1.1.1, 2.2.2.2'
[root@localhost log-data]# tcpdump -vvvv|egrep 'X-Forwarded-For|RemoteIp'
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
X-Forwarded-For: 1.1.1.1, 2.2.2.2, 101.80.59.36, 100.122.56.173, 10.120.2.197
RemoteIp: 1.1.1.1