Introduction
In this tutorial, we will continue to learn about OpenBSD 6 by setting up a SSH server alongside a SFTP server. As most of you may know, SSH is essential for remote administration. Nowadays, more and more network administration is done remotely and it is more important than ever to properly configure and secure outward facing services. Additionally, we often need to transfer files, either for patches, reuse configuration files or install additional applications, especially if your OpenBSD server is not Internet-accessible. In a later post of this tutorial, we will use a specific form of port knocking to hide the presence of our services to background scans to prevent brute-force and dictionary attacks. However for now, we will setup our SSH and SFTP servers. A companion video is available on YouTube.
Overview
While OpenBSD makes it easy to enable SSH and SFTP, we will do some additional preparation for increased robustness. First we will create the appropriate users and groups and then we will install each of these services within their own chroot directory to limit damage should ever these services get compromised. Once that done, we’ll enable the SSH daemon, including the internal SFTP service, and make sure they are accessible and working properly. Once done, we will customize and harden their configuration. For the purpose of this post, we will assume that you have a fresh install of OpenBSD 6.1 as if you just finished the steps listed in this previous tutorial, i.e. SSHD was NOT enabled during installation.
Creating the Chroot Directories
While optional, enclosing your services in chroot, especially the one exposed to external hosts, is an excellent security practice. Ideally, they should even be on their own partition. To keep the scope of this post on SSH and SFTP, we will simply create a new tree node and setup our chroot containers from there:
1 2 |
mkdir -p /chroot/ssh mkdir /chroot/ftp |
We will then install the basic required files from the OpenBSD 6.1 CD to create our chroot. Within the SSH chroot:
# mount -t cd9660 /dev/cd0a /mnt
And unarchive the base packages unto our chroot:
1 2 3 |
# tar -xvzf /mnt/6.1/amd64/base61.tgz # tar -xvzf /mnt/6.1/amd64/comp61.tgz # tar -xvzf /mnt/6.1/amd64/man61.tgz |
In any chroot, we need the /dev directory to exist and populated with the required sub directory. Fortunately, OpenBSD makes it easy for us to do so using the MAKEDEV script:
1 2 |
# cd dev # ./MAKEDEV all |
Finally, we will link the shared libraries required by most programs with out chroot and enable our new sandbox:
1 |
# chroot /chroot/ssh ldconfig /usr/lib /usr/local/lib |
The chroot directory doesn’t require any special action since it doesn’t need to execute any program. The only thing left to do now is to set the ownership and permissions:
1 2 3 4 |
# chown root:wheel /chroot/ssh # chown root:wheel /chroot/ftp # chmod 755 /chroot/ssh # chmod 755 /chroot/ftp |
Creating the users and groups
This step is optional if you intent to have this server only for your own personal use or a very few selected people. However if you expect your user base to grow and have different permissions, having groups makes it so much easier to manage your server while ensuring tighter controls on permissions. We’ll create 2 groups: ssh-users and ftp-users. Within each of these groups, we will have a single user. We’ll create ssh-user for accessing the SSH service and ftp-user for accessing the SFTP service by using the useradd and groupadd commands:
1 2 3 4 5 6 7 8 9 10 11 12 |
# groupadd ssh-users # groupadd ftp-users # useradd -g ssh-users -d /chroot/ssh/home/ssh-user -m ssh-user # useradd -g ftp-users -d /chroot/ftp/ -m -s /sbin/nologin ftp-user # passwd ssh-user Changing password for ssh-user. New Password: Retype new password: # passwd ftp-user Changing password for ftp-user. New Password: Retype new password: |
While adding groups requires no explanation, it is important to note that ftp-user requires some specific parameters. Namely, the shell is set to /sbin/nologin. FTP are not required to use a shell and are limited to the FTP server, which is actually integrated into the SSH daemon.
Setting up SSHD
In many cases, sshd will have been enabled during installation and automatically starts at boot. If you are unsure, you can quickly verify if the sshd is running:
1 |
# ps -A | grep sshd |
If there’s no output, then the sshd is not started. Let’s quickly check that SSH works by first enabling and starting the service, and then testing it out. To enable the service, use the rcctl command:
1 |
# rcctl enable sshd |
Then start the daemon to actively listen for SSH connections:
1 2 |
# rcctl start sshd sshd(ok) |
And confirm that the SSH daemon is listening by using netstat:
1 2 3 |
# netstat -al | grep ssh tcp 0 0 *.ssh *.* LISTEN tcp6 0 0 *.ssh *.* LISTEN |
And now, lets try to connect to our SSH service using the IPv6 loopback interface using # ssh root@::1 . After entering your password, you should be greeted in your new shell.
Without much work, you already have a solid SSH server available within minutes with OpenBSD. However, let’s configure it further to our needs. We’ll stop the server for now:
1 |
# rcctl stop sshd |
First configuration items we will change is to disable remote root login and allow users part of the ssh-users group to access SSH. All configuration for the SSH and SFTP services are done thru the /etc/ssh/sshd_config file. Before editing it, you may want to make a backup to your /root directory. We will edit using the vi editor:
1 |
# vi /etc/ssh/sshd_config |
The first change we will make is to prevent the root account from using SSH. We’ll do this by setting the PermitRootLogin option to no. If the line is commented, uncommented it by deleting the ‘#‘:
1 |
PermitRootLogin no |
Next we’ll specify SSH to use our specially created chroot sandbox for any SSH connection by adding or setting the following property:
1 |
ChrootDirectory /chroot/ssh |
And the last thing for now, we’ll allow only users part of the ssh-users and ftp-users groups to use SSH by setting this line in our configuration file:
1 |
AllowGroups ssh-users ftp-users |
Save you configuration and let’s restart our SSH server using rcctl to confirm these basic settings:
1 2 |
# rcctl start sshd sshd(ok) |
First, we should not be allow to login as root anymore. If you try to login as root, you should get denied access:
1 2 3 4 5 6 7 8 |
# ssh root@::1 ssh root@::1 root@::1's password: Permission denied, please try again. root@::1's password: Permission denied, please try again. root@::1's password: Permission denied (publickey,password,keyboard-interactive). |
Excellent. Now let’s log as ssh-user and confirm we are in our chroot sandbox:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#ssh ssh-user@::1 The authenticity of host '::1' can't be established. ECDSA key fingerprint is SHA256:HlHcpYpsthqxY/oqge0Ecv98+yGzCDAkDKlAUGLhPYc. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.9.101' (ECDSA) to the list of known hosts. ssh-user@::1's password: Last login: Fri Jun 30 04:05:03 2017 from ::1 ksh: No controlling tty (open /dev/tty: No such file or directory) ksh: warning: won't have full job control $ pwd / $ ls altroot dev home root sys usr bin etc mnt sbin tmp var $ exit Connection to ::1 closed. |
Setting up the SFTP Server
Now that we have a basic SSH server running, we’ll configure the basic SFTP server as well. The SFTP server is provided through the SSH daemon and as such, is configured via the sshd_config file as well. This is because SFTP is actually the FTP protocol tunneled through the SSH protocol. As such, the sshd includes a FTP server within itself. To enable SFTP, we simply need to tell sshd to
1 2 3 4 |
Match Group ftp-users ForceCommand internal-sftp ChrootDirectory /chroot/ftp Banner none |
And ask sshd to use the internal-sftp subsystem by modifying the Subsystem sftp option to Subsystem sftp internal-sftp. Save the file again and restart the SSH server:
1 |
# rcctl restart sshd |
And let’s test our SFTP server.
1 2 3 4 |
# sftp ftp-user@::1 ftp_user@::1's password: Connected to ::1. sftp> |
You may run into a few issues here if something is misconfigured. To help you diagnosed the problem, consult the /var/log/authlog. For example, you encounter this rather cryptic error message when trying to connect to your ftp server: "Received message too long 1416128883" . This is often caused by the server producing an unexpected output message. In the context of OpenBSD. This may be caused by the banner send by default which is contained in /etc/motd, in which case you need to specify Banner none in sections relating to the SFTP server.
You may also get disconnected as soon as you attempt to reach your SFTP server, in which case you will get an error message stating:
1 2 |
ftp-user@::1's password: Permission denied, please try again. |
In which, you can check the log file to troubleshoot your problem
1 2 3 4 |
# tail -10 /var/log/authlog ... sshd[12399]: fatal: bad ownership or modes for chroot directory component "/chroot/ftp/" ... |
In this case, OpenBSD is complaining about the permissions set on the SFTP chroot directory. If they are too lax, sshd will simply refuse to allow connections to it. As such, make sure you have the appropriate directory permissions.
At this point, you have a server with SSH and SFTP enabled. You can be stop here if this configuration fills you needs, otherwise we can still customize furthermore the servers.
Additional Settings
For one thing, you may want to disable IPv4 if it’s not needed and allow only IPv6. In your sshd_config file, we will do so by setting the AddressFamily to inet6:
1 |
# AddressFamily inet6 |
Another useful customization depending on your line of work is to change the SSH port. In this case, we will change the port to 443, which is usually reserved for HTTPS connections. The reason for that is that if I need to reach back to my server from a network with connection restrictions, local connections to remote hosts via port 443 is usually allows. In other words, if a firewall is blocking outbound connections to port 22, establishing as SSH connections via port 443 will usually be allowed, unless there are protocol restrictions in place. In any case, we can change the port with:
1 |
Port 443 |
Depending on your level of paranoia, we can also tighten some controls relating to connectivity to mitigate brute-force or dictionary attacks:
1 2 3 4 |
MaxAuthTries 3 LoginGraceTime 60s ClientAliveCountMax 3 MaxStartups 5:60:10 |
The MaxStartups property is interesting and warrant further details. From the man page:
it specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection.
It allows for unauthenticated connections to be denied at random in order to mitigate noisy scanning or DDoS from the Internet. In the example above, we specified the value “5:60:10“, which means that if 5 unauthenticated connections are alive, further unauthenticated connections will be refused with a 60% probability. If 10 unauthenticated connections are established, all further attempts will be denied.
And to further ensure additional security controls, confirm that the following parameters are commented so that the defaults value be used:
1 2 3 4 5 6 |
# Protocol 2 # PermitEmptyPasswords no # StrictModes yes # UsePrivilegeSeparation yes # X11Forwarding no # IgnoreRhosts yes |
Authentication Modes
Another feature that you may want to customize based on your needs is how you or your users connect to the server. Three modes are usually considered to do so:
- PubkeyAuthentication: requires your client to provide a public key in order to connect to your SSH client. If you have a limited number of users which connects from the same location, this is probably the best option. However if you intent to connect to your SSH server from multiple hosts, you would have to bring your public key with you.
- PasswordAuthentication and ChallengeResponseAuthentication are very similar in practice. PasswordAuthentication request the client to provide a password via the SSH connection while the ChallengeResponseAuthentication can ask the client one or more question via a TTY. However in most cases, ChallengeResponseAuthentication is configured to ask a password and the only real difference is that the requesting client must type the password rather than providing it via the command line.
For example, the following command would not work with PasswordAuthentication set to “no” and ChallengeResponseAuthentication set to “yes“:
1 |
# echo $PASSWORD | ssh ssh-user@::1 |
That being said, there are ways to provide SSH password via the command line, such as using the sshpass package. There is therefore little difference between them. In this example, we configure these parameters as follow:
1 2 3 |
PubkeyAuthentication yes ChallengeResponseAuthentication no PasswordAuthentication no |
Hashing Known Hosts Files
When a client connects, the SSHD will store information about the client in the known_host file, which is located in ~/.ssh/. This file will contain the hostname of the client, its IP address and its key. This information is stored in plain text. An additional step to make the life of an intruder harder should your server get compromised is to obfuscated the data in this file be hashing its contents.
The listing above shows the contents of the file before hashing it. To tell SSHD to hash newly added data of the known_hosts file, we will add the following the HashKnownHosts line in ~/.ssh/config.
From now on, all data added will be hashed. Should you need to hash data already residing in this file, use the command below:
1 |
ssh-keygen -H -f ~/.ssh/known_hosts |
We now have a very solid SSH server. You still have to remain vigilant about new vulnerabilities that may pop up for SSHD or one of its component. In the second part of this series, we’ll cloak our SSH server using some form of port knocking. For now, let’s just tweak our SFTP server slightly. Before that, let’s restart our server.
Final Touch on the SFTP server
We previously set our FTP chroot readonly, but we might want to upload some files to it. If we try it right now, we’ll get the following error message:
1 2 3 4 |
sftp> put tcpdump6.pcap Uploading tcpdump6.pcap to /tcpdump6.pcap remote open("/tcpdump6.pcap"): Permission denied sftp> |
We’ll finish this tutorial by adding an upload directory and make it writable to the users of the ftp-users group:
1 2 3 |
mkdir /chroot/ftp/uploads chmod 775 /chroot/ftp/uploads chown root:ftp-users /chroot/ftp/uploads |
Conclusion
We’ll conclude this part of the tutorial for now. In this post, we detailed how to enable a SSH server on OpenBSD 6.1. We also enabled SFTP and securely configure each service to increase robustness. That being said, nothing is impossible and vulnerabilities may remain: keys can be stolen or confiscated, misconfiguration of other services may be present or malicious internal users may still abuse the system. If you’re a network admin, make sure logging is enabled and more importantly, that logs are analyze either via software or if you have time, manually. In the next part of this tutorial, we will enable a form of port knocking to hide our SSH service to scanning from external hosts. By doing so, we will prevent detection by roaming threats and prevent or at least greatly limit effectiveness of brute force and dictionary attacks against our server.
References
- “OpenSSH/Logging and Troubleshooting.” OpenSSH/Logging and Troubleshooting – Wikibooks, open books for an open world. Accessed July 01, 2017. https://en.wikibooks.org/wiki/OpenSSH/Logging_and_Troubleshooting.
- Pedersen, Karsten. “Creating a Chroot in OpenBSD.” Karsten Pedersen Blog. July 19, 2014. Accessed June 29, 2017. https://www.ibm.com/developerworks/community/blogs/karsten/entry/openbsd_chroot? lang=en.
- “SSH PasswordAuthentication vs ChallengeResponseAuthentication.” Blog甡nky Woo. September 14, 2013. Accessed June 29, 2017. https://blog.tankywoo.com/linux/2013/09/14/ssh-passwordauthentication-vs- challengeresponseauthentication.html.
- Cusack, F., and M. Forssen. ” Generic Message Exchange Authentication for the Secure Shell Protocol (SSH).” SSH, The Secure Shell: The Definitive Guide. January 2006. Accessed June 29, 2017. http://www.snailbook.com/docs/keyboard-interactive.txt.
- Maxwell, Doug. “Five Minutes to a More Secure SSH.” Unixlore.net – Linux and Unix Commandline tips, hacks and howtos. Accessed June 29, 2017. http://www.unixlore.net/articles/five-minutes-to-more-secure-ssh.html.
- Maxwell, Doug. “Five Minutes to an Even More Secure SSH” Unixlore.net – Linux and Unix Commandline tips, hacks and howtos. Accessed June 29, 2017. http://www.unixlore.net/articles/five-minutes-to-more-secure-ssh.html.
Additional Readings
- Lucas, Michael W. Absolute OpenBSD: UNIX for the Practical Paranoid. No Starch Press, 2013.
- Barrett, Daniel J., Richard E. Silverman, and Robert G. Byrnes. SSH, The Secure Shell: The Definitive Guide: The Definitive Guide. ” O’Reilly Media, Inc.”, 2005.
- Barrett, Daniel J. Linux Pocket Guide: Essential Commands. ” O’Reilly Media, Inc.”, 2016.