Linux Tutorial / Protect a Linux Server with Firewalls, Accounts, and Updates
Protecting a Linux server combines limited accounts and exposed ports, controlled administrative privileges, timely security updates, and recovery access. Before tightening remote-access policy, retain the current session and console access and test a fresh connection after each change.
Before changing rules remotely, confirm SSH access and console recovery. Verify a new connection before closing the original session.
System configuration exercises use a conventional Ubuntu 26.04 LTS or Rocky Linux 9 VM as the reference environment. Containers, WSL, and other releases can differ in service and package configuration. Prepare console recovery and record your versions using the virtual machine setup lesson.
Inventory exposure and preserve recovery access
id
getent group sudo
getent group wheel
sudo ss -lntup
systemctl --failed
Ubuntu commonly delegates administration through sudo and Rocky Linux through wheel, subject to actual sudoers policy. Match listening ports to installed services and legitimate uses. After checking dependencies, stop or disable unnecessary services and allow required traffic only. Cloud security groups and the host firewall are separate layers.
Verify an actual recovery channel independent of SSH, such as a VM console. Record firewall state, SSH configuration, and account policy, and back up configuration files. An existing session remaining open does not prove that new logins are still permitted.
Verify key access before changing SSH policy
Test key authentication and sudo using a fresh session under a normal administrator account. Before restricting passwords, inspect Include files, Match blocks, and provisioning settings. Repeatedly appending directives can leave effective behavior different from what you intended.
sudo /usr/sbin/sshd -t
sudo /usr/sbin/sshd -T | grep -E "^(port|permitrootlogin|passwordauthentication|pubkeyauthentication) "
sshd -t checks configuration and key validity, while -T prints effective settings. With Match conditions, evaluate the relevant connection using -C as well. Reload the correct service only after validation, then test a new login. If it fails, restore the backup through the retained session or console and validate again.
Allow the verified management path before enabling UFW
This example assumes the lab server actually uses TCP port 22 for SSH; replace it consistently if the port differs. Restricting management by source can be appropriate, but an incorrect NAT or VPN egress address can lock you out. Inspect state and add the required allow rule before enabling the firewall.
sudo ufw status verbose
sudo ufw --dry-run allow 22/tcp
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status numbered
This rule permits 22/tcp from all sources and is not a complete Internet-facing access policy. Test a new connection, add and test any narrower source policy, then remove a broader rule only when the replacement works. Use the current numbered list and recorded original state to remove the exact intended rule.
Distinguish firewalld zones, runtime, and persistence
sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --get-default-zone
Identify the zone assigned to the actual interface. Replace REPLACE_WITH_ACTIVE_ZONE below and inspect --info-service=ssh to confirm it matches the SSH port. Test the runtime change first, then save only that intended rule permanently.
zone=REPLACE_WITH_ACTIVE_ZONE
sudo firewall-cmd --info-service=ssh
sudo firewall-cmd --zone="$zone" --add-service=ssh
sudo firewall-cmd --zone="$zone" --list-all
sudo firewall-cmd --permanent --zone="$zone" --add-service=ssh
sudo firewall-cmd --permanent --zone="$zone" --list-all
Runtime and permanent state differ: a reload can discard unsaved runtime changes. Copying all runtime state to permanent can unintentionally retain temporary allowances. Roll back only rules newly added by this exercise, in both states where applicable, and preserve management access until an alternative has been verified.
Maintain updates without bypassing SELinux
sudo apt update
apt list --upgradable
sudo dnf check-update
getenforce
Use the first block on Ubuntu and the second on Rocky Linux. A dnf check-update status of 100 can mean updates are available rather than a generic error. Apply updates after reviewing backups, service impact, and reboot requirements, then verify actual service responses and post-reboot behavior.
On Rocky Linux, SELinux controls access through labels and process policy. If a web service cannot read a file, inspect permissions, labels, and audit records instead of disabling enforcement. Nonstandard paths may need persistent labeling rules and restorecon. SELinux and firewall filtering solve different problems.




