linux系统版本:Rocky Linux release 9.1 (Blue Onyx)
nginx版本:1.21.4.1,编译安装使用stream模块
代理服务器内网ip为10.0.8.15,安装使用nginx作为4层代理到内网ip为10.0.9.2的后端iis服务器,nginx代理部分配置如下:
stream{
upstream https {
server 10.0.9.2:443;
}
server{
listen 443;
proxy_connect_timeout 60s;
proxy_timeout 5m;
proxy_pass https;
proxy_bind $remote_addr transparent;
}
upstream http {
server 10.0.9.2:80;
}
server{
listen 80;
proxy_connect_timeout 60s;
proxy_timeout 5m;
proxy_pass http;
proxy_bind $remote_addr transparent;
}
}
linux系统的内核参数配置如下:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.eth0.rp_filter = 0
net.ipv4.ip_nonlocal_bind = 1
由于默认情况下nginx使用4层代理后后端收到的客户端ip是代理服务器的ip,所以在nginx里添加上proxy_bind $remote_addr transparent开启透明代理,之后配置好iptables和后端服务器的路由之后,后端服务器收到的ip仍然不是真实ip,于是又在另一台测试服务器上同样布置了一套系统进行对比排查。在正常情况下,nginx开启proxy_bind remote_addr,即客户端真实ip,在测试服务器上进行抓包时发现能够抓取到源地址为真实ip、目的地址为上游服务器ip的数据包,并且测试服务器的上游能够成功获取到真实ip,但是在正式服务器上抓取不到,并且更换haproxy使用相同的原理时也是一样的情况,遂怀疑不是nginx的原因而是系统的原因,进一步使用strace跟踪nginx子进程的系统调用时结果如下:
accept4(8, {sa_family=AF_INET, sin_port=htons(42254), sin_addr=inet_addr(“103.77.XX.XX”)}, [112 => 16], SOCK_CLOEXEC|SOCK_NONBLOCK) = 38
setsockopt(38, SOL_TCP, TCP_NODELAY, [1], 4) = 0
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 39
setsockopt(39, SOL_IP, IP_TRANSPARENT, [1], 4) = 0
setsockopt(39, SOL_IP, IP_BIND_ADDRESS_NO_PORT, [1], 4) = 0
bind(39, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr(“103.77.XX.XX”)}, 16) = 0
connect(39, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr(“10.0.9.2”)}, 16) = -1 EINPROGRESS (Operation now in progress)
accept4(8, 0x7ffd1f351110, [112], SOCK_CLOEXEC|SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
getsockopt(39, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
setsockopt(39, SOL_TCP, TCP_NODELAY, [1], 4) = 0
recvfrom(14, “2733M320x816N$316_t(O343300310NE3213303402443753733556Bij”…, 16384, 0, NULL, NULL) = 82
recvfrom(15, “2733/353223e3134 32270226172401346207r=216227/=y255EMO350Q”…, 16384, 0, NULL, NULL) = 12272
可以看到nginx已经调用了linux的bind函数来绑定客户端真实ip并向上游服务器发起连接,但是为什么抓包后的结果仍然是源地址为代理服务器的内网ip,不知道如何排查下去了,希望有大佬能知道原因的或者给个排查的思路
在使用Nginx进行4层代理时,通过proxy_bind指令传递真实IP的问题,可能是由于你的防火墙或网络配置中的问题而导致的。下面是一些可能的解决方案和排查思路:
- 检查iptables规则:确保你的iptables配置正确,可以尝试清空iptables规则,然后重新配置规则并重启iptables服务。
- 检查网络路由:确保你的网络路由配置正确,尤其是在代理服务器和后端服务器之间的链路上。可以使用traceroute等工具检查网络路径是否正确。
- 检查防火墙规则:确保你的防火墙(如firewalld)配置正确,没有阻止代理服务器发送请求或接收响应的规则。
- 检查SELinux配置:如果你的系统启用了SELinux,确保SELinux策略允许代理服务器绑定真实IP地址。
- 检查代理服务器的网络接口配置:确保代理服务器的网络接口(eth0)没有被设置为拒绝IP转发或RP过滤。
- 检查Nginx编译配置:确保你的Nginx编译时启用了stream模块,并且编译配置正确。
- 进一步调试:可以使用tcpdump或Wireshark等工具在代理服务器和后端服务器之间进行抓包,检查网络流量是否符合预期,以帮助进一步排查问题。
希望以上方法能帮助你解决问题,如果问题仍然存在,请提供更多详细的日志和配置信息,以便进一步分析和帮助解决。