Getting SSH to listen to different ports on different interfaces

Why do you want to do this?

Maybe you've got a local network, maybe with many users, that you trust, and an external connection which is hammering your SSH port (#22) constantly with dictionary/DOS attacks. So you want to turn off that port externally, but keep using that default port number as the default when local users want to connect internally. Or at least I do.


Presumably you've already got SSH up and running, and you have IPtables.

I assume that you want port 22 as the default port for internal users, and 2222 isn't suffering a dictionary/DOS attack.

Trivial but flawed method - tweak SSH config

# /etc/ssh/sshd_config
# This listens to port 22 internally, and port 2222 externally (and internally)
Port 2222
ListenAddress [myhostname_or_myinternalIPaddress]:22

The problem with this is that it closes 22 to the outside world, but leaves both 22 and 2222 open for the internal network.

IPtables rewriting method

Here, we let sshd remain blissfully unaware of the existence of the external network, and then get IPtables to reroute packets from the chosen external port to an internal one.

# /etc/ssh/sshd_config
# This listens to port 22 internally and not externally. iptables will permit external rerouting
Port 22
ListenAddress [myhostname_or_myinternalIPaddress]
# /etc/rc.local
/sbin/iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2222 -j DNAT --to [myhostname_or_myinternalIPaddress]:22
One 'problem' with this method is that it bypasses the normal /etc/hosts.allow protections that you might have. I personally like the fact that the external port can be changed on the fly without needing to restart sshd - simply remove the IPtables rule and add a new one with a different port. (This will screw up any SSH sessions currently active, of course.)
/sbin/iptables -t nat -L --line-numbers
/sbin/iptables -t nat -D PREROUTING [rule_number_to_delete]


All balls-ups are mine, and all the useful info came from The Debian IRC channel, in particular from dudes (or dudettes) calling themselves 'felixs' and 'petemc'