Why UFW Matters for Ubuntu Servers

Every server connected to the internet receives unwanted traffic. Port scans, automated exploit probes, spam bots, and brute force attempts are constant. A firewall is the first line of defence — it decides what traffic to accept and what to block before that traffic reaches your application.

UFW (Uncomplicated Firewall) is Ubuntu's default firewall interface. It is a simplified front-end to iptables, which is the actual Linux kernel firewall. iptables is powerful but verbose and complex. UFW provides the essential functionality with a much simpler command structure, which makes it practical for most use cases without sacrificing the security that matters.

This guide covers UFW setup that applies to any Ubuntu web server, whether it is a VPS, a cloud instance, or a physical server. For a broader look at securing a new Ubuntu installation, the guide to Ubuntu 22.04 security hardening covers the first steps worth taking after provisioning a server.

Understanding the Default Policy

UFW has two default policies: incoming traffic is denied by default, and outgoing traffic is allowed by default. This is the correct starting point. You explicitly allow the incoming services you need, and everything else is blocked.

Never change the default incoming policy to allow without a specific reason. If you do, your server accepts all incoming connections, which defeats the purpose of having a firewall.

sudo ufw default deny incoming
sudo ufw default allow outgoing

These two commands establish the baseline. From here, you add exceptions for the services you actually need to run.

Allowing SSH Before Enabling the Firewall

The single most important step before enabling UFW: ensure SSH is allowed. If you enable the firewall with SSH blocked, you lock yourself out of the server. This is a common mistake that causes unnecessary downtime.

Always allow SSH first:

sudo ufw allow 22/tcp

If you have changed your SSH port from the default 22 to something else, use that port instead:

sudo ufw allow 2222/tcp

The /tcp specifies the protocol. SSH uses TCP, so including it is correct and prevents UDP traffic on that port from being allowed.

For servers where you connect from a fixed IP address, restricting SSH access to that IP only is more secure. If your IP changes frequently, rate limiting (covered later) provides better protection against brute force attempts.

Allowing Web Traffic

A web server needs to accept HTTP and HTTPS traffic from anywhere:

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

Alternatively, use the Apache profile if Apache is your web server. UFW has profiles for common applications that open the correct ports automatically:

sudo ufw allow 'Apache Full'

This opens both port 80 and port 443. The quoted name must match the profile name exactly, which you can list with:

sudo ufw app list

UFW profiles are convenient because they handle the port details automatically. If a profile changes which ports it uses in a future update, using the profile means your firewall rules stay correct without manual adjustment.

Enabling UFW

With SSH and web traffic allowed, enable the firewall:

sudo ufw enable

UFW will ask for confirmation. Type y. The command output confirms the firewall is active. Verify with:

sudo ufw status verbose

The verbose output shows the default policies, the rules in order, and confirms the firewall is active. Checking this output after enabling UFW is good practice — it confirms your rules are loaded correctly before you potentially lose access to the server.

Understanding UFW Rule Order

UFW processes rules in the order they are added. The first matching rule wins. This means if you allow SSH on port 22 and then later deny all incoming traffic, the allow rule takes precedence because it comes first.

List all rules in order:

sudo ufw status numbered

You can delete a rule by its number:

sudo ufw delete 3

Or insert a rule at a specific position:

sudo ufw insert 1 allow from 203.0.113.50 to any port 22

This inserts a rule at position 1 that allows SSH only from the IP address 203.0.113.50. This is the most restrictive SSH access pattern — lock it to a specific IP rather than allowing it from anywhere.

When managing rules, always verify the order makes sense before testing. A misplaced rule can block legitimate traffic or expose services you intended to restrict.

Allowing Traffic from Specific IP Addresses Only

For services that should not be publicly accessible, restrict them to known IP addresses. The admin panel of a web application, phpMyAdmin, or a staging environment should not be accessible from any IP on the internet.

Allow access to a specific IP or subnet:

sudo ufw allow from 203.0.113.0/24 to any port 3306

This allows MySQL connections only from the 203.0.113.0/24 subnet. MySQL listens on port 3306 by default, so this rule restricts database access to your internal network or a specific set of trusted IPs. Never expose MySQL to the internet directly.

Allow from your home or office IP address to a specific application port:

sudo ufw allow from YOUR_HOME_IP to any port 8080

Find your home IP address with:

curl ifconfig.me

If you are setting up restricted access for phpMyAdmin, the guide to securing phpMyAdmin on Ubuntu covers the full configuration, including the firewall rules needed to allow access only from trusted IPs.

