How To

UFW Firewall Commands with Examples on Ubuntu 24.04 / 22.04

UFW (Uncomplicated Firewall) is the default firewall management tool on Ubuntu and other Debian-based distributions. It provides a straightforward command-line interface on top of iptables (or nftables on newer kernels) for managing host-based firewall rules. Instead of writing raw iptables rules, UFW lets you allow or block traffic with simple, readable commands.

Original content from computingforgeeks.com - post 145106

This guide covers every common UFW operation – from basic allow/deny rules to rate limiting, Docker integration, port forwarding, and logging. All commands were tested on Ubuntu 24.04 with UFW 0.36.2.

Prerequisites

To follow this guide, you need:

  • Ubuntu 24.04 or 22.04 (server or desktop)
  • Root access or a user with sudo privileges
  • SSH access to the server (if remote)

Step 1: Install and Enable UFW

UFW comes pre-installed on Ubuntu. Verify it is present and check the version:

sudo apt install ufw

Check the installed version:

ufw version

Output:

ufw 0.36.2
Copyright 2008-2023 Canonical Ltd.

Before enabling UFW, set default policies. This is important because the defaults determine what happens to traffic that does not match any explicit rule. Deny all incoming connections and allow all outgoing:

sudo ufw default deny incoming
sudo ufw default allow outgoing

If you are connected over SSH, allow SSH traffic before enabling UFW. Skipping this step will lock you out of the server:

sudo ufw allow ssh

Now enable UFW:

sudo ufw enable

Output:

Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Verify the firewall status with verbose output:

sudo ufw status verbose

Output:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)

Step 2: Allow Services and Ports

UFW accepts both service names (from /etc/services) and port numbers. Here are the most common ways to open ports.

Allow by service name:

sudo ufw allow http
sudo ufw allow https

Allow by port number and protocol:

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

Allow a port with a comment (useful for tracking why a rule exists):

sudo ufw allow 8080/tcp comment 'Web app'

Allow a range of ports. You must specify the protocol when using ranges:

sudo ufw allow 6000:6100/tcp

Allow UDP traffic on a specific port (for example, DNS):

sudo ufw allow 53/udp

Step 3: Allow from Specific IPs and Subnets

For tighter security, restrict access to specific source IPs or subnets instead of opening ports to the entire internet.

Allow all traffic from a single IP address:

sudo ufw allow from 10.0.1.50

Allow all traffic from a subnet:

sudo ufw allow from 10.0.1.0/24

Allow a subnet to connect to a specific port (for example, MySQL on port 3306):

sudo ufw allow from 192.168.1.0/24 to any port 3306

Allow an IP to reach a specific port on a specific network interface:

sudo ufw allow in on eth0 from 10.0.1.0/24 to any port 22

This is useful on multi-homed servers where you want SSH access only on the management interface.

Step 4: Deny and Reject Traffic

UFW supports two ways to block traffic: deny and reject. Both prevent the connection, but they behave differently:

  • deny – silently drops the packet. The sender gets no response and eventually times out.
  • reject – drops the packet but sends an ICMP “port unreachable” response. The sender immediately knows the connection was refused.

Use deny for external-facing rules (attackers learn nothing) and reject for internal networks (faster feedback for legitimate users hitting the wrong port).

Deny all traffic from a specific IP:

sudo ufw deny from 203.0.113.100

Deny an entire subnet:

sudo ufw deny from 203.0.113.0/24

Deny outgoing traffic on a port (for example, block outbound SMTP to prevent spam):

sudo ufw deny out 25

Reject incoming traffic on a specific interface and port:

sudo ufw reject in on eth0 to any port 80

Step 5: Rate Limiting for Brute Force Protection

UFW has a built-in rate limiting feature that denies connections from an IP address if it attempts 6 or more connections within 30 seconds. This is effective against SSH brute force attacks without needing additional tools like Fail2ban.

Enable rate limiting on SSH:

sudo ufw limit ssh/tcp

Output:

Rule updated
Rule updated (v6)

