iptables转发从A到B的stream量,其中A不是B的网关

我想转发从A端口2222的Sshstream量到B端口22.我在两个接口上都有ipv4转发设置为1。 不过,这是行不通的。 哪里不对?

机器A:eth0 192.168.0.150 eth1 217.27.166.110

机器B:eth0 192.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 

现在我一直在处理这个相同的问题。 这个似乎对我有效的解决scheme(至less在我使用虚拟机进行演示的时候)看起来与你在这里发布的内容有很大的不同。

真的很快,这里是我的configuration:

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

 连锁PREROUTING(政策接受)
目标人select源目的地 
DNAT tcp - 在任何地方tcp dpt:2222到:192.168.0.200:22

连锁input(政策接受)
目标人select源目的地

链式输出(策略ACCEPT)
目标人select源目的地

连锁POSTROUTING(政策接受)
目标人select源目的地
SNAT tcp – 在任何地方tcp dpt:22到: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规则已经足够让客户端的第一个数据包转发到Machine 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的机器上的eth1,并注意到机器B的数据包的源地址仍然是客户机的源地址。 然后,我使用POSTROUTING表将源地址更改为机器A在eth1上的IP地址,以便机器B知道将响应发送给机器A而不是网关。

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

此时,我可以build立从与机器A的eth0接口相同的networking上的客户机到机器B的连接。虽然我不能100%确定防火墙如何知道如何处理从机器发送的响应包B到客户端机器,我认为最可能的原因是INPUT链中的规则允许通过防火墙build立连接:

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