In one of our previous articles we demonstrated how to configure chrooted sftp user accounts.  Along with the configuration of chrooted sftp accounts you can actually configure a mechanism for chrooted ssh access as well. This type of chrooted ssh setup is commonly referred to as a chroot jail and we will be explaining it’s configuration step by step in this article. Chrooted jails are a means of separating specific user operations from the rest of the Linux system.  This configuration changes the apparent root directory for the current running user process and its child process with new root directory called a chrooted jail.

Step 1: Create chroot home directory.

[root@linuxnix ~]# mkdir -p /chroot/home/sahil
[root@linuxnix ~]# ls -ld /chroot/home/sahil
drwxr-xr-x. 2 root root 4096 Jul 22 22:34 /chroot/home/sahil
[root@linuxnix ~]#
[root@linuxnix ~]# chmod 700 /chroot/home/sahil

We need to disable SELinux for this setup to work.

[root@linuxnix ~]# setenforce 0

We will be copying certain binaries and library files into this directory. So, let’s create the sub-directories in which we will place these binaries and library files.

[root@linuxnix ~]# cd /chroot
[root@linuxnix chroot]# mkdir bin/ lib64/ lib/ dev/
[root@linuxnix chroot]# ls
bin lib lib64 dev
[root@linuxnix chroot]#

Now under the dev/ directory we will be creating certain required character device files 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.

[root@linuxnix ~]# mknod /chroot/dev/null c 1 3
[root@linuxnix ~]# mknod /chroot/dev/zero c 1 5
[root@linuxnix ~]# mknod -m 666 /chroot/dev/tty c 5 0
[root@linuxnix ~]# mknod -m 666 /chroot/dev/ptmx c 5 2


Step 2: Copy bash binary to chrooted home directory
Since a jailed environment is isolated from the rest of the system, we will not have access to any user commands not even the bash shell while we are in the chroted jailed environment. So, in order to have access to the bash shell we will copy the bash binary to our chrooted home directory along with the shared libraries required by bash. To know which shared libraries are required by a binary we run the ldd command followed by the full path of the binary.

[root@linuxnix chroot]# ldd /bin/bash => (0x00007fff4f19a000) => /lib64/ (0x0000003dfc200000) => /lib64/ (0x0000003deee00000) => /lib64/ (0x0000003dee600000)
/lib64/ (0x0000003dede00000)

Now we will need to copy the above mentioned library files along with the /bin/bash binary file to the appropriate directories in the /chroot/home directory.

[root@linuxnix chroot]# cp -v /lib64/ /chroot/home/lib64/
`/lib64/' -> `/chroot/home/lib64/'
[root@linuxnix chroot]# cp -v /lib64/ /chroot/home/lib64/
`/lib64/' -> `/chroot/home/lib64/'
[root@linuxnix chroot]# cp -v /lib64/ /chroot/home/lib64/
`/lib64/' -> `/chroot/home/lib64/'
[root@linuxnix chroot]# cp -v /lib64/ /chroot/home/lib64/
`/lib64/' -> `/chroot/home/lib64/'
[root@linuxnix chroot]#
[root@linuxnix chroot]# cp -v /bin/bash /chroot/home/bin/
`/bin/bash' -> `/chroot/home/bin/bash'
[root@linuxnix chroot]#

We now need to execute the chroot command followed by the chrooted home directory name to comlplete the chroot environment setup.

[root@linuxnix chroot]# chroot /chroot/home
bash-4.1# ls /
bash: ls: command not found

As you may observe once we entered the chrooted environment even the ls command did not work since the required binary files and libraries files are not available. However since we had copied the bash shell binary and associated library files, we have access to the bash shell along with it’s built ins.

bash-4.1# pwd
bash-4.1# cd
bash: cd: /root: No such file or directory
bash-4.1# history
1 ls /
2 pwd
3 cd
4 history

Step 3: Copy required binary files and associated library files.
To copy the required library files we’ve written a small script using which you only have to specify the full path of the binary and the script will copy the required library files.

[root@linuxnix ~]# cat chroot_library_copy.bash


#create chroot directory if it does not already exist##

mkdir $CHROOT