If you previously had a plain allow rule for SSH, the limit command replaces it. You can verify with sudo ufw status – the Action column will show LIMIT IN instead of ALLOW IN.

For production servers exposed to the internet, rate limiting SSH is one of the first hardening steps you should apply. For more advanced blocking patterns (repeated failures across longer time windows, multiple services), install Fail2ban alongside UFW.

Step 6: Delete UFW Rules

There are two ways to delete rules: by rule number or by rule specification.

First, list all rules with their numbers:

sudo ufw status numbered

Output:

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     LIMIT IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443/tcp                    ALLOW IN    Anywhere
[ 4] 8080/tcp                   ALLOW IN    Anywhere                   # Web app
[ 5] 6000:6100/tcp              ALLOW IN    Anywhere
[ 6] 53/udp                     ALLOW IN    Anywhere
[ 7] Anywhere                   ALLOW IN    10.0.1.50
[ 8] Anywhere                   ALLOW IN    10.0.1.0/24
[ 9] 3306                       ALLOW IN    192.168.1.0/24
[10] 22/tcp (v6)                LIMIT IN    Anywhere (v6)
[11] 80/tcp (v6)                ALLOW IN    Anywhere (v6)
[12] 443/tcp (v6)               ALLOW IN    Anywhere (v6)
[13] 8080/tcp (v6)              ALLOW IN    Anywhere (v6)
[14] 6000:6100/tcp (v6)         ALLOW IN    Anywhere (v6)
[15] 53/udp (v6)                ALLOW IN    Anywhere (v6)

Delete a rule by its number. For example, to remove the port range rule at position 5:

sudo ufw delete 5

Delete a rule by specification (matches the exact rule you originally added):

sudo ufw delete allow 6000:6100/tcp

When deleting by number, rule numbers shift after each deletion. If you need to delete multiple rules, delete from the highest number first to avoid renumbering issues.

Step 7: Insert Rules at a Specific Position

UFW evaluates rules in order – the first matching rule wins. This means rule position matters. If a deny rule appears before an allow rule for the same traffic, the deny takes precedence.

Insert a rule at a specific position using insert:

sudo ufw insert 1 allow from 10.0.1.50

This places the rule at position 1 (top of the list), ensuring it is evaluated before any other rules. This is useful when you have a general deny rule but want to add an exception for a trusted IP.

Step 8: Application Profiles

Application profiles are predefined rule sets stored in /etc/ufw/applications.d/. Packages like OpenSSH and Nginx install their own profiles automatically.

List available application profiles:

sudo ufw app list

Output (on a minimal Ubuntu install):

Available applications:
  OpenSSH

View details about a specific profile:

sudo ufw app info OpenSSH

Output:

Profile: OpenSSH
Title: Secure Shell Server
Description: OpenSSH is a free implementation of the Secure Shell protocol.

Ports:
  22/tcp

Allow traffic using the application profile name:

sudo ufw allow OpenSSH

Create Custom Application Profiles

You can create custom profiles for your own applications. Create a file in /etc/ufw/applications.d/:

sudo nano /etc/ufw/applications.d/mywebapp

Add the following content:

[MyWebApp]
title=My Custom Web Application
description=Web application running on port 8443
ports=8443/tcp

After creating the profile, reload the app list and allow it:

sudo ufw app update MyWebApp
sudo ufw allow MyWebApp

Step 9: UFW Logging

UFW logging helps you monitor blocked connections, detect scanning attempts, and troubleshoot connectivity issues.

Enable logging:

sudo ufw logging on

UFW supports five logging levels, each progressively more verbose:

  • off – no logging
  • low – logs blocked packets that do not match the default policy, plus packets matching logged rules
  • medium – same as low plus invalid packets, new connections, and rate-limited packets
  • high – same as medium plus all packets with rate limiting
  • full – logs everything without rate limiting (generates a lot of output)

Set the logging level:

sudo ufw logging medium

Output:

Logging enabled

UFW writes logs to /var/log/ufw.log. Each log entry contains useful information:

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

