Conditional ssh Configuration: iptables & sshd
By Chris Pepper on Monday, November 2 2009, 16:00 - ssh - Permalink
I have an Internet server which accepts ssh connections from the Internet. I want to lock down Internet connections more tightly, while leaving connections from the local network a bit more open.
On Mac OS X, the way to do this is through the Match directive in /etc/sshd_config. Unfortunately, RHEL/CentOS 5 & SLES 10 include openssh v4.x, which lacks the Match directive.
Things are complicated by multiple overlapping directives to control password authentication in OpenSSH, which behave differently on different platforms. But the OpenSSH developers have suggested global settings in /etc/sshd_config like:
Protocol 2
ChallengeResponseAuthentication no
PasswordAuthentication no
KbdInteractiveAuthentication no
And overrides along the lines of:
Match 10.0.0.0/8
PasswordAuthentication yes
KbdInteractiveAuthentication yes
On CentOS Match isn't available, so we run two different sshd daemons. Here's the init script that runs them both (I couldn't just copy and tweak one, because they'd interfere with each other):
[root@c54 ~]# diff -u /etc/init.d/sshd.c54 /etc/init.d/sshd
--- /etc/init.d/sshd.c54 2009-10-26 19:47:06.000000000 -0400
+++ /etc/init.d/sshd 2009-11-02 13:02:24.000000000 -0500
@@ -96,6 +96,12 @@
failure $"Configuration file or keys are invalid"
echo
fi
+ $SSHD -t -f /etc/ssh/sshd_config.222
+ RETVAL=$?
+ if [ ! "$RETVAL" = 0 ]; then
+ failure $"External configuration file or keys are invalid"
+ echo
+ fi
}
start()
@@ -108,7 +114,7 @@
cp -af /etc/localtime /var/empty/sshd/etc
echo -n $"Starting $prog: "
- $SSHD $OPTIONS && success || failure
+ $SSHD $OPTIONS && PID_FILE=$PID_FILE_EXT $SSHD -f /etc/ssh/sshd_config.222 $OPTIONS && success || failure
RETVAL=$?
[ "$RETVAL" = 0 ] && touch /var/lock/subsys/sshd
echo
@@ -117,11 +123,7 @@
stop()
{
echo -n $"Stopping $prog: "
- if [ -n "`pidfileofproc $SSHD`" ] ; then
- killproc $SSHD
- else
- failure $"Stopping $prog"
- fi
+ killall $SSHD
RETVAL=$?
# if we are in halt or reboot runlevel kill all running sessions
# so the TCP connections are closed cleanly
Their configurations are slightly different:
[root@c54 ~]# diff -u /etc/ssh/sshd_config /etc/ssh/sshd_config.222
--- /etc/ssh/sshd_config 2009-11-02 16:59:40.000000000 -0500
+++ /etc/ssh/sshd_config.222 2009-11-02 16:59:46.000000000 -0500
@@ -57,7 +57,7 @@
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
-#PasswordAuthentication yes
+PasswordAuthentication yes
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
@@ -119,5 +119,5 @@
Subsystem sftp /usr/libexec/openssh/sftp-server
-# sshd for external (Internet) connections: no passwords allowed
-PasswordAuthentication no
+# sshd for internal (campus) connections: passwords allowed
+Port 222
The intelligent switching occurs in /etc/sysconfig/iptables, which redirects internal connections to the alternat port (and thus daemon). Unfortunately, due to the way iptables works, 'trusted' connections must be both REDIRECTed and ACCEPTed:
*nat
:PREROUTING ACCEPT
:POSTROUTING ACCEPT
:OUTPUT ACCEPT
-A PREROUTING -p tcp --dport 22 -s 10.0.0.0/24 -j REDIRECT --to-port 222
# Connections from 10.0.0. are more trusted, so send them to the private sshd on port 222.
# Each subnet must also be ACCEPTed below.
COMMIT
*filter
:INPUT DROP
:FORWARD DROP
:OUTPUT ACCEPT
-A INPUT -j ACCEPT -i lo
-A INPUT -j DROP -s 127.0.0.0/8
-A INPUT -j DROP -d 127.0.0.0/8
# Allow loopback connections, but drop forged pseudo-local packets
-A INPUT -j ACCEPT -m state --state RELATED,ESTABLISHED
# Continue established connections
-A INPUT -j ACCEPT -p tcp --dport 22
# sshd on port 22, for Internet connections (no passwords)
-A INPUT -j ACCEPT -p tcp --dport 222 -s 10.0.0.0/24
# sshd on port 222, for trusted connections
# Each subnet must also be REDIRECTed above.
COMMIT