Restrict SSH users with rSSH and lock them into a specific folder (CentOS 5.4)

Sometimes we have to give access to developers, but we don’t trust FTP protocol of it’s bad security. This is where rSSH comes in play. Most of the servers will have SSH enabled by default, so we can use this protocol (with some tweaks) to allow restricted SSH access to our server. We will jail to user only to his folder and we will mount everything that we need him to change in his folder also, so he will be able to interact only with allowed files and folders.

INSTALL rSSH:

# cd /tmp
# wget http://dag.wieers.com/rpm/packages/rssh/rssh-2.3.2-1.2.el5.rf.i386.rpm
# rpm -ivh rssh-2.3.2-1.2.el5.rf.i386.rpm
==================================================

Create the mkchroot.sh

#!/bin/sh
#####################################################################
# Mkchroot update for 32/64-bit RHEL Systems support by Luis Iafigliola.
# Dated 29th June 2010.

#####################################################################
#####################################################################
##
## mkchroot.sh - set up a chroot jail.
##
## This script is written to work for Red Hat 8/9 systems, but may work on
## other systems.  Or, it may not...  In fact, it may not work at all.  Use at
## your own risk.  🙂
##

fail() {

        echo "`basename $0`: fatal error" >&2
        echo "$1" >&2
        exit $2
}

#####################################################################
#
# Initialize - handle command-line args, and set up variables and such.
#
# $1 is the directory to make the root of the chroot jail (required)
# $2, if given, is the user who should own the jail (optional)
# $3, if given,  is the permissions on the directory (optional)
#

if [ -z "$1" ]; then
        echo "`basename $0`: error parsing command line" >&2
        echo "  You must specify a directory to use as the chroot jail." >&2
        exit 1
fi

jail_dir="$1"

if [ -n "$2" ]; then
        owner="$2"
fi

if [ -n "$3" ]; then
        perms="$3"
fi

if [ -n "$4" ]; then
        group="$4"
fi

# Check for 64-bit platform, will affect libraries location.

platform=`uname -a|grep x86_64`

if [ $? -eq 0 ]
then
   lib_dir="lib64"
else
   lib_dir="lib"
fi

echo "library support = $lib_dir"

#####################################################################
#
# build the jail
#

# now make the directory

if [ ! -d "$jail_dir" ]; then
        echo "Creating root jail directory."
        mkdir -p "$jail_dir"

        if [ $? -ne 0 ]; then
                echo "  `basename $0`: error creating jail directory." >&2
                echo "Check permissions on parent directory." >&2
                exit 2
        fi
fi

if [ -n "$owner" -a `whoami` = "root" ]; then
        echo "Setting owner of jail."
        chown "$owner" "$jail_dir"
        if [ $? -ne 0 ]; then
                echo "  `basename $0`: error changing owner of jail directory." >&2
                exit 3
         fi
else
        echo -e "NOT changing owner of root jail. \c"
        if [ `whoami` != "root" ]; then
                echo "You are not root."
        else
                echo
        fi
fi

if [ -n "$perms" -a `whoami` = "root" ]; then
        echo "Setting permissions of jail."
        chmod "$perms" "$jail_dir"
        if [ $? -ne 0 ]; then
                echo "  `basename $0`: error changing perms of jail directory." >&2
                exit 3
        fi
else
        echo -e "NOT changing perms of root jail. \c"
        if [ `whoami` != "root" ]; then
                echo "You are not root."
        else
                echo
        fi
fi

if [ -n "$group" -a `whoami` = "root" ]; then
        echo "Setting group of jail."
        chgrp "$group" "$jail_dir"
        if [ $? -ne 0 ]; then
                echo "   `basename $0`: error changing group of jail directory." >&2
                exit 3
        fi
fi

# copy SSH files

rsync_path="/usr/bin/rsync"
scp_path="/usr/bin/scp"
sftp_server_path="/usr/libexec/openssh/sftp-server"
rssh_path="/usr/bin/rssh"
chroot_helper_path="/usr/libexec/rssh_chroot_helper"

for jail_path in `dirname "$jail_dir$rsync_path"` `dirname "$jail_dir$scp_path"` `dirname "$jail_dir$sftp_server_path"` `dirname "$jail_dir$rssh_path"` `dirname "$jail_dir$chroot_helper_path"`; do

        echo "setting up $jail_path"

        if [ ! -d "$jail_path" ]; then
                mkdir -p "$jail_path" || \
                        fail "Error creating $jail_path. Exiting." 4
        fi

done

cp -p "$rsync_path" "$jail_dir$rsync_path" || \
        fail "Error copying $rsync_path. Exiting." 5
cp -p "$scp_path" "$jail_dir$scp_path" || \
        fail "Error copying $scp_path. Exiting." 5
cp -p "$sftp_server_path" "$jail_dir$sftp_server_path" || \
        fail "Error copying $sftp_server_path. Exiting." 5
cp -p "$rssh_path" "$jail_dir$rssh_path" || \
        fail "Error copying $rssh_path. Exiting." 5
cp -p "$chroot_helper_path" "$jail_dir$chroot_helper_path" || \
        fail "Error copying $chroot_helper_path. Exiting." 5

#####################################################################
#
# identify and copy libraries needed in the jail
#

for prog in $rsync_path $scp_path $sftp_server_path $rssh_path $chroot_helper_path; do
        echo "Copying libraries for $prog."
        libs=`ldd $prog | tr -s ' ' | cut -d' ' -f3|egrep -v ^'\('`
        echo "libs for $prog = $libs"
        for lib in $libs; do
           mkdir -p "$jail_dir$(dirname $lib)"
           echo -e "\t$lib"
           cp -p "$lib" "$jail_dir/$lib"
        done
