This post was written 2020-06-13 18:43:00 -0700 by Robert Whitney and has been viewed an unknown number of times since unknown time. This post was last viewed an unknown length of time ago.
The systems of which I am working with as I write this post are installed with Ubuntu 18.04. These techniques should work on most distributions but configuration paths, software versions, etc. may differ slightly.
This page last updated
This blog post will not come even close to being everything that you need to do to secure a Linux system. But I try to be as comprehensive as possible without writing a book. Please remember throughout this guide to not just have a more secure system, but be a more secure admin. A computer system can only be so secure, but it is as weak as it's weakest administrator. The human element always remains insecure, and by understanding that you will understand why, as comprehensive as this guide becomes to be, it will never be enough.
I want to start off by saying that these are just tricks that I picked up along the way as a researcher, and hobbyist. While I have worked in the field of IT, and have secured systems while working in the field, I've never actually recieved any sort of diploma or certificate in the realm of cyber security. This guide is entirely based off of real world experience. I will likely update it with new and improved techniques in the future, especially as I work towards my degree in cyber security & data assurance.
SSH is a secure shell into a system via the internet. It allows you to run commands in a terminal to that machine. Certainly this is a service that you will very much like to protect from potential intruders. This guide will go over several steps that you can take to secure your SSH server.
The first thing that you should do when setting up SSH for terminal services is generate and use SSH keys for authentication. This will allow you to securily connect via decrypting a message sent by the server and encrypted with your public key. The messages is decrypted with your private key, stored on the client machine. If setup correctly, the SSH server will not allow password authentication, preventing bruteforce attacks from working.
On Linux, Mac, or Windows type the following command into your terminal, command prompt, or powershell.
$ ssh-keygen -b 8192
This will take you through the steps of generating your very first, 8192 bit SSH private & public key pair. You may choose to generate a 2048 bit (default) or 4096 bit key instead by replacing the argument for -b. By default this keypair will be stored in your home/user directory in the .ssh folder. It is recommended that you back these files up on an external drive in which you will not lose them. This is very important, if you lose access to your SSH keys you may lock yourself out of your server entirely.
When prompted, make sure that you set a password on your private key. This password should be something secure, that you will remember. If you lose access to this key, you will likely lose access to your servers! Do not forget your SSH key password! Congratulations, you have taken the first steps towards securing your SSH key!
When handling your SSH keys make sure that you obey the following rules of thumb to make sure that your key, and servers, stay protected.
Make the following changes to your /etc/ssh/sshd_config file:
PubKeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
PubKeyAuthentication determines whether or not SSH key
authentication is enabled on
the SSH server. It must be set to yes in order to activate SSH key
authentication.
PasswordAuthentication determines whether or not password
authentication is enabled
on the SSH server. Set this to no to enforce key authentication only.
PermitEmptyPasswords determines whether or not empty
passwords are permitted on
the SSH server. This should always be set to no.
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1275687091653419"
crossorigin="anonymous"></script> <!-- page-post-header -->
PAM stands for Pluggable Authentication Modules, and it provides dynamic authentication support for applications and services on Linux. There are many things that we can do to harden PAM, but this guide will cover a few of the basics.
If you make the following changes to /etc/pam.d/su, then users who are not in the "wheel" group will not be able to login to an account using su even if the password given is correct.
auth sufficient pam_rootok.so auth required pam_wheel.so group=wheel
The first line will allow the user root to use su whenever. The second line will only allow users to use su if they are in the "wheel" group.
To make sure that the system administrators are able to use root privileges you may want to setup sudo. This allows someone to type sudo before a command, and it will escalate privileges to root as long as they are listed in the /etc/sudoers file.
Remember that giving sudo privileges is no different from giving users direct access to the root account. Users with sudo will be able to execute specified commands, or all commands as root, depending on what is specified in the /etc/sudoers file.
Your files are critical, and so therefore it is critical to back them up in a way that they cannot be tampered with. This means making sure that an outside system is able to securely access files from the machine over an encrypted protocol. Suggested here is to use something like rsync.
It is absolutely critical that you pull backups to your backup server, instead of pushing them to the backup server. The reason for this is that if the source system can access the backup files, then the integrity of your backups is already compromised. This can however be prevented by using backup software that appends backups instead of allowing access to overwrite/modify them.
Whenever possible you should use File / Folder encryption for your
backups. Some file syncing solutions, such as Ubuntu's backup solution or
resilliosync, have encryption options as well. These programs will
typically allow you to encrypt backups on the remote end, so that the
remote server never sees the plain text files. For a Linux desktop you
should use the full disk encryption options which are typically provided
by the installation medium of your flavor of Linux. I don't personally set
this up on servers, but you may want to do that as well. A con of doing so
is that if the server, for whatever reason, reboots then you will need to
enter that password at the console or over KVM before the server will
fully come back on.
Since your backup server will need access to all of your other servers, I provide and recommend the following tips for securing your backup server:
If an attacker gains access to your system, then you want to complicate
things as much as possible. mount -o remount,rw,hidepid=2 /proc
will remount your /proc directory with the option hidepid=2. This means
that users will only be able to see their own running processes. To make
this change permanent, add the following line to /etc/fstab
:
proc /proc proc defaults,hidepid=2 0 0
dev@dev:~$ ps faux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND dev 10380 0.7 0.4 12476 4432 pts/0 Ss 09:47 0:00 -bash dev 10389 0.0 0.1 29800 1564 pts/0 R+ 09:47 0:00 \_ ps faux dev 10372 0.0 0.5 56404 5340 ? Ss 09:47 0:00 /lib/systemd/systemd --user
To prevent fork bombs (never ending process spawning) you will need to add the following to the end of the /etc/security/limits.conf file.
* hard nproc 100
This will allow all users to only spawn 100 processes. You may want to increase or decrease that limit depending on what your server is doing.
Most Linux distributions come packaged with iptables. Here is an example allowing access to SSH for a single host and denying everything else:
iptables -A INPUT -p tcp -s 192.168.1.10/32 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT # Allow 192.168.1.10 to port 22/TCP.
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT # Allow established outbound connections to port 22/TCP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # Allow established inbound connects to port 22/TCP
iptables -A INPUT -j DROP # Drop all other traffic
Each line of the above example is commented so that you can understand what each line does. It is recommended that you use strict ingress rules.
It's not typical, but I recommend using very strict egress traffic rules. The following rules will allow the most common traffic on a Linux server, which requires updates via HTTP(S), as well as DNS, NTP, identd, and git over SSH. These rules are setup for IPv4 and IPv6.
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 113 -j ACCEPT
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
iptables -A OUTPUT -j REJECT
ip6tables -A OUTPUT -p tcp --dport 22 -j ACCEPT
ip6tables -A OUTPUT -p udp --dport 53 -j ACCEPT
ip6tables -A OUTPUT -p tcp --dport 80 -j ACCEPT
ip6tables -A OUTPUT -p tcp --dport 113 -j ACCEPT
ip6tables -A OUTPUT -p udp --dport 123 -j ACCEPT
ip6tables -A OUTPUT -p tcp --dport 443 -j ACCEPT
ip6tables -A OUTPUT -p icmp -j ACCEPT
ip6tables -A OUTPUT -j REJECT
If you want to learn more in depth about iptables take a look at this guide on opensource.com.
I know that I've barely scratched the surface of this topic, so if you have any suggestions as to what to add, or you feel like I missed something, please feel free to leave a comment below. I plan on adding to this guide in the future, so be sure to bookmark it and check back for updates!
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1275687091653419"
crossorigin="anonymous"></script> <!-- page-post-header -->
Update Jan 17, 2021: The code for this page was a real mess! I've cleaned up the design and a bit of the code, and will make more updates to the information contained within soon.
Update June 15, 2020: I've updated the guide based on some reddit suggestions.
Next up:
I am a programmer, writer, and avid PC gamer with a passion for technology and storytelling. My background in programming allows me to bring a unique perspective to my writing, and I enjoy sharing my knowledge and experiences with others through my blog. I look forward to connecting with like-minded individuals and exploring the latest developments in the tech world.
Sóc un programador, escriptor i jugador apassionat de PC amb una passió per la tecnologia i la narrativa. La meva formació en programació em permet tenir una perspectiva única en la meva escriptura, i m'agrada compartir els meus coneixements i les meves experiències amb altres a través del meu blog. Espero connectar amb persones amb interessos similars i explorar les darreres novetats en el món de la tecnologia.