/bin/false, /sbin/nologin and SSH

It is common knowledge that if on a linux system, a local account is set to /bin/false or /sbin/nologin, that user cannot use SSH, right?




As one of my clients learned the hard way.  Alerted to the fact his server was blacklisted on a (large!) number of RBLs, we started investigating how and why spam was getting sent from his server.  What we found was that a local user account (listed in /etc/passwd) had been compromised, due to an easy to guess password.

On all the recent Linux distributions I attempted this on, it is possible to connect to the SSH daemon and initiate not a shell, but a TCP port forwarding session. Using /sbin/nologin as a shell only causes the SSH daemon to spawn a shell that closes immediately. So if you tell SSH not to spawn a shell, and use TCP port forwardings instead, you can then exploit the remote host.

Here is how it works.


if I create a user with [/bin/false|/sbin/nologin] as a shell, and give him a password. I can then SSH to the machine and forward a local port.

Like this:

[user@panel~]ssh -N testacct@linuxserver.cconn.info -L 2525:

this forwards my local port of 2525 to the remote port 25. Allowing me to spam via the remote server, via my local TCP 2525 socket I just created:

[user@panel ~] telnet localhost 2525
 Trying ::1...
 Connected to localhost.
 Escape character is '^]'.
 220 linuxserver.cconn.info ESMTP Sendmail 8.14.4/8.14.4; Sun, 6 May 2012 18:06:57 -0400

From “panel” I can connect to “linuxserver” over my ssh tunnel, and spam…my email appears to come from when you look at the headers, causing a certain level of difficulty in tracing the spam back to that account after the fact;

Received: from foo (localhost [])
 by linuxserver.cconn.info (8.14.4/8.14.4) with SMTP id q36MAbio019457
 for spambait@sucker.com; Sun, 6 May 2012 18:10:48 -0400

Why does this work?  Because sshd by default is configured, on my distros anyway, to use PAM for authentication, and has TCP port forwardings enabled by default.  If a shell listed in /etc/shells is configured for the account (/sbin/nologin is listed in /etc/shells), the password is valid and TCP port forwarding is enabled, this allows an account to establish said port forwardings and utilize services on the remote host.  Spam is an example, but there could be more.

How can this be fixed?


Well, there are a number of ways.  The simplest and most drastic, if possible in your scenario, is to simply disable TCP port forwarding in your sshd configuration file (/etc/ssh/sshd_config on many systems):

AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no

However, note that this will not deny the actual ssh connection to be established; it will simply deny the ability to exploit the forwarding (see below);

ssh -N testacct@linuxserver.cconn.info -L 2525:
testacct@tohs.cconn.info's password:
channel 2: open failed: administratively prohibited: open failed
channel 2: open failed: administratively prohibited: open failed

The SSH session is allowed, however when I try to connect to my local 2525 TCP port, I note a “prohibited” error.  Therefore there is still room for exploitation possibly via DoS.  As far as I know however it is not possible to spam using this method 😉

Another way appears to be by not have the user shell listed in /etc/shells (/bin/false is not in every distro I checked).  Adding users with an invalid shell will invalidate this exact issue since sshd, via PAM, checks if the shell exists.  However, this will break any other system daemon that queries PAM for this very information, for example vsftpd/proftpd.  Therefore this “solution” is just a broken way of limiting ssh, however could have other, nasty consequences.

The other, smarter ways, would be to use AllowUser/AllowGroup directives in the sshd configuration, to specify exactly which users can and cannot connect.  And in all cases, it would be ideal to deny the ability to connect via SSH in iptables/ip6tables since OpenSSH has in the past (and likely will again) had security vulnerabilities that could be exploited to gain root access an pnwn the server :-\  As well, having your ssh socket open to the Internet attracts people to bruteforce scan your server, which is ugly in itself and causes a massive amout of syslog spam.



Tracepath6 – MTU and IPv6

IPv6, fragmentation and MTU

Unlike IPv4 where routers can (and do) fragment packets when a larger MTU packet must be forwarded over a path that does not support it.  Assuming the packet doesn’t have the df-bit set, the IPv4 router will fragment a packet and forward two or more packets downstream for reassembly by the end host.

In the IPv6 world, routers or intermediate nodes do not fragment packets.  A packet received by a router that is too large to forward will cause the router to drop the packet.  This practice was likely designed into IPv6 for certain security vulnerabilities, where sending fragments could hide protocol level header information and cause reassembly surprises, DoS  a host or router when trying to process these fragments or reassemble them, and a slew of various issues that made fragmentation become a IPv4 four-letter word.

