SUSE Support

Here When You Need Us

How to chroot SFTP sessions on SLES 10 SP4 or higher version.

This document (7009112) is provided subject to the disclaimer at the end of this document.

Environment

SUSE Linux Enterprise Server 15
SUSE Linux Enterprise Server 12
SUSE Linux Enterprise Server 11
SUSE Linux Enterprise Server 10 Service Pack 4

Situation

It is desired to put SFTP users in a change-root (chroot) jail.

Resolution

OpenSSH version 5.1 introduced a chroot feature for jailing SFTP users in a specified location.  In SLES products, this new feature is available through an updated openssh package (with major version number 5.1 or higher) present in SLES 10 SP4 and SLES 11 and higher.  NOTE:  Chrooted users will not be able to login to a server via ssh, only through sftp.
 
Fundamentally, jailing (or chrooting) users to a directory is done in /etc/ssh/sshd_config with 2 settings, discussed in sections 1 and 2 below.  The basic method is simple but is usually not adequate by itself.  For important security reasons and to avoid having to scrap and redesign an approach, it is recommended to read this entire document very carefully before planning the chroot implementation.
 
 
1.  Edit /etc/ssh/sshd_config .  Find the "Subsystem" line that defines sftp.  This originally points to a individual sftp-server executable such as /usr/lib64/ssh/sftp-server. Change that line so it points to sshd's own internal sftp server code:
 
Subsystem sftp internal-sftp
 
This is necessary because once a session is chrooted to a certain path, it cannot get out of that location in order to find other code to execute -- not even to find the sftp-server binary.  By pointing to sshd's own internal sftp service, the sessions will avoid the need to find sftp code outside the chroot location.
 
 
2.  The chroot location can then be controlled by adding the syntax:

ChrootDirectory /path

NOTE:  Globally jailing everyone to one location is usually not preferred, so the remaining sections of this document should be considered.


3.  Although sections 1 and 2 can be used to implement a chroot, it is rarely adequate or preferred to implement it in such simple and global manner.  There are several crucial points to consider:

3.1.  It is usually not desirable to make a ChrootDirectory setting effective for everyone because some users (such as root) may need greater access.  Most administrators govern the chroot on a per-user or per-group basis. Therefore, instead of setting a ChrootDirectory in the main section of the sshd_config file, it is typically put at the end of the file, in a "Match" block, so it only applies to certain users, groups, addresses, etc.  A Match block looks something like:

Match group group1
   ForceCommand internal-sftp
   ChrootDirectory /path
 
The above syntax is literal except for "group1" which should be replaced by the group name in question, and "path" which should be replaced by the chroot path.  This section can hold other settings as well, to be applied to this group.  For example, is it common to add "AllowTcpForwarding no " to these blocks as well.
 
These Match blocks must go at the end of the sshd_config.  Any setting other than "Match" which comes later will be treated as belonging to the Match block, and not as a global setting.  The only thing allowed to come after a Match block is another Match block.  Match blocks can apply to users, groups, addresses, or hosts. See the man page for sshd_config and find the explanation of the "Match" setting for more details.
 
Also note that the "Subsystem internal-sftp " line mentioned in section 1 above is required in the main section of the sshd_config, even though a line with the same purpose is needed inside this Match block.  This is not true of the "ChrootDirectory" line, which should only appear in the Match block.
 
3.2.  The philosophy of sshd's chroot method is one of the most security-conscious implementations around.  While that is very comforting, it also poses some challenges.  Openssh insists that the chroot location (and its parent directory, grandparent directory, etc.) be owned by root and no other user or group can have write access to these locations.  There can be subdirectories within the chroot location which are owned by non-root users and are writable, but not the chroot location itself, or its parents.  This means that any directory mentioned in the entire "ChrootDirectory" path definition must be owned by user root and have permissions 755 (or less).  This is very strictly enforced.  Even if the group assigned to the location is "root" group, assigning write to that group (775) will result in the failure.
 
When this kind of denial occurs, the sshd server side will log (by default in /var/log/messages):

