如何配置iptables实现全流量转发并让目标主机获取客户端真实IP
如何配置iptables实现全流量转发并让目标主机获取客户端真实IP
嗨,我太懂你这个痛点了——之前用DNAT加MASQUERADE确实能实现转发,但MASQUERADE本质是源地址转换(SNAT),它会把所有客户端的源IP替换成Server A的IP,这就是为什么Server B的日志里全是Server A的地址。其实你要的是「透明转发且保留真实源IP」,完全可以做到,核心就是去掉SNAT/MASQUERADE,靠正确的路由配置来完成,下面是具体步骤:
1. 先开启Server A的IP转发功能
Linux默认是关闭IP转发的,得先打开:
- 临时生效(重启后失效):
echo 1 > /proc/sys/net/ipv4/ip_forward - 永久生效(重启后依然有效):
编辑/etc/sysctl.conf文件,找到net.ipv4.ip_forward这一行,把注释去掉并设置为1:
然后执行命令让配置生效:net.ipv4.ip_forward=1sysctl -p
2. 配置DNAT规则,把Server A的流量转发到Server B
针对TCP、UDP、ICMP分别配置DNAT规则(也可以用-p all覆盖所有协议,但分开配置更清晰):
假设Server A的公网IP是[Server_A_Public_IP],Server B的内网IP是[Server_B_Private_IP],执行以下命令:
# 转发TCP流量 iptables -t nat -A PREROUTING -d [Server_A_Public_IP] -p tcp -j DNAT --to-destination [Server_B_Private_IP] # 转发UDP流量 iptables -t nat -A PREROUTING -d [Server_A_Public_IP] -p udp -j DNAT --to-destination [Server_B_Private_IP] # 转发ICMP流量(比如ping) iptables -t nat -A PREROUTING -d [Server_A_Public_IP] -p icmp -j DNAT --to-destination [Server_B_Private_IP]
3. 关键:不要用MASQUERADE,而是配置Server B的路由
这一步是保留真实IP的核心:
- 把Server B的默认网关设置为Server A的内网IP(前提是Server A和Server B在同一个内网环境,或者Server A有一个能被Server B访问到的IP)。这样当Server B处理完请求后,会直接把回包发给Server A,而不是自己的原网关。
- 同时在Server A上添加转发允许规则,确保流量能正常通过:
# 允许发往Server B的流量 iptables -A FORWARD -d [Server_B_Private_IP] -j ACCEPT # 允许Server B返回的流量 iptables -A FORWARD -s [Server_B_Private_IP] -j ACCEPT
原理说明
之前的MASQUERADE会把客户端的源IP替换成Server A的,所以Server B只能看到Server A的地址;现在去掉SNAT规则后,Server A只做目标地址转换(DNAT)——把客户端发往Server A的数据包目标IP改成Server B,但源IP依然保留客户端的真实地址。只要Server B的回包能正确回到Server A,Server A就会直接把回包转发给客户端,整个过程中源IP没有被修改,Server B的日志自然就能看到真实的客户端IP了。
注意事项
- 如果Server A和Server B不在同一个内网,需要确保Server A有一条能到达Server B的路由,同时Server B的默认网关必须指向Server A的那个可达IP,否则回包无法正确返回。
- 如果你之前配置过MASQUERADE规则,记得把它删掉:
iptables -t nat -D POSTROUTING -s [Server_B_Private_IP] -j MASQUERADE(或者根据你之前的规则调整删除命令)。 - 部分Linux发行版的iptables默认FORWARD链是拒绝的,所以一定要添加上面的FORWARD允许规则,否则流量会被拦截。
备注:内容来源于stack exchange,提问作者Robert L.
相关产品推荐
相关产品推荐

