Securing my Linode server

Posted
Categorized as Software

Thanks to a hackers and/or bots trying to inject malware into my WordPress installation, I am forced to learn how to administrate my host better. Surprisingly enough, I find myself enjoying learning how to manage and secure a production server; A skill which will definitely help me become a better developer moving forward. So far here’s what I’ve done to deter and hopefully mitigate the hacking attempts on my site.

This guide assumes you are running an Ununtu 14.x up.

Set the proper timezone

This will make log files easier to understand and keep track of SSL certificates

dpkg-reconfigure tzdata

Setup a hostname

You can name this anything you want, I used “livehost”

echo "livehost" > /etc/hostname
hostname -F /etc/hostname

Now verify the hostname change

hostname

Now setup a Fully Qualified Domain Name (FQDN) in your /etc/hosts file

127.0.0.1          localhost.localdomain   localhost
127.0.1.1          ubuntu
<your server ip>   livehost.example.com       livehost

Now you can set an A Record to your domain name pointing to your hostname livehost.example.com to access your server.

Disabled remote root login and changed the SSH port

I changed my SSH port to something lower than 1024 but not 22 (learn why here) then set PermitRootLogin to no.

sudo nano /etc/ssh/sshd_config

Installed Fail2Ban

installed it with the following command

sudo apt install fail2ban

We’ll copy the default config  and jail settings and modify the copies we made.

sudo cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

SSH is already enabled by default in Ubuntu, so you’ll just need to enable the services you want to watch over. Do note that Fail2Ban won’t start if you enable a filter on a service that’s not installed/running.In this instance I just added a custom filter and changed the destemail setting so I can get notifications. You will need to install sendmail to get this feature working, see below.

[DEFAULT]
destemail = email@example.com

[wordpress]
enabled  = true
filter   = wordpress
logpath  = /var/www/html/example.com/log/access.log
port     = 80,443

I also made a custom wordpress filter in /etc/fail2ban/filter.d/wordpress.conf , you can read more about it here. This basically checks the access log of my site and filters it using regular expressions.

# Fail2Ban filter for WordPress
#
#

[Definition]

failregex = <HOST> - - \[(\d{2})/\w{3}/\d{4}:\1:\1:\1 -\d{4}\] "POST /wp-login.php HTTP/1.1" 200
ignoreregex =

after saving the changes, restart the service.

sudo service fail2ban restart

Installed and Setup IPTables

IPTables is already installed with Ubuntu so I just needed to setup a new configuration file

sudo nano /etc/iptables.firewall.rules

I used the following configuration which I Googled to allow SSH, HTTP/HTTPS and a few other ports for testing then closed everything else for security Note that the port setting should be the same as with setting in the /etc/fail2ban/jail.local and /etc/ssh/sshd_config values.

*filter

#  Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

#  Accept all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allow all outbound traffic - you can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

#  Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

#  Allow ports for webmin
-A INPUT -p tcp --dport 10000 -j ACCEPT

#  Allow SSH connections
#  The -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 321 -j ACCEPT

#  Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# Allow sendmail
-A OUTPUT -p tcp --dport 25 -j ACCEPT
-A OUTPUT -p udp --dport 53 -j ACCEPT

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

#  Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

Activate the new firewall rules now

sudo iptables-restore < /etc/iptables.firewall.rules

Then make sure to run the firewall rules on startup by editing this file

sudo nano /etc/network/if-pre-up.d/firewall

Insert the following script

#!/bin/sh
/sbin/iptables-restore < /etc/iptables.firewall.rules

Save the changes then set the permissions

sudo chmod +x /etc/network/if-pre-up.d/firewall

Install Let’s Encrypt

Let’s encrypt is a free SSL certificate supported by a lot of popular browsers. I use this to encrypt traffic on my sites at no extra cost. Before installing the package make sure you have set your timezone and hostname already. If you’ve done that already you can update everything first.

sudo apt update && sudo apt upgrade

Once everything has updated, install GIT so we can clone the repository on Gtihub later

sudo apt-get install git

Now clone the official GitHub repository to /opt/letsencrypt

sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Then navigate to /opt/letsencrypt

cd /opt/letsencrypt

Now make sure nothing is using port 80. I had trouble with this even after closing Apache which was the only application I though was using port 80. So to keep it simple I just killed all processes using port 80

sudo lsof -t -i tcp:80 -s tcp:listen | sudo xargs kill

Now we are ready to create a certificate that will auto renew. Just change the domain name to the domain name you’re creating a certificate for.

sudo -H ./letsencrypt-auto certonly --standalone --renew-by-default -d example.com -d www.example.com

If everything worked properly you should see something like this. Take note of the Certificate and key paths, we will need this later when configuring the SSL certificate for Apache.


Now we will set a cron job to automatically renew the certificate and update Let’s Encrypt. Open crontab

sudo crontab -e

Then append the following lines

0 0 1 * * /opt/letsencrypt/letsencrypt-auto renew
0 0 1 * * cd /opt/letsencrypt && git pull

Now we need configure apache for the SSL certificate. Appenbd this to your sites config file typically found in /etc/apache2/sites-available/example.com.conf. The SSLCertificateFile and SSLCertificateKeyFile paths were echoed after you created your certificate earlier. This will also set TLSv1.2 to be used instead of the default TLSv1

<VirtualHost *:443>
	SSLEngine On
	SSLProtocol -all +TLSv1.2
	SSLCertificateFile /etc/letsencrypt/live/mikemamaril.com/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/mikemamaril.com/privkey.pem
	
	ServerAdmin root@mikemamaril.com
	ServerName  mikemamaril.com
	ServerAlias www.mikemamaril.com

	# Index file and Document Root (where the public files are located)
	DirectoryIndex index.html index.php
	DocumentRoot /var/www/html/mikemamaril.com/public_html
	# Log file locations
	LogLevel warn
	ErrorLog  /var/www/html/mikemamaril.com/log/error.log
	CustomLog /var/www/html/mikemamaril.com/log/access.log combined
</VirtualHost>

Ensure that the Apache SSL module is enabled, and enable the virtualhost configuration:

a2enmod ssl
a2ensite example.com

Then restart the Apache service

service apache2 restart

You can visit WhyNoPadlock to troubleshoot any insecure content you may have on your page. If you’re using WordPress you can use Really Simple SSL to force HTTPS to any visitors visitors to your site.

Get alerts when someone uses sudo

For that extra touch to paranoia, I also setup an email notification to let me know if someone uses the sudo command.  I start off by making a new file

sudo nano /etc/sudoers.d/my_sudoers

pasting in the following content, you’ll need to change the email address to the one you wish to use.

Defaults    mail_always
Defaults    mailto="your@email.com"

Save the changes then set the file permissions

sudo chmod 0440 /etc/sudoers.d/my_sudoer

If you don’t have a mail server setup yet you will need to install one. I used sendmail.

sudo apt install sendmail

The install script hanged on me and I found that the following commands worked to finished the installation.

cd /etc/mail/tls
sudo openssl dsaparam -out sendmail-common.prm 2048
sudo chown root:smmsp sendmail-common.prm
sudo chmod 0640 sendmail-common.prm
sudo dpkg --configure -a

When you’re done installing sendmail, configure it:

sudo sendmailconfig

Reboot server on OOM (Out Of Memory)

This will reboot the server if the system panics, literally.

sudo nano /etc/sysctl.conf

the append this to the config

vm.panic_on_oom=1
kernel.panic=10

 


Leave a Reply