Set Up a Firewall with UFW
Set up a simple firewall with UFW in this Linux tutorial. Learn hands-on steps, troubleshooting, and what to study next in the networking track.
Focus: set up a simple firewall with ufw
You've built your Linux box, configured SSH, and even mastered systemd — but right now, every port on your server is a door, and you have no idea which ones are open for strangers. A default Ubuntu install has services listening on ports you never asked for, and without a firewall, you're one curl away from exposing a database or a debugging API to the entire internet. This lesson turns that panic into control: you'll learn to set up a simple firewall with ufw in under ten minutes, turning your server from a sieve into a fortress with a few deliberate commands.
The problem this lesson solves
Every network service you run — SSH, a web server, a database — listens on a TCP or UDP port. By default, Linux doesn't block any of them; if a process binds to a port, it's reachable from any machine that can reach your server's IP. That includes the whole internet if your server has a public address.
Consider a typical dev machine: you might run Postgres on 5432, Redis on 6379, or a Flask dev server on 5000. None of these were designed for public exposure, yet nothing stops a random scanner from finding them. Worse, if you ever install a package that opens a port for a status page or admin panel, you won't even notice until it's too late.
A firewall is your first line of defense — it decides which traffic is allowed in and out based on rules you define. The problem this lesson solves is simple: you need a fast, reliable way to say "allow SSH and HTTP, block everything else." UFW (Uncomplicated Firewall) is that tool.
Core concept / mental model
Think of your server as a building, and each port as a door. Without a firewall, every door is unlocked — any passerby can walk in. With a firewall, you become the security guard: you unlock specific doors for specific visitors, and you lock everything else by default.
UFW is a front-end for iptables, the Linux kernel's packet-filtering framework. It gives you a human-friendly syntax like allow 22 instead of wrestling with -A INPUT -p tcp --dport 22 -j ACCEPT. Under the hood, it still writes iptables rules, but you never have to see them.
Core mental model:
- Default policy — what to do with traffic that doesn't match any rule (usually deny incoming, allow outgoing).
- Rule — a specific exception: allow or deny a port, a protocol, or an IP.
- State — the firewall is either enabled or disabled. Rules exist but do nothing until you enable the firewall.
Here's the sequence that matters:
- Start with a deny-all default (except SSH, so you don't lock yourself out).
- Allow the ports you actually use.
- Enable the firewall.
- Verify the rules are applied.
Once you internalize that pattern, you can adapt it to any server.
How it works step by step
UFW manages rules through a set of simple commands. Let's walk through the logical flow:
Step 1: Check if UFW is installed
On Ubuntu and most Debian-based systems, UFW is installed by default. Verify with:
sudo ufw status
You'll likely see Status: inactive. That's fine — it means the firewall is present but not enforcing anything.
Step 2: Set default policies
The safest starting point is to deny all incoming traffic and allow all outgoing traffic:
sudo ufw default deny incoming
sudo ufw default allow outgoing
Setting these defaults before adding any allow rules ensures you never accidentally leave a port open while you're configuring.
Step 3: Allow the ports you need
Now add rules for the services you actually want to expose. The most critical one is SSH — if you're connecting remotely, blocking port 22 will lock you out:
sudo ufw allow ssh
UFW recognizes service names from /etc/services, so ssh maps to port 22. You can also use numbers directly:
sudo ufw allow 22
For a web server, allow HTTP and HTTPS:
sudo ufw allow http
sudo ufw allow https
Or specify a port and protocol:
sudo ufw allow 8080/tcp
Step 4: Enable the firewall
Here comes the critical moment — enabling the firewall can cut your connection if you didn't allow SSH first:
sudo ufw enable
You'll be prompted to confirm. After that, check the status:
sudo ufw status verbose
Output should look like:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
Step 5: Test your rules
From another machine, try connecting to an allowed port (SSH) and a disallowed port (e.g., 5432 if you didn't allow it). The disallowed port should time out or refuse the connection.
That's the entire flow. Once you've done it a few times, it takes under a minute.
Hands-on walkthrough
Let's set up a real firewall for a typical web server. This exercise also teaches you how to understand what you're changing.
Step 1: Inspect what's listening
Before you set any rules, see what services are currently listening:
sudo ss -tlnp
You'll see output like:
State Local Address:Port Process
LISTEN 0.0.0.0:22 sshd
LISTEN 0.0.0.0:8080 python3
Make a note of the ports — these are the doors you need to open.
Step 2: Apply the basic UFW configuration
Run these commands in order:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 8080/tcp
sudo ufw enable
Step 3: Verify with a full status
sudo ufw status numbered
You'll see numbered rules. This matters later for deleting specific rules from a VPS (see troubleshooting).
Step 4: Test the firewall
From a different machine, attempt to connect to a blocked port. For example, if port 5432 isn't allowed:
nc -zv your-server-ip 5432
Expected output:
nc: connect to your-server-ip port 5432 (tcp) failed: Connection refused
If you get Connection refused, the firewall is working — the port is blocked. If you get a successful connection, your firewall isn't active or the rule isn't right.
Once everything passes, you have a production-ready firewall for a simple web server.
Compare options / when to choose what
UFW is not the only way to filter traffic on Linux. Here's how it stacks up against the alternatives:
| Tool | Complexity | Best for | Drawbacks |
|---|---|---|---|
| UFW | Low | Simple servers, learning, time-critical tasks | Limited advanced features |
| iptables | High | Complex rules, direct control, legacy systems | Steep learning curve, verbose syntax |
| nftables | Medium-High | Modern Linux, complex setups | Newer syntax, steeper learning curve than UFW |
| Firewalld | Medium | Red Hat/CentOS systems, dynamic zones | Different zone model, not default on Debian/Ubuntu |
| Cloud security groups | Low | Cloud VMs (AWS, GCP, Azure) | Only works on the cloud provider, not the OS |
When to choose UFW:
- You're on Ubuntu or Debian and need a quick, reliable host-level defense.
- You want rules written with simple
allow/denysyntax. - You need to teach a team member how to manage firewall rules without a deep iptables background.
When to look elsewhere:
- If you need stateful inspection, port forwarding, or NAT, iptables/nftables give you more power.
- On a cloud VM, security groups act as an external firewall — combine them with UFW for defense-in-depth.
- If you're managing many servers with dynamic environments, consider configuration management like Ansible with the
ufwmodule.
Troubleshooting & edge cases
Every firewall setup hits a snag eventually. Here are the most common ones and how to fix them:
I locked myself out of SSH — I can't connect
Symptom: You ran ufw enable and your SSH session dropped.
Fix: If you still have console access (e.g., your cloud provider's web console), run sudo ufw allow ssh and then sudo ufw reload. If you've completely lost access, you may need to reboot into recovery or use the provider's console to disable the firewall (sudo ufw disable).
Prevention: Always set allow ssh before enabling, and test with a rule that only allows SSH from your IP if possible:
sudo ufw allow from YOUR_IP to any port 22
I allowed port 80 but the web server is still unreachable
Symptom: ufw status shows port 80 allowed, but external clients can't connect.
Checks:
- Is the web server actually running?
sudo ss -tlnp | grep :80. - Is it listening on
0.0.0.0:80or only on127.0.0.1? If it's bound to localhost, the firewall isn't the problem. - Are you on a cloud VM with a security group blocking port 80? Check the cloud provider's console.
UFW rules are being ignored or behave unexpectedly
Symptom: You allowed a port but traffic is dropped.
Potential causes:
- Docker bypasses UFW entirely because it manipulates iptables directly. A port mapped with
-pwill be open even if UFW denies it. - There's an earlier deny rule that conflicts. Check the order with
sudo ufw status numbered; the first matching rule wins. - The service uses a protocol you didn't allow (e.g., you allowed
80/tcpbut it needs80/udpfor DNS).
I can't remember what I enabled
Symptom: You see unexpected open ports.
Fix: Use sudo ufw status numbered to list rules with numbers. You can delete a rule by number:
sudo ufw delete 3
That's especially useful on a VPS where you can't easily "undo" a misconfigured rule.
What you learned & what's next
You now understand how to set up a simple firewall with ufw, and you can apply it in less than ten minutes. You learned that a firewall is a gatekeeper deciding which ports are open based on rules, that the safest approach is default deny plus explicit allow rules, and that enabling the firewall is the trigger that actually enforces those rules. You also saw how to compare UFW against alternatives and how to troubleshoot the classic mistakes — SSH lockout, placeholder rules, and Docker interference.
The core objectives are met: you can explain the mental model behind UFW, and you've completed a hands-on walkthrough that simulates a real web server scenario. This is a foundational networking skill that applies to nearly every server you'll ever touch.
Your next step in the Linux · networking · telemetry track is to move beyond firewalls and into observing what's happening on those open ports. You'll learn how to inspect traffic, monitor connections, and build a telemetry picture of your server. A firewall controls access — telemetry tells you who's knocking and what they're doing. Master both, and you'll have full control over your infrastructure.
Ready to open the next door? :fire:
Practice recap
For practice, curl ifconfig.me to find your public IP, then temporarily allow SSH only from that IP using sudo ufw allow from YOUR_IP to any port 22, disable UFW, and re-enable to confirm access persists. Next, try setting up a deny rule for a specific port you don't use and verify with nc -zv from another machine.
Common mistakes
- Enabling UFW before adding an SSH allow rule — instant lockout. Always run
sudo ufw allow sshfirst, thenenable. - Using
sudo ufw allow 8080without specifying the protocol — UFW then allows both TCP and UDP, which is broader than you usually need. - Forgetting that Docker bypasses UFW; an exposed container port is open regardless of your firewall rules.
- Assuming
ufw status inactivemeans the firewall is off — it's not enforced, but rules may still exist from prior configs; checkverbose.
Variations
- Use
sudo ufw allow from 192.168.1.0/24to restrict access to a subnets instead of opening a port to the entire internet. - For a dynamic, zone-based firewall on Red Hat family, try
firewalldwith itsfirewall-cmdinterface. - Rely on cloud security groups (AWS Security Groups, GCP firewall rules) for an external layer, and keep UFW as a second layer inside the OS.
Real-world use cases
- Securing a plain Ubuntu web server hosting a public site: allow SSH, HTTP, and HTTPS; deny everything else.
- Protecting a private API server that only responds to requests from a known internal network or a specific dev machine IP.
- Locking down a database server so only the application server's IP can reach port 5432, blocking all other public access.
Key takeaways
- A firewall enforces traffic rules; UFW makes that easy with allow/deny syntax.
- Always start with a default-deny incoming policy to minimize the attack surface.
- Explicitly allow SSH before enabling the firewall to avoid locking yourself out.
- Ports can be specified by name, number, or with a protocol (e.g.,
/tcp). - Enable the firewall to activate rules; verify with
ufw status verbose. - Watch out for things that bypass UFW, like Docker and misconfigured cloud security groups.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.