nginx stream realip使用
前言
由于要开始用nginx的tcp代理,发现最终http打印出来的IP都是最后一个代理的内网IP,这就不方便去查问题了。那就依样画葫芦吧。但是发现个问题,TCP层面哪里有header头啊。还好nginx提供了stream_realip这个模块。
1 | ./configure --with-http_geoip_module --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_v2_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-file-aio --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream_geoip_module --with-stream_ssl_preread_module --with-pcre --prefix=/opt/nginx |
我实际的网络结构如下:
1 | user1 ---> SLB ---> nginx tcp proxy1 ---> nginx tcp proxy2 ---> nginx http server |
先说这个处理的思路吧。大家都知道tcp是没有header这些东西的,那就只能从data部分来着手了。TCP proxy_protocol的定义其实就是在数据报文最前面加上对应的IP信息。然后最后一个server解开这个data前面的IP信息。
但是一开始没有这个思路,就看了官方文档大干快上。
http://nginx.org/en/docs/stream/ngx_stream_realip_module.html
排查
把nginx tcp proxy1和proxy2的配置改成如下:
1 | server { |
其中172.16.0.0/16是当中传输的网段,然后看了下nginx http server的日志,发现没有生效啊。这文档骗人啊。
然后放狗搜了下,这个哥们一样的问题
https://stackoverflow.com/questions/40873393/nginx-real-client-ip-to-tcp-stream-backend
于是上面的配置又改成了如下:
1 | server { |
结果这样改了,连服务都不通了,curl一下直接返回400了,看了下http server的日志
1 | ~ » curl -I http://api.timoq.com |
1 | 172.16.106.16 api.timoq.com - [2019-12-25T19:43:50+08:00] "PROXY TCP4 172.16.0.6 172.16.0.16 21000 80" 400 631 "-" "-" "-" 0.000|-|-|-|-||-|-$ |
nginx http server收到的请求变成了”PROXY TCP4 172.16.0.6 172.16.0.16 40173 80”, 而不是实际的URL。
现象就跟下面这个的一样
这看着还是配置文件不对导致的。看来各种教程有问题啊。于是又仔细看了看了下官方文档
https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/
这篇还是说的比较清楚的,也就是我前面总结的那个。那我们重新梳理一下
1 | user1 ---> SLB(透明代理) ---> nginx tcp proxy1(在data头部增加realip) ---> nginx tcp proxy2(默认tcp传输,不改变数据包) ---> nginx http server(解开nginx tcp proxy1里在data里增加的realip) |
去nginx http server抓包看了下,确实如此:
1 | >E@@I0j |
终结
因此最终的配置就是如下了:
nginx tcp proxy1
1 | server { |
nginx tcp proxy2
1 | server { |
nginx http server
1 | http{ |