sshd[pid]: fatal: bad ownership or modes for chroot directory /path
 
The failure at the ssh client will typically be seen rather generically.  For example, the Linux openssh sftp command would show:

Couldn't read packet: Connection reset by peer
 
Of course, the requirement that root own the chroot location can be very undesirable if you are trying to chroot someone to their home directory location.  Read on to section 3.3 which includes some extra notes on that subject.
 
3.3.  Special note for using variables to designate chroot paths:
 
In some cases, a single ChrootDirectory rule is being created for a multiple users (for example, a group), but it is desired that each individual user go to separate locations.  To accomplish this, use the %h (home directory) variable, or the %u (username) variable.  Some examples:
 
ChrootDirectory /sftpchroots/%h
or
ChrootDirectory /sftpchroots/%u
 
3.3.1.  As noted above, using a home directory or the %h variable above can can be useful.  However, keep in mind that it is sometimes undesirable to set the required root ownership with 755 permissions on a user's official home directory.  That would restrict the user from being able to write in their official home directory and may cause other issues.  This is why the example in section 3.3 lists "%h" as only a part of the chroot path, not the entire chroot path.

Because of cases where users must own chroot locations, an exception to the "root must be the owner" rule has been created in openssh.  (NOTE:  The author is not certain when the exception was created.  It is confirmed to exist in openssh 6.6p1 and later.  It may or may not have existed in openssh 5.1.)
 
A user is allowed to be the owner of the chroot location under the following conditions:
 
a.  The file system containing the chroot location should be mounted with "nodev" and with either "noexec" or "nosuid".  This also implies that the chroot location would not be part of the root file system, since those options would rarely be used there.
 
b.  Other restrictions may still apply.  This may be loosened in later openssh revisions, but it is possible that no entity other than the user may have write access at the chroot point itself, and parent directories may still need to be owned by root and with permissions no more than 755.
 
As a result of this exception, instead of the error mentioned in section 3.2 ("...bad ownership or modes..."), the following error may be logged:
 
sshd[pid]: fatal: chroot into directory without nodev and either noexec or nosuid
 
Upon seeing that error, the choices to resolve it are either to abide by the root ownership and permissions restrictions (section 3.2 above), or to place the chroot locations in a file system mounted with options "nodev" and either "noexec" or "nosuid".
 
 
4.  Special note for those using key-pair authentication:
 
The normal location of public key info on an sshd server is within the user's official home directory, inside a .ssh subdirectory.  For example:

/home/username/.ssh/authorized_keys
 
SSHD (by default) will lookup public key information in the user's true, absolute home directory.  This default behavior happens regardless of where the chroot location is.  Even if a relative path underneath the chroot directory will end up looking the same as the absolute path to the user's official home directory, the official home location is used by default.  The authentication process (and access to the keys file) is performed before sshd determines and imposes the chroot location.
 
In other words:  If a user's home directory is set to /home/username, then ssh key information needs to be found within ./.ssh under that true absolute path.  Even if the chroot location is /chrootdir, and even if there is a directory /chrootdir/home/username, which the user ends up seeing as "/home/username" after login, that is NOT the location where sshd will search for keys.  Keys will be searched under the true, absolute path /home/username.
 
In many cases, this is not a concern.  Most of the time, it is fine for keys to exist under a user's true home directory (i.e. /home/username) and not to exist within the chrooted area.  But it can be a source of confusion, and sometimes people put their keys in the wrong place.
 
For various reasons (though not in most cases) some administrators find it helpful or preferred for keys to exist within the chrooted area.  However, since the chrooted area is not the normal place to search for keys, extra steps are needed to make this work.  There may be various ways to accomplish this, but a couple of suggestions are:
 
a.  If it is desired that keys be visible BOTH under the normal (absolute) /home/username location, and also within the /chrootdir/home/username location, administrators often create symbolic links to accomplish this.  For example, /chroot/home/username could be a symbolic link to /home/username.  Or vice-versa.
 
