Chroot sftp using openssh and logging

Introduction

I have seen many posts on how to set up chroot jail’ed sftp using openssh, but few cover the logging aspects in detail. This tries to cover some of the issues and solutions.

SFTP

SFTP is ftp wrapped in a SSH secure environment. It is used to transfer files securely and is now used widely to transfer files between servers securely. Open SSH is the most common ssh implementation and includes all the required configuration logic to allow group based access control and chroot jail’ing of users.

Chroot Configuration

In this example I am going to set up a group of users that require SFTP access only (no SSH) and are going to copy files to a filesystem on a SFTP server. The location of the filesystem is going to be /sftp and users will reside in seperate folders under here.

Initially a new group should be created, here called “sftpuser”. Each user that requires SFTP access will be placed in this group.

The sshd_config (on debian in /etc/ssh) should be edited and the following added on the end:-

Match group sftpuser
 ChrootDirectory /sftp/%u
 X11Forwarding no
 AllowTcpForwarding no
 ForceCommand internal-sftp -l VERBOSE -f LOCAL6

This does the following:-

  1. Forces all users connecting via ssh on port 22 to have sftp only
  2. Runs their sftp session in a chroot jail in directory /sftp/$USER
  3. Prevents them TCP of X11 forwarding connections
  4. Runs the internal sftp server getting it to log verbose and to syslog channel name LOCAL6

Now a user should be created, without creating a home directory and in the default group sftpuser. On ubuntu you can enter:-

adduser --home / --gecos "First Test SFTP User" --group sftpuser --no-create-home --shell /bin/false testuser1

The reason the home directory is set to / is that the sftp will chroot to /sftp/testuser1. Next the users home directory will need creating:-

mkdir /sftp/testuser1
chmod 755 /sftp/testuser1
mkdir /sftp/tstuser1/in
mkdir /sftp/testuser1/out
chown testuser1 /sftp/testuse1/in

Note that the directory structure and permissions that you set may differ depending on your requirements. The users password should be set, and sshd restarted (on debian service ssh restart).

Now it should be possible to sftp files to the host using the command line sftp tool, but it should not be possible to ssh to the server as user testuser1.

Logging

You will see verbose sftp logging being produced in the /var/logmessages for each chroot’ed user, where by default this should go to the daemon.log. The reason for this is that the chroot’ed sftp process can not open /dev/log as this is not within the chrooted filesystem.

There are two fixes to this problem, depending on the filesystem configuration.

If the users sftp directory /sftp/user is on the root filesystem

You can create a hard link to mimic the device:-

mkdir /sftp/testuser1/dev
chmod 755 /sftp/testuser1/dev
ln /dev/log /sftp/testuser1/dev/log

If the users sftp directory is NOT on the root filesystem

First syslog or rsyslog will need use an additonal logging socket within the users filesystem. For my example /sftp is a seperate sftp filesystem.

For Redhat

On redhat syslog is used, so I altered /etc/sysconfif/syslog so that the line:-

SYSLOGD_OPTIONS="-m 0"

reads:-

SYSLOGD_OPTIONS="-m 0 -a /sftp/sftp.log.socket

Finally the syslog daemon needs to be told to log messages for LOCAL6 to the /var/log/sftp.log file, so the following was added to /etc/syslog.conf:-

# For SFTP logging
local6.*                        /var/log/sftp.log

and syslog was restarted.

For Ubuntu Lucid

On Ubuntu lucid I created /etc/rsyslog.d/sshd.conf containing:-

# Create an additional socket for some of the sshd chrooted users.
$AddUnixListenSocket /sftp/sftp.log.socket
# Log internal-sftp in a separate file
:programname, isequal, "internal-sftp" -/var/log/sftp.log
:programname, isequal, "internal-sftp" ~

… and restarted rsyslogd.

Creating log devices for users

Now for each user a /dev/log device needs creating:-

mkdir /sftp/testuser1/dev
chmod 755 /sftp/testuser1/dev
ln /sftp/sftp.log.socket /sftp/testuser1/dev/log

Log Rotation

TBD

Producing xfer logs

The format of the logging from openssh’es sftp server is a little cryptic. The perl script here can be used to produce an proftp like xfer log. Bigmite Software Solutions are experts in finding simple solutions to everyday problems.

Several people have said they had trouble running the script to produce Xfer logs. I’ll try to write a wrapper for ubuntu logroate and redhat later, but for now:-

Save script somewhere sensible and run “chmod +x createXferLog”, then to create a Xfer log from another log file simply type:-

createXferLog logfile > xfer.log

The file will be the syslog, or daemon log depending on system, the file with sshd logs in,

or

cat logfile | createXferLog > xfer.log

Author: admin

A research engineer in electronics engineering with over 20 years research and development experience. Specialist in software architechture and design.

8 thoughts on “Chroot sftp using openssh and logging”

  1. Hello,
    For the ubuntu version… this works until next restart: After that,

    rm /sftp/testuser1/dev/log
    ln /sftp/sftp.log.socket /sftp/testuser1/dev/log

    is needed to restore logging in /var/log/sftp.log

    As the inode for sftp.log.socket is made at rsyslogd restart, the link must be created again… If you have any solution to avoid this?!

  2. As a reference count is kept, I’ll have to create a script to recrete the link to the other files, which itself is a group of hard linked files!.

    Not so easy – I’ll look into this….

  3. As for logging, I don’t understand why you create a symbolic link when it works well without it (just working with $AddUnixListenSocket /chroot/testuser1/dev/log) but on this part I’m not quite sure because all my users are chrooted to the same path (no separate folder for each user).

    As for the logging format, first I don’t know what to do with your perl script :-/
    Unless it is supposed to be runned separately (or with a cron task), I don’t see how to embed it in the process.
    So I searched some way further and found that there is no need for such a script if its main purpose is to guess the year.

    Indeed it’s possible to change the time format in the logs :
    just go to “/etc/rsyslog.conf” and change the “$ActionFileDefaultTemplate” from “RSYSLOG_TraditionalFileFormat” to an other format (“RSYSLOG_FileFormat” for example which also add the time zone information).

    Still thank you for your tuto which was very useful.

  4. The design for your web site is a little bit off in Epiphany. Nevertheless I like your blog. I might have to use a “normal” web browser just to enjoy it.

  5. The choice not to alter the syslog format was interfere with other logging, as logwatch, or other things may be in place.

    The perl script was run on the logs to change them to common log file format, I wrapped this into a logrotate script, which also dthe compress a required.

    The hard link (not a sym link) allows the client FTP service which is chrooted to the users FTP directory to be able to log – yes each user has it’s own chrooted jail – hence we’d need a logger per user, and on the system in question this would exceed 500. When chrooted, the processes root file system is the users FTP directory, hence no /dev/log device exists. A hard link points directly to the inode, so allows a shared log device. The snag with sys log is it creates a new file on startup, so I added a script which following syslog start recreates all the users logger hardlinks. Oddly when syslog creates the new file, all the clients /dev/log files point to same file, which is not the syslog one.

    Since the ftp location is on a separate partition to /dev, syslog needed changing, if on the same this need not happen.

  6. How to use the createXferLog perl script.

    I just tried to run it as perl createXferLog. but nothing happend

Leave a Reply

Your email address will not be published.