≡ Menu

redhat chroot

How to: Restrict Users to SCP and SFTP and Block SSH Shell Access with rssh

FTP is insecure protocol, but file-transfer is required all time. You can use OpenSSH Server to transfer file using SCP and SFTP (secure ftp) without setting up an FTP server. However, this feature also grants ssh shell access to a user. Basically OpenSSH requires a valid shell. Here is how sftp works:

SCP/SFTP -> SSHD -> Call sftpd subsystem -> Requires a shell -> User can login to server and run other commands.

In this article series we will help you provide secure restricted file-transfer services to your users without resorting to FTP. It also covers chroot jail setup instructions to lock down users to their own home directories (allow users to transfer files but not browse the entire Linux / UNIX file system of the server) as well as per user configurations.

rssh ~ a restricted shell

rssh is a restricted shell for use with OpenSSH, allowing only scp and/or sftp. It now also includes support for rdist, rsync, and cvs. For example, if you have a server which you only want to allow users to copy files off of via scp, without providing shell access, you can use rssh to do that.

Supported operations using rssh

Restricted shell only allows following operations only:

  • scp - Secure file copy
  • sftp - Secure FTP
  • cvs - Concurrent Versions System ~ you can easily retrieve old versions to see exactly which change caused the bug
  • rsync - Backup and sync file system
  • rdist - Backup / RDist program maintains identical copies of files on multiple hosts.

Install rssh

CentOS / Fedora / RHEL Linux rssh installation

Visit Dag's repo to grab rssh package
# 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

Debian / Ubuntu Linux rssh installation

Use apt-get command:
$ sudo apt-get install rssh

FreeBSD installation

# cd /usr/ports/shells/rssh
# make install clean

Make sure you build binary with rsync support.

rssh configuration file

  • Default configuration file is located at /etc/rssh.conf (FreeBSD - /usr/local/etc/rssh.conf)
  • Default rssh binary location /usr/bin/rssh (FreeBSD - /usr/local/bin/rssh)
  • Default port none - ( openssh 22 port used - rssh is shell with security features)

rssh: Per User Configuration Options For Chroot Jail

rssh is a restricted shell for providing limited access to a host via ssh. It also allows system wide configuration and per user configuration. From the man page:
The user configuration directive allows for the configuration of options on a per-user basis. THIS KEYWORD OVERRIDES ALL OTHER KEYWORDS FOR THE SPECIFIED USER. That is, if you use a user keyword for user foo, then foo will use only the settings in that user line, and not any of the settings set with the keywords above. The user keyword’s argument consists of a group of fields separated by a colon (:), as shown below. The fields are, in order:

  • username : The username of the user for whom the entry provides options
  • umask : The umask for this user, in octal, just as it would be specified to the shell access bits. Five binary digits, which indicate whether the user is allowed to use rsync, rdist, cvs, sftp, and scp, in that order. One means the command is allowed, zero means it is not.
  • path : The directory to which this user should be chrooted (this is not a command, it is a directory name).

rssh examples of configuring per-user options

Open /etc/rssh.conf file:
# vi /etc/rssh.conf
All user tom to bypass our chroot jail:
Provide jerry cvs access with no chroot:
Provide spike rsync access with no chroot:
Provide tyke access with chroot jail located at /users
user="tyke:011:00001:/users" # whole user string can be quoted
if your chroot_path contains spaces, it must be quoted. Provide nibbles scp access with chroot directory:
user=nibbles:011:00001:"/usr/local/tv/shows/tom and jerry"

Recommended readings:

=> rssh home page
=> Redhat specific chroot jail script (outdated)
=> Refer man pages: rssh.conf, rssh, ssh, sshd, sftp, scp, rsync, sshd_config

Linux Configure rssh Chroot Jail To Lock Users To Their Home Directories Only

rssh support chrooting option. If you want to chroot users, use chrootpath option. It is used to set the directory where the root of the chroot jail will be located. This is a security feature.

A chroot on Linux or Unix OS is an operation that changes the root directory. It affects only the current process and its children. If your default home directory is /home/vivek normal user can access files in /etc, /sbin or /bin directory. This allows an attacker to install programs / backdoor via your web server in /tmp. chroot allows to restrict file system access and locks down user to their own directory.

