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

Sponsored

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:

  1. Start with a deny-all default (except SSH, so you don't lock yourself out).
  2. Allow the ports you actually use.
  3. Enable the firewall.
  4. 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/deny syntax.
  • 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 ufw module.

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:

  1. Is the web server actually running? sudo ss -tlnp | grep :80.
  2. Is it listening on 0.0.0.0:80 or only on 127.0.0.1? If it's bound to localhost, the firewall isn't the problem.
  3. 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 -p will 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/tcp but it needs 80/udp for 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 ssh first, then enable.
  • Using sudo ufw allow 8080 without 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 inactive means the firewall is off — it's not enforced, but rules may still exist from prior configs; check verbose.

Variations

  1. Use sudo ufw allow from 192.168.1.0/24 to restrict access to a subnets instead of opening a port to the entire internet.
  2. For a dynamic, zone-based firewall on Red Hat family, try firewalld with its firewall-cmd interface.
  3. 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.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.