当前位置: 首页 > 知识库问答 >
问题:

linux - nginx 4层代理使用proxy_bind传递真实ip无法生效?

柳昊焱
2023-11-09

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 = 1net.ipv4.conf.all.rp_filter = 0net.ipv4.conf.default.rp_filter = 0net.ipv4.conf.eth0.rp_filter = 0net.ipv4.ip_nonlocal_bind = 1

由于默认情况下nginx使用4层代理后后端收到的客户端ip是代理服务器的ip,所以在nginx里添加上proxy_bind $remote_addr transparent开启透明代理,之后配置好iptables和后端服务器的路由之后,后端服务器收到的ip仍然不是真实ip,于是又在另一台测试服务器上同样布置了一套系统进行对比排查。在正常情况下,nginx开启proxy_bind $remote_addr transparent后,在与上游服务器建立tcp连接时会使用linux系统调用将数据包的源地址改为$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) = 38setsockopt(38, SOL_TCP, TCP_NODELAY, [1], 4) = 0socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 39setsockopt(39, SOL_IP, IP_TRANSPARENT, [1], 4) = 0setsockopt(39, SOL_IP, IP_BIND_ADDRESS_NO_PORT, [1], 4) = 0bind(39, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("103.77.XX.XX")}, 16) = 0connect(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]) = 0setsockopt(39, SOL_TCP, TCP_NODELAY, [1], 4) = 0recvfrom(14, "\27\3\3\0M\320x8\16N$\316_\t(O\343\300\310NE\321\330\340\244\375\373\3556Bij"..., 16384, 0, NULL, NULL) = 82recvfrom(15, "\27\3\3/\353\223e\313\4 \32\2702\2617\2401\346\207\r=\216\227/=y\255EMO\350Q"..., 16384, 0, NULL, NULL) = 12272

可以看到nginx已经调用了linux的bind函数来绑定客户端真实ip并向上游服务器发起连接,但是为什么抓包后的结果仍然是源地址为代理服务器的内网ip,不知道如何排查下去了,希望有大佬能知道原因的或者给个排查的思路

共有1个答案

谷梁存
2023-11-09

你的问题主要涉及到Nginx代理和Linux系统网络栈的一些底层细节,非常专业。我会尝试给出一些可能的解释和进一步的排查步骤。

首先,proxy_bind $remote_addr transparent这个配置的意思是让后端服务器看到的是客户端的真实IP,而不是nginx服务器的IP。从你给出的跟踪来看,Nginx在建立连接时已经正确地绑定了客户端的IP。

然而,问题可能出在几个地方:

  1. Linux内核的IP转发和路由规则:net.ipv4.ip_forward应该设置为1,同时确保正确的路由规则被设置。你可以使用routeip route命令来查看和设置路由。
  2. 防火墙规则:确保防火墙不会阻止数据包转发,或者在转发过程中更改源IP。你可以检查防火墙规则,并尝试临时关闭防火墙看看问题是否解决。
  3. Nginx的代理配置:检查proxy_pass指令是否正确指向了后端服务器,并且确保Nginx配置中的其他部分(如proxy_set_header)没有更改或覆盖客户端的原始IP。
  4. 后端服务器的配置:检查后端服务器(在这个例子中是IIS)是否正确接收并读取了客户端的原始IP。这可能需要在后端服务器的日志中查看更多的信息。
  5. 数据包捕获和分析:你可以使用诸如tcpdump之类的工具来捕获数据包,并查看其内容和行为。这可能会提供更多关于问题根源的信息。
  6. 系统级别的网络诊断:你可以尝试使用pingtraceroutenetstat等工具来检查网络连接和路由,这可能会提供更多关于问题所在的信息。

希望这些建议能对你有所帮助!

 类似资料:
  • http代理 <?php $http = HttpRequest::newSession(); $response = $http->proxy('127.0.0.1', 808) // 常见的http代理这样用 ->get('https://www.baidu.com/'); $content = $response->body(); // 网页源码 sock

  • 透过nginx/apache代理如何获取客户端真实ip ? 使用nginx/apache作为workerman代理,nginx/apache实际上充当了workerman的客户端,所以在workerman上获取的客户端ip为nginx/apache服务器的ip,并非实际的客户端ip。如何获取客户端真实ip可以参考下面的方法。 原理: nginx/apache将客户端真实ip通过http heade

  • 本文向大家介绍asp.net获取真实ip的方法,包括了asp.net获取真实ip的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了asp.net获取真实ip的方法。分享给大家供大家参考。具体如下: 希望本文所述对大家的asp.net程序设计有所帮助。

  • 本文向大家介绍使用python验证代理ip是否可用的实现方法,包括了使用python验证代理ip是否可用的实现方法的使用技巧和注意事项,需要的朋友参考一下 在使用爬虫爬取网络数据时,如果长时间对一个网站进行抓取时可能会遇到IP被封的情况,这种情况可以使用代理更换ip来突破服务器封IP的限制。 随手在百度上搜索免费代理IP,可以得到一系列的网站,这里我们通过对西刺网站的抓取来举例。 通过编写一个爬虫

  • 我的a域是在CloudFlare的免费工具后面管理的。我想添加一个名为“test”的子域,但我希望它指向在我的服务器端口8183上运行的第二个webserver。在Cloudflare DNS portal中,我有一个“test.example.com”的A记录,它指向我的WebServer的IP地址,该地址也被代理以隐藏我的WebServer的实际IP地址。所有流量都通过HTTPS路由,证书也由

  • 本文向大家介绍Nginx作为反向代理时传递客户端IP的设置方法,包括了Nginx作为反向代理时传递客户端IP的设置方法的使用技巧和注意事项,需要的朋友参考一下 nginx默认配置文件里面是没有进行日志转发配置的,这个需要我们自己手动来操作了,当然后端的real server不同时操作方法是不一样的,这里我们分别例举几种情况来说明一下。 nginx做前端,转发日志到后端nginx服务器: 因为架构的