In IPv6, although the packet is dropped, the router or node that drops the packet sends a ICMPv6 message “packet too big” back to the source host (Minimum IPv6 MTU has been defined as 1280).  The source host then must perform the fragmentation and re-transmit the ensuing flow at a smaller MTU.  The end node performs packet reassembly.    This behaviour clearly indicates that arbitrarily dropping ICMP, which was a common practice by clueless IPv4 system administrators of yesteryear, is now a deprecated practice 😉

Ensuring ICMPv6 messaging delivery is particularly important in today’s reality, as a significant proportion of IPv6-capable networks are utilizing a tunneling mechanism of some sort, be it Hurricane Electric’s excellent tunnel broker service, 6RD, or static IPv6-over-IPv4 tunnels; a 1500 MTU cannot be assumed.  The use of path mtu discovery (PMTUD), is critical.


The use of tracepath6, becomes particularily interesting – my distro (RedHat et al) seems to include it in the iputils package:

Here is an example of non-tunnelled, native dual-stack tracepath from a node to www.ripe.net:


tracepath6 www.ripe.net -n
 1?: [LOCALHOST]                      pmtu 1500
 1:  2001:db1::3                       1.785ms
 2:  2001:db1::2                     asymm  1   1.944ms
 3:  2001:db1:2:16::9                 asymm  2   2.937ms
 4:  ::ffff:               asymm 11  16.193ms
 5:  ::ffff:              asymm 11  16. 60ms
 6:  ::ffff:               asymm 11  16. 69ms
 7:  ::ffff:             asymm 11  16.279ms
 8:  2001:550:3::8a                   asymm  9  15.860ms
 9:  2001:5a0:600:500::a              asymm  8  16.746ms
10:  2001:5a0:f00:400::1               19.212ms
11:  2001:5a0:2000:400::19            asymm  9  90.538ms
12:  2001:5a0:2000:500::1             asymm  8  86.440ms
13:  2001:5a0:2000:500::a             asymm  9 103.741ms
14:  2001:5a0:200:100::5              asymm 11 103.324ms
15:  2001:5a0:200:200::16             asymm  9  97.851ms
16:  no reply
17:  2001:67c:2e8:27::1               asymm 13  98.410ms !A
     Resume: pmtu 1500


Apologies for the ::ffff:154.0.0.xx IPv4 mapped addresses, AS174 (Cogent…) seems to return them in traceroutes…Yuck!  And the asymm warning, which normally can indicate an asymmetrical path, is apparently caused by my local network’s use of HSRP.  It can also appear in certain tracepaths when an intermediate router is a Juniper, which I am told reduces the TTL by one before transmitting ICMP, and tracepath(6) uses TTL to determine path symmetry.  I don’t have a Juniper to test this <:-)

Anyway, here is an example of a tracepath through a IPv6-over-IPv4 tunnel:

tracepath6 -n www.ripe.net
 1?: [LOCALHOST]                      pmtu 1500
 1:  2001:db1:ffff:fffd::1             5.301ms
 1:  2001:db1:ffff:fffd::1             5.135ms
 2:  2001:db1:ffff:fffd::1             5.144ms pmtu 1480
 2:  2001:db1:ffff:ffff::1             7.608ms
 2:  2001:db1:ffff:ffff::1             8.031ms
 3:  2001:db1:2:16::9                   8.369ms
 4:  ::ffff:                20.434ms asymm 13
 5:  ::ffff:              20.127ms asymm 13
 6:  ::ffff:                23.160ms asymm 13
 7:  ::ffff:               23.119ms asymm 13
 8:  2001:550:3::8a                    29.943ms asymm 11
 9:  2001:5a0:600:500::a               25.208ms asymm 10
10:  2001:5a0:f00:400::1               25.141ms asymm 12
11:  2001:5a0:2000:400::19             95.158ms
12:  2001:5a0:2000:500::1              95.819ms asymm 10
13:  2001:5a0:2000:500::a             109.372ms asymm 11
14:  2001:5a0:200:100::5              111.653ms asymm 12
15:  2001:5a0:200:200::16             107.308ms asymm 11
16:  2001:7f8:1::a500:3333:2          181.523ms asymm 15
17:  2001:67c:2e8:27::1               105.202ms !A
     Resume: pmtu 1480


tracepath6 is a useful tool, especially in today’s Internet where IPv6 connectivity is not necessarily the usual 1500-byte MTU standard of the past and many hosts use tunneling transition mechanisms to access IPv6 content.  It will be useful to identify broken ICMPv6 paths, which for v6 traffic is essential for reliable communication.   Until dual-stack or even IPv6-only nodes are the norm, PMTUD and ICMPv6 will be critically important.  Here is hoping sysadmins will be wise enough to follow best practices and allow ICMPv6 messages, especially “packet too big” and “destination unreachable” messages.