Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

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`
share|improve this question
    
What does sysctl net.ipv4.ip_forward say? What is the complete output from iptables-save? –  Steven Monday Nov 12 '10 at 15:24
    
Steven, sorry, not enough space, will edit the answer in a second to add more details. –  Nick Nov 12 '10 at 15:28

3 Answers 3

up vote 3 down vote accepted

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 ;)

share|improve this answer
    
Doesn't seem to do the trick for me, I wonder if I am missing something in SLES setup, firewall is off, but I did do echo 1 > /proc/sys/net/ipv4/ip_forward. Also, should not --dport in FORWARD be 22? –  Nick Nov 12 '10 at 15:39
    
You are correct, typo on my part. The forward rule should go to port 22. –  pehrs Nov 12 '10 at 15:45
1  
+1. One little quibble though: The ACCEPT rule on the FORWARD chain is redundant, since the policy on the FORWARD chain is already to ACCEPT. Oh, and the --to really should be --to-destination. –  Steven Monday Nov 12 '10 at 16:10
    
I see what my problem might be. When I do ssh -v MACHINE_Y -p 1234, wireshark listening on eth1 one shows that there are packets coming from the eth4 ip address, to the ip address of the box I am trying to ssh into (it's on eth1 network). So it feels like I need a SNAT rule that will change the eth4 ip address to eth1 ip address, no? –  Nick Nov 12 '10 at 16:21
    
added this: iptables -t nat -I POSTROUTING -p tcp -o eth1 --dport 22 -j SNAT --to-source x.x.x.x, where x.x.x.x is eth1's ip address and it seems to work now. Praise to you guys for the direction and WireShark, I was slowly going insane. :) –  Nick Nov 12 '10 at 16:25

I hope there is more to your iptables configuration than what you're showing us. In the *filter table, INPUT is set to accept by default. For people that are new to iptables, they may take that and run with it and leave their system exposed. You may want to set the default chains in filter to DROP then only open the ports you want to get to your box, otherwise you would have a "chain-link fence" instead of a firewall. With your POSTROUTING rule, it would work but you would have to create a similar rule for each port opened. Something like this [iptables -A POSTROUTING -t nat -o eth4 -j SNAT --to pu.bl.ic.ip] would work for all ports going to the external interface. In the FORWARD chain it is a good idea to use "belt and suspenders" to protect your box. You can add -s yo.ur.ext.ip so if anyone else tries to access on that port, they will be dropped. I hope this helps someone.

share|improve this answer

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
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.