Restrict SSH User Access to Certain Directory Using Chrooted Jail

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}
Listing Required Files

Listing Required Files

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
Create /dev and Required Files

Create /dev and Required Files

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
Set Permissions on Directory

Set Permissions on Directory

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/
Copy Files to bin Directory

Copy Files to bin Directory

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/
Copy Shared Library Files

Copy Shared Library Files

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/
Copy Password Files

Copy Password Files

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
Configure SSH Chroot Jail

Configure SSH Chroot Jail

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
Testing SSH User Chroot Jail

Testing SSH User Chroot Jail

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
SSH Built-in Commands

SSH Built-in Commands

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
Create SSH User Home Directory

Create SSH User Home Directory

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/
Add Commands to SSH User

Add Commands to SSH User

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/
Copy Shared Libraries

Copy Shared Libraries

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]
Test SSH Chroot Jail

Test SSH Chroot Jail

Try using SFTP as follows:

# sftp [email protected]
Testing sFTP SSH User

Testing sFTP SSH User

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.

If You Appreciate What We Do Here On TecMint, You Should Consider:

TecMint is the fastest growing and most trusted community site for any kind of Linux Articles, Guides and Books on the web. Millions of people visit TecMint! to search or browse the thousands of published articles available FREELY to all.

If you like what you are reading, please consider buying us a coffee ( or 2 ) as a token of appreciation.

Support Us

We are thankful for your never ending support.

Aaron Kili

Aaron Kili is a Linux and F.O.S.S enthusiast, an upcoming Linux SysAdmin, web developer, and currently a content creator for TecMint who loves working with computers and strongly believes in sharing knowledge.

Your name can also be listed here. Got a tip? Submit it here to become an TecMint author.

RedHat RHCE and RHCSA Certification Book
Linux Foundation LFCS and LFCE Certification Preparation Guide

You may also like...

44 Responses

  1. chris says:

    Followed and tested the procedure but when I get to Step 5: Testing SSH with Chroot Jail and use my installed putty on my laptop, the SSH screen goes out or closes after I supplied the password. But when I tried commenting out the ChrootDirectory /home/test I was able to login using the user “tecmint”

    #define username to apply chroot jail to
    Match User tecmint
    #specify chroot jail
    #ChrootDirectory /home/test <——————— this one!

    Newbie here not really a Linux guy.. any help is appreciated.

  2. Fax says:

    Hi, I’m not being able to go past the broken pipe problem.

    I noticed that in point Step1.3 stdin/stdout/stderr are not create, is that correct?

    Also in Step2.6 linux-vdso.so.1 is not copied

    Maybe these the cause of my problems?

    Thanks

  3. Fabricio Dias says:
    # Users/Groups
    mkdir -p /home/jail/etc ;
    rm -rf /home/jail/etc/* ;
    /bin/cp -nvp /etc/{passwd,group} /home/jail/etc/ ;
    cat > /home/jail/etc/profile < ~/.bash_history ;
    EOF
    chmod +x /home/jail/etc/profile ;
    
    # Install Apps
    mkdir -p /home/jail/bin ;
    mkdir -p /home/jail/lib64 ;
    app_paths=(
        "/bin/bash"
        "/bin/date"
        "/bin/ls"
        "/bin/mkdir"
        "/bin/rm"
        "/bin/cp"
        "/bin/mv"
        "/bin/cat"
        "/bin/unlink"
    );
    for app_path in "${app_paths[@]}"; do
        echo "App: $app_path" ;
        /bin/cp -nvp $app_path /home/jail/bin/ ;
        for lib_path in $(ldd $app_path | awk '{print $1}'); do
            echo "    Lib: $lib_path" ;
            if [ ! -f "/home/jail/lib64/$lib_path" ] && [ -f "$lib_path" ]; then
                /bin/cp -nvp $lib_path /home/jail/$lib_path ;
            fi
            if [ ! -f "/home/jail/lib64/$lib_path" ] && [ -f "/lib64/$lib_path" ]; then
                /bin/cp -nvp /lib64/$lib_path /home/jail/lib64/$lib_path ;
            fi
        done
    done
    
  4. Mauricio says:

    I followed your tutorial but I cannot connect with the user I chrooted. The error message is client_loop: send disconnect: Broken pipe.

    • Aaron Kili says:

      @Mauricio

      This could be bad ownership or modes for chroot directory. Ensure that the ssh user is allowed to access the chrooted directory. For this guide, we used the root account which can access any directory on the system.

  5. Riccardo says:

    To make SSH works, you should add urandom under dev, all libnss and nsswitch.conf:

    # mknod -m 0644 urandom c 1 9
    # cp -v /dev/libnss* /home/.../dev
    # cp -v /etc/nsswitch.conf /home/../etc
    
  6. Engel says:

    Hi there,

    I followed all steps in this article and works just fine, but I got a problem, I need that the jailed user runs certain commands as sudoer. In order to achieve that I edit /etc/sudoers but when I execute sudo in jailed session I got this error.

    sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set
    
  7. argmuy says:

    Excellent post! Please how can i use SSH client from jailed user to connect to to other server?

    I want to set up only one server whit ssh open port with a jailed user and from here can connect to others servers on my LAN.

    Thanks.

  8. zodiac says:

    Above commands should be accessible to the user when they SSH to the server. That is my requirement. But it isn’t working in this process. could you help to achieve that??

  9. Infrarchitect says:

    I have some issue making SFTP work at the same time.

    The answer is to have the following line in sshd_config :

    Subsystem sftp internal-sftp
    
  10. Alex says:

    AWESOME write-up. Combining this with AD is a huge step in maintaining good security controls that mitigate many risks inherent in FOSS. I’ve been doing this stuff for many years and always appreciate concise and accurate write-ups like these. For file servers things like getfacl, setfacl and id [email protected] come to mind…

Got something to say? Join the discussion.

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.