done

echo "copying name service resolution libraries..."
tar -cf - /$lib_dir/libnss*_files* | tar -C "$jail_dir" -xvf - |sed 's/^/\t/'

#echo "copy /lib contents for dependencies..."
#tar -cf - /$lib_dir/* | tar -C "$jail_dir" -xvf - |sed 's/^/\t/'

cp -p /$lib_dir/ld-linux* $jail_dir/$lib_dir/
cp -p /$lib_dir/libcrypt* $jail_dir/$lib_dir/
cp -p /$lib_dir/libnss_compat* $jail_dir/$lib_dir/

#####################################################################
#
# copy config files for the dynamic linker, nsswitch.conf, and the passwd file
#

echo "Setting up /etc, /dev, /tmp in the chroot jail"

mkdir -p "$jail_dir/dev"
mkdir -p "$jail_dir/etc"

cp -a /dev/null "$jail_dir/dev/"
cp -pr /etc/ld.* "$jail_dir/etc/"

grep $owner /etc/passwd >> $jail_dir/etc/passwd
grep $group /etc/group >> $jail_dir/etc/group

echo -e "Chroot jail configuration completed."
echo -e "\nNOTE: if you are not using the passwd file for authentication,"
echo -e "you may need to copy some of the /lib/libnss_* files into the jail.\n"

#####################################################################
#
# For end user to dump files.
# Also helps to circumvent strange refresh problem.
# Occurs if user attempts to open non-readable directory above.
# Then if user refreshes jail session, they lose visibility.
# Workaround is to view tmp and then refresh does not do this.

#chmod g+w,o-r $jail_dir/tmp

# Base directories of chroot jail (/dev, /lib, /usr) not readable to others

chmod go-r $jail_dir/dev
chmod go-r $jail_dir/etc
chmod go-r $jail_dir/$lib_dir
chmod go-r $jail_dir/usr

#####################################################################
#
# set up /dev/log
#

echo -e "NOTE: you must MANUALLY edit your syslog rc script to start syslogd"
echo -e "with appropriate options to log to $jail_dir/dev/log.  In most cases,"
echo -e "you will need to start syslog as:\n"
echo -e "   /sbin/syslogd -a $jail_dir/dev/log\n"

echo -e "NOTE: we make no guarantee that ANY of this will work for you... \c"
echo -e "if it\ndoesn't, you're on your own.  Sorry!\n"

#####################################################################

Copy and save this as a mkchroot.sh
The script is modified to be used in CentOS 5.4

Create the user:

$ useradd {user name}

Set the password:

$ passwd {password for user}

Change the user group to be www-data:

$ usermod -g www-data {user name} 

Change the user shell to rssh:

$ chsh -s /usr/bin/rssh {user name} 
$ cd /users/

Create the jail, and change the group permissions”

$ ./mkchroot.sh /users/{user name} {user name} 2775 www-data 

Sometimes it will lose the permissions, so make sure it is executable:

$ sudo chmod u+s /usr/libexec/rssh_chroot_helper 

You have to create those first. We will make the structure exactly the same as /var/www/html to avoid any confusion:

$ cd /users/{user name}/var/www/html/ 
$ mkdir {name of the site to be shared} 

Mount the site to be shared with this user into his jail, so the user will have access to it:

$ mount --bind /var/www/html/{name of the site to be shared} {name of the site to be shared} 

Change the owner to the www-data group:

$ chown -R :www-data /var/www/html/{name of the site to be shared}/ 

Set the proper permissions, and make sure that all the new files will be owned by www-data:

$ chmod -R g+s /var/www/html/{name of the site to be shared}/ 

Make the owner to be www-data:

$ chgrp www-data /users/{user name}/{name of the site to be shared}/ 
$ chmod 2775 /users/{user name}/{name of the site to be shared}/ 

Set all the additional settings here:

$ nano /etc/rssh.conf 

==================================================
IMPORTANT: Before you delete the {name of the site to be shared} folder you HAVE to ‘umount’ it
like this: umount /users/{user name}/{name of the site to be shared}/
otherwise it will DELETE the original files also!

The same procedure should be followed for every new user.
All the users are locked to their folders, so they cannot see the any other files on the server.
In order to provide them with access to var/www we are mounting the folder they need to access
into their jail folder (/users/{user name}/{name of the site to be shared}/)

————————————————————————————
Disclaimer: I am not responsible for any problems, lost accounts and server problems you may encounter during this procedure. I use this method, and it is proven to work on my server. Do not attempt to do any of the things mentioned here if you are not sure what you are doing.

  3 comments for “Restrict SSH users with rSSH and lock them into a specific folder (CentOS 5.4)

  1. October 30, 2010 at 18:50

    Hey Andrey, just thought I’d let you know that I was having some strange errors with my chroot, but was able to set it up very quickly using your method on Centos 5.5. Only wish I found this sooner haha.
    Thanks for taking the time to post this.

  2. October 30, 2010 at 19:06

    What kind of errors did you have, Nate? Maybe it is CentOS 5.5 specific (since everything is working fine in 5.4)…

  3. April 15, 2011 at 04:36

    Спасибо, Андрей!
    Твои инструкции оказались очень кстати, Для меня (CentOS 5.6) они работают

Leave a Reply

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