SSH ChrootDirectory / sftponly not working [FIXED]
Monday, July 13th, 2015
I was trying to setup a jail for SSH on Ubuntu 14.04, but it didn’t seem to work. The user I was trying to jail using ChrootDirectory could login with SFTP, but could still see everything. Turns out there were a few issues that were causing this. The summary is:
- All directories to the ChrootDirectory path must be owned by root and must not have world or group writability permissions.
- Ubuntu 14.04 sysv init and upstart scripts don’t actually restart SSH, so changing the config file doesn’t take effect.
- The “Match User XXXX” or “Match Group XXXX” configuration section must be placed at the end of the sshd.config file.
- Also don’t forget to make your user a member of the sftponly group if you’re using “Match Group sftponly”.
All paths to the jail must have correct ownerships and permissions
All directories in the path to the jail must be owned by root. So if you configure the jail as:
ChrootDirectory /home/backup/jail
Than /home, /home/backup/ and /home/backup/jail must be owned by root:<usergroup>:
chown root:root /home chown root:backup /home/backup chown root:backup /home/backup/jail
Permissions on at least the home directory and the jail directory must not include world-writability or group-writability:
chmod 750 /home/backup chmod 750 /home/backup/jail
Ubuntu’s SSH init script sucks
Ubuntu’s SSH init script (both sysv init and upstart) suck. They don’t actually even restart SSH (notice the PID):
# netstat -pant | grep LISTEN | grep sshd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 13838/sshd # /etc/init.d/ssh restart [root@eek]~# netstat -pant | grep LISTEN | grep sshd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 13838/sshd
The PID never changes! SSH isn’t actually being restarted! The bug has been reported here: https://bugs.launchpad.net/ubuntu/+source/openssh/+bug/1390012.
To restart it you should use the “service” command, but even then it might not actually restart:
# service ssh restart ssh stop/waiting ssh start/running [root@eek]~# netstat -pant | grep LISTEN | grep sshd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 13838/sshd
This generally happens because you’ve got an error in your ssh configuration file. Naturally they don’t actually bother with telling you as much, and the log file also shows nothing.
The Match section in the SSHd configuration must be placed at the end of the file
When I finally figured out that SSH wasn’t being restarted, I tried starting it by hand. You might run into the following error:
# sshd -d sshd re-exec requires execution with an absolute path
You should execute it with the full path because SSHd will start new sshd processes for each connection, so it needs to know where it lives:
# /usr/sbin/sshd
Now I finally found out the real problem:
# /usr/sbin/sshd /etc/ssh/sshd_config line 94: Directive 'UsePAM' is not allowed within a Match block
My config looked like this:
Match User obnam ChrootDirectory /home/obnam/jail X11Forwarding no AllowTcpForwarding no ForceCommand internal-sftp UsePAM yes UseDNS no
Aparently SSH is too stupid to realize the Match section is indented and thinks it runs until the end of the file. The answer here is to move the section to the end of the file:
UsePAM yes UseDNS no Match User obnam ChrootDirectory /home/obnam/jail X11Forwarding no AllowTcpForwarding no ForceCommand internal-sftp
This will fix the problem and sftponly should work now.