What you will build
Every public-facing server on the internet is probed within minutes of going live — automated bots scan for open ports and hammer SSH with credential guesses. Two lightweight, battle-tested tools handle most of this for you:
- UFW (Uncomplicated Firewall) — a friendly front-end to
iptables/nftablesthat controls which ports are open. - Fail2ban — watches log files for repeated failed logins and temporarily bans the offending IP addresses.
This tutorial walks through configuring both on a Debian or Ubuntu server (commands are nearly identical on other distributions). It applies whether you run a cloud server, VPS, or dedicated machine, and is part of our VPS and cloud servers in Saudi Arabia knowledge cluster.
Prerequisites
- A Linux server you can reach over SSH.
- A user with
sudoprivileges (never do this asrootover an exposed connection without a fallback). - Your SSH port (the default is
22; if you changed it, use your real value throughout).
Warning: A firewall can lock you out. Before enabling UFW, make sure the rule that allows SSH is in place. If you use a cloud provider, keep its web console or recovery access open so you can recover if you make a mistake.
Step 1 — Install and configure UFW
UFW ships with most Ubuntu images. Install it if needed:
sudo apt update
sudo apt install ufw
Set sane defaults — deny all incoming traffic, allow all outgoing:
sudo ufw default deny incoming
sudo ufw default allow outgoing
This is the core of a good firewall posture: nothing reaches your services unless you explicitly permit it.
Step 2 — Allow the services you actually need
Before turning the firewall on, open the ports your server uses. Always allow SSH first or you will be disconnected:
sudo ufw allow OpenSSH
UFW reads named application profiles from /etc/ufw/applications.d. List what is available with sudo ufw app list. If you changed your SSH port, allow it explicitly instead:
sudo ufw allow 2222/tcp
Open web traffic if you run a site or business email and web services:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
You can restrict a rule to a trusted source — for example, only allow database access from your application server:
sudo ufw allow from 10.0.0.5 to any port 3306 proto tcp
Step 3 — Rate-limit SSH and enable the firewall
UFW's limit rule throttles connections from any IP that attempts to connect more than 6 times in 30 seconds — a cheap, effective speed bump against brute-force tools:
sudo ufw limit OpenSSH
Now enable the firewall:
sudo ufw enable
Confirm your rules with a numbered listing:
sudo ufw status numbered
Expected output resembles:
Status: active
To Action From
-- ------ ----
[ 1] OpenSSH LIMIT Anywhere
[ 2] 80/tcp ALLOW Anywhere
[ 3] 443/tcp ALLOW Anywhere
To delete a rule, reference its number: sudo ufw delete 2.
Step 4 — Install Fail2ban
UFW closes ports, but the ports you must keep open (like SSH) are still exposed to guessing. Fail2ban watches the logs and bans repeat offenders:
sudo apt install fail2ban
On modern systems Fail2ban reads its journal via systemd, so it works out of the box. Confirm the service is running:
sudo systemctl status fail2ban
Step 5 — Configure Fail2ban with a jail.local file
Never edit jail.conf directly — it is overwritten on upgrade. Create a local override instead:
sudo nano /etc/fail2ban/jail.local
Add the following:
[DEFAULT]
# Don't ban your own trusted networks. Add your office/home IP.
ignoreip = 127.0.0.1/8 ::1
# How long a ban lasts (10 minutes).
bantime = 10m
# Time window for counting failures.
findtime = 10m
# Failures allowed before a ban.
maxretry = 5
# Tell Fail2ban to act through UFW.
banaction = ufw
[sshd]
enabled = true
The [sshd] jail uses the built-in sshd filter at /etc/fail2ban/filter.d/sshd.conf. Setting banaction = ufw makes Fail2ban insert deny rules through your existing firewall rather than touching raw iptables.
Restart to apply:
sudo systemctl restart fail2ban
Step 6 — Verify and monitor
Check overall status and the SSH jail specifically:
sudo fail2ban-client status
sudo fail2ban-client status sshd
The jail status shows currently failed and banned IPs:
Status for the jail: sshd
|- Filter
| |- Currently failed: 1
| |- Total failed: 23
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 1
|- Total banned: 4
`- Banned IP list: 203.0.113.42
To unban an address manually:
sudo fail2ban-client set sshd unbanip 203.0.113.42
Recommended baseline
| Setting | Value | Why |
|---|---|---|
| UFW default incoming | deny |
Closed by default |
| SSH rule | limit |
Slows brute force |
bantime |
10m–1h |
Punishes repeat offenders |
maxretry |
3–5 |
Tight but tolerant of typos |
ignoreip |
your admin IPs | Avoid locking yourself out |
Going further
For production servers, also enable jails for any service you expose (for example nginx-http-auth or your mail stack), use SSH keys instead of passwords, and consider a longer or escalating bantime. UFW and Fail2ban are a strong baseline, not a complete security program — keep packages patched and back up regularly with cloud backup.
Hosting your workload in-Kingdom matters for performance and for PDPL, NCA, and SDAIA data-residency requirements. Skyline Cloud runs cloud servers, VPS, and dedicated hardware inside Saudi Arabia with local Arabic support and transparent pricing.
Ready to deploy a hardened server? Create your Skyline Cloud account and launch a VPS in minutes.
Comments
0 total · 0 threads