b. For a chrooted user, if the keys should be searched for within the chrooted area, sshd server can set a non-default location for public key information.  Edit /etc/ssh/sshd_config.  Find the "Match" block which applies to the user in question.  As part of that block, set the appropriate spec for the keys file.

For example, within a Match block for a single user, this might be something like either of the following:
 
AuthorizedKeysFile /chrootdir/.ssh/authorized_keys
or
AuthorizedKeysFile /chrootdir/home/username/.ssh/authorized_keys
 
Within a Match block for a group, address, or host, which could apply to multiple users, this might be something like either of the following:
 
AuthorizedKeysFile /chrootdir/%u/.ssh/authorized_keys
or
AuthorizedKeysFile /chrootdir/%h/.ssh/authorized_keys
 
Where %u and %h are literally placed in the syntax.  They are variables which will resolve to username or home directory (respectively).  The use of the %u or %h variables would allow different users to use different keys, even though just one setting is used for an entire group.


5.  Special notes for using chrooted SFTP in connection with "Open Enterprise Server" (OES):

NOTE:  This information originally came from older versions of OES, a 3rd party product from Novell and later Micro Focus.  While it is expected to still be very accurate, it is not being maintained and therefore may become out of date.  Even so, this information is preserved here as a courtesy to our mutual customers.

5.1.  For authenticating / matching OES users, also known as eDirectory or eDir users:

NAM (Novell Account Management) is case insensitive by default.  In contrast, sshd and most functions of Linux are case sensitive.  This can cause a security concern when a Match block (see section 3, above) tries to match user names and jail them.  An administrator may configure /etc/ssh/sshd_config to jail eDir user "bob".  If someone then logs in as Bob, BoB, bOB, etc., the eDir login will succeed but the user will not be jailed, as the name submitted didn't exactly match "bob".

Therefore, if eDir users are involved, it may be better to match by group than by username.  The Match block should use a group name which matches the upper- and lowercase which exists in eDir.  Later, during logins, the group name is looked up within eDir rather than typed by the user, so this type of mismatch will not occur.

If it is absolutely necessary to match by eDir user name, it is recommended to make eDir logins case sensitive on the OES server.  NOTE:  This could effect other OES processes (especially user-customized scripts) which may not expect to be required to submit case-sensitive names.

You can make eDir logins case sensitive by editing /etc/nam.conf, and find/set:

case-sensitive=yes

Then save.  Then put this in effect with the commands:

rcnamcd restart

namconfig cache_refresh


5.2.  For systems where the desired chroot location is on a NSS volume:

An NSS volume will display posix permissions but does not determine primary access control from those permissions.  However, the chroot libraries used by sshd will still look at the file system's posix permissions in order to determine whether the chroot location is valid.  NSS volumes normally report permissions of 777 just about everywhere (unless special attributes have been set).  This will violate sshd chroot permissions restrictions (section 2, above).  The default permissions display on NSS can be altered to solve this concern:

Edit /etc/opt/novell/nss/nssstart.cfg and set:

/PosixPermissionMask=0755

This setting can also be set temporarily on the fly within nsscon.  After starting nsscon, issue the command:

nss /PosixPermissionMask=0755

Disclaimer

This Support Knowledgebase provides a valuable tool for SUSE customers and parties interested in our products and solutions to acquire information, ideas and learn from one another. Materials are provided for informational, personal or non-commercial use within your organization and are presented "AS IS" WITHOUT WARRANTY OF ANY KIND.

  • Document ID:7009112
  • Creation Date: 03-Aug-2011
  • Modified Date:22-Sep-2021
    • SUSE Linux Enterprise Server

< Back to Support Search

For questions or concerns with the SUSE Knowledgebase please contact: tidfeedback[at]suse.com

SUSE Support Forums

Get your questions answered by experienced Sys Ops or interact with other SUSE community experts.

Support Resources

Learn how to get the most from the technical support you receive with your SUSE Subscription, Premium Support, Academic Program, or Partner Program.

Open an Incident

Open an incident with SUSE Technical Support, manage your subscriptions, download patches, or manage user access.