There are several reasons to restrict a SSH user session to a particular directory, especially on web servers, but the obvious one is a system security. In order to lock SSH users in a certain directory, we can use chroot mechanism.
change root (chroot) in Unix-like systems such as Linux, is a means of separating specific user operations from the rest of the Linux system; changes the apparent root directory for the current running user process and its child process with new root directory called a chrooted jail.
In this tutorial, we’ll show you how to restrict a SSH user access to a given directory in Linux. Note that we’ll run the all the commands as root, use the sudo command if you are logged into server as a normal user.
Step 1: Create SSH Chroot Jail
1. Start by creating the chroot jail using the mkdir command below:
# mkdir -p /home/test
2. Next, identify required files, according to the sshd_config man page, the ChrootDirectory
option specifies the pathname of the directory to chroot to after authentication. The directory must contain the necessary files and directories to support a user’s session.
For an interactive session, this requires at least a shell, commonly sh
, and basic /dev
nodes such as null, zero, stdin, stdout, stderr, and tty devices:
# ls -l /dev/{null,zero,stdin,stdout,stderr,random,tty}

3. Now, create the /dev
files as follows using the mknod command. In the command below, the -m
flag is used to specify the file permissions bits, c
means character file and the two numbers are major and minor numbers that the files point to.
# mkdir -p /home/test/dev/ # cd /home/test/dev/ # mknod -m 666 null c 1 3 # mknod -m 666 tty c 5 0 # mknod -m 666 zero c 1 5 # mknod -m 666 random c 1 8

4. Afterwards, set the appropriate permission on the chroot jail. Note that the chroot jail and its subdirectories and subfiles must be owned by root user, and not writable by any normal user or group:
# chown root:root /home/test # chmod 0755 /home/test # ls -ld /home/test

Step 2: Setup Interactive Shell for SSH Chroot Jail
5. First, create the bin
directory and then copy the /bin/bash
files into the bin
directory as follows:
# mkdir -p /home/test/bin # cp -v /bin/bash /home/test/bin/

6. Now, identify bash required shared libs
, as below and copy them into the lib
directory:
# ldd /bin/bash # mkdir -p /home/test/lib64 # cp -v /lib64/{libtinfo.so.5,libdl.so.2,libc.so.6,ld-linux-x86-64.so.2} /home/test/lib64/

Step 3: Create and Configure SSH User
7. Now, create the SSH user with the useradd command and set a secure password for the user:
# useradd tecmint # passwd tecmint
8. Create the chroot jail general configurations directory, /home/test/etc
and copy the updated account files (/etc/passwd and /etc/group) into this directory as follows:
# mkdir /home/test/etc # cp -vf /etc/{passwd,group} /home/test/etc/

Note: Each time you add more SSH users to the system, you will need to copy the updated account files into the /home/test/etc
directory.
Step 4: Configure SSH to Use Chroot Jail
9. Now, open the sshd_config
file.
# vi /etc/ssh/sshd_config
and add/modify the lines below in the file.
#define username to apply chroot jail to Match User tecmint #specify chroot jail ChrootDirectory /home/test

Save the file and exit, and restart the SSHD services:
# systemctl restart sshd OR # service sshd restart
Step 5: Testing SSH with Chroot Jail
10. At this point, test if the chroot jail setup is working as expected:
# ssh [email protected] -bash-4.1$ ls -bash-4.1$ date -bash-4.1$ uname

From the screenshot above, we can see that the SSH user is locked in the chrooted jail, and can’t run any external commands (ls, date, uname etc).
The user can only execute bash and its builtin commands such as(pwd, history, echo etc) as seen below:
# ssh [email protected] -bash-4.1$ pwd -bash-4.1$ echo "Tecmint - Fastest Growing Linux Site" -bash-4.1$ history

Step 6. Create SSH User’s Home Directory and Add Linux Commands
11. From the previous step, we can notice that the user is locked in the root directory, we can create a home directory for the the SSH user like so (do this for all future users):
# mkdir -p /home/test/home/tecmint # chown -R tecmint:tecmint /home/test/home/tecmint # chmod -R 0700 /home/test/home/tecmint

12. Next, install a few user commands such as ls, date, mkdir in the bin
directory:
# cp -v /bin/ls /home/test/bin/ # cp -v /bin/date /home/test/bin/ # cp -v /bin/mkdir /home/test/bin/

13. Next, check the shared libraries for the commands above and move them into the chrooted jail libraries directory:
# ldd /bin/ls # cp -v /lib64/{libselinux.so.1,libcap.so.2,libacl.so.1,libc.so.6,libpcre.so.1,libdl.so.2,ld-linux-x86-64.so.2,libattr.so.1,libpthread.so.0} /home/test/lib64/