Configuring rssh chroot

=> Chroot directory: /users.
Tip: If possible mount /users filesystem with the noexec/nosuid option to improve security.

=> Required directories in jail:

  • /users/dev - Device file
  • /users/etc - Configuration file such as passwd
  • /users/lib - Shared libs
  • /users/usr - rssh and other binaries
  • /users/bin - Copy default shell such as /bin/csh or /bin/bash

=> Required files in jail at /users directory (default for RHEL / CentOS / Debian Linux):

  • /etc/ld.so.cache
  • /etc/ld.so.cache.d/*
  • /etc/ld.so.conf
  • /etc/nsswitch.conf
  • /etc/passwd
  • /etc/group
  • /etc/hosts
  • /etc/resolv.conf
  • /usr/bin/scp
  • /usr/bin/rssh
  • /usr/bin/sftp
  • /usr/libexec/openssh/sftp-server OR /usr/lib/openssh/sftp-server
  • /usr/libexec/rssh_chroot_helper OR /usr/lib/rssh/rssh_chroot_helper (suid must be set on this binary)
  • /bin/sh or /bin/bash (default shell)

Tip: Limit the binaries which live in the jail to the absolute minimum required to improve security. Usually /bin/bash and /bin/sh is not required but some system may give out error.

A note about jail file system

Note: The files need to be placed in the jail directory (such as /users) in directories that mimic their placement in the root (/) file system. So you need to copy all required files. For example, /usr/bin/rssh is located on / file system. If your jail is located at /users, then copy /usr/bin/rssh to /users/usr/bin/rssh. Following instuctions are tested on:

  • FreeBSD
  • Solaris UNIX
  • RHEL / Redhat / Fedora / CentOS Linux
  • Debian Linux

Building the Chrooted Jail

Create all required directories:
# mkdir -p /users/{dev,etc,lib,usr,bin}
# mkdir -p /users/usr/bin
# mkdir -p /users/libexec/openssh

Create /users/dev/null:
# mknod -m 666 /users/dev/null c 1 3
Copy required /etc/ configuration files, as described above to your jail directory /users/etc:
# cd /users/etc
# cp /etc/ld.so.cache .
# cp -avr /etc/ld.so.cache.d/ .
# cp /etc/ld.so.conf .
# cp /etc/nsswitch.conf .
# cp /etc/passwd .
# cp /etc/group .
# cp /etc/hosts .
# cp /etc/resolv.conf .

Open /usres/group and /users/passwd file and remove root and all other accounts.

Copy required binary files, as described above to your jail directory /users/bin and other locations:
# cd /users/usr/bin
# cp /usr/bin/scp .
# cp /usr/bin/rssh .
# cp /usr/bin/sftp .
# cd /users/usr/libexec/openssh/
# cp /usr/libexec/openssh/sftp-server .

# cp /usr/lib/openssh/sftp-server .
# cd /users/usr/libexec/
# cp /usr/libexec/rssh_chroot_helper

# cp /usr/lib/rssh/rssh_chroot_helper
# cd /users/bin/
# cp /bin/sh .

# cp /bin/bash .

Copy all shared library files

The library files that any of these binary files need can be found by using the ldd / strace command. For example, running ldd against /usr/bin/sftp provides the following output:
ldd /usr/bin/sftp

     linux-gate.so.1 =>  (0x00456000)
        libresolv.so.2 => /lib/libresolv.so.2 (0x0050e000)
        libcrypto.so.6 => /lib/libcrypto.so.6 (0x0013e000)
        libutil.so.1 => /lib/libutil.so.1 (0x008ba000)
        libz.so.1 => /usr/lib/libz.so.1 (0x00110000)
        libnsl.so.1 => /lib/libnsl.so.1 (0x0080e000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0x00a8c000)
        libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00656000)
        libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x00271000)
        libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x00304000)
        libcom_err.so.2 => /lib/libcom_err.so.2 (0x00777000)
        libdl.so.2 => /lib/libdl.so.2 (0x00123000)
        libnss3.so => /usr/lib/libnss3.so (0x00569000)
        libc.so.6 => /lib/libc.so.6 (0x00b6c000)
        libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0x00127000)
        libkeyutils.so.1 => /lib/libkeyutils.so.1 (0x00130000)
        /lib/ld-linux.so.2 (0x00525000)
        libplc4.so => /usr/lib/libplc4.so (0x008c9000)
        libplds4.so => /usr/lib/libplds4.so (0x00133000)
        libnspr4.so => /usr/lib/libnspr4.so (0x00d04000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x0032a000)
        libselinux.so.1 => /lib/libselinux.so.1 (0x00341000)
        libsepol.so.1 => /lib/libsepol.so.1 (0x00964000)

You need to copy all those libraries to /lib and other appropriate location. However, I recommend using my automated script called l2chroot:
# cd /sbin
# wget -O l2chroot http://www.cyberciti.biz/files/lighttpd/l2chroot.txt
# chmod +x l2chroot

Open l2chroot and set BASE variable to point to chroot directory (jail) location:
Now copy all shared library files
# l2chroot /usr/bin/scp
# l2chroot /usr/bin/rssh
# l2chroot /usr/bin/sftp
# l2chroot /usr/libexec/openssh/sftp-server

# l2chroot /usr/lib/openssh/sftp-server
# l2chroot /usr/libexec/rssh_chroot_helper

# l2chroot /usr/lib/rssh/rssh_chroot_helper
# l2chroot /bin/sh

# l2chroot /bin/bash

Modify syslogd configuration

The syslog library function works by writing messages into a FIFO file such as /dev/log. You need to pass -a /path/to/chroot/dev/log option. Using this argument you can specify additional sockets from that syslogd has to listen to. This is needed if you’re going to let some daemon run within a chroot() environment. You can use up to 19 additional sockets. If your environment needs even more, you have to increase the symbol MAXFUNIX within the syslogd.c source file. Open /etc/sysconfig/syslog file:
# vi /etc/sysconfig/syslog
Find line that read as follows:
Append -a /users/dev/log
SYSLOGD_OPTIONS="-m 0 -a /users/dev/log"
Save and close the file. Restart syslog:
# /etc/init.d/syslog restart
If you are using Debian / Ubuntu Linux apply changes to /etc/default/syslogd file.

Set chroot path

Open configuration file /etc/rssh.conf:
# vi /etc/rssh.conf
Set chrootpath to /users
Save and close the file. If sshd is not running start it:
# /etc/init.d/sshd start

Add user to jail

As explained eariler, configure rssh user account. For example, add user vivek in chrooted jail with the following command:
# useradd -m -d /users/vivek -s /usr/bin/rssh vivek
# passwd vivek

Now vivek can login using sftp or copy files using scp:

sftp vivek@my-server.com
vivek@my-server.com's password:
sftp> ls
sftp> pwd
Remote working directory: /vivek
sftp> cd /tmp
Couldn't canonicalise: No such file or directory

User vivek is allowed to login to server to trasfer files, but not allowed to browse entier file system.

CentOS / Redhat Enterprise Linux Setup Lighttpd in Chroot Jail

Many people asked me to write about setting up Lighttpd under CentOS or RHEL 5 Linux using chroot() call. The instructions are almost same but you need to make little modification as compare to Debian / Ubuntu Linux instructions.

For example purpose we will build jail at /webroot location.
=> Default document root : /home/lighttpd/default/
=> Port : 80
=> IP: Your Public IP address
=> Virtual domain1: /home/lighttpd/vdomain1.com/
=> Virtual domain1 access log file: /var/log/lighttpd/vomain1.com/
=> Default access log file:/var/log/lighttpd/access.log
=> Default error log file:/var/log/lighttpd/error.log
=> Default php error log file: /var/log/lighttpd/php.log


These installation instructions assume you have:

  • Linux distribution
  • Required RPMs (see below for installation instructions)
    • php, php-pear, php-common, php-pdo, php-ldap, php-gd, php-cli, php-mysql
    • mysql, mysql-server etc
    • lighttpd, lighttpd-fastcgi (rpm available here)
  • Installations were tested on Red Hat Enterprise Linux v4/5 or CentOS v4/5 or Fedora Linux 7

Step # 1: Install required packages

Install php and related packages:
# yum install php php-pear php-common php-pdo php-ldap php-gd php-cli php-mysql
Install mysql and related packages:
# yum install mysql mysql-server
Install lighttpd and mod_fastcgi for lighttpd:
# rpm -ivh http://dag.wieers.com/rpm/packages/lighttpd/lighttpd-1.4.18-1.el5.rf.i386.rpm
# rpm -ivh http://dag.wieers.com/rpm/packages/lighttpd/lighttpd-fastcgi-1.4.18-1.el5.rf.i386.rpm

Step # 2: Create /webroot and related directories

# mkdir /webroot
# cd /webroot
# mkdir etc
# mkdir tmp
# chmod 1777 tmp/
# mkdir -p usr/bin
# mkdir -p home/lighttpd/default
# mkdir -p var/run/lighttpd
# mkdir -p var/log/lighttpd
# chown lighttpd:lighttpd var/run/lighttpd/
# chown lighttpd:lighttpd var/log/lighttpd/
# chown -R lighttpd:lighttpd home/

Step # 3: Install chroot script

You need to download and install my script that will help you to build lighttpd in jail:
# cd /sbin/
# wget http://www.cyberciti.biz/files/lighttpd/l2chroot.txt
# mv l2chroot.txt l2chroot
# chmod +x l2chroot

Step # 4: Install php in jail

Now copy php-cgi binary and related shared libraries using l2chroot script:
# cd /webroot/usr/bin
# cp /usr/bin/php-cgi .
# l2chroot php-cgi

Step # 5: Copy required files to /etc

Now you must copy php.ini and related all files to /etc/
# cd /webroot/etc
# cp /etc/passwd .
# cp /etc/group .
# cp /etc/hosts .
# cp /etc/nsswitch.conf .
# cp /etc/resolv.conf .
# cp /etc/php.ini .
# cp -avr /etc/php.d/ .
# cp -avr /etc/ld* .

Update (Oct-1-2008, 1:52pm) : You need to copy entire /etc/ and /usr/share/zoneinfo files to work with latest php version:
# cd /webroot/etc
# /bin/cp -avr /etc/* .

Copy all files from /usr/share/zoneinfo/:
# mkdir -p /webroot/usr/share/
# cd /webroot/usr/share/
# cp -avr /usr/share/zoneinfo/ .

Open group and passwd file and only keep entries for root and lighttpd user:
# vi /webroot/etc/group
Make sure file look as follows:

Also open passwd file inside jail:
# vi /webroot/etc/passwd
Make sure file look as follows:
lighttpd:x:100:101:lighttpd web server:/srv/www/lighttpd:/sbin/nologin

Step # 5: Copy php modules

Now copy php mysql support, php gd and other all modules:
# cd /webroot/usr/lib/
# cp -avr /usr/lib/php/ .
# cd php/modules
# for l in *.so; do l2chroot $l; done

Step # 6: Configure lighttpd chroot call

Open /etc/lighttpd/lighttpd.conf file:
# vi /etc/lighttpd/lighttpd.conf
Setup default document root and chroot directory:
server.document-root = "/home/lighttpd/default/"

Save and close the file.

Step # 7: Restart lighttpd

Type the following command:
# /etc/init.d/lighttpd restart

Jail size

# du -ch /webroot/

12K     /webroot/var/log/lighttpd
16K     /webroot/var/log
4.0K    /webroot/var/run/lighttpd
8.0K    /webroot/var/run
28K     /webroot/var
8.0K    /webroot/etc/ld.so.conf.d
36K     /webroot/etc/php.d
160K    /webroot/etc
8.0K    /webroot/home/lighttpd/default
12K     /webroot/home/lighttpd
16K     /webroot/home
5.3M    /webroot/lib
4.0K    /webroot/tmp
872K    /webroot/usr/lib/sse2
1.4M    /webroot/usr/lib/mysql
676K    /webroot/usr/lib/php/modules
4.0K    /webroot/usr/lib/php/pear
684K    /webroot/usr/lib/php
9.9M    /webroot/usr/lib
2.9M    /webroot/usr/bin
13M     /webroot/usr
19M     /webroot/
19M     total


Always go thought /var/log/messages and server log files:
# tail -f /var/log/messages

Download mysql testing script

Copy and test php mysql connectivity with this script.