Linux Firewall Basics

By Vishvesh Patel · DevOps EngineerUpdated September 16, 2026

Configure a Linux firewall without locking yourself out. Ufw, firewalld and iptables compared, allowing SSH first, zones and persistence.

Why Firewalls Matter

A firewall controls which network traffic is allowed into and out of a Linux system. Even if your application is secure, leaving unnecessary ports open increases risk.

In DevOps, firewall rules help enforce the principle of least exposure: allow only the services that should be reachable and block everything else by default.

UFW on Ubuntu

UFW stands for Uncomplicated Firewall. It provides a friendlier interface over lower-level packet filtering.

Basic UFW workflow

Enable the firewall:

sudo ufw enable

Check status and rules:

sudo ufw status
sudo ufw status numbered

Allow SSH so you do not lock yourself out:

sudo ufw allow ssh
sudo ufw allow 22/tcp

Allow a web port:

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

Deny a port:

sudo ufw deny 8080/tcp

Delete a rule:

sudo ufw delete allow 8080/tcp

UFW can also allow by application profile when profiles exist:

sudo ufw app list
sudo ufw allow "Nginx Full"

Tip: Before enabling a firewall on a remote server, always allow SSH first. Otherwise you can block your own access.

iptables Basics

iptables is a classic low-level firewall tool. Many higher-level interfaces ultimately build rules on top of similar kernel packet filtering mechanisms.

Three important built-in chains are:

  • INPUT for traffic coming into the host
  • OUTPUT for traffic leaving the host
  • FORWARD for traffic being routed through the host

Common actions include:

  • ACCEPT to allow traffic
  • DROP to silently discard traffic
  • REJECT to deny traffic and usually send a response

Example rules:

sudo iptables -L -n -v
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -j DROP

This illustrates a common pattern: allow specific traffic, then drop the rest.

Note: Raw iptables changes may not persist across reboots unless the system has a persistence mechanism configured.

firewalld on RHEL and CentOS Style Systems

firewalld is common on RHEL family systems and introduces the idea of zones. A zone represents a trust level and associated rules.

Check firewall state:

sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones

List allowed services in the default zone:

sudo firewall-cmd --list-services

Allow HTTP and HTTPS permanently:

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

Open a specific port:

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

Remove a port rule:

sudo firewall-cmd --remove-port=8080/tcp --permanent
sudo firewall-cmd --reload

Zones let you apply different rule sets based on interface or network context, which is helpful on more complex hosts.

Default Deny and Least Privilege

A good firewall strategy usually starts with a restrictive baseline:

  • deny unsolicited inbound traffic by default
  • allow only required ports and protocols
  • review rules regularly
  • document why each exposed port exists

For example, a public web server might allow:

  • 22/tcp for SSH from admin networks
  • 80/tcp for HTTP
  • 443/tcp for HTTPS

Everything else should stay blocked unless there is a clear need.

A Practical Example

Suppose you deploy an application on port 3000 behind Nginx. The outside world should reach ports 80 and 443, but not port 3000 directly.

A safe setup could be:

sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 3000/tcp
sudo ufw status

This keeps the app reachable through the reverse proxy but not exposed directly.

Choosing the Right Tool

  • use UFW for simpler Ubuntu administration
  • use firewalld on many RHEL style systems
  • learn iptables to understand the underlying traffic filtering model

The exact tool changes by distribution, but the core ideas stay the same: identify required traffic, allow it intentionally, and block unnecessary access.

What You Should Remember

Linux firewalls are about controlled exposure, not just blocking everything randomly. UFW simplifies common Ubuntu tasks, iptables teaches the core model of chains and targets, and firewalld adds zone-based management for many enterprise systems.

If you follow a default-deny mindset and open only what is necessary, you will already be much closer to a secure server baseline.

Test Your Understanding

Exercise

Exercise 1: Allowing web traffic with UFW

Which UFW command allows inbound HTTPS traffic on the standard port?

Exercise

Exercise 2: Understanding iptables chains

Which iptables chain handles traffic arriving at the local host?

Exercise

Exercise 3: Secure firewall posture

Which practice best matches the lesson's recommended firewall approach?


Frequently Asked Questions

Should I use ufw, firewalld or iptables?

Use whichever your distribution manages, and use only one. ufw is the Ubuntu and Debian front end and is the simplest, ufw allow 22/tcp and you are done. firewalld is the RHEL, CentOS and Fedora equivalent, organised around zones. Both write rules through the kernel's packet filter for you, so running iptables commands alongside them produces a rule set that looks nothing like either tool reports. Work with iptables or nftables directly only when you genuinely need rules the front end cannot express.

Why is my port still blocked after allowing it in the firewall?

Check three things in order, because the firewall is only one of them. First, is something actually listening, and on which address, sudo ss -tlnp, where 127.0.0.1:8080 means the service will never accept an external connection regardless of firewall rules. Second, is the rule active, ufw status verbose or firewall-cmd --list-all. Third, is there a firewall outside the host: a cloud security group, network ACL or load balancer rule, which is the most commonly forgotten layer on AWS, Azure and GCP.

How do I allow SSH before enabling ufw?

sudo ufw allow 22/tcp (or sudo ufw allow OpenSSH) before sudo ufw enable, because ufw's default policy denies incoming traffic and enabling it first drops your current SSH session with no way back in on a remote machine. The command even warns you. If you have already locked yourself out, recovery means console access through your cloud provider or hypervisor. Change the port in the rule if SSH is not on 22.

What does firewalld's zone concept mean?

A zone is a named set of rules applied to interfaces or source addresses, so the same host can treat traffic differently depending on where it arrives from, public for an internet-facing interface, internal or trusted for a private network. Rules are added per zone: firewall-cmd --zone=public --add-service=https. firewall-cmd --get-active-zones shows which interface is in which zone, and the most common surprise is adding a rule to the default zone while the interface you care about is in a different one.

How do I make firewall rules survive a reboot?

ufw and firewalld both persist by design, with one catch for firewalld: changes are runtime-only unless you pass --permanent, so the pattern is firewall-cmd --permanent --add-service=https followed by firewall-cmd --reload. Raw iptables rules are not persistent and vanish on reboot, which is why iptables-persistent (or iptables-save into a file loaded at boot) exists. Verify by checking the rules after a reboot rather than assuming.

What does "default deny" mean and why does it matter?

Blocking all incoming traffic by default and explicitly allowing only what is needed, rather than allowing everything and blocking known-bad ports. The difference is what happens to something you did not think about: with default deny, a service that starts listening unexpectedly, a debug port, a database bound to 0.0.0.0, a container publishing a port, is unreachable rather than exposed. ufw default deny incoming plus ufw default allow outgoing is the standard starting point.

Continue Learning

Explore Related Topics

Try the Tool

Practise this in the browser

Linux Playground

Practise real shell commands in a simulated terminal.

When it breaks

Related Resources