Permitting SFTP file access while denying shell login

When you google on how to configure remote file access on linux most tutorials and how-tos will guide you towards ftp (file transer protocol) which has existed for ages and is well supported across all devices from mobile to desktop. However using FTP in these day and age without securing it using SSL is kind a naive. User credentials are sent over in clear-text and I don’t have to tell you that sooner or later the credentials will be compromised and your data might be at risk.

FTP similar to Telnet was never a protocol designed with security in mind. There are several solutions to FTP’s shortcomings. As mentioned, you can use FTP in combination with SSL or you can use SSH’s File Transfer Protocol SFTP for securily transferring data using the SSH network protocol.

In general, SSH is used for securely logging into a system remotely. By default, every user with SSH access automatically also has SFTP file access. The issue with simply adding a user to the system for SFTP access is that they also automatically receive shell-access. This grants them the right to run processes and potentially administer your system you may not wish them to run on your server. This tutorial will show you how to add a user to your system without granting them shell permissions but still allowing them file-access.

First, if you haven’t yet installed the openssh server yet, do so now (prepend every command with “sudo” if not logged-in as root):

[bash]
# apt-get install openssh-server
[/bash]

Once the ssh-server is installed we need to add a user we wish to only allow SFTP access. Add a new usegroup to consolidate multiple users that should only receive SFTP access:

[bash]
# addgroup sftponly
[/bash]

Next, edit the ssh-daemon configuration file: /etc/ssh/sshd_config (you can use vim or whaever editor you prefer)
Look for the following line:

[bash]
Subsystem sftp /usr/lib/openssh/sftp-server
[/bash]

