Community Tutorials Ubuntu Securing Ubuntu Server: SSH Hardening, UFW Firewall, and Fail2ban

Securing Ubuntu Server: SSH Hardening, UFW Firewall, and Fail2ban

The three controls that stop 99 percent of internet noise — SSH key-only access, a default-deny UFW firewall, and Fail2ban brute-force protection — configured the right way on Ubuntu 24.04.

Default Ubuntu Server is sensible, but it is not "internet hardened." This guide layers the three controls that stop 99 percent of the noise we see in honeypots: SSH key-only access, a default-deny UFW firewall, and Fail2ban to drop brute-force traffic before it consumes a worker.

Prerequisites

  • Ubuntu 24.04 LTS Server with sudo access.
  • An Ed25519 key pair generated on your workstation:
ssh-keygen -t ed25519 -C "your.name@example.sa"
  • A second SSH session held open while you make changes — locking yourself out once is a great teacher, but only once.

Step 1: Push your SSH key to the server

ssh-copy-id ubuntu@server.example.sa

Now confirm key-only access works before disabling passwords:

ssh -o PasswordAuthentication=no ubuntu@server.example.sa

If that prompt drops you straight to a shell, proceed. If it asks for a password, fix the key copy first.

Step 2: Harden sshd_config

Edit /etc/ssh/sshd_config (or, better, drop a file in /etc/ssh/sshd_config.d/99-skyline.conf):

# /etc/ssh/sshd_config.d/99-skyline.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
Protocol 2

# Optional: move SSH off port 22 to cut log noise.
# Port 2222

Validate and reload — never restart without a syntax check:

sudo sshd -t && sudo systemctl reload ssh

If sshd -t returns anything, fix the syntax before reloading. A bad reload locks you out of fresh sessions.

Step 3: UFW — default-deny firewall

Ubuntu ships with UFW disabled. Enable it with sensible defaults:

sudo apt install -y ufw

# Default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow your SSH port — substitute 2222 if you moved it
sudo ufw allow 22/tcp comment 'ssh'

# Common web ports (only if this host serves HTTP)
sudo ufw allow 80/tcp  comment 'http'
sudo ufw allow 443/tcp comment 'https'

# Office IP allow-list example
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp comment 'office'

sudo ufw --force enable
sudo ufw status verbose

Tip: if you have IPv6 connectivity, also confirm IPV6=yes in /etc/default/ufw.

Step 4: Fail2ban — drop brute-force traffic

Fail2ban watches your auth logs and adds offenders to a UFW chain.

sudo apt install -y fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Edit /etc/fail2ban/jail.local and adjust the [DEFAULT] and [sshd] sections:

[DEFAULT]
ignoreip   = 127.0.0.1/8 ::1 203.0.113.0/24
bantime    = 1h
findtime   = 10m
maxretry   = 5
banaction  = ufw
backend    = systemd

[sshd]
enabled  = true
port     = 22
filter   = sshd
maxretry = 3

Enable and start:

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Inspect bans after a few hours:

sudo fail2ban-client status sshd
sudo zgrep "Ban " /var/log/fail2ban.log* | tail

Step 5: Kernel network hardening

Drop a small sysctl file to disable IP forwarding, harden the SYN backlog, and ignore source-routed packets:

sudo tee /etc/sysctl.d/99-skyline-net.conf <<'EOF'
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.rp_filter = 1
EOF

sudo sysctl --system | tail -10

Step 6: Audit and revisit

A monthly review keeps the controls honest:

sudo lynis audit system --quick     # broad system audit
sudo ufw status numbered            # is the rule list still tidy?
sudo systemctl status fail2ban      # is the watchdog up?
sudo last -i | head -20             # recent successful logins

Conclusion

Three controls — SSH key-only, UFW default-deny, Fail2ban — drop attack surface by orders of magnitude with maybe twenty minutes of work. Layer on Lynis monthly and you have an Ubuntu host most attackers will simply walk past.

Next steps

SKYLINE Engineering

@skyline

The engineering team at SKYLINE Industrial Solutions. We publish field-tested guides drawn from real KSA and GCC deployments.

See author profile

Comments

0 total · 0 threads
Be the first to leave a comment.