Basics of securing a Linux server

One of the most important jobs that someone who calls themselves a “System Administrator” has is securing their servers. Whether it’s a personal server you are tinkering with, or a production server at work somewhere, keeping a server secure is paramount for many reasons, not just keeping your data safe. If your server were to get compromised, depending on what happened, it could be used as a zombie to target other machines in a massive DDoS attack. It might be used to send yet more spam out to the users of the world, or it could even be setup as a platform to launch more viruses and attacks against unsuspecting users all over the Internet.

The point is that there are a great many reasons to keep your server secure, and I don’t think there is anyone out there who would disagree. That being said, I have written up some basic steps that I go through to begin the process of securing my Linux boxes, thus hoping you can use it to help you secure yours. I decided to start with Linux because many people are testing and playing with it since it is very powerful and free. These are guidelines, as well as examples of how I do it. It’s too simple to say that there are better or worse ways of doing things. Read what I have below here and apply it to your situation, lots of things in this article can even be applied to Windows, as they are good practices regardless of the OS. Let’s get started shall we?

Basic steps to securing your server

After the initial install (RedHat Enterprise 4, CentOS 4, and probably most Fedora Core releases will apply for the examples), there are a few things that you really should do to bump up the security posture of the server. Here I will go over some basic things that I do. There are always other things you can do, and you can get more and more detailed, but this addressing of the basics will cover a great majority of threats out there, and is at the very least a good place to start.

Configure/enable TCP_WRAPPERS

I am sure you have at least heard of TCP_WRAPPERS, it is a piece of software that allows you to “wrap” TCP services with an extra layer of security. This will effectively allow you to choose who can and cannot connect to those services, kind of like a firewall in that you can allow or block by IP, subnet, hostname, etc. You configure what to deny and what to allow in two files, appropriately named hosts.allow and hosts.deny.

The rule of thumb when setting this up, is basically the same as when I build a firewall, which is deny all, permit by exception. This means that by default, everything coming in gets denied. Period. Then, we only let in what we want which is the secure way to do things. If we were to do the opposite, then we would let everything in, and try to block the bad stuff. The problem is that we would have to know about it before we can block it. It makes much more sense to deny all first, and then only allow what we absolutely need.

Therefore, the first thing we want to do is to deny all, so edit the file /etc/hosts.deny and add ALL: ALL to it, this should be the only thing in the file aside from comments.

Example:

#
# hosts.deny This file describes the names of the hosts which are
# *not* allowed to use the local INET services, as decided
# by the '/usr/sbin/tcpd' server.
#
# The portmap line is redundant, but it is left to remind you that
# the new secure portmap uses hosts.deny and hosts.allow. In particular
# you should know that NFS uses portmap!
ALL: ALL

After you do this, be sure to put something in the /etc/hosts.allow file so you can get back into your server, like with SSH or anything else. You can put blanket allowances in, like we did with the denial, but you may want to break it out by the actual service. For example, you can allow sendmail to many if needed, but restrict SSH to only a particular network. Entries can be made in the form of a single IP, or a network or hostname.

For example, to add a single IP SSH access, it would be:
sshd: 10.10.10.10

To allow the whole 10.10.10.x network, it would be:
sshd: 10.10.10. <= note the trailing period

The same applies for hostnames, to allow a single host it would be:
sshd: myserver.domain.com

To allow all hosts under a given domain it would be:
sshd: .domain.com <= note the leading period

Some common service phrases are as follows, and you should be able to put anything in here that is a common tcp service name:
in.ftpd = ftp daemon
sendmail = sendmail mail server
sshd = SSH server
ALL = Just like it says

Turn off un-needed services

If it’s available, you can use the command /sbin/ntsysv to easily and quickly turn on and off services. One thing to note here is that from what I have seen, the ntsysv command is a RedHat specific tool and even then has not been included in newer releases of the operating system and it’s derivatives (this includes RedHat, Fedora, CentOS). Therefore, if you are using a distribution without the handy dandy ntsysv, or if you simply prefer to, you can use the chkconfig command to manage services.

In this case, I want to turn off anything that I don’t need, so the only thing I leave turned on to start with is the following:

autofs
cpuspeed
crond
gpm
haldaemon
iptables
irqbalance
messagebus
microcode_ctl
network
rawdevices
readahead
readahead_early
sshd
syslog
xfs
xinetd

Yes, I even turn off sendmail and apache and all that until they are patched. No sense giving hackers any more chances than we have to. You can leave them enabled for startup and simply stop them if you want, it’s up to you.

