iptables: forwarding ssh ports

I have a server with two NICs: eth4 - listens on the outside network. eth1 - is on the same network as machine Y.

I want to be able to ssh into machine Y by doing: ssh server -p 1234 from the outside network.

I've come up with the following rules:

iptables -A PREROUTING -i eth4 -t nat -p tcp --dport 1234 -m state --state NEW,ESTABLISHED,RELATED -j DNAT --to-destination $MACHINE_Y_IP:22

and

iptables -A FORWARD -i eth4 -o eth1 -p tcp --dport 22 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

When I try to ssh, the connection is not refused right away, but it feels like iptables are not forwarding packets back. Any clue as to what I might doing wrong? OS is SLES, if that matters for the syntax.

Edit: sysctl net.ipv4.ip_forward reports net.ipv4.ip_forward = 1

iptables-save generate:

`# Generated by iptables-save v1.4.2-rc1 on Fri Nov 12 10:28:26 2010
*mangle
:PREROUTING ACCEPT [48787:5748712]
:INPUT ACCEPT [48725:5742333]
:FORWARD ACCEPT [29:1740]
:OUTPUT ACCEPT [25938:4009532]
:POSTROUTING ACCEPT [25967:4011272]
COMMIT
# Completed on Fri Nov 12 10:28:26 2010
# Generated by iptables-save v1.4.2-rc1 on Fri Nov 12 10:28:26 2010
*nat
:PREROUTING ACCEPT [68959:12817029]
:POSTROUTING ACCEPT [19579:1207747]
:OUTPUT ACCEPT [19566:1206967]
-A PREROUTING -i eth4 -p tcp -m tcp --dport 1234 -m state --state NEW,RELATED,ESTABLISHED -j DNAT --to-destination x.x.x.x:22 
COMMIT
# Completed on Fri Nov 12 10:28:26 2010
# Generated by iptables-save v1.4.2-rc1 on Fri Nov 12 10:28:26 2010
*filter
:INPUT ACCEPT [60982622:59727981305]
:FORWARD ACCEPT [10:600]
:OUTPUT ACCEPT [32438834:64059260511]
-A FORWARD -i eth4 -o eth1 -p tcp -m tcp --dport 22 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT 
COMMIT
# Completed on Fri Nov 12 10:28:26 2010`

Solution 1:

The rules should look something like this.

iptables -t nat -I PREROUTING -p tcp -i eth4 --dport 1234 -j DNAT --to server:22
iptables -A FORWARD -i eth4 -o eth1 -p tcp --dport 22 -j ACCEPT

Don't bother mixing in the state module. It is most likely what causes your problems. The NAT module will keep the states you need.

Oh, make sure you have ip_forwarding turned on also ;)

Solution 2:

Below are my working rules - but I use state module:

*nat
:PREROUTING ACCEPT [101:9081]
:POSTROUTING ACCEPT [89:5340]
:OUTPUT ACCEPT [209:13346]

# DNAT to local ip
#-A PREROUTING -p tcp --dport $FW_EXTERNAL_PORT -d $FW_EXTERNAL_IP -j DNAT --to-destination $INTERNAL_MACHINE_IP:$INTERNAL_MACHINE_PORT

# ssh to server 192.168.0.3
-A PREROUTING -p tcp --dport 1234 -d 10.10.10.10 -j DNAT --to-destination 192.168.0.3:22
...
COMMIT

*filter
:INPUT ACCEPT [5583:2021142]
:FORWARD DROP [24:2378]
:OUTPUT ACCEPT [6291:2229990]

#rules for DNAT
#-A FORWARD -p tcp --dport $INTERNAL_MACHINE_PORT -d $INTERNAL_MACHINE_IP -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# SSH to 192.168.0.3
-A FORWARD -p tcp --sport 22 -s 192.168.0.3 -j ACCEPT
-A FORWARD -p tcp --dport 22 -d 192.168.0.3 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
... 
COMMIT