A typical log line looks like:

Mar 23 10:15:42 server kernel: [UFW BLOCK] IN=eth0 OUT= MAC=... SRC=203.0.113.50 DST=10.0.1.10 LEN=44 TOS=0x00 PROTO=TCP SPT=54321 DPT=22 WINDOW=1024 SYN

Key fields to look at:

  • [UFW BLOCK] – the action taken (BLOCK, ALLOW, or AUDIT)
  • SRC – source IP address
  • DST – destination IP address
  • DPT – destination port
  • PROTO – protocol (TCP, UDP, ICMP)

Step 10: UFW with Docker (Critical Fix)

This is one of the most common pitfalls for Ubuntu servers running Docker. Docker manipulates iptables directly by inserting rules into the DOCKER chain, which bypasses UFW entirely. This means a container exposing port 8080 is accessible from the internet even if UFW has no rule allowing port 8080.

Fix 1: Use the DOCKER-USER Chain

Docker provides a DOCKER-USER chain specifically for user-defined rules. Add custom iptables rules to /etc/ufw/after.rules (before the COMMIT line at the end of the file):

sudo nano /etc/ufw/after.rules

Add the following block at the end of the file:

# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward

-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16

-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
-A DOCKER-USER -j ufw-docker-logging-deny
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP

COMMIT
# END UFW AND DOCKER

Then restart UFW:

sudo ufw reload

With this configuration, Docker containers can communicate with each other and reach the internet, but external traffic to container ports is blocked unless you explicitly allow it through UFW.

Fix 2: Disable Docker’s iptables Management

An alternative approach is to disable Docker’s iptables manipulation entirely. Edit or create /etc/docker/daemon.json:

sudo nano /etc/docker/daemon.json

Add this configuration:

{
  "iptables": false
}

Restart Docker:

sudo systemctl restart docker

With this approach, you manage all port exposure through UFW manually. Container-to-container networking still works over Docker networks, but published ports will not be reachable from external hosts unless you add UFW rules for them. This gives you full control but requires more manual configuration.

Step 11: Port Forwarding and NAT with UFW

UFW can handle port forwarding (DNAT) by adding rules to /etc/ufw/before.rules. This is useful when your server acts as a gateway and you need to forward incoming traffic to an internal server.

First, enable IP forwarding. Edit /etc/ufw/sysctl.conf:

sudo nano /etc/ufw/sysctl.conf

Uncomment or add this line:

net/ipv4/ip_forward=1

Next, add NAT rules to /etc/ufw/before.rules. Add the following block before the *filter section at the top of the file:

sudo nano /etc/ufw/before.rules

Add before the *filter line:

# NAT table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# Forward port 80 to internal server 10.0.1.20
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.1.20:80

# Masquerade outgoing traffic from internal network
-A POSTROUTING -s 10.0.1.0/24 -o eth0 -j MASQUERADE

COMMIT

Also allow forwarded traffic in UFW. Change the default forward policy in /etc/default/ufw:

sudo nano /etc/default/ufw

Change this line:

DEFAULT_FORWARD_POLICY="ACCEPT"

Reload UFW to apply the changes:

sudo ufw reload

Step 12: Reset and Disable UFW

To disable UFW without removing any rules (rules are preserved and will be active again when you re-enable):

sudo ufw disable

Output:

Firewall stopped and disabled on system startup

To completely reset UFW, removing all rules and returning to default settings:

sudo ufw reset

Output:

Resetting all rules to installed defaults. This may disrupt existing ssh
connections. Proceed with operation (y|n)? y
Backing up 'user.rules' to '/etc/ufw/user.rules.20260323_101542'
Backing up 'before.rules' to '/etc/ufw/before.rules.20260323_101542'
Backing up 'after.rules' to '/etc/ufw/after.rules.20260323_101542'
Backing up 'user6.rules' to '/etc/ufw/user6.rules.20260323_101542'
Backing up 'before6.rules' to '/etc/ufw/before6.rules.20260323_101542'
Backing up 'after6.rules' to '/etc/ufw/after6.rules.20260323_101542'