and replace the line with this instruction (you can also simply comment out the above line using # and insert the following line below):

[bash]
Subsystem sftp internal-sftp
[/bash]

At the end of the same file add the following lines to restrict the access of the users bleonging to the sftponly user-group:

[bash]
# Rules for sftponly group
Match group sftponly
ChrootDirectory %h
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
[/bash]

Save the file and restart the ssh-daemon via:

[bash]
# /etc/init.d/ssh restart
[/bash]

Next, create the directory which the users will be jailed too:

[bash]
# mkdir /srv/sftponly/
[/bash]

Optionally you can use a mount-bind to map a specific filesystem into that folder. My share is located at /mnt/fs and I use mount-bind to map the shared-folder to sftponly:

[bash]
# mount –bind /mnt/fs /srv/sftponly/
[/bash]

Add a new user to the system and specify the previously created group as the user’s primary group. Disable shell-login and don’t create a home directory. See man-pages about adduser for more information about the available command-line switches:

[bash]
# adduser –home /srv/nfs4/fs/ –no-create-home –ingroup sftponly –disabled-login <username>
[/bash]

Set a password for the new user:

[bash]
# passwd <username>
[/bash]

In order for the user to be chrooted (jailed) to the specified directory the user’s home directory must be owned by root as well as only be writable by root:

[bash]
# chown root:root /srv/sftponly/
[/bash]

In case you are not able to log-in using the newly added user or even worse if the user is not getting jailed it’s best to check the auth.log in /var/log/auth.log

[bash]
Apr 20 12:34:04 fs sshd[12015]: Server listening on 0.0.0.0 port 22.
Apr 20 12:34:04 fs sshd[12015]: Server listening on :: port 22.
Apr 20 12:34:09 fs sshd[12018]: Accepted password for <username> from 10.1.1.185 port 54493 ssh2
Apr 20 12:34:09 fs sshd[12018]: pam_unix(sshd:session): session opened for user <username> by (uid=0)
Apr 20 12:34:09 fs sshd[12023]: fatal: bad ownership or modes for chroot directory "/srv/sftponly"
Apr 20 12:34:09 fs sshd[12018]: pam_unix(sshd:session): session closed for user<username>
Apr 20 12:34:25 fs sshd[12029]: Accepted password for <username> from 10.1.1.185 port 54494 ssh2
Apr 20 12:34:25 fs sshd[12029]: pam_unix(sshd:session): session opened for user username by (uid=0)
Apr 20 12:34:25 fs sshd[12037]: fatal: bad ownership or modes for chroot directory "/srv/sftponly"
Apr 20 12:34:25 fs sshd[12029]: pam_unix(sshd:session): session closed for user <username>
Apr 20 12:37:02 fs sshd[12076]: Accepted password for <username> from 10.1.1.185 port 54516 ssh2
Apr 20 12:37:02 fs sshd[12076]: pam_unix(sshd:session): session opened for user <username> by (uid=0)
Apr 20 12:37:02 fs sshd[12081]: fatal: bad ownership or modes for chroot directory "/srv/sftponly"
Apr 20 12:37:02 fs sshd[12076]: pam_unix(sshd:session): session closed for user <username>

[/bash]

In my case the specific user wasn’t getting jailed because the permissions on the root-folder were not correctly set. Make sure the home directory is owned by root and not the user itself.

Remove write permissions from others:

[bash]
# chmod go-w /srv/sftponly/
[/bash]

NFSv4 performance woes on Debian

Over the weekend I took the opportunity to reinstall the OS on my workstation at home. Instead of choosing Debian unstable I decided to go with Debian stable + backports this time. The reason is simply to not deal with package upgrades braking the current system again. Manually fixing my local gitlab installation after a ruby upgrade annoyed the hell out of me and I simply can’t be bothered with manually going through package management and pinning down a working version of ruby and ruby-gems just to keep my current setup working.

When I started to configure system services such as ssh, nfsv4, ftpd etc. I noticed that mounting NFSv4 shares on Debian 7 (Wheezy) was quite slow (around 11 to 15 seconds). Oddly enough, once the NFS share was mounted into my local filesystem I was able to copy files as quickly as usual.

I checked dmesg and /var/log/messages after mounting the NFS share and noticed the following entries:

[bash]
[17603.799651] Key type dns_resolver registered
[17603.804909] NFS: Registering the id_resolver key type
[17603.804918] Key type id_resolver registered
[17603.804918] Key type id_legacy registered
[17618.828292] RPC: AUTH_GSS upcall timed out.
[17618.828292] Please check user daemon is running.
[/bash]

According to the following thread, rpc-svcgssd is responsible for the nfs Kerberos authentication at the server side. I have no intention of using Kerberos at home as the time required for the set-up outweigh the benefits of single-sign-on for just a single user. I can simply set-up the same account with the same credentials on my computers. Therefore kerberos authentication should also be optional at the client side. Well it actually is, but the implementation at the moment is rather tedious. It waits for a timeout that occurs after roughly 15 seconds which introduces the delay when mounting a share.

On Redhat’s bugtracker the following entry was posted: Bug 1001934 – 15 sec timeout when mounting with nfs4:
Marcindulak provided the following workaround to fix the issue until the client is updated

blacklist the rpcsec_gss_krb5 module on the client and reboot or simply unload the kernel module

[bash]
echo "blacklist rpcsec_gss_krb5" > /etc/modprobe.d/blacklist-nfs-gss-krb5.conf
reboot
[/bash]

or instead of rebooting you can simply use rmmod to unload the currently loaded module:
[bash]
rmmod rpcsec_gss_krb5
[/bash]

This should eliminate the delay when mounting NFSv4 shares on Debian.

Unpacking OSX .PKG Files

It used to be that .PKG files were simply folders wrapped up as a bundle using a special “bundle” folder attribute which you could either right-click and use “Show Contents” or just cd into the .pkg files from the command line. For Mac applications that you drag and drop into the “/Applications” folder this is still the case.

However more recently, the format of the installation packages seems to have changed, making it more difficult into extracting the application from pkg file in case you are not interested in installing a pkg.
As an example I will extract the TeamViewer application from the PKG-File in the disc image that can be provided from Teamviewer’s Download Site

Unpacking the .PKG File

The .pkg file itself is an “xar” – archive, an archive format that is able to handle files of arbitrary large file size by storing the toc (“table of content”) at the beginning of the archive and thereby allowing for a efficient stream-like handling of the files within an archive.

First copy the .pkg file from the disk image into a temporary folder and unpack it using the xar cmd tool.
[bash]
chris@chris-rmbp:~/Downloads$ cp /Volumes/TeamViewer/Install\ TeamViewer.pkg ~/Downloads/_tmp/
chris@chris-rmbp:~/Downloads/_tmp$ xar -xf Install\ TeamViewer.pkg
chris@chris-rmbp:~/Downloads/_tmp$ ls -la
total 32336
drwxr-xr-x 11 chris staff 374B Feb 18 21:56 ./
drwx—r-x+ 155 chris staff 5.1K Feb 18 21:02 ../
-rw-r–r–@ 1 chris staff 6.0K Feb 18 21:56 .DS_Store
-rw-r–r– 1 chris staff 2.0K Feb 18 21:56 Distribution
drwx—— 5 chris staff 170B Jan 1 1970 Font.pkg/
-rw-r–r–@ 1 chris staff 16M Feb 18 21:48 Install TeamViewer.pkg
drwx—— 6 chris staff 204B Jan 1 1970 LauncherFull.pkg/
drwx—— 4 chris staff 136B Jan 1 1970 Resources/
drwx—— 6 chris staff 204B Jan 1 1970 TeamViewerApp.pkg/
chris@chris-rmbp:~/Downloads/_tmp$ cd TeamViewerApp.pkg/
chris@chris-rmbp:~/Downloads/_tmp/TeamViewerApp.pkg$ ls -la
total 32632
drwx—— 6 chris staff 204B Jan 1 1970 ./
drwxr-xr-x 11 chris staff 374B Feb 18 21:56 ../
-rw-r–r– 1 chris staff 262K Feb 5 15:20 Bom
-rw-r–r– 1 chris staff 795B Feb 18 21:56 PackageInfo
-rw-r–r– 1 chris staff 16M Feb 5 15:20 Payload
-rw-r–r– 1 chris staff 542B Feb 5 15:20 Scripts
chris@chris-rmbp:~/Downloads/_tmp/TeamViewerApp.pkg$
[/bash]

Simply judging by the size you can tell that Payload must contain the application we are interested in. The Payload itself is a cpio archive compressed with gzip. The file can be extracted using the cpio archiver after piping it through gzip:

[bash]
chris@chris-rmbp:~/Downloads/_tmp/TeamViewerApp.pkg$ cat Payload | gzip -d – | cpio -id
93074 blocks
chris@chris-rmbp:~/Downloads/_tmp/TeamViewerApp.pkg$ ls -la
total 32632
drwxr-xr-x 7 chris staff 238B Feb 18 22:08 ./
drwxr-xr-x 11 chris staff 374B Feb 18 21:56 ../
-rw-r–r– 1 chris staff 262K Feb 5 15:20 Bom
-rw-r–r– 1 chris staff 795B Feb 18 21:56 PackageInfo
-rw-r–r– 1 chris staff 16M Feb 5 15:20 Payload
-rw-r–r– 1 chris staff 542B Feb 5 15:20 Scripts
drwxr-xr-x 3 chris staff 102B Feb 18 22:08 TeamViewer.app/
chris@chris-rmbp:~/Downloads/_tmp/TeamViewerApp.pkg$
[/bash]
In case new folders and files appear such as usr, private folders they contain the files and folders that would be installed relative to the root directory of the hard drive when the installer would be run normally.
In this case the only interesting file is the TeamViewer.app that contains the TeamViewer application which you can drag and drop this file to the /Application folder without having to install the launchagents that automatically start TeamViewer on login.

Silent Install of OSX Applications

Applications that are provided in an .pkg or .mpkg application bundle format can be installed silently in the background even while a user is currently logged into the system without him noticing. (.mpkg bundles are more customizable compared to their pkg. counterpart)

To Run the package installer in silent mode without showing the GUI-user-dialog the installer needs to be run from command line:

[bash]sudo -S installer -verbose -pkg your_installer_file.pkg -target /[/bash]

Target indicates the destination volume the package is going to be installed. The installer will run without showing the installer in the ui. You will have to enter your systems – administrator password in case the installer needs root permissions to copy various configuration files.
It’s possible (but not recommended) to fully automate the process with the command line by echoing the password

[bash]echo password | sudo -S installer -verbose -pkg your_installer_file.pkg -target /[/bash]

Attention: Your password will be stored in the bash_history in cleartext, therefore I DON’T  recommend it.