There is no such thing as a completely secure server: as long as you provide public access to services running on a server, there is a risk that somebody at some point is going to try something like a privilege escalation or denial of service. What one can do is to minimize the chance of success of such attack or at least to minimize the damages.
I am not going to provide here some “high tech” security mechanisms but rather some “common sense” ones; such measures will most likely prevent speculative attackers or bots from doing their stuff. Let’s start with the first trick from the book:
1. Set up iptables
One may think: why set the firewall up? If I provide 3 services to the world and those are the only ones with listening sockets, why would I need a completely configured firewall?
The answer is: the firewall is always necessary. Having a policy of “deny all + exceptions” will render useless any rogue service that an attacker may inject through some privilege escalation attack.
On a RedHat (CentOS) system one will find the firewall configuration file as /etc/sysconfig/iptables. A typical restrictive configuration might be:
*filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT
The configuration above allows new tcp traffic (new connections) to ports 22 (ssh), 80 (http) and 443 (https), while allowing all outgoing traffic and also the responses received in relation to such traffic. It also allows icmp (ping), but denies everything else.
2. Secure /tmp
The /tmp directory is the best known location on any Linux server where anybody can create new files. On a default installation /tmp is just another directory on the root partition and this opens the door for issues like:
An attacker can create many files in /tmp, filling up the space to full or (worse) causing the file system to run out of inodes;
One can put some full fledged attack scripts in /tmp and run them, speculating either some kernel bug or some issue in a daemon that is being run as root;
If the planned attack exceeds the abilities of a scripting language, the attacker may even bring in a compiler to get a binary file for the attack.
The solution for a secure /tmp may be to create a separate mount point and then use some special mount options (noexec or, if not possible, nosuid). The first option simply disables the ability to run anything on /tmp, even for the superuser. The second disables setting the “suid” bit for executables, preventing a class of privilege escalation techniques that involves such scripts or binaries.
Some example /etc/fstab line might be:
/dev/xvdf2 /tmp xfs defaults,nosuid,noexec 1 2
3. Isolate the user files
The user files may be located in /home (the classical Linux installation) or somewhere within /var (for a web server). The main idea is that such files must be located on a dedicated mount point. The reasons for this are significant:
The sysadmin can enforce quotas on mountpoint level only. Having a dedicated mount point makes the configuration easier;
Even if quotas cannot be applied, no user is able to disrupt overall server functionality by creating files to the point of filling up the space or exhausting the file system inode count;
No hard links are possible for system files. If they were permitted, some rogue user would be able to keep a buggy version of some suid binary for his/her own use and the sysadmin would be none the wiser;
The sysadmin may be able to enforce mountpoint options like noexec or nosuid on user files only, without affecting the overall system functionality.
4. Login via ssh keys only
Password login is unsecure; passwords are easier to steal than private keys, and also easier to guess. When administering large installations with many nodes, remembering passwords or entering passwords for every login is not only unpractical but it is also a hinderance.
Such setting effectively prevents the bots that do brute-force password guesses from even having a theoretical chance of breaking in.
5. No root login for production
This actually should be put first. No direct root access in production, be it by password or by ssh key, period. All administrative tasks should be done with sudo from a special, dedicated, normal user account (which must be accessible by a ssh key).
For lower level environments or completely private servers this rule may be safely ignored.
Enable SYN cookies (if not already enabled by default);
Use a fail2ban-like solution;
Consider using SELinux.
This was it. Hope you enjoyed it!
(NB: photo from my personal collection depicting some old servers in a data center.)