UFW backs up your rules before resetting, so you can restore them if needed. After a reset, you need to re-enable UFW and add your rules from scratch.

Step 13: UFW vs iptables vs nftables vs firewalld

Linux has several firewall management tools. Here is how they compare:

FeatureUFWiptablesnftablesfirewalld
Ease of useVery easyComplexModerateEasy
Default onUbuntu, DebianLegacy LinuxDebian 11+, RHEL 9+RHEL, Rocky, Alma, Fedora
Backendiptables or nftablesNetfilter (legacy)Netfilter (modern)nftables (or iptables)
Zone supportNoNoNoYes
Dynamic reloadNo (requires reload)NoYesYes
IPv6 supportYes (automatic)Separate ip6tablesYes (unified)Yes (automatic)
Rich rulesLimitedFull controlFull controlRich rule syntax
Best forSingle servers, VPSAdvanced custom rulesModern custom rulesEnterprise RHEL servers

For Ubuntu servers, UFW is the right choice for most use cases. If you need zone-based rules or manage RHEL-family systems, see our guide on configuring firewalld on Rocky Linux / AlmaLinux / RHEL. For Ubuntu systems where you prefer firewalld over UFW, we also have a guide on installing firewalld on Ubuntu.

Quick Reference: Common UFW Commands

The table below summarizes every common UFW command covered in this guide for quick reference.

ActionCommand
Enable UFWsudo ufw enable
Disable UFWsudo ufw disable
Check statussudo ufw status verbose
Set default deny incomingsudo ufw default deny incoming
Set default allow outgoingsudo ufw default allow outgoing
Allow port (TCP)sudo ufw allow 80/tcp
Allow port (UDP)sudo ufw allow 53/udp
Allow service by namesudo ufw allow ssh
Allow port rangesudo ufw allow 6000:6100/tcp
Allow from IPsudo ufw allow from 10.0.1.50
Allow from subnet to portsudo ufw allow from 192.168.1.0/24 to any port 3306
Deny from IPsudo ufw deny from 203.0.113.100
Deny outgoing portsudo ufw deny out 25
Reject trafficsudo ufw reject in on eth0 to any port 80
Rate limit SSHsudo ufw limit ssh/tcp
Delete rule by numbersudo ufw delete 5
Delete rule by specsudo ufw delete allow 80/tcp
Insert rule at positionsudo ufw insert 1 allow from 10.0.1.50
List app profilessudo ufw app list
Show numbered rulessudo ufw status numbered
Enable loggingsudo ufw logging medium
Reset all rulessudo ufw reset
Reload rulessudo ufw reload

Conclusion

UFW provides a straightforward way to manage firewall rules on Ubuntu servers. For production deployments, keep these practices in mind:

  • Always set default policies (deny incoming, allow outgoing) before adding specific rules
  • Allow SSH before enabling UFW on remote servers – getting locked out is painful
  • Use rate limiting on SSH (sudo ufw limit ssh/tcp) as a first line of defense against brute force
  • If running Docker, apply the DOCKER-USER chain fix – Docker bypasses UFW by default
  • Restrict database ports (3306, 5432, 6379) to specific IPs or subnets, never open them to the world
  • Enable logging at medium level for good visibility without excessive noise
  • Review rules periodically with sudo ufw status numbered and remove anything no longer needed

For securing SSH access on your Ubuntu server beyond firewall rules, see our guide on installing and configuring SSH server on Ubuntu. If you run a WireGuard VPN, remember to allow the VPN port (typically 51820/udp) in UFW as well.

Related Articles

oVirt Configuring oVirt / RHEV Manager Certificate Security on browser Debian How To Install PHP with Apache on Ubuntu and Debian Debian Install WordPress with Nginx on Ubuntu 24.04 / Debian 13 Web Hosting Install Drupal on Ubuntu 24.04 with Nginx

Leave a Comment

Press ESC to close