Difference between revisions of "SFTP chroot"

From ArchWiki
Jump to: navigation, search
(Adding new chrooted users: Already added above, and shell changes should not be needed/adviced)
m (casing)
(36 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 
[[Category:File Transfer Protocol]]
 
[[Category:File Transfer Protocol]]
 
[[Category:Secure Shell]]
 
[[Category:Secure Shell]]
[[OpenSSH]] 4.9+ includes a built-in chroot for sftp, but requires a few tweaks to the normal install.
+
[[ja:SFTP chroot]]
 +
{{Related articles start}}
 +
{{Related|SSHFS}}
 +
{{Related articles end}}
 +
 
 +
[[OpenSSH]] 4.9+ includes a built-in chroot for SFTP, but requires a few tweaks to the normal install.
  
 
== Installation ==
 
== Installation ==
  
[[Install]] and configure [[OpenSSH]]. Once running, SFTP is available by default.
+
[[Install]] and configure [[OpenSSH]]. Once running, make sure {{ic|sftp-server}} has been set correctly:
 +
 
 +
{{hc|/etc/ssh/sshd_config|
 +
Subsystem sftp /usr/lib/ssh/sftp-server
 +
}}
  
Access files with the ''sftp'' program or [[SSHFS]]. Many standard [[List_of_applications#File_transfer_clients|FTP clients]] should work as well.
+
Access files with ''sftp'' or [[SSHFS]]. Many standard [[List_of_applications#File_transfer_clients|FTP clients]] should work as well.
  
 
==Configuration==
 
==Configuration==
  
 
===Setup the filesystem===
 
===Setup the filesystem===
Create a jail directory:
+
{{Note|
 
+
* 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 {{ic
  # mkdir -p /var/lib/jail
+
|/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 {{ic|/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, {{ic|/mnt/data/share}} is to be used, owned by [[user]] {{ic|root}} and has octal [[permissions]] of {{ic|755}}:
 
Bind mount the live [[filesystem]] to be shared to this directory. In this example, {{ic|/mnt/data/share}} is to be used, owned by [[user]] {{ic|root}} and has octal [[permissions]] of {{ic|755}}:
  
# mount -o bind /mnt/data/share /var/lib/jail
 
 
  # chown root:root /mnt/data/share
 
  # chown root:root /mnt/data/share
 
  # chmod 755 /mnt/data/share
 
  # chmod 755 /mnt/data/share
 +
# mkdir -p /srv/ssh/jail
 +
# mount -o bind /mnt/data/share /srv/ssh/jail
  
{{Note|
+
Add entries to [[fstab]] to make the bind mount survive on a reboot:
*Add entries to [[fstab]] to make the bind mount survive on a reboot.
+
  /mnt/data/share /srv/ssh/jail none  bind   0  0
*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 {{ic
 
|/var/lib/jail}} - it can be accomplished on the live partition which will be mounted via a bind mount as well.
 
}}
 
  
 
=== Create an unprivileged user ===
 
=== Create an unprivileged user ===
{{Note|You don't need to create a group, it is possible to {{ic|Match User}} instead of {{ic|Match Group}}.}}
+
{{Note|You do not need to create a group, it is possible to use {{ic|Match User}} instead of {{ic|Match Group}}.}}
  
First, we need to create the {{ic|sftponly}} [[group]]:
+
Create the {{ic|sftponly}} [[group]]:
  
 
  # groupadd sftponly  
 
  # groupadd sftponly  
  
Create a [[user]]:
+
Create a [[user]] that uses ''sftponly'' as main group and has [[shell]] login access denied:
  
  # useradd -g sftponly -d ''/var/lib/jail'' ''username''
+
  # useradd -g sftponly -s /usr/bin/nologin -d ''/srv/ssh/jail'' ''username''
  
To deny SSH [[shell]] access, run the following command:
+
Set a (complex) password to prevent {{ic|account is locked}} error:
  
  # usermod ''username'' -s /bin/false
+
  # passwd ''username''
  
 
=== Configure OpenSSH ===
 
=== Configure OpenSSH ===
{{Note|Use {{ic|Match User}} instead of {{ic|Match Group}} when not using the given group.}}
+
{{Note|You may want to use {{ic|Match User}} instead of {{ic|Match Group}} as been given in the previous step.}}
  
 
{{hc|/etc/ssh/sshd_config|<nowiki>
 
{{hc|/etc/ssh/sshd_config|<nowiki>
 +
Subsystem sftp /usr/lib/ssh/sftp-server
 +
 
Match Group sftponly
 
Match Group sftponly
 
   ChrootDirectory %h
 
   ChrootDirectory %h
Line 58: Line 71:
  
 
==== Fixing path for authorized_keys ====
 
==== Fixing path for authorized_keys ====
With the standard path of ''AuthorizedKeysFile'', the [[SSH keys]] authentication will fail for chrooted-users. To fix this, [[append]] ''AuthorizedKeysFile'' to {{ic|/etc/openssh/sshd_config}} on a root-owned directory, e.g. {{ic|/etc/ssh/authorized_keys}}.
+
{{Tip|Use the [[SSH_keys#Key_ignored_by_the_server|debug mode]] of OpenSSH on the client and server in case of {{ic|(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 {{ic|/etc/openssh/sshd_config}} e.g. {{ic|/etc/ssh/authorized_keys}}, as example:
  
AuthorizedKeysFile /etc/ssh/authorized_keys .ssh/authorized_keys
+
{{hc|/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'' file, generate a [[SSH_keys#Choosing_the_key_location_and_passphrase|SSH-key]] on the client, [[SSH_keys#Manual_method|copy]] the contents of the key to {{ic|/etc/ssh/authorized_keys}} of the server and [[SSH_keys#Key_ignored_by_the_server|setup permissions]]:
+
Create ''authorized_keys'' folder, generate a [[SSH_keys#Choosing_the_key_location_and_passphrase|SSH-key]] on the client, [[SSH_keys#Manual_method|copy]] the contents of the key to {{ic|/etc/ssh/authorized_keys}} (or any other preferred method) of the server and [[SSH_keys#Key_ignored_by_the_server|set correct permissions]]:
  
  # touch ''/etc/ssh/authorized_keys''
+
  # mkdir /etc/ssh/authorized_keys
  # echo 'ssh-rsa <key> <username@host>' >> ''/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]] {{ic|sshd.service}}.
 
[[Restart]] {{ic|sshd.service}}.
  
== Logging ==
+
==Tips and tricks==
 +
=== Write permissions ===
 +
The [[#Setup the filesystem|bind]] path needs to be fully owned by {{ic|root}}, however files and/or subdirectories don't have to be.
 +
In the following example the [[user]] ''www-demo'' uses {{ic|/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 ===
 +
{{Accuracy|Is this possible with systemd-journal? Are there no security concerns?}}
  
 
The user will not be able to access {{ic|/dev/log}}. This can be seen by running {{ic|strace}} on the process once the user connects and attempts to download a file.  
 
The user will not be able to access {{ic|/dev/log}}. This can be seen by running {{ic|strace}} on the process once the user connects and attempts to download a file.  
  
=== Create sub directory ===
+
==== Create sub directory ====
 
Create the sub-directory {{ic|dev}} in the {{ic|ChrootDirectory}}, for example:
 
Create the sub-directory {{ic|dev}} in the {{ic|ChrootDirectory}}, for example:
 
  # mkdir /usr/local/chroot/user/dev
 
  # mkdir /usr/local/chroot/user/dev
Line 80: Line 114:
 
{{ic|syslog-ng}} will create the device {{ic|/usr/local/chroot/theuser/dev/log}} once configured.
 
{{ic|syslog-ng}} will create the device {{ic|/usr/local/chroot/theuser/dev/log}} once configured.
  
=== Syslog-ng configuration ===
+
==== Syslog-ng configuration ====
 
Add to {{ic|/etc/syslog-ng/syslog-ng.conf}} a new source for the log and add the configuration, for example change the section:
 
Add to {{ic|/etc/syslog-ng/syslog-ng.conf}} a new source for the log and add the configuration, for example change the section:
 
{{bc|<nowiki>source src {
 
{{bc|<nowiki>source src {
Line 105: Line 139:
 
}}
 
}}
  
(Optional) If you'd like to similarly log SSH messages to it's own file:
+
(Optional) If you would like to similarly log SSH messages to its own file:
  
 
{{bc|<nowiki>#sshd configuration
 
{{bc|<nowiki>#sshd configuration
Line 114: Line 148:
 
(From [[Syslog-ng#Move log to another file]])
 
(From [[Syslog-ng#Move log to another file]])
  
=== sshd configuration ===
+
==== OpenSSH configuration ====
  
 
Edit {{ic|/etc/ssh/sshd_config}} to replace all instances of {{ic|internal-sftp}} with {{ic|internal-sftp -f AUTH -l VERBOSE}}
 
Edit {{ic|/etc/ssh/sshd_config}} to replace all instances of {{ic|internal-sftp}} with {{ic|internal-sftp -f AUTH -l VERBOSE}}
  
=== Restart service ===
+
==== Restart service ====
  
 
[[Restart]] service {{ic|syslog-ng}} and {{ic|sshd}}.
 
[[Restart]] service {{ic|syslog-ng}} and {{ic|sshd}}.
Line 124: Line 158:
 
{{ic|/usr/local/chroot/theuser/dev/log}} should now exist.
 
{{ic|/usr/local/chroot/theuser/dev/log}} should now exist.
  
==Testing your chroot==
+
== Alternatives to SFTP ==
# ssh username@localhost
 
 
 
should refuse the connection or fail on login. The response varies, possibly due to the version of OpenSSH used.
 
 
 
# sftp username@localhost
 
 
 
should place you in the chroot'd environment.
 
 
 
==Troubleshooting==
 
Error while trying to connect
 
Write failed: Broken pipe                                                                                             
 
Couldn't read packet: Connection reset by peer
 
If you also find similar message in /var/log/auth.log
 
sshd[12399]: fatal: bad ownership or modes for chroot directory component "/path/of/chroot/directory/" 
 
  
This is a {{ic|ChrootDirectory}} ownership problem. sshd will reject SFTP connections to accounts that are set to chroot into any directory that has ownership/permissions that sshd considers insecure. sshd's strict ownership/permissions requirements dictate that every directory in the chroot path must be owned by root and only writable by the owner.  So, for example, if the chroot environment is /home must be owned by root.
+
=== Secure copy protocol (SCP) ===
See below for possible alternatives.
+
Installing {{Pkg|openssh}} provides the ''scp'' command to transfer files. SCP may be faster than using SFTP [https://superuser.com/questions/134901/whats-the-difference-between-scp-and-sftp].
  
The reason for this is to [http://lists.mindrot.org/pipermail/openssh-unix-dev/2009-May/027651.html prevent a user from escalating their privileges] and becoming root, escaping the chroot environment.
+
[[Install]] {{Aur|rssh}} or {{Pkg|scponly}} as alternative shell solutions.
  
If chroot environment is in user's home directory, make sure user have access to it's home directory, or user would not be able to access it's publickey, produce following error
+
==== Scponly ====
Permission denied (publickey).
 
  
== Write access to chroot dir ==
+
[[install]] {{Pkg|scponly}}.
  
As above, if a user is able to write to the chroot directory then it is possible for them to escalate their privileges to root and escape the chroot.  One way around this is to give the user two home directories - one "real" home they can write to, and one SFTP home that is locked down to keep sshd happy and your system secure.  By using {{ic|mount --bind}} you can make the real home directory appear as a subdirectory inside the SFTP home directory, allowing them full access to their real home directory.
+
For existing users, simply set the user's shell to scponly:
  
This can also be used to achieve other goals. For example, a user's home directory can be locked down per the sshd chroot rules, and bind mounts used to provide users access to other directories:
+
  # usermod -s /usr/bin/scponly ''username''
  
# mkdir /home/user/web
+
See [https://github.com/scponly/scponly/wiki the Scponly Wiki] for more details.
# mount --bind /srv/web/example.com /home/user/web
 
  
Optional add an entry to {{ic|/etc/fstab}}:
+
==== Adding a chroot jail ====
  
# echo '/srv/web/example.com/ /home/user/web        none    bind' >> /etc/fstab
+
The package comes with a script to create a chroot. To use it, run:
  
Now the user can log in with SFTP, they are chrooted to {{ic|/home/user}}, but they see a folder called "web" they can access to manipulate files on a web site (assuming they have correct permissions in {{ic|/srv/web/example.com}}.
+
# /usr/share/doc/scponly/setup_chroot.sh
 +
* Provide answers
 +
* Check that {{ic|/path/to/chroot}} has {{ic|root:root}} owner and {{ic|r-x}} for others
 +
* Change the shell for selected user to {{ic|/usr/bin/scponlyc}}
 +
* sftp-server may require some libnss modules such as libnss_files. Copy them to chroot's {{ic|/lib}} path.
  
 
== See also ==
 
== See also ==
 
*[http://www.minstrel.org.uk/papers/sftp/ http://www.minstrel.org.uk/papers/sftp/builtin/]
 
*[http://www.minstrel.org.uk/papers/sftp/ http://www.minstrel.org.uk/papers/sftp/builtin/]
 
*[http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config]
 
*[http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config]

Revision as of 05:18, 31 December 2017

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

Note:
  • 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

Note: You do not need to create a group, it is possible to use Match User instead of Match Group.

Create the sftponly 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:

# passwd username

Configure OpenSSH

Note: You may want to use 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

Tip: Use the debug mode of OpenSSH on the client and server in case of (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 don't 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

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: Is this possible with systemd-journal? Are there no security concerns? (Discuss in Talk:SFTP chroot#)

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

syslog-ng will create the device /usr/local/chroot/theuser/dev/log once configured.

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

install 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 has root:root owner and r-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.

See also