I want to forward ssh traffic from A port 2222 to B port 22. I do have ipv4 forwarding set to 1 on both interfaces. Still, this does not work. What is wrong?
Machine A:
eth0 192.168.0.150
eth1 217.27.166.110
Machine 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
Update
I got help from the nice guys at irc@freenode, so here is my working iptables-save
file:
*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
I've been working on this same problem for a while now. The solution that seems to work for me (at least when I demoed it using VMs) wound up looking significantly different than what you have posted here.
Real quick, here are my configurations:
iptables -L
:iptables -S
:(Just to clarify, that last INPUT rule is to allow ssh access into Machine A.)
iptables -t nat -L
:iptables -t nat -S
:So, interestingly, I didn't need anything in the FORWARD chain, but it appears that the PREROUTING rule was enough to get the first packet from the client forwarded to Machine B.
The problem, then, was the response packet getting lost by going through the Gateway. I didn't realize this until I Wiresharked the eth1 on Machine A and noticed that the source address on the packet bound for Machine B was still that of the client machine. I then used the POSTROUTING table to change the source address to Machine A's IP address on eth1 so that Machine B would know to send the response to Machine A and not the Gateway.
At this point, I was able to establish the connection from a client sitting on the same network as Machine A's eth0 interface to Machine B. While I'm not 100% sure how the firewall knew what to do with the response packets sent from Machine B to the client machine, I think the most likely reason is the rule in the INPUT chain that allows established connections through the firewall: