我需要一位专家来配置 NAT 重定向 (iptables) 以维护客户端的源地址。目前我的服务器可以正常工作,但所有客户端都显示为我的 vLAN 的私有 IP。
我的服务器重定向操作示例:
VPS 1 (Public IP) redirect traffic to VPS 5 (Private IP)
VPS 2 (Public IP) redirect traffic to VPS 5 (Private IP)
VPS 3 (Public IP) redirect traffic to VPS 5 (Private IP)
VPS 4 (Public IP) redirect traffic to VPS 5 (Private IP)
但是重定向流量时会将客户端的 IP 更改为客户端访问的公共服务器的私有 IP。
TCPDUMP:
IP 10.0.1.130.61570> 10.0.1.138.85: UDP, length 35
IP 10.0.1.132.63112> 10.0.1.138.85: UDP, length 35
IP 10.0.1.133.63435> 10.0.1.138.85: UDP, length 35
IP 10.0.1.136.63432> 10.0.1.138.85: UDP, length 35
问题是,当重定向完成时,所有客户端都被分配了私有 IP,而我需要维护客户端的真实 IP。
如果我删除规则“iptables -t nat -A POSTROUTING -j MASQUERADE”
然后客户端的 IP 将被保留,但服务器会使用私有 IP 向客户端的 IP 响应数据包。
TCPDUMP:
IP 10.0.1.138.85> client1.isp.net.61570: UDP, length 45
IP 10.0.1.138.85> client2.isp.net.63112: UDP, length 45
IP 10.0.1.138.85> client3.isp.net.63435: UDP, length 45
IP 10.0.1.138.85> client4.isp.net.63432: UDP, length 45
我想保留客户端的真实 IP,但(VPS 5)不会将数据包路由回互联网。
答案1
我知道两种方法可以解决你的问题:
简单的方法
DNAT
您可以在没有规则的 VPS 主机上使用规则中的附加端口范围SNAT
。并根据这些端口号VPS-5
通过正确的主机路由回复。
简短示例:
规划其他主机将从客户端转发数据包到的附加端口号
VPS-5
。我们猜想VPS-1
将数据包转发到VPS-5 tcp/10001
、VPS2
- 等等VPS-5 tcp/10002
。在每个
VPS
主机上,你只需要一条规则即可将流量转发到 的特殊端口VPS-5
。因此,VPS-1
规则将如下所示:
# vps-1 host
iptables -t nat -A PREROUTING \
--dst <vps-1-pub-ip> -p udp --dport <srv-port> \
-j DNAT --to-destination <vps-5-ip>:10001
在 上,
VPS-5
您需要更复杂的配置。诀窍在于,接收VPS5
转发请求的端口号也指向应通过其路由回复的 VPS 主机。在 上,
VPS-5
您需要单独的路由表和每个其他VPS
主机的路由规则。VPS-1
和 的示例VPS-2
:
# vps-5 host
ip route add <connected-subnet> dev <iface> table 1
ip route add 0/0 via <VPS-1-INT-IP> dev <iface> table 1
ip rule add fwmark 1 lookup 1 pref 10001
ip route add <connected-subnet> dev <iface> table 2
ip route add 0/0 via <VPS-2-INT-IP> dev <iface> table 2
ip rule add fwmark 2 lookup 2 pref 10002
- 标记来自 VPS 主机的传入连接并将其保存到 conntrack 条目中:
# vps-5 host
iptables -t mangle -A PREROUTING \
-m conntrack --ctstate NEW \
-p udp --dport 10001 \
-j CONNMARK --set-mark 0x1
- 将请求重定向到服务端口:
# vps-5 host
iptables -t nat -A PREROUTING \
--dst <vps-5-ip> -p udp --dport 10001:10004 \
-j REDIRECT --to-ports 85
- 在回复数据包上设置防火墙标记,以将它们路由回正确的 VPS 主机:
# vps-5 host
iptables -t mangle -A OUTPUT \
-m conntrack --ctstate DNAT --ctdir REPLY \
-j CONNMARK --restore-mark
此方法仅适用于主机直接连接的情况。否则,您应该使用下一种方法。
隧道模式
在某些情况下,服务器不是直接相互连接,而是通过一些路由器连接。在这些情况下,上述方法不起作用,因为每个中间路由器都会独立做出路由决定。
据我所知,保存客户端的源地址并将数据包从前端主机(VPS-1
- VPS-4
)重定向到目标主机(VPS-5
)的唯一方法是使用隧道。
简化的解决方案: * 规划隧道内使用的附加 IP 地址。 * 在每个前端主机 ( VPS-1
- VPS-4
) 上创建到 的隧道VPS-5
。您可以根据需要创建任何类型的隧道。最简单的方法是使用静态 GRE 隧道,但它有一些限制,例如避免 NAT。 * 在每个前端主机上,您只需要一条规则即可将流量转发到VPS-5
。示例VPS-
:
# vps-1 host
iptables -t nat -A PREROUTING \
--dst <vps-1-pub-ip> -p udp --dport <srv-port> \
-j DNAT --to-destination <vps-5-tun-ip>
- 在上
VPS-5
你还应该配置额外的路由表和路由规则来通过正确的前端主机进行回复:
# vps-5 host
ip route add 0/0 dev <vps-1-tun-iface> table 1
ip rule add fwmark 1 lookup 1 pref 10001
- 根据输入接口标记传入的连接并将其保存到 conntrack 条目中:
iptables -t mangle -A PREROUTING \
-m conntrack --ctstate NEW \
-i <vps-1-tun-iface> \
-j CONNMARK --set-mark 0x1
- 如果您的应用程序没有监听隧道 IP 地址,您应该将来自前端主机的传入数据包重定向到监听的地址:
iptables -t nat -A PREROUTING \
-i <vps-1-tun-iface> \
-p udp --dport <srv-port> \
-j DNAT --to-destination <srv-listen-ip>
- 在回复数据包上设置防火墙标记:
iptables -t mangle -A OUTPUT \
-j CONNMARK --restore-mark
- 不要忘记在过滤表中允许这些数据包:
iptables -t filter -A INPUT \
-m conntrack --ctstate ESTABLISHED,RELATED
-j ACCEPT
...
iptables -t filter -A INPUT \
-p udp --dport <srv-port>
-j ACCEPT