I’m putting this here mainly to store it for myself, so these are going to be rough notes until I have time or inclination to review and edit this post.
Note: this solution was formulated on a server running Ubuntu Server 14.04 LTS
To setup sftp chroot directories for sftp-only users, and yet still log all actions & transfers like a “xferlog”, you need to somehow get the chrooted user to be allowed to write log data into the main syslog daemon.
First of all, you need the following in your sshd_config, and make certain to pay attention to the “ForceCommand” line, as I was missing that at first, and therefore, you are not changing the logging for the chroot users, just the non-chroot users:
Subsystem sftp internal-sftp -l VERBOSE -f LOCAL6
# Next section restricts users in sftpusers group to chrootDirectory
Match Group sftpusers
ForceCommand internal-sftp -u 002 -l VERBOSE -f LOCAL6
Now, you want to have a line like this in your
/etc/rsyslog.d/50-default.conf or other
/etc/rsyslog.d/*.conf file, in order to direct the sftp verbose logs to a specific file:
Then, you have a couple of options on how to proceed. The first way I got working was to add another listening socket in the rsyslogd config, with this line:
You could also use this method:
chmod 511 /home/username/dev
chattr +i /home/username/dev
mount --bind /dev/log /home/username/dev/log
Either one should work for you – the question is how you want to handle the situation, especially if you have either a large number of users, or a constantly changing user base; you’ll have to orchestrate either adding the special mount point and then having a lot of extra mounts, or adding a lot of extra listening socket files in rsyslogd. I leave it to you to decide which is better for your situation.
I also saw a method that didn’t work for me, but was for HP-UX, and might work for Solaris, too, over here: http://community.hpe.com/t5/Security/ssh-subsystem-internal-sftp-chroot-and-logging/td-p/5272802
Updated Thursday 31 August 2017 by David J. Pryke:
Following up on this, if you want certain information that is only available at the higher-verbosity log levels, such as INFO or VERBOSE, but those levels are too verbose, you can pipe the syslog output to a separate command that can filter certain things out of the stream that are very “chatty”, or filter the data stream down to only the exact info you want.
First, edit the syslog configuration line to pipe the output to a separate command:
local6.* |exec /usr/local/sbin/sftp-server-log-filter
Then create a script to filter in/out any data you want.
For example, to filter out lines that have the words “opendir” or “closedir” on them (since this can be voluminous in sftp-server’s logs on VERBOSE):
while read foo
echo $foo|/usr/bin/egrep -v "opendir|closedir" >> /var/log/sftp.log
Or to filter the output down to ONLY a few lines that are interesting with you, such as those that begin with “open “, “close “, and “session “, try:
while read foo
echo $foo|/usr/bin/egrep ".*\]: open |.*\]: close |.*\]: session " >> /var/log/sftp.log
Note that the regex patterns with “.*\]: ” are because these lines typically look like:
Aug 31 11:02:09 hostname sftp-server: session opened for local user username from [192.168.1.2]
Aug 31 11:02:24 hostname sftp-server: open "/usr/home/username/filename" flags READ mode 0666
Aug 31 11:02:24 hostname sftp-server: close "/usr/home/username/filename" bytes read 1147 written 0
Aug 31 11:02:27 hostname sftp-server: open "/usr/home/username/filename" flags WRITE,CREATE,TRUNCATE mode 0644
Aug 31 11:02:27 hostname sftp-server: close "/usr/home/username/filename" bytes read 0 written 1147
Aug 31 11:02:28 hostname sftp-server: session closed for local user username from [192.168.1.2]