SFTP chroot
OpenSSH 4.9+ includes a built-in chroot for SFTP, but requires a few tweaks to the normal install.
Installation
Install and configure OpenSSH. Once running, make sure sftp-server
has been set correctly:
/etc/ssh/sshd_config
Subsystem sftp /usr/lib/ssh/sftp-server
Access files with sftp or SSHFS. Many standard FTP clients should work as well.
Configuration
Setup the filesystem
- Readers may select a file access scheme on their own. For example, optionally create a subdirectory for an incoming (writable) space and/or a read-only space. This need not be done directly under
/srv/ssh/jail
- it can be accomplished on the live partition which will be mounted via a bind mount as well. - It is also possible chrooting into
/home
directory thus skipping the usage of bind, however the desired user home directory should be owned by root:
# chown root:root /home/<username> # chmod 0755 /home/<username>
Bind mount the live filesystem to be shared to this directory. In this example, /mnt/data/share
is to be used, owned by user root
and has octal permissions of 755
:
# chown root:root /mnt/data/share # chmod 755 /mnt/data/share # mkdir -p /srv/ssh/jail # mount -o bind /mnt/data/share /srv/ssh/jail
Add entries to fstab to make the bind mount survive on a reboot:
/mnt/data/share /srv/ssh/jail none bind 0 0
Create an unprivileged user
Match User
instead of Match Group
.Create the sftponly
user group:
# groupadd sftponly
Create a user that uses sftponly as main group and has shell login access denied:
# useradd -g sftponly -s /usr/bin/nologin -d /srv/ssh/jail username
Set a (complex) password to prevent account is locked
error (may appear even with key authentication):
# passwd username
Configure OpenSSH
Match User
instead of Match Group
as been given in the previous step./etc/ssh/sshd_config
Subsystem sftp /usr/lib/ssh/sftp-server Match Group sftponly ChrootDirectory %h ForceCommand internal-sftp AllowTcpForwarding no X11Forwarding no PasswordAuthentication no
Restart sshd.service
to confirm the changes.
Fixing path for authorized_keys
(pre)auth
error(s).With the standard path of AuthorizedKeysFile, the SSH keys authentication will fail for chrooted-users. To fix this, append a root-owned directory on AuthorizedKeysFile to /etc/openssh/sshd_config
e.g. /etc/ssh/authorized_keys
, as example:
/etc/ssh/sshd_config
AuthorizedKeysFile /etc/ssh/authorized_keys/%u .ssh/authorized_keys PermitRootLogin no PasswordAuthentication no PermitEmptyPasswords no Subsystem sftp /usr/lib/ssh/sftp-server
Create authorized_keys folder, generate a SSH-key on the client, copy the contents of the key to /etc/ssh/authorized_keys
(or any other preferred method) of the server and set correct permissions:
# mkdir /etc/ssh/authorized_keys # chown root:root /etc/ssh/authorized_keys # chmod 755 /etc/ssh/authorized_keys # echo 'ssh-rsa <key> <username@host>' >> /etc/ssh/authorized_keys/username # chmod 644 /etc/ssh/authorized_keys/username
Restart sshd.service
.
Tips and tricks
Write permissions
The bind path needs to be fully owned by root
, however files and/or subdirectories do not have to be.
In the following example the user www-demo uses /srv/ssh/www/demo
as the jail-directory:
# mkdir /srv/ssh/www/demo/public_html # chown www-demo:sftponly /srv/ssh/www/demo/public_html # chmod 755 /srv/ssh/www/demo/public_html
The user should now be able to create files/subdirectories inside this directory. See File permissions and attributes for more information.
Logging
The user will not be able to access /dev/log
. This can be seen by running strace
on the process once the user connects and attempts to download a file.
Create sub directory
Create the sub-directory dev
in the ChrootDirectory
, for example:
# mkdir /usr/local/chroot/user/dev # chmod 755 /usr/local/chroot/user/dev
Now you should create socket at /usr/local/chroot/user/dev/log
which will be used by openssh. You may directly bind this socket to /dev/log
(or /run/systemd/journal/dev-log
in case you are using journald) or create using syslog-ng
/rsyslog
.
Bind to journald
# touch /usr/local/chroot/user/dev/log # mount --bind /run/systemd/journal/dev-log /usr/local/chroot/user/dev/log
Syslog-ng configuration
Add to /etc/syslog-ng/syslog-ng.conf
a new source for the log and add the configuration, for example change the section:
source src { unix-dgram("/dev/log"); internal(); file("/proc/kmsg"); };
to:
source src { unix-dgram("/dev/log"); internal(); file("/proc/kmsg"); unix-dgram("/usr/local/chroot/theuser/dev/log"); };
and append:
#sftp configuration destination sftp { file("/var/log/sftp.log"); }; filter f_sftp { program("internal-sftp"); }; log { source(src); filter(f_sftp); destination(sftp); };
(Optional) If you would like to similarly log SSH messages to its own file:
#sshd configuration destination ssh { file("/var/log/ssh.log"); }; filter f_ssh { program("sshd"); }; log { source(src); filter(f_ssh); destination(ssh); };
(From Syslog-ng#Move log to another file)
OpenSSH configuration
Edit /etc/ssh/sshd_config
to replace all instances of internal-sftp
with internal-sftp -f AUTH -l VERBOSE
Restart service
Restart service syslog-ng
and sshd
.
/usr/local/chroot/theuser/dev/log
should now exist.
Alternatives to SFTP
Secure copy protocol (SCP)
Installing openssh provides the scp command to transfer files. SCP may be faster than using SFTP [1].
Install rsshAUR or scponly as alternative shell solutions.
Scponly
For existing users, simply set the user's shell to scponly:
# usermod -s /usr/bin/scponly username
See the Scponly Wiki for more details.
Adding a chroot jail
The package comes with a script to create a chroot. To use it, run:
# /usr/share/doc/scponly/setup_chroot.sh
- Provide answers
- Check that
/path/to/chroot
hasroot:root
owner andr-x
for others - Change the shell for selected user to
/usr/bin/scponlyc
- sftp-server may require some libnss modules such as libnss_files. Copy them to chroot's
/lib
path.