Note: This guide does not take in mind using policies of SELinux. If you are using SELinux, various commands need also to be followed by policy changes, so tread carefully. To verify if you are running SELinux, you can run getenforce to verify. If you are not, you may safely proceed
To begin...Install basic packages
Let's install some basic packages we need for the rest of this how-to
sudo yum install epel-release #For adding certain packags sudo yum install nano #Best text editor ever sudo yum install htop #To be able to monitor our server sudo yum install nginx #For adding a webserver sudo yum install fail2ban fail2ban-systemd #For capturing failed logins
Hardening the server!
We should not be using the root account to do our work. Instead, we should have a different one, that sudo's every time it needs to do a system change. Root creds should be ultra hard to come up with (you should have a huuugee password for it) and be kept somewhere out of sight!
So let's create a new user and add a password
useradd YOURUSER passwd YOURUSER
Also add the new user to the WHEEL group to enable that user to use the sudo command.
usermod -aG wheel YOURUSER
Enable user account to login with an ssh key
Generate an ssh key on your client machine (use ssh-keygen, native on Mac, use in Bash if you have it on Windows. It usually ships with Git installations, or if you are using the linux subsystem)
After you have your key, run ON THE CLIENT machine the following command:
Host can be your server domain, or IP. The command is going to attempt and login to your remote server, and install the key for the specified user automatically. During this process, password is going to be asked for the user. After successful authentication, the command copies the key on the server. You should be able to login over ssh using your key now. To test it, from bash, run:
ssh -i ~/.ssh/mykey YOURUSER@<host>
For making the key usable with Putty, run PuTTyGen, import the key (if you used the default settings, that would be id_rsa found in your home folder under the .ssh folder) and subsequently save it in a .ppk format.
SSH Service Configuration
We will try to implement the following
- Disallowing root logins
- Limit allowed users that can login through ssh
- Block an IP after 3 failed login attempts
- Changing the default port (Not Implemented yet)
- Disabling password authentication (Not Implemented yet)
First open /etc/ssh/sshd_config on your server using your favorite editor (use nano, we installed it before!) so we can work with it
sudo nano /etc/ssh/sshd_config
Quick nano tutorial: to save anything, you hit 'Ctrl+X', and nano asks what to do. You can choose to discard changes, of save changes by hitting the appropriate letters on your keyboard. In case you are saving, it will also ask for a name. Hit enter to overwrite, or type a new one to create a new file. Super simple!
Disallowing Root Logins
Locate the following entry and change it to no
# Prevent root logins: PermitRootLogin no
Setting allowed users
You can limit the possibility for login to specific user accounts. If you have limited people that should be able to login, then this greatly enhances your security policies!
Add this at the end of the sshd_config file, by separating different usernames using space. Only these users will be able to login afterwards
AllowUsers YOURUSER YOURUSER2
Now save all the changes to the file and restart sshd server to pickup the configuration
To restart the sshd server to apply all the changes...
sudo systemctl reload sshd.service
sudo service sshd restart
Block an IP after 3 failed login attempts
To achieve this, we are gonna use the fail2ban. If you haven't done so, install the EPEL repository, and then install fail2ban
sudo yum install epel-release sudo yum install fail2ban fail2ban-systemd
To configure fail2ban, we create an sshd.local file in the proper folder
sudo nano /etc/fail2ban/jail.d/sshd.local
with the following config
[sshd] enabled = true port = 22 logpath = %(sshd_log)s maxretry = 3 bantime = 900 //That's in seconds. this equals to 15 minutes
Save the file, enable the service, and start it. By enabling the service, fail2ban will be autostarted automatically whenever the whole server gets rebooted.
sudo systemctl enable fail2ban sudo systemctl start fail2ban
Setting up a firewall using firewalld
First, check the state of your firewalld, whether it's already running or not. If not, let's shoot it up! (Don't worry, you probably won't get locked out as the default config allows ssh port)
sudo firewall-cmd --state sudo systemctl status firewalld ... sudo systemctl start firewalld
To check current configuration (after you started the firewall), run
sudo firewall-cmd --zone=public --list-all
Notice the services that are being allowed right now. Probably you have ssh already configured.
FirewallD makes it convenient to set it up by using service definitions rather than using ports (although you can definitely use ports if you need to).
So you could enable ports 80 and 143 for http/https serving easily by issuing:
sudo firewall-cmd --add-service=http sudo firewall-cmd --add-service=https
The services get enabled on the default interface, which if you haven't specified one, it will be 'public' by default. FirewallD allows you to have different configurations for different interfaces (eg for internal network, or a dmz or whatever) by it's too advanced for us to get into in this quick how-to!
Now, if the configuration feels ok (check the status and make sure ssh it's still available, so you do not get locked out), you need to make this configuration permanent. FirewallD, has 2 configuration levels. The runtime configuration, and the permanent one. With this method, if for some reason you do a setting that locks you out of your remote machine, you could restart it and get rid of that wrong configuration on reboot. Only when you are certain about a setting, you should move it to the permanent configuration. The permanent configuration it's the one loaded every time the system (and firewallD) starts.
To make our configuration permanent, you should either rerun the above commands using the --permanent flag
sudo firewall-cmd --add-service=http --permanent sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --runtime-to-permanent
which copies the current running configuration to the permanent one.
After saving our configuration and make it permanent, the firewall needs no further reloading.
In case we want to reload it to make sure it's running with the proper configuration (if you are the insecure type of person), then you can do so by issuing
sudo firewall-cmd --reload
Finally, let's enable the firewall to run automatically after system restarts, if it's not already enabled
sudo systemctl enable firewalld
Et voila! We are behind a firewall! If by any chance you have any other services running without your knowledge, you have at least blocked access to them from the outside. From now on, for whatever service you wanna expose to the outside world (eg adding ftp access, although you should be using ssh to transfer your files in the first place) you need to also add the service to the firewall using the firewall-cmd similarly as above.
For more info on firewalld configuration checkout:
Installing Nginx for serving a web page/app
If you haven't installed it before, do it now:
sudo yum install nginx
Then start the service
sudo systemctl start nginx
Add Nginx to your firewalld rules, if you are running firewalld
sudo firewall-cmd --permanent --zone=public --add-service=http sudo firewall-cmd --permanent --zone=public --add-service=https sudo firewall-cmd --reload
Check that everything worked by visiting http://server_domain_or_ip. The nginx welcoming page should show up
Finally, make Nginx to automatically start after server reboots
sudo systemctl enable nginx
Configuration for Ngnix can vary a lot, depending on what type of a web app you will be serving, hence I am gonna leave that out for now. In case you are the Django type, you could check one of my other posts that goes through the steps of installing python, Let's Encrypt for issuing an SSL certificate and using systemd along with gunicorn to handle the django app!
Note: This article is a work in progress, as I keep updating it with more current information. If there is anything you would like me to address specifically, please leave a message to try and include it on future updates!
To sum up what we have achieved up to now: your brand new CentOS 8 Box has been configured to be slightly more secure, has a firewall up and running and does not allow brute-force attacks by blocking clients with more than 3 failed attemps. An Nginx webserver is also up and running and now it's pending configuration to be able to load your web project!