A QPKG file that creates the described configuration is attached to this post.
Requirements:
- You have installed and enabled Optware
- You are familiar with working from the command line
- You can edit text files on the system
A basic understanding of openSSH would help, too.
In the following text we assume the NAS is using a RAID configuration with the data in /share/MD0_DATA, if you have a single drive configuration or more than one volume and want to use a different volume then you have to replace MD0_DATA with the correct directory.
User configuration
In the web interface (Access Right Management->User Groups) we add two groups, one named ssh and the other sftponly.
Any user in the ssh group has shell access (and sftp access).
Any user in the sftponly group has only sftp access (in a chroot environment).
Assign users to the groups. Once again, be aware of the implications of enabling shell access to a user.
Install openssh
There are several different ways to install Optware's openssh and most of them replace the default ssh server. In this HOWTO we use a way that doesn't interfere with the default ssh server at all (also described as the "alternative way" in How To Replace SSH Daemon With OpenSSH). The benefit of this solution is that even if Optware would stop working for some reason we can still login using the default ssh server (remote replication jobs also continue to work when using a secure connection).
First we configure the default ssh server to run on a different port in the web interface (Network Services->Telnet/SSH)
Login as admin using the new port and install openSSH from the command line
Code: Select all
ipkg update
ipkg install openssh
Prepare directories
We create a new directory and corresponding subdirectories for the authorized keys (for optional public key authentication) and the chroot environment.
Code: Select all
/bin/mkdir -m 750 /share/MD0_DATA/openssh
/bin/chown admin:everyone /share/MD0_DATA/openssh
/bin/mkdir -m 710 /share/MD0_DATA/openssh/authorized_keys
/bin/chown admin:everyone /share/MD0_DATA/openssh/authorized_keys
/bin/mkdir -m 750 /share/MD0_DATA/openssh/sftpusers
/bin/chown admin:sftponly /share/MD0_DATA/openssh/sftpusers
Now, the chroot handling is very picky about the permission on all directories in the path and since we don't want to mess with the permissions on /share/MD0_DATA we create a new directory and bind mount /share/MD0_DATA/openssh to it. This directory must be re-created after a reboot and bind mounted again. We will automate that later.
Code: Select all
/bin/mkdir /openssh
/bin/mount --bind /share/MD0_DATA/openssh /openssh
For each user with sftp-only access we create a home directory in /openssh/sftpusers with restricted permissions only allowing the owner to access the directory (each user can relax that setting if they want to).
Code: Select all
for user in $(/bin/grep sftponly /etc/group | /bin/cut -d: -f4 | /bin/tr ',' ' '); do /bin/mkdir -m 700 /openssh/sftpusers/$user; /bin/chown $user:everyone /openssh/sftpusers/$user; done
When a new user is added to the sftponly group a home directory should also be created in /openssh/sftpusers.
Configure sshd
Open /opt/etc/openssh/sshd_config in your favourite editor (or do it on the desktop and then copy the modified file back to the NAS).
To simplify the chroot environment we must use sshd's internal sftp server. Locate the Subsystem option, comment it out and add the new option
Code: Select all
# override default of no subsystems
#Subsystem sftp /opt/libexec/sftp-server
Subsystem sftp internal-sftp
Last in the sshd_config file we add a Match block that is used to confine users in the sftponly group to the chroot environment
Code: Select all
Match Group sftponly
ForceCommand internal-sftp
ChrootDirectory /openssh/sftpusers
X11Forwarding no
AllowTcpForwarding no
This force the use of the internal sftp server, so that users in the sftponly group don't have the possibility to open a regular ssh session, assign users to the chroot environment in /openssh/sftpusers and prevent users from forwarding ports or starting remote X applications (the X11 forwarding is probably not required on a QNAP NAS, but it is included for completeness; if you ever attempt to implement a similar solution on a server running X11 it would be wise to prevent X11 forwarding)
To be able to use public key authentication for the sftp-only users we assign a new path to the public keys. Locate the AuthorizedKeysFile option (it should be commented out, but otherwise comment it out now) and add the new option
Code: Select all
#AuthorizedKeysFile .ssh/authorized_keys
AuthorizedKeysFile /openssh/authorized_keys/%u
This makes the server look for any public keys in a file with the same name as the user (%u is replaced with the username of the user being authenticated).
We also add a new option to only allow users in the ssh or sftponly groups to login.
Code: Select all
AllowGroups ssh sftponly
Save the file and exit the editor.
Now, we can test the new sshd configuration. Start a sshd process on an available port
Code: Select all
/opt/sbin/sshd -d -f /opt/etc/openssh/sshd_config -p 2222
and try to login from your desktop computer using a user with sftp-only access (on the given port).
If you have users with shell access you can try that, too, but you have to restart the sshd process, since it is a one-time only session.
If everything seems to be working you can start the openssh server and start using it.
Code: Select all
/opt/etc/init.d/S40sshd
Restore mount bind and start ssh server after reboot
To automatically create the /openssh directory, bind mount it to /share/MD0_DATA/openssh, and start the ssh server we can add the following to /etc/config/qpkg.conf (add it after the Optware section to make sure that Optware is up and running before our script runs)
Code: Select all
[openSSH]
Name = openSSH
Shell = /share/MD0_DATA/openssh/openssh.sh
and create this script in /share/MD0_DATA/openssh/openssh.sh
Code: Select all
#!/bin/sh
case "$1" in
start)
if [ -d /share/MD0_DATA/openssh ]; then
/bin/mkdir -p /openssh
/bin/mount --bind /share/MD0_DATA/openssh /openssh
fi
if [ -x /opt/etc/init.d/S40sshd ]; then
/opt/etc/init.d/S40sshd
fi
;;
stop)
umount /openssh
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
exit 0
Remember to make the script executable
Code: Select all
/bin/chmod +x /share/MD0_DATA/openssh/openssh.sh
Optional configuration
To get usernames and group names instead of uid values an etc directory could be created in /openssh/sftpusers and either unmodified copies of /etc/passwd and /etc/group could copied to the directory or they could be modified to only include admin and the sftponly users in the passwd file and administrators, everyone, and sftponly in the group file to not give away any information about what other users and groups exist on the system.
Code: Select all
/bin/mkdir -m 755 /openssh/sftpusers/etc
/bin/cp /etc/passwd /openssh/sftpusers/etc
/bin/cp /etc/group /openssh/sftpusers/etc
/bin/chmod 644 /openssh/sftpusers/etc/{group,passwd}
When new users are added to the sftponly group the passwd and group files should also be updated.
To give the users a way to exchange files with each other a tmp directory could be created that all users would have write access to, but they could only delete their own files (using the sticky bit). This directory should probably be cleaned regularly by admin.
Code: Select all
mkdir -m 1777 /openssh/sftpusers/tmp
To use public authentication for the sftp-only users and the shell access users, the user should generate the private and public key on their desktop and in some secure way send the public key to admin. The admin user can then add the public key in a file with the same name as the user and placed in the /openssh/authorized_keys/ directory. Set restricted permissions on the file.
Code: Select all
/bin/chown user:everyone /openssh/authorized_keys/user
/bin/chmod 600 /openssh/authorized_keys/user
Now, the user can login without using a password (apart from whatever passphrase they might have assigned to the private key).
If all users (both sftp-only and shell access) use public key authentication then it is also possible to set PasswordAuthentication to no in sshd_config to further increase the security of the system.
I have tested the steps in this HOWTO on a TS-239 and a TS-419P.
Any feedback or suggestions for improvements are welcome.
EDIT:
I rewrote the openssh init script (/opt/etc/init.d/S40sshd) like this
Code: Select all
#!/bin/sh
[ -e /opt/etc/default/openssh ] && . /opt/etc/default/openssh
case "$1" in
start)
if [ "$SSHD_ENABLE" = "no" ]; then
exit 1
fi
if [ -f /opt/var/run/sshd.pid ] ; then
echo "sshd already running"
exit 1
fi
umask 077
/opt/sbin/sshd
;;
stop)
if [ -f /opt/var/run/sshd.pid ] ; then
kill `cat /opt/var/run/sshd.pid`
else
if [ -n "$SSHD_NO_PID_KILLALL" ] ; then
killall $SSHD_NO_PID_KILLALL
else
killall /opt/sbin/sshd
fi
fi
rm -f /opt/var/run/sshd.pid
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
Now, when it is possible to start and stop the sshd using different commands I could update my own openssh script (/share/MD0_DATA/openssh/openssh.sh)
Code: Select all
#!/bin/sh
case "$1" in
start)
if [ -d /share/MD0_DATA/openssh ]; then
/bin/mkdir -p /openssh
/bin/mount --bind /share/MD0_DATA/openssh /openssh
fi
if [ -x /opt/etc/init.d/S40sshd ]; then
/opt/etc/init.d/S40sshd start
fi
;;
stop)
if [ -x /opt/etc/init.d/S40sshd ]; then
/opt/etc/init.d/S40sshd stop
fi
/bin/grep -q openssh /etc/mtab
if [ "$?" = "0" ]; then
/bin/umount /openssh
/bin/rmdir /openssh
fi
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
esac
exit 0
Add an Enable option to the qpkg.conf file and it is possible to enable/disable sshd and the sftp configuration using the QPKG interface.
Code: Select all
[openSSH]
Name = openSSH
Enable = TRUE
Shell = /share/MD0_DATA/openssh/openssh.sh
QPKG
Optware must be installed before installing this QPKG file. If the default ssh server uses port 22 then the installed openssh locates a free port (starting with 222). The port that is used by openssh is included in the system log (in the log entry about the successful installation/upgrade of the QPKG).
At installation the ssh and sftponly groups are created unless they already exist and the openssh directory is created on the same volume that Public is located on (usually /share/MD0_DATA/ on a RAID system and /share/HDA_DATA/ on a single-drive).
If the openssh ipkg package from Optware isn't installed then it is installed automatically. Backups of the current sshd_config and S40sshd script are created (and if they haven't been removed also restored when the QPKG is removed). New versions of sshd_config and S40sshd are installed to support the sftp in a chroot environment.
By default home directories are created for the users in the sftponly group when openSSH is enabled. It will not touch any existing directories so when new users have been added to the sftponly group then it is safe to toggle the openSSH setting (disable/enable) in the QPKG interface to create the directories. To stop creating home directories by default for new users in the sftponly group the CREATE_SFTP_DIRS variable in /etc/init.d/openssh can be set to FALSE.
When the QPKG package is removed then it, as mentioned above, restores the sshd_config file in /opt/etc/openssh, the S40sshd init-script in /opt/etc/init.d, and restarts the sshd daemon using the original configuration file. It won't remove the ssh and sftponly groups. Neither does it remove the directory with the user data nor the openssh ipkg package.
/Mike