##copy library
for lib in $( ldd $* | awk '/lib/ {print $3}' | sed 's/://' | sort | uniq )
cp ${lib} ${CHROOT}/lib64

if [ -f /lib64/ ]; then
cp /lib64/ ${CHROOT}/lib64
[root@linuxnix ~]#

Let’s execute this script now.

[root@linuxnix ~]# bash -x ./chroot_library_copy.bash /bin/{ls,cat,echo,rm,date,bash,uname,vi}
+ CHROOT=/chroot/home
+ mkdir /chroot/home
mkdir: cannot create directory `/chroot/home': File exists
++ sort
++ uniq
++ awk '/lib/ {print $3}'
++ sed s/://
++ ldd /bin/ls /bin/cat /bin/echo /bin/rm /bin/date /bin/bash /bin/uname /bin/vi
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ for lib in '$( ldd $* | awk '\''/lib/ {print $3}'\'' | sed '\''s/://'\'' | sort | uniq )'
+ cp /lib64/ /chroot/home/lib64
+ '[' -f /lib64/ ']'
+ cp /lib64/ /chroot/home/lib64
[root@linuxnix ~]#

[root@linuxnix ~]# cp -v /bin/{ls,cat,echo,rm,date,bash,uname,vi} /chroot/home/bin
`/bin/ls' -> `/chroot/home/bin/ls'
`/bin/cat' -> `/chroot/home/bin/cat'
`/bin/echo' -> `/chroot/home/bin/echo'
`/bin/rm' -> `/chroot/home/bin/rm'
`/bin/date' -> `/chroot/home/bin/date'
cp: overwrite `/chroot/home/bin/bash'? y
`/bin/bash' -> `/chroot/home/bin/bash'
`/bin/uname' -> `/chroot/home/bin/uname'
`/bin/vi' -> `/chroot/home/bin/vi'
[root@linuxnix ~]#

Step 4: Add user that is to be jailed.
While adding the user account to be jailed we will also be creating a group named sshonly and add it as a secondary group to the user that we are going to create.

[root@linuxnix ~]# groupadd sshonly
[root@linuxnix ~]# seradd -G sshonly -c "Restricted User" sahil
-bash: seradd: command not found
[root@linuxnix ~]# useradd -G sshonly -c "Restricted User" sahil
[root@linuxnix ~]# passwd sahil
Changing password for user sahil.
New password:
BAD PASSWORD: it is WAY too short
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updated successfully.

We will make use of the group sshonly in the sshd_config file such that any member of this group will be given a jailed ssh environment.

Step 5: Modify /etc/ssh/sshd_config file and restart sshd service
Add the following lines to the /etc/ssh/sshd_config file and then restart the sshd service.

[root@linuxnix ~]# tail -n 5 /etc/ssh/sshd_config 
# Use Match Group and ChrootDirectory options to Chroot members of 'sshonly` after authentication
Match Group sshonly
ChrootDirectory /chroot
AllowTcpForwarding no
X11Forwarding no
[root@linuxnix ~]# service sshd restart
Stopping sshd: [ OK ]
Starting sshd: [ OK ]

Step 6: Test and validate the setup
Now that we have completed the configuration let’s try to login as the user sahil and test it.

[root@linuxnix ~]# ssh sahil@
The authenticity of host ' (' can't be established.
RSA key fingerprint is 60:d4:8e:1a:4d:f8:f4:a8:9e:d5:b7:3b:2d:c7:f2:90.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '' (RSA) to the list of known hosts.
sahil@'s password:
-bash-4.1$ ls
-bash-4.1$ pwd


In this article we demonstrated step by step how you would setup a chroot jailed ssh account. We hope that you found this post to be useful and we look forward towards your suggestions and feedback.

The following two tabs change content below.

Sahil Suri

He started his career in IT in 2011 as a system administrator. He has since worked with HP-UX, Solaris and Linux operating systems along with exposure to high availability and virtualization solutions. He has a keen interest in shell, Python and Perl scripting and is learning the ropes on AWS cloud, DevOps tools, and methodologies. He enjoys sharing the knowledge he's gained over the years with the rest of the community.