This article describes how to setup a SFTP server installation,
plus some advices from a security point of view.
The users will find themselves inside a chrooted environment, and
the file system permissions are active:
Every user may have a seperated, isolated environment.
Step 1: Prepare your system
Create a group for users that are allowed to use sftp, and add some users to it. Since those users communicate with the ssh server without needing a login shell, we will disable shell access for them by setting /bin/false as login shell.
root@testkraxn /home/tester # groupadd sftponly
root@testkraxn /home/tester # cat /etc/group | tail -n 1
sftponly:x:1001:
root@testkraxn /home/tester # useradd garfield -d / -g 1001 -M -N -o -u 1001
root@testkraxn /home/tester # passwd garfield
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@testkraxn ~tester # chsh garfield
Changing the login shell for garfield
Enter the new value, or press ENTER for the default
Login Shell [/bin/sh]: /bin/false
root@testkraxn /home/tester # cat /etc/passwd | tail -n 1
garfield:x:1001:1001::/:/bin/false
Step 2: Configure the SSH Server
root@testkraxn /home/tester # cp /etc/ssh/sshd_config /etc/ssh/sshd_config.`date +%F_%T`.backup root@testkraxn /home/tester # vim /etc/ssh/sshd_config
replace line:
Subsystem sftp /usr/lib/openssh/sftp-server
with
Subsystem sftp internal-sftp
Then, append these lines at the end of the file:
Match group sftponly
ChrootDirectory /var/www
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
my whole config, to be complete here:
root@killerkraxn ~ # grep -vE '^\s*(#.*|)$' /etc/ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 768
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
AcceptEnv LANG LC_*
Subsystem sftp internal-sftp
UsePAM yes
Match group sftponly
ChrootDirectory /data/sftpusers
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
Step 2: Create some test directories
I use a script like this to create a new user: (run as root)
NEW_USER=$1 echo crating user: $NEW_USER useradd $NEW_USER -d / -G sftponly -M -s /bin/false groups $NEW_USER cd /data/sftpusers echo "setting up home directories..." mkdir $NEW_USER chown root:$NEW_USER $NEW_USER chmod 750 $NEW_USER mkdir $NEW_USER/readonly chmod 755 $NEW_USER/readonly echo "you cannot change this file" > $NEW_USER/readonly/test.txt chmod 644 $NEW_USER/readonly/test.txt mkdir $NEW_USER/readwrite echo "delete me if you wish" > $NEW_USER/readwrite/test.txt chown $NEW_USER:$NEW_USER -R $NEW_USER/readwrite mkdir $NEW_USER/no-access chmod 700 $NEW_USER/no-access echo "you won't ever read this, douchebag!" > $NEW_USER/no-access/test.txt echo "you should set a password for the user: passwd $NEW_USER"
If you want to provide access to other folders to the users, you can mount
the directory into the users base dir.
In this example, i will grant access to /media/misc/foo to the user garfield:
root@testkraxn ~ # mkdir -p /data/sftpusers/garfield/media root@testkraxn ~ # mount --bind /media/misc/foo /data/sftpusers/garfield/media
Finally, the directory structure for the user looks like this:
root@killerkraxn /data/sftpusers # tree
.
└── garfield
├── no-access
│ └── test.txt
├── readonly
│ └── test.txt
├── readwrite
│ └── test.txt
└── misc
└── foo --> mountpoint of /media/misc/foo
└── foo-contents
Restart the ssh server and test the setup:
root@testkraxn ~ # service ssh restart
andre@buenosaires ~ % sftp garfield@ 192.168.56.102
garfield@ 192.168.56.102's password:
Connected to 192.168.56.102.
sftp> cd /
sftp> pwd
Remote working directory: /
sftp> ls
foo readonly readwrite no-access
sftp> cd no-access
sftp> pwd
Remote working directory: /no-access
sftp> ls
remote readdir("/no-access"): Permission denied
sftp> cd /readwrite
sftp> mkdir bar
sftp> ls
bar test.txt
sftp> cd /readonly
sftp> mkdir bar
Couldn't create directory: Permission denied
sftp> ls
test.txt
sftp> cd /misc
sftp> pwd
Remote working directory: /misc
sftp> ls
foo
sftp> exit
And the users do not have access to a shell when trying to connect via ssh:
andre@buenosaires ~ % ssh garfield @192.168.56.102 garfield@ 192.168.56.102's password: This service allows sftp connections only. Connection to 192.168.56.102 closed.