Level 1

Linux security baseline updates firewall and least privilege

Maximilian B. 5 min read 3 views

Security baseline work is routine system maintenance, not a one-time project. If a server was built six months ago and never reviewed, it usually has extra open ports, old service accounts, and broad sudo access that nobody still needs. Entry-level technicians can fix most of this with a short checklist: confirm required network ports, set a default deny policy, and reduce privileges for users and services.

In production, these changes have direct results. Fewer open ports means fewer paths for scanning and brute-force traffic. Least privilege means one compromised account does not automatically become full root access. The goal is simple: small, controlled blast radius when something goes wrong.

Start with a clear baseline, then change one layer at a time

Before editing rules, collect current state and write it down. This avoids accidental outages and helps rollback if needed.

# Current listening ports and owning processes
sudo ss -tulpn

# Running services (look for old or unknown daemons)
sudo systemctl list-units --type=service --state=running

# Current firewall framework in use
sudo nft list ruleset
sudo systemctl is-active firewalld || true
sudo ufw status verbose || true

For beginners, this step prevents "I locked out SSH" incidents. For operators, it provides evidence for change reviews. If port 3306 is listening but your database should be private, fix network policy before patch day, not after an incident.

Apply a firewall baseline that matches your distro family

All modern distributions here use the Linux nftables stack underneath, but day-to-day tools differ. Debian and Ubuntu teams often prefer UFW for simple host rules. Fedora and RHEL teams usually standardize on firewalld because it supports zones and integrates well with enterprise policy workflows.

Example baseline with UFW (Debian 13.3, Ubuntu 24.04.3 LTS, Ubuntu 25.10)

# Install if missing
sudo apt update
sudo apt install -y ufw

# Baseline policy
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Required services only
sudo ufw allow OpenSSH
sudo ufw allow 443/tcp

# Enable and verify
sudo ufw enable
sudo ufw status numbered

Production consequence: if a developer temporarily starts a debug server on port 3000, it stays blocked from external clients unless you explicitly allow it.

Example baseline with firewalld (Fedora 43, RHEL 10.1, RHEL 9.7)

# Install/start if needed
sudo dnf install -y firewalld
sudo systemctl enable --now firewalld

# Keep public zone strict
sudo firewall-cmd --set-default-zone=public
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=https

# Remove anything not required in your environment
sudo firewall-cmd --permanent --remove-service=cockpit

# Apply and verify
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

If your organization uses Cockpit, keep it and restrict source networks instead of removing it. The point is explicit allow rules, not guessing what is safe.

Enforce least privilege for people and services

Least privilege means each identity gets only what it needs for its job, nothing more. Two common problems are shared admin accounts and services running as root when they do not need to.

Create a dedicated service user

# Service account without shell login
sudo useradd --system --home /srv/inventory --shell /usr/sbin/nologin inventorysvc

# Data directories with minimum required access
sudo install -d -o inventorysvc -g inventorysvc -m 0750 /srv/inventory
sudo install -d -o root -g inventorysvc -m 0750 /etc/inventory

Now the application owns only its own data path. If exploited, the process cannot edit `/etc/shadow` or random system files.

Scope sudo to one command, then validate syntax

# /etc/sudoers.d/inventoryops
inventoryops ALL=(root) NOPASSWD:/usr/bin/systemctl restart inventory-api

# Always validate before closing your terminal
sudo visudo -cf /etc/sudoers.d/inventoryops

Operational effect: on-call staff can restart one service during incidents without getting full root shell access.

Harden systemd service boundaries

# /etc/systemd/system/inventory-api.service (service section excerpt)
[Service]
User=inventorysvc
Group=inventorysvc
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/srv/inventory
CapabilityBoundingSet=
AmbientCapabilities=

These options are supported on Debian 13.3, Ubuntu 24.04.3 LTS, Ubuntu 25.10, Fedora 43, RHEL 10.1, and RHEL 9.7. They limit filesystem writes and Linux capabilities, which reduces post-exploit movement.

Compatibility notes for current distro targets

Distribution Firewall path Least privilege focus
Debian 13.3 UFW or direct nftables. Keep inbound default deny. Use system users and strict file modes (`0750`, `0640`).
Ubuntu 24.04.3 LTS / 25.10 UFW is common for host-level policy. Validate cloud security groups too. Combine sudo scoping with AppArmor profiles where available.
Fedora 43 firewalld with zone-based policy is default practice. Keep SELinux enforcing and label service data correctly.
RHEL 10.1 firewalld standard, persistent rules via `--permanent`. Harden unit files and avoid persistent root sessions.
RHEL 9.7 (compatibility) Same firewalld commands as RHEL 10.1 for this baseline. Same sudoers and systemd hardening approach works unchanged.

Verify changes and keep a rollback path

Do not mark security work done until you test from both inside and outside the server.

# Local verification
sudo ss -tulpn
sudo ufw status verbose 2>/dev/null || sudo firewall-cmd --list-all
sudo -l -U inventoryops
sudo systemd-analyze security inventory-api.service

# Remote verification (from another host)
nmap -Pn -p 22,80,443 your-server.example.com

Keep rollback notes in the same ticket: previous firewall state, removed sudo rules, and prior unit file content. In outages, speed matters. Good rollback notes save real downtime.

Summary

A usable Linux security baseline has two parts: strict network exposure and strict privileges. Start by measuring what is running, then allow only required ports. Run services as dedicated accounts, scope sudo to exact commands, and harden systemd units. Finally, verify with command output and remote tests. This workflow is simple enough for junior technicians and strong enough for production operations across Debian 13.3, Ubuntu 24.04.3 LTS and 25.10, Fedora 43, RHEL 10.1, and RHEL 9.7 environments.

Share this article
X / Twitter LinkedIn Reddit