Free tech learning for everyone, from basics to pro

Cyber Security LabsLabsIntermediate

Lab: hardening a Linux server (SSH, firewall, updates)

In short: An internet-facing Linux server is probed within minutes of going online. In this lab you harden an Ubuntu Server VM: patch it, create a sudo user, allow SSH by key only, block everything else with UFW and turn on automatic security updates.

Aim and what you need

The aim is to apply the handful of controls that protect most Linux servers: current patches, no direct root login, key-based SSH, a default-deny firewall and as few running services as possible.

  • An Ubuntu Server LTS VM (for example 24.04) at 10.10.10.20 in your isolated lab, with temporary internet access for updates.
  • A client VM (Kali or any Linux) at 10.10.10.10 to connect from.
  • A snapshot taken before you begin.

Design

Linux server hardening layersUpdatesapt, unattended upgradesAccountssudo user, no root loginSSHkeys only, limited usersFirewallUFW default denyServicesremove what is unusedLoggingauth log, fail2ban
Figure 1. Each layer narrows the attack surface of the server, from patching at the top to logging and response at the bottom.

Tip: when you change SSH or firewall settings on a remote server, keep your current session open and test with a second session. If the new settings lock you out, you can still fix them from the first.

Steps

  1. Update the system and turn on automatic security updates.
  2. Create an admin user with sudo rights.
  3. On the client, create an Ed25519 key pair and copy the public key to the server.
  4. Create an SSH drop-in file that disables root and password logins, then test the syntax and reload.
  5. Set the firewall to deny incoming traffic by default and allow SSH only from the lab network.
  6. List listening services and remove any you do not need.
sudo apt update && sudo apt full-upgrade -y
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
sudo adduser labadmin
sudo usermod -aG sudo labadmin

On the client:

ssh-keygen -t ed25519 -C "labadmin@lab"
ssh-copy-id [email protected]
ssh [email protected]

On the server, create /etc/ssh/sshd_config.d/50-hardening.conf with sudo nano and add:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
AllowUsers labadmin
X11Forwarding no
sudo sshd -t
sudo systemctl reload ssh
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 10.10.10.0/24 to any port 22 proto tcp
sudo ufw enable
sudo ss -tulpn
sudo systemctl disable --now <unused-service>

Verify

From the client, test each control. Success means: key login as labadmin works; root login is refused; a password-only attempt is refused with "Permission denied (publickey)"; UFW is active with only your SSH rule; ss lists only the services you expect.

ssh [email protected]
ssh [email protected]
ssh -o PubkeyAuthentication=no [email protected]
sudo ufw status verbose
sudo sshd -T | grep -E "permitrootlogin|passwordauthentication"
systemctl status unattended-upgrades
nmap -p- 10.10.10.20

The final Nmap scan, run from the client, should show only port 22 open. Compare it with a scan taken before hardening, as in the Nmap inventory lab.

Troubleshooting and clean-up

  • Locked out: use the VM console in the hypervisor, fix the drop-in file, run sudo sshd -t and reload.
  • Settings ignored: in OpenSSH, the first value read wins. A cloud-init file such as 50-cloud-init.conf may set PasswordAuthentication yes; check with sudo sshd -T, which prints the effective settings.
  • Key not accepted: permissions on ~/.ssh must be 700 and authorized_keys 600.
  • UFW blocks a needed service: add a specific allow rule rather than turning the firewall off.

Optionally add fail2ban to ban addresses after repeated failures, and see the log analysis lab for reading failed logins. Restore your snapshot to repeat the lab. Keep the private key safe; never copy it to the server.

Practice

Why test SSH changes with a second session?
If the change locks you out, the first session is still connected and you can undo it.
What does sudo sshd -T show that the config file does not?
The effective settings after all included files are read, so you can see which value actually applies.
Why allow SSH only from 10.10.10.0/24?
It limits who can even attempt to log in, reducing exposure to scanning and password guessing.

Key takeaways

  • Patch first and turn on unattended security upgrades.
  • Use a named sudo user; disable root and password logins for SSH.
  • Put SSH settings in a drop-in file and check them with sshd -t and sshd -T.
  • Use UFW with default deny incoming and narrow allow rules.
  • Verify from another machine, including an Nmap scan.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.