Securing a VPS or web facing VM
Setting up a VM or VPS is easy but, you need to make it secure. Here we discover 2 of the basic tools UFW and Fail2ban. This is a post of how to set it up and the results.
Initial step
Crete a small VPS on your favorite platform. You don't need more than 1 core and 2G disk and some RAM. We use Docker to host the device.
Replace <username> with a real username e.g., nalle.
apt update && apt upgrade -y
apt install duf btop
adduser --disabled-password <username>nano /etc/sudoers.d/90-<ausername>Paste in <username> ALL=(ALL) NOPASSWD
SSH setup
The following is a minimum
PermitRootLogin no
PubkeyAuthentication yes
StrictModes yes
AllowUsers <username> Creating an SSH Key Pair
We need an SSH Key Pair for each server.
Generate a key pair using ed25519 on your local machine.
Then paste the public part to the VPS.
The key pair consisting of two files in your home directory under ~/.ssh.
id_ed25519- The private key shall be kept safe, like a password, and not passed on.
id_ed25519.pub- The public part is meant to be public, no need to be kept secret
Depositing the Public Key
mkdir -p /home/nalle/.ssh
nano /home/nalle/.ssh/authorized_keys
# paste the public key here and save the file
chmod 600 /home/nalle/.ssh/authorized_keys
chown holu:holu /home/nalle/.ssh/authorized_keysExample where <username> has been replaced with my name
Test for success
Open a new terminal window and type `ssh <user>@<your host>
Activating the new configuration
systemctl restart sshdInstall UFW
To set up a firewall we will use the program Uncomplicated Firewall (UFW), (an abstraction of iptables), because the rules can be managed much easier and more comfortable than with iptables directly. It simplifies the complex iptables configuration, making it accessible for users who may not be familiar with advanced firewall management.
Installation
The ufw package can be installed from the apt package manager.
sudo apt install ufwFirst rule
Create a rule that blocks all incoming connections that are not explicitly allowed.
sudo ufw default deny incomingBefore we activate the firewall, we must of course release our SSH port, otherwise we lock ourselves out of the server. Use ufw allow ssh or use the port ufw allow 22/tcp
sudo ufw allow ssh Activate UFW
Activate the Uncomplicated Firewall with the command:
sudo ufw enableWith the command ufw status all created rules can be listed. This command must also be executed as root or using sudo.
Install Fail2ban
Install it and check your UFW status
sudo apt update && sudo apt install fail2ban
sudo ufw status verbose
systemctl is-enabled fail2ban
systemctl is-active fail2banCheck fail2ban status
systemctl is-enabled fail2ban
systemctl is-active fail2banIf it is enabled and active we need to shut it down
sudo systemctl stop fail2banConfigure to ban through UFW
Do not edit the .conf files, they are overwritten at upgrades, create .local instead e.g., /etc/fail2ban/jail.local, they are not changed.
sudo nano /etc/fail2ban/jail.localAdd the following: Ban for 1 hour after 5 failures within 10 minutes using UFW instead of the default iptables.
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
banaction = ufw
[sshd]
enabled = true
backend = systemdTo note:
- banaction – tells Fail2ban to use the
ufwaction that ships in/etc/fail2ban/action.d/ufw.conf, instead of its defaultiptablesaction. Bans become UFW rule - backend – For the SSHD jail. OpenSSH logs to the systemd journal, so the journal backend is the reliable way for Fail2ban to read failed logins.
Save the file.
Enable and start the service in one step:
sudo systemctl enable --now fail2banConfirm the jail is running:
sudo fail2ban-client status sshdStatus for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:Example output
Nothing is banned yet, which is expected. The Journal matches line confirms Fail2ban is reading SSH events from the journal.
Ban and Unban an IP
The subnet 198.51.100.0/24 is a reserved for documentation, so the address below is safe to run. You don't need to wait for a real attacker to confirm the integration works, it will be a short wait but, it's not safe to unban any attacker.
Ban an IP
sudo fail2ban-client set sshd banip 198.51.100.40Unban an IP
sudo fail2ban-client set sshd unbanip 198.51.100.40Results
Why do I need to run ufw and/or fail2ban on my web facing VM/VPS?
I created a VPS for testing and during the first day I got these results:
sudo fail2ban-client status sshd- Total failed: 1062
- Total banned: 166
Actually, much lower results than expected. But, it's scary, isn't it.
Fail2Ban is one layer in a broader Linux security strategy, and works best with:
- SSH key authentication
- Properly configured firewall rules
- Regular software updates
- Strong access control policies
References
Fail2ban [1] UFW [2] About IPs [3]
Fail2Ban on GitHub. FAQ, and HOWTOs to be found on fail2ban manpage, Wiki, Developers documentation and the website ↩︎
Uncomplicated Firewall (UFW), has been available by default in all Debian installations since 10 homepage, getting started wiki, Git, wikipedia, man page ↩︎
IPv4 Address Blocks for Documentation are by RFC 5737:
TEST-NET-1 =192.0.2.0/24, -2 =198.51.100.0/24, -3 =203.0.113.0/24↩︎