Step 7. Testing SFTP with Chroot Jail
14. Do a final test using sftp; check if the commands you have just installed are working.
Add the line below in the /etc/ssh/sshd_config
file:
#Enable sftp to chrooted jail ForceCommand internal-sftp
Save the file and exit. Then restart the SSHD services:
# systemctl restart sshd OR # service sshd restart
15. Now, test using SSH, you’ll get the following error:
# ssh [email protected]

Try using SFTP as follows:
# sftp [email protected]

Suggested Read: Restrict SFTP Users to Home Directories Using chroot Jail
That’s it for now!. In this article, we showed you how to restrict a SSH user in a given directory (chrooted jail) in Linux. Use the comment section below to offer us your thoughts about this guide.
I already did:
but ls still not working…
I’m unable to get
ls
to work for the new user after following the directions. Below is the comparison between the bin directories for each showing they have the same library entriesI m getting error ls command not found when login with ssh in chroot jail environment.
Please help me…
@Bharat
Did you copy the commands to the chrooted jail directory and perform step 13, to check the shared libraries for the commands you copied and move them into the chrooted jail libraries directory?
Hi,
[[email protected] bin]# ls
bash date ls mkdir
[[email protected] bin]# pwd
/home/backup/bin
–
[[email protected] lib64]# ls
ld-linux-x86-64.so.2 libattr.so.1 libc.so.6 libpcre.so.1 libselinux.so.1
libacl.so.1 libcap.so.2 libdl.so.2 libpthread.so.0 libtinfo.so.5
[[email protected] lib64]# pwd
/home/backup/lib64
–
Last login: Fri Nov 27 11:35:54 2020 from 1XX.XXX.XXX.XXX
-bash-4.2$ ls
-bash: ls: command not found
–
still not working…
Hi! Very nice theme and article! Thanks
There is a problem when I try to use mkdir or ls by with user-created with your scheme, I get restriction message
but I was execute
where I make wrong?
(CentOS 7)
@Yuriy
Did you run this command to check the shared libraries for the ls command?
And did you copy shared libraries into the chrooted jail libraries directory?
Thank you.
Help me a lot off.
Hi,
I add ssh along with the libs and id as well. When using ssh I am getting.
This article has interesting concepts and worked partially, complemented with this other one, OK for CentOS 7.5.
https://serverfault.com/questions/699346/a-proper-way-to-create-a-chrooted-ssh-on-centos-7
@Fernando
Based on your comment and those from the other readers, we will review the article soon. Thanks for the feedback.
@chris One thing that isn’t explained in this is once you add the ForceCommand, it will only allow sftp connections with that user.
Yes, from my understanding and how I’ve been using ssh and sftp it does only force sftp for the users that have the “ForceCommand internal-sftp” in their “Match User” segment.
In my example I have 3 users, one regular, root, and one sftp user:
The regular user can use sftp, ssh, X11Forwarding, but is only allowed to use key auth.
root, can’t do X11 but otherwise is set up like the regular user (except the key is on the same network)
while the sftp user can only log in to sftp with passwords (I’d love to have key auth but one software isn’t compatible with them).
It seems this page might be a bit out of date. I Was struggling but found https://www.digitalocean.com/community/questions/sftp-connection-error-received-unexpected-end-of-file-from-sftp-server
Then scroll down until you see this line:
Leave that line commented out, but underneath it write this:
Launched another putty instance and tried to log in using “tecmint” user but SSH terminal closes after supplying the password.
Please help..
As many people have pointed out ls (or date) doesn’t seem to work when you connect through ssh, and yeah I’ve used ldd and made sure every library was in place. (tested with Manjaro and OpenSUSE)
I haven’t tried other programs, what I’ve tried is to remove/don’t add ls to the bin directory and connect through sftp. I was able to use ls, so for me, that isn’t a problem as this jail was meant to an sftp user.
As for Step 8. I do not understand why it’s needed?
When I connect to sftp I don̈́’t really want that user to see ALL of the available users on my system or group for that matter. Again I didn’t do that step and everything (ssh and sftp) works just fine, there’s no need to copy this file to the chroot jail… or am I missing something?
I honestly do not have enough Linux experience to justify my reasoning except that I can still login through ssh and sftp without adding passwd or group.
It’s my understanding that you’d want to add as little as possible into the jail to prevent them from having access to anything that they (user or app) don’t need to use or see.