Setting up a secure Linux server

Lock It

Article from Issue 183/2016

When you set up a new Linux server, take a few extra steps to ensure the system is truly secure.

I recently signed up for a cloud-based server system to replace my last co-located physical server, which had given up the ghost. The sign-up for the new system was painless, aside from the need to relinquish my precious credit card details, and within no more than a minute, I had a brand new Debian 8.1 "Jessie" server with a static IPv4 address.

It's relatively unusual for me to manually build boxes from scratch. However, because this Debian system is destined for service as a development server, I thought, for once, I'd take note of the steps I took to secure it.

The eclectic mixture of the following steps comprise a unique, personal-preference approach, but perhaps this summary will give you food for thought about how to secure your own servers. Start with these steps and add your own. Some of the settings you might be thinking about will be missing from this list (because the spectrum of possible security steps is simply too large to cover succinctly), but you might also find some ideas you hadn't considered.

This article shows what I did to set up a Debian Jessie server from scratch. The plan, as always, is to keep the number of packages to a minimum to help reduce security holes and reduce the need for ongoing package updates and maintenance. This article focuses on hardening a single Debian server system. Keep in mind that maintaining the overall security of your network requires many other steps, including maintaining security for routers, firewalls, intrusion prevention services, and much more.


Once I had changed my DNS to point at the static IP address proffered by the cloud host, I logged into the system over SSH and immediately changed the root password to one of my liking (and which hadn't arrived over email!). A simple suggestion to the cloud provider would be, procedurally speaking, only offering the initial root password from their web interface (which uses HTTPS). Email is horribly insecure, and we're talking about a fresh server installation that is supposed to be trusted for a long time to come. To their credit, the cloud provider does encourage users to create an SSH key immediately which is the safest way of accessing SSH as opposed to passwords.

Once I logged in as "root" user over SSH, I got to work. The superuser should never be able to log in remotely over SSH without a user of less privilege to let them in through the front door first, so I shuddered at the sight of the prompt initially. I'll deal with that soon.

The first command I ran was to check that my new ISP had provisioned the size of machine correctly. I checked the RAM specifically:

# free -m

See Figure 1 for an example of the free -m command. In my case, the command showed me under the top line of the column "used" that I had only used a remarkable 93MB of RAM to boot up my Debian instance without many running services (compare that to many, many more megabytes required by a fresh Windows installation).

Figure 1: Checking RAM memory with free -m.

Additionally, it showed me 401MB of free RAM under the "free" column, which meant I had been specified a tiny 512MB instance as expected. That's no problem for my needs when Linux is so fantastically efficient.

Next, I rapidly moved onto securing the box a little more to my liking. This next step was to shut down any services that exposed network ports to the Internet; initially, all I wanted open was my SSH server. To achieve this, I ran the following command:

# lsof -i | grep LISTEN

On the left-hand side, I saw service names (usually correlating to start/stop filenames in the /etc/init.d directory) and on the right-hand side the network ports which they had opened. Those ports are usually listed as "service names" translated by the file /etc/services from numbers to names.

I immediately spotted two services that weren't welcome (and potentially a security risk) and sought to shut them down. I figured out that /etc/init.d/rpcbind was responsible for the first service so, remembering that init was a thing of the past and this was a Systemd build, I promptly typed:

# systemctl stop rpcbind

followed by this command so rpcbind wouldn't start up again after a reboot:

# systemctl disable rpcbind

Then, having seen that another port was open, I eventually figured out that the Systemd startup service called nfs-common was responsible and disabled it also, simply replacing rpcbind with that service name in the preceding commands.

If you get stuck (e.g., because you're not using Debian Jessie's version of the lsof command but another distribution's) try tweaking the command below. It works for me on Jessie. The command searches for any listening services and outputs the name of the service along the user account responsible for spawning the service.

# lsof -i | grep LISTEN | awk '{print $1,$3}'
rpcbind rpc
master root
sshd root
httpd root
httpd apache

In addition to shutting off services, you might also want to use this command to experiment with changing services to more secure user accounts. With some trial and error, you can successfully switch some of these services to non-root user accounts, which can only be a good thing for increasing your security.


My next step was to move the SSH daemon sshd off the predictable port 22. Edit the file /etc/ssh/sshd_config carefully, uncommenting the top line shown in Figure 2 and changing 22 to a port number of your choice like 2222. This precaution will stop automated port 22 attacks from harassing your server.

Figure 2: In the sshd_config file, alter the top line to say port 2222 or similarly obscure port number after uncommenting the line by removing the hash or pound symbol.

You'll also want to prevent the root user from logging in as we mentioned. Set the PermitRootLogin parameter to no:

PermitRootLogin no

Next, I'll quickly create that less-privileged user that I mentioned, but first, I'll make sure only the users I want to have permission to log in remotely. I add a line to the SSH config file (at the top of the file to remind me that I've made these changes the next time I view the file):

AllowUsers lionel, luis, neymar

Only three users can SSH into the box now. I need to make I create these accounts before logging out or restarting the OpenSSH server or I will be locked out. With a few pertinent questions, I type:

# adduser lionel

Hardening the SSH config file further is for another day (but you should definitely do it and understand what you have changed). Restart sshd to make the changes live:

# systemctl restart ssh

To put my mind at rest, I'll do a quick check to ensure SSH is still allowing me to log in and peek at Systemd's syslog (by running journalctl -a and looking at the last few entries) for errors. I still need to become fully familiar with the freshly released Systemd errors, but I don't see anything in the file relating to the changes I've made, so I'm happy for now.

The next step is to open up /etc/hosts.allow and fiddle with TCP wrappers briefly by removing anything else that isn't commented and adding the IP addresses I connect from:


Now only three IP addresses can log in over SSH, and the user must be one of the triumvirate's user names configured previously, such as lionel. I then add the following line to hosts.deny:

sshd: ALL

And, as if by magic, I'm all set. Remember not to shut your initial login window until you've tested a fresh SSH login.

Command History

I always struggle with Ctrl-R to reverse search through the command history, so I prefer to enable Page-Up and Page-Down key functionality. This change is not security related, but it helps me zip through the command line much more efficiently.

Figure 3 shows the two lines in the file /etc/inputrc file I need to uncomment. I'll just wait for the next reboot to set it live; it's not urgent unless you've got loads of typing ahead.

Figure 3: Boost your typing speeds on the command line with Page-Up and Page-Down search capability.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Command Line: More Secure Passwords

    Even with encrypted drives, account passwords remain one of the prime security methods for any Linux system. With a little knowledge of the available commands and their options, you can make your account passwords more secure.

  • System Hardening

    A good reputation does not protect your Linux systems from attack. We'll show you some tips for detecting and warding off intruders.

  • Password Tools

    Create secure passwords with the help of a password generator and check for quality at the same time.

  • Strong Passwords

    Regular password changes are a thing of the past: Strong passwords for each individual service provide more protection. Charly pimped his Ubuntu accordingly with a suitable PAM module.

  • Charly's Column – pwquality

    Regular password changes are a thing of the past: Strong passwords for each individual service provide more protection. Charly pimped his Ubuntu accordingly with a suitable PAM module.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More