Denying Specific Traffic

By default, everything not explicitly allowed is denied. You can also add explicit deny rules, which is useful for blocking known bad IPs or subnets:

sudo ufw deny from 198.51.100.0/24

Add this before any more permissive rules if you want to ensure these IPs are blocked regardless of other allow rules. Use explicit deny rules for IPs you know are hostile, identified from your logs or from security advisories.

Checking your logs regularly helps identify hostile traffic patterns. If an IP shows consistent probing behaviour over days or weeks, adding an explicit deny rule reduces noise in your logs and prevents resources being spent on handling their requests.

Rate Limiting with UFW

UFW has a built-in rate limit feature for SSH. This blocks IPs that make too many SSH connection attempts in a short time, providing automatic protection against SSH brute force attacks while still allowing legitimate connections:

sudo ufw limit 22/tcp

This is better than simply allowing SSH from a specific IP if your IP address changes regularly, since it allows normal use but blocks rapid repeated attempts. Rate limiting works well alongside other measures like fail2ban, which can provide more sophisticated detection of attack patterns. The guide to Fail2Ban SSH and HTTP protection explains how these tools complement each other.

UFW Profiles for Common Applications

UFW ships with application profiles that know which ports a service needs. List them:

sudo ufw app list

Show the details of a profile to see exactly which ports and protocols it opens:

sudo ufw app info 'Nginx Full'

Available profiles include Apache (HTTP only), Apache Full (HTTP and HTTPS), Nginx Full (HTTP and HTTPS), and Postfix (SMTP). Using profiles is more convenient than remembering specific port numbers.

When you install a web server like Nginx or Apache on Ubuntu, the installation process registers the appropriate UFW profile automatically. You can check available profiles at any time with sudo ufw app list.

Disabling and Resetting UFW

To temporarily disable the firewall (for maintenance or troubleshooting):

sudo ufw disable

Remember to re-enable it when done. To reset UFW to its default state (deleting all rules):

sudo ufw reset

This is useful when you have a complex rule set that needs a clean start. Resetting requires you to reconfigure your allow rules from scratch, so only do it when you are starting fresh.

Before running a reset, export your current rules if you might need to review them later:

sudo ufw status verbose > ~/ufw-backup.txt

This creates a text file with your current configuration that you can refer to when rebuilding your rules.

Testing and Verifying Your Rules

After configuring UFW, test that it works as expected. From a machine not in your allowed IP list, verify that blocked services are indeed inaccessible. From an allowed IP, verify you can reach the services you have opened.

Check the logs for blocked connection attempts, which tells you what traffic is reaching your server:

sudo tail -f /var/log/ufw.log

Patterns of blocked connections from the same IP address indicate probing or scanning activity. If an IP is clearly hostile (high volume of probing over days or weeks), block it explicitly with a deny rule.

When testing, be methodical. Start with the services you have opened and confirm they are reachable from the expected locations. Then test that services you have restricted are not reachable from untrusted IPs. Document your testing results so you have a record of what works before making changes in production.

Baseline Configuration for a Web Server

The correct baseline configuration for a typical web server looks like this:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 'Apache Full'
sudo ufw enable

Everything else is exception-based — allow what you need, deny what you do not. Add FTP only if you genuinely use FTP. Add mail ports only if you run a mail server. The fewer open ports, the smaller the attack surface.

This baseline assumes a standard Apache web server. For Nginx, use sudo ufw allow 'Nginx Full' instead. The principle remains the same regardless of which web server you use.

Regular Maintenance Tasks

UFW rules do not require frequent changes, but regular review is worthwhile. Every few months, check your active rules and compare them against what your server actually needs to run. Services that have been removed may still have firewall rules allowing traffic that is no longer necessary.

When you install new software, check whether it registers a UFW profile. Many popular services do, which makes adding the correct firewall rules straightforward. For services without a profile, check the documentation to identify which ports need to be open.

After any firewall change, verify the result with sudo ufw status verbose. This habit catches mistakes before they cause problems.

What to Do Next

Configuring UFW is one part of securing an Ubuntu server. A complete security posture also includes keeping software updated, using fail2ban to detect automated attacks, configuring secure SSH settings, and maintaining working backups. Each of these layers reduces risk without requiring constant attention once it is set up correctly.

If your server is new or has not had a security review recently, a practical hardening check can identify the settings that matter most for your specific setup. A Ubuntu security hardening review covers the key areas worth checking on a fresh installation or an existing server that has not been audited recently.