Iptables 将流量从 A 转发到 B,其中 A 不是 B 的网关

Iptables 将流量从 A 转发到 B,其中 A 不是 B 的网关

我想将 ssh 流量从 A 端口 2222 转发到 B 端口 22。我在两个接口上都已将 ipv4 转发设置为 1。但仍然不起作用。哪里出了问题?

机器A:eth0 192.168.0.150 eth1217.27.166.110

机器B:eth0192.168.0.200

iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             192.168.0.200        tcp dpt:ssh state NEW,RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

iptables -L -t nat

root@lbpub01:~# iptables -L -tnat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             217.27.166.110       tcp dpt:2222 to:192.168.0.200:22

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  217.27.166.110       192.168.0.200        tcp dpt:ssh

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

更新

我得到了 irc@freenode 的好心人的帮助,所以这是我的工作iptables-save文件:

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp -d 217.27.166.110 --dport 2222 -j DNAT --to-destination 192.168.0.200:22
-A POSTROUTING -o eth+ -j MASQUERADE
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp --dport http -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -j DROP
COMMIT

答案1

我已经研究这个问题一段时间了。对我来说似乎有效的解决方案(至少在我使用虚拟机演示时)最终看起来与您在此处发布的内容有很大不同。

很快,以下是我的配置:

iptables -L

Chain INPUT (policy DROP)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

iptables -S

-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

(需要澄清的是,最后的 INPUT 规则是允许 ssh 访问机器 A。)

iptables -t nat -L

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT tcp -- anywhere anywhere tcp dpt:2222 to:192.168.0.200:22

Chain INPUT (policy ACCEPT) target prot opt source destination

Chain OUTPUT (policy ACCEPT) target prot opt source destination

Chain POSTROUTING (policy ACCEPT) target prot opt source destination
SNAT tcp -- anywhere anywhere tcp dpt:22 to:217.27.166.110

iptables -t nat -S

-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A PREROUTING -i eth0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 192.168.0.200:22
-A POSTROUTING -p tcp -m tcp --dport 22 -j SNAT --to-source 217.27.166.110

因此,有趣的是,我不需要 FORWARD 链中的任何东西,但看起来 PREROUTING 规则足以将来自客户端的第一个数据包转发到机器 B。

iptables -t nat -A PREROUTING -i <external_interface> -p <tcp/udp> --dport <port_to_accept_connections_through> -j DNAT --to <destination_address:destination_port>

那么,问题就是响应数据包在通过网关时丢失了。直到我使用 Wireshark 测试了机器 A 上的 eth1 并注意到发往机器 B 的数据包上的源地址仍然是客户端机器的源地址时,我才意识到这一点。然后我使用 POSTROUTING 表将源地址更改为 eth1 上机器 A 的 IP 地址,这样机器 B 就知道将响应发送到机器 A 而不是网关。

iptables -t nat -A POSTROUTING -p <tcp/udp> --dport <destination_port> -j SNAT --to <internal_IP_address_of_machine_a>

此时,我能够从与机器 A 的 eth0 接口位于同一网络上的客户端与机器 B 建立连接。虽然我不能 100% 确定防火墙如何处理从机器 B 发送到客户端机器的响应数据包,但我认为最可能的原因是 INPUT 链中的规则允许通过防火墙建立连接:

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

相关内容