You are currently viewing Linux Firewall Basics: Safer UFW and firewalld Rules

Linux Firewall Basics: Safer UFW and firewalld Rules

Start with one question: which inbound connections does this machine actually need? A personal workstation may need none. A development server may need SSH from a trusted network plus web traffic on ports 80 and 443. Every open port without a clear purpose increases the system’s exposed surface.

On most current distributions, the Linux kernel enforces firewall rules through netfilter. UFW and firewalld provide more approachable ways to manage those rules than jumping straight into nftables or iptables. For beginners, the aim is a small policy you can understand, test, and recover from if something goes wrong.

Start with a connection inventory

Before changing any rules, check which services are listening for network connections. Run this locally:

sudo ss -tulpn

The output lists listening TCP and UDP sockets and, where permissions permit, the process behind each one. Focus on the address and port:

  • 127.0.0.1:3000 is bound only to the local machine and cannot be reached directly from the network.
  • 0.0.0.0:22 accepts SSH connections on every IPv4 network interface.
  • [::]:80 accepts HTTP traffic on every IPv6 interface.

A service may be configured correctly and still be more exposed than intended if it listens on every interface. Firewall rules provide a useful second layer, but stopping an unneeded service or binding it to localhost is usually preferable to leaving it running and blocking the port.

Also establish how you administer the system. If you are connected over SSH, applying a default-deny inbound policy before allowing SSH can lock you out. Keep a second authenticated session open while you test changes. If available, have a provider console, physical access, or another approved recovery method ready.

Terminal showing a Linux firewall rule check

Choose the management tool already suited to your distribution

Use one firewall management layer at a time. Combining UFW with firewalld, or adding legacy iptables rules without understanding how they interact, makes the active policy harder to predict.

Tool Common use Good fit for
UFW Often available on Ubuntu and Debian-based systems Single machines and simple server policies
firewalld Common on Fedora, RHEL, Rocky Linux, and similar systems Zone-based policies and systems managed dynamically
nftables Native rules framework on current Linux kernels Advanced users building explicit custom policies

Check what is already running before installing or enabling another tool:

sudo systemctl status ufw
sudo systemctl status firewalld

On distributions that use UFW, it is usually the least error-prone starting point. On systems built around firewalld, work with its zones instead of replacing the existing setup. Raw nftables is powerful, but it requires a solid grasp of packet flow, connection tracking, and rule order.

Set up a cautious UFW policy

UFW makes a common baseline easy to express: deny unsolicited inbound traffic, allow normal outbound traffic, then add only the inbound exceptions you need. First, review the current state:

sudo ufw status verbose

If you are administering the machine remotely over SSH, allow the management port before enabling UFW. Port 22 is the usual SSH port, but use the port configured on your server.

sudo ufw allow 22/tcp
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
sudo ufw status numbered

For a web server, add HTTP and HTTPS explicitly:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

When available, service profiles can make rules easier to read:

sudo ufw app list
sudo ufw allow 'OpenSSH'

Check which ports a profile includes before using it. A profile is only a convenience label; it may not match your architecture.

Restrict administrative access by source address

SSH rarely needs to be available to every address if administration comes from a fixed office, VPN, or home network. For example, this rule permits SSH only from the private network 192.168.50.0/24:

sudo ufw allow from 192.168.50.0/24 to any port 22 proto tcp

Use this approach only when the source range is stable and correctly identified. If an administrator's address changes often, a managed VPN or a planned access method may be more practical than repeatedly widening firewall rules.

Review rules by number and remove them precisely:

sudo ufw status numbered
sudo ufw delete 3

Confirm the rule number immediately before deletion, since numbering changes after a rule is removed.

Use firewalld zones on Fedora and RHEL-family systems

firewalld groups network trust levels into zones. An interface might belong to public, home, or trusted. The label matters less than the rules attached to it, so do not assume a zone is safe because its name sounds familiar.

Check active zones and the interfaces assigned to them:

sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all

To permanently allow SSH in the active public zone, run:

sudo firewall-cmd --permanent --zone=public --add-service=ssh
sudo firewall-cmd --reload

For a web service, add the predefined HTTP and HTTPS services:

sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload

The --permanent option saves the configuration across reboots, but permanent changes usually need a reload before they take effect. Without one, a rule may work temporarily and then disappear when the service reloads or the machine restarts. Inspect the result with:

sudo firewall-cmd --zone=public --list-all

Ports versus services

Use a service definition when it accurately describes the protocol you are exposing. It documents intent: allowing https is clearer than allowing an unexplained port number. Custom development services often need a port rule instead:

sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp
sudo firewall-cmd --reload

Do not leave a test API exposed on a public interface longer than necessary. During local development, bind it to 127.0.0.1 whenever possible. If it must be reachable inside a private lab network, limit access through an appropriate zone or source rule, then remove the exception when testing is finished.

Server protected by a clearly defined network policy

Understand what a basic firewall does and does not do

A host firewall filters traffic entering or leaving that host. It can block unwanted inbound connection attempts, limit access to a service, and reduce accidental exposure. It does not replace secure service configuration, timely patching, strong authentication, backups, or application security controls.

Allowing port 443, for example, is necessary for a public HTTPS site, but it does not protect an application with weak authorization checks. Similarly, blocking inbound database traffic does not stop a vulnerable web application from misusing a database that remains available locally.

Stateful rules matter too. Modern Linux firewall tools usually use connection tracking, which allows reply traffic for an established connection. That is why a workstation can deny unsolicited inbound traffic while still browsing the web, downloading package updates, and receiving responses to connections it started.

Include IPv6 in the policy

Ignoring IPv6 creates a common gap. A machine may have both IPv4 and IPv6 connectivity, and a rule intended for one protocol can leave the other route open. UFW often manages both when IPv6 support is enabled in its configuration. Verify this with sudo ufw status verbose and look for IPv6 rules in the output.

With firewalld, inspect active interfaces and rules instead of assuming IPv6 coverage. Test from an authorized device on the relevant network by using the service normally—for example, connect with SSH to the server's authorized address. Do not broadly probe systems or networks you do not own or administer.

Test safely and keep a recovery path

Test the exact service and access path you intend to support. From an approved client system, try a legitimate SSH login, load the web application over HTTPS, or connect to the relevant development service. On the protected host, confirm that the service is still listening and that logs do not show unexpected denials.

Useful local checks include:

sudo ss -tulpn
sudo ufw status verbose
sudo firewall-cmd --list-all

Run only the command that matches the firewall tool you chose. If a change blocks legitimate traffic, inspect the active rules, confirm the service address and port, and check whether the client is using IPv4 or IPv6. Do not solve the problem by permanently allowing an overly broad range of ports or source addresses.

For servers, document every exception in operational notes: the service name, port and protocol, source restrictions, business purpose, owner, and review date. A brief entry such as “TCP 22 from VPN subnet only; infrastructure administration; review quarterly” makes later cleanup safer.

Maintain rules as services change

Firewall configuration is not a one-time task. Remove rules when a project ends, review them after deploying new services, and check the policy after network-interface or VPN changes. Package upgrades can also alter service behavior, especially when a daemon starts listening on additional addresses.

A minimal web-server policy might include default-deny inbound behavior, outbound access required by the host, SSH restricted to an administration network, and TCP 80 and 443 for the public application. If the application moves behind a reverse proxy, remove the backend port from the public firewall policy and bind it to localhost or a private interface where possible.

After a planned rule change, save the command output in your change record. During a maintenance window, reboot and confirm that the intended rules, listening services, and remote administrative access all remain in place.