That takes care of basic services that startup when the server starts, the next thing would be to check any services that start when xinetd (the old inetd replacement) starts up. To do this, you go to the /etc/xinetd.d directory and look at the files there. These files control the startup of xinetd services (telnet for example). This is controlled by the directives in each file, and the directive we are concerned with is called “disable”. If disable = yes, the service won’t start, and we want them all to be disabled until we need them. The easiest way to do this is to keep xinetd from starting. The problem from my point of view is that if you ignore these control files, when xinetd might get started later, either on purpose or by accident, you run the risk of accidentally opening up a security hole, so let’s plug it now.

I just grep for disable in all of these control files, and see which ones come back with “no”, for example, in the /etc/xinet.d directory I would:

[root@yuri xinetd.d]# grep disable *
chargen: disable = yes
chargen-udp: disable = yes
cups-lpd: disable = yes
daytime: disable = yes
daytime-udp: disable = yes
echo: disable = yes
echo-udp: disable = yes
eklogin: disable = yes
gssftp: disable = yes
klogin: disable = yes
krb5-telnet: disable = yes
kshell: disable = yes
ktalk: disable = yes
rsync: disable = yes
time: disable = yes
time-udp: disable = yes

There you go, all xinetd services are disabled. If any came back with a “no” in there, you simply edit the file and change no to yes.

Patch, patch, patch the server

Probably the most important and most obvious thing to do to secure your server is to make sure it is up to date on patches. Ironically, you do this with the up2date command. If you are running RedHat Enterprise, you need a paid subscription. If you are running CentOS and presumably Fedore Core, you don’t. Here are the steps to get patched quickly and easily from the command line. The “nox” option tells up2date not to use it’s X interface.

To list all available patches:
up2date --nox -l

To install all patches that are not excluded (kernel patches are excluded by default):
up2date --nox -u

To install all patches including those that have been excluded:
up2date --nox -uf

The first time you update the server, it will take some time, so once you start the patching it would be a good time to go get a scone. I usually list and look at the patches first, then patch everything but the kernel and make sure they are successful. Then I will apply the kernel patches. Be sure to reboot after patching to make sure the kernel patches take affect. I haven’t dug into the latest Fedora Core releases, but I believe up2date has been replaced by yum.

Secure all system accounts

What do I mean by this? Well, in the past, linux distros would ship with default passwords or no passwords for some accounts and this was an attack vector for unwanted visitors. What I do is take all accounts that don’t require an actual login, like system accounts, lock them, and make sure they don’t have a shell.

If this is being done on a server that has just been installed, in most cases you want to do this for every account on there except for root, and whatever account you created during the install. You’ll need to make the call on which accounts to lock, based on your situation.

We lock the account and change the shell with the /usr/sbin/usermod command, for example:

/usr/sbin/usermod -L -s /bin/false fred

This command locks the account fred, and sets fred’s shell to /bin/false, which is a fake shell, not a real shell. So even if someone got around the lockout, they couldn’t login without a real shell.

Here is a script that I use to hit all the accounts on the server. Be sure to edit the script, at the top and enter your user name, and any other users you don’t want locked in the quotes where we set the TOSKIP variable. It’s simple, but it works. Use this with caution!

#!/bin/bash
# Put usernames to skip here, use "name|name|name" format
TOSKIP="barney"
###
LOG="/tmp/lockaccounts_execution.log"
>$LOG
for a in `cat /etc/passwd | awk -F: '{print $1}' | egrep -v "root|${TOSKIP}"`
do
echo -n "Locking the account $a ... "
/usr/sbin/usermod -L -s /bin/false $a >> $LOG 2>&1
echo "done."
done
echo
echo "Script complete, check $LOG for any errors."

Setup appropriate /etc/motd and /etc/issue files

I like to put warning banners up for all to see when connecting remotely and logging in. You can put your verbage in the files /etc/motd (message of the day) and /etc/issue. So if you want something like “Scram, keep out and go away” displayed whenever someone connects, put that in those two files. Good things to put in there are not “Welcome”, and should be something that states that access is for “authorized” personnel only. If you have “Welcome to my server” in your greeting banner, you can pretty much forget prosecuting a hacker that gets into your machine because you just invited him or her in.

Summary

As I said earlier, this list is not all inclusive, and I plan to add more as time goes on. But even just these few simple steps can go a long way to making your server much less appealing to a hacker, and probably downright unavailable to the script kiddies out there. Having built and run an ISP in the past, I have had my share of run ins with nefarious visitors trying to break into systems. You can take it from me, it’s much better to put some effort in now and keep them out, than to be slaking in the short run and get compromised.

One thought on “Basics of securing a Linux server

  1. Pingback: Wrap Margin » Blog Archive » Basics of Securing Linux Servers

Tell me what you are thinking?