Firewalls with ufw
Default-deny policies, allowing services and ports, rate limiting, and firewalld on Fedora/RHEL.
A firewall decides which network traffic may enter (and leave) a machine. On a server, the safest policy is simple: deny everything incoming, then allow only the services you actually run, typically SSH, HTTP and HTTPS. Under the hood Linux uses the kernel's netfilter framework (managed through nftables or the older iptables), but you'll rarely write those rules by hand. On Ubuntu you use ufw (Uncomplicated Firewall), and on Fedora/RHEL firewalld.
💡 These commands need root and a real (virtual) machine. They won't work inside most containers. Practise on a throwaway VM or cloud server, and keep a second SSH session or the provider's web console open in case you lock yourself out.
Why bother?#
Run sudo ss -tlnp on a fresh server and you'll often see more listening services than you expected: a database, a cache, an admin panel, something a package started. A firewall makes sure that only the ones you choose are reachable from outside, even if a service is misconfigured to listen on 0.0.0.0. It's a core layer of defence in depth.
ufw on Ubuntu and Debian#
ufw ships with Ubuntu but is inactive by default. On Debian, install it with sudo apt install ufw.
A safe first setup
ufw creates IPv6 rules automatically (controlled by IPV6=yes in /etc/default/ufw).
Allowing traffic
💡 Restrict databases and admin tools by source. MySQL (3306), PostgreSQL (5432), Redis (6379) and Elasticsearch (9200) should almost never be open to
Anywhere. Allow them only from the app servers' IPs or private network, or keep them on127.0.0.1.
Rate limiting SSH
limit allows the connection but denies an IP that attempts 6 or more connections within 30 seconds, which slows down brute-force bots. It shows as LIMIT IN in the status.
Deleting and inserting rules
Rules are evaluated top to bottom and the first match wins. That's why a deny for one IP must come before a broad allow.
Other useful commands
The Docker gotcha
Docker inserts its own iptables rules for published ports (docker run -p 8080:80), and they are processed before ufw's rules. A container port published on 0.0.0.0 is reachable from the internet even if ufw denies it. Fixes:
- publish on localhost only:
-p 127.0.0.1:8080:80, and put a reverse proxy in front; - or configure the
DOCKER-USERchain, or use a cloud firewall in front of the server.
firewalld on Fedora, RHEL, Rocky and AlmaLinux#
firewalld is enabled by default on Fedora and RHEL-family systems. It organises rules into zones (public, internal, trusted, ...), and each network interface belongs to one. Changes are runtime-only unless you add --permanent:
(That's the output of --list-all, abridged.) Don't run ufw and firewalld together; pick the one your distribution uses.
Cloud firewalls#
Cloud providers have their own network-level firewalls: AWS security groups, GCP VPC firewall rules, Azure NSGs, and DigitalOcean/Hetzner cloud firewalls. Traffic must pass both the cloud firewall and the host firewall. Use them together: the cloud firewall as the outer wall, ufw/firewalld as the inner one. When a port "won't open", check both.
Testing your firewall#
From another machine (not the server itself, since local traffic isn't filtered the same way):
On the server, sudo ss -tlnp shows what's listening, and sudo ufw status shows what's allowed. The difference between the two lists is what your firewall is protecting.
Common mistakes#
- Enabling the firewall before allowing SSH on a remote server, and getting locked out. Recover through the provider's web console.
- Opening database ports to
Anywhere. Restrict them by source IP or subnet. - Forgetting IPv6. If the server has an IPv6 address, rules must cover it (ufw does this by default).
- Assuming ufw protects Docker containers. Published ports bypass it.
- Deleting rules by number twice in a row. The numbers shift after each delete.
- firewalld changes without
--permanent, which disappear on the next reload or reboot.
What's next#
A firewall controls who can reach your services. Next, learn to keep an eye on how those services are performing, with performance monitoring: CPU, memory, disk I/O and network bottlenecks.
Check your understanding
Quick quiz
1.You're configuring ufw on a remote server over SSH. What must you do BEFORE
sudo ufw enable?2.What does
sudo ufw limit 22/tcpdo?3.On Fedora/RHEL with firewalld, how do you make a rule survive a reload or reboot?
Finished reading?
Mark this lesson complete to track your progress.