Firewall Basics With UFW and firewalld
A firewall is one of the most important security controls on a Linux computer or server. It decides which network connections are allowed, which are blocked and which services can be reached from other devices.
Linux includes powerful firewall capabilities through the kernel’s Netfilter system. However, configuring the underlying rules directly can be complicated. Tools such as UFW and firewalld provide simpler ways to manage those rules without having to build an entire firewall configuration manually. (firewalld)
This guide explains the basics of both tools, including how to enable a firewall safely, open and close ports, restrict access and avoid accidentally locking yourself out of a remote server.
What Does a Linux Firewall Actually Do?
A host-based firewall controls network traffic entering, leaving or passing through a Linux machine.
For most desktops and servers, the main concern is incoming traffic. A firewall can prevent another device from connecting to a service unless you have explicitly allowed it.
For example, a server might be running:
- SSH on TCP port 22
- A website on TCP port 80
- An encrypted website on TCP port 443
- A database on TCP port 3306
- A custom application on TCP port 8080
Without suitable firewall rules, some of these services may be reachable from networks that should not have access to them.
A common baseline policy is therefore:
- Deny unsolicited incoming connections
- Allow normal outgoing connections
- Open only the services that are genuinely required
- Restrict administrative services to trusted addresses where possible
A firewall does not replace software updates, strong passwords, multi-factor authentication or secure application configuration. It adds another protective layer.
UFW and firewalld: What Is the Difference?
UFW stands for Uncomplicated Firewall. It is designed to make straightforward firewall rules easier to create and manage. It is commonly associated with Ubuntu and other Debian-based distributions.
firewalld is a dynamically managed firewall service commonly used by distributions in the Red Hat family, including Fedora, Rocky Linux, AlmaLinux and Red Hat Enterprise Linux. It organises rules around zones, services and network interfaces.
Both tools ultimately manage Linux firewall rules, but their operating models are different.
UFW is usually easier when:
- You are managing a desktop or straightforward server
- The machine has a small number of network interfaces
- You want simple allow-and-deny rules
- You are using Ubuntu or a related distribution
firewalld is usually better when:
- The machine connects to networks with different trust levels
- You need different rules for different interfaces
- You want to use predefined service definitions
- You are managing Fedora, RHEL or a related distribution
- Firewall rules need to be changed without restarting the firewall service
firewalld uses zones to represent different levels of network trust. A public Wi-Fi connection, for example, should normally be assigned a less-trusted zone than an internal office network. (firewalld)
You would not normally run UFW and firewalld as competing firewall managers on the same machine. Choose the tool supported by your distribution and manage the rules consistently through it.
Part One: UFW Basics
Check Whether UFW Is Installed
On Ubuntu, UFW is often installed by default. Check its status with:
sudo ufw status
You may see:
Status: inactive
This means UFW is installed but is not currently enforcing its rules.
Install it on a Debian-based distribution with:
sudo apt update
sudo apt install ufw
Set Sensible Default Policies
Before enabling UFW, define the default behaviour:
sudo ufw default deny incoming
sudo ufw default allow outgoing
This blocks unsolicited incoming connections while allowing the machine to initiate normal outbound connections.
For many desktops and conventional servers, this is a sensible starting position.
Protect Remote SSH Access Before Enabling UFW
This is one of the most important steps in the entire guide.
When configuring a remote server, allow SSH before enabling the firewall:
sudo ufw allow OpenSSH
Alternatively, allow the port directly:
sudo ufw allow 22/tcp
If SSH is using a custom port, allow that port instead:
sudo ufw allow 2222/tcp
Failing to allow the correct SSH port before enabling the firewall could disconnect your current session and prevent you from reconnecting. Ubuntu’s guidance similarly recommends permitting OpenSSH before enabling UFW on a remote system. (Ubuntu Documentation)
Ideally, keep a provider console, hypervisor console or other recovery route available when changing remote firewall rules.
Enable UFW
After confirming that required management access is allowed, enable the firewall:
sudo ufw enable
Check the result:
sudo ufw status verbose
A typical result might show:
Status: active
Logging: on
Default: deny (incoming), allow (outgoing), disabled (routed)
Allow a Port
To allow HTTP traffic on TCP port 80:
sudo ufw allow 80/tcp
Allow HTTPS on TCP port 443:
sudo ufw allow 443/tcp
Allow a custom TCP application:
sudo ufw allow 8080/tcp
Allow a UDP service:
sudo ufw allow 51820/udp
Specifying TCP or UDP avoids creating a broader rule than necessary.
Allow a Named Application Profile
Some installed applications provide predefined UFW profiles.
List them with:
sudo ufw app list
You might see entries such as:
OpenSSH
Nginx Full
Nginx HTTP
Nginx HTTPS
Allow a profile with:
sudo ufw allow "Nginx Full"
Inspect what a profile permits before using it:
sudo ufw app info "Nginx Full"
Application profiles can make configurations easier to understand than lists of unexplained port numbers.
Allow Access From One IP Address
To allow all traffic from a trusted management address:
sudo ufw allow from 203.0.113.25
A safer approach is usually to limit the address to a particular service:
sudo ufw allow from 203.0.113.25 to any port 22 proto tcp
This permits SSH from that source without giving it unrestricted access to every listening service.
Allow Access From a Local Network
To allow SSH from a private subnet:
sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp
This can be useful for internal systems that should be administered only from the office network or a management VLAN.
Be careful with private address ranges on cloud servers. The source address seen by the server may not always be the one you expect because of VPNs, proxies, network address translation or load balancers.
Deny a Connection Explicitly
UFW’s default incoming policy may already block the connection, but explicit deny rules can make your intentions clearer:
sudo ufw deny 23/tcp
To block a particular address:
sudo ufw deny from 203.0.113.50
Rate-Limit SSH Connections
UFW includes a simple rate-limiting option:
sudo ufw limit OpenSSH
Or:
sudo ufw limit 22/tcp
This may reduce repeated rapid connection attempts. It should not be treated as a complete defence against brute-force attacks, however. SSH keys, disabled password login where appropriate, multi-factor authentication and proper monitoring remain important.
View Numbered Rules
To display active rules with numbers:
sudo ufw status numbered
Example:
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 80/tcp ALLOW IN Anywhere
[ 3] 443/tcp ALLOW IN Anywhere
Numbered output makes removing rules easier.
Delete a UFW Rule
Delete a rule by repeating it with the delete keyword:
sudo ufw delete allow 8080/tcp
Or delete it by number:
sudo ufw status numbered
sudo ufw delete 3
Check the numbered list again after a deletion because the remaining rule numbers may change.
Enable Logging
Enable standard logging with:
sudo ufw logging on
Select a logging level if needed:
sudo ufw logging low
sudo ufw logging medium
sudo ufw logging high
Higher logging levels can generate a significant amount of data, particularly on an internet-facing system.
Logs may be available through the system journal or files under /var/log, depending on the distribution’s logging configuration.
Temporarily Disable UFW
To stop enforcing UFW rules:
sudo ufw disable
This keeps the configuration but disables the firewall.
To remove the rules and restore UFW to its default state:
sudo ufw reset
A reset is destructive. Review the impact before using it on a remote or production machine.
Part Two: firewalld Basics
Check Whether firewalld Is Running
Check the service through systemd:
sudo systemctl status firewalld
You can also ask firewalld directly:
sudo firewall-cmd --state
A running service should return:
running
firewall-cmd is the main command-line client for checking and changing firewalld configurations. (firewalld)
Install firewalld on a supported distribution through its package manager. For example:
sudo dnf install firewalld
Start it and enable it at boot:
sudo systemctl enable --now firewalld
Understanding firewalld Zones
Zones are central to firewalld.
A zone contains a set of rules defining which services and ports are allowed. A network interface or source address can then be assigned to that zone.
Common predefined zones include:
- drop
- block
- public
- external
- internal
- dmz
- work
- home
- trusted
The names suggest their intended trust levels, but you should inspect the actual configuration rather than relying only on the label.
List available zones:
sudo firewall-cmd --get-zones
Show active zones and their interfaces:
sudo firewall-cmd --get-active-zones
Check the default zone:
sudo firewall-cmd --get-default-zone
Inspect the public zone:
sudo firewall-cmd --zone=public --list-all
firewalld stores vendor-supplied defaults separately from locally customised zone configurations. Custom zone files are normally kept under /etc/firewalld/zones. (firewalld)
Runtime and Permanent Rules
firewalld separates its runtime configuration from its permanent configuration.
A runtime change takes effect immediately but normally disappears after a reload or restart.
A permanent change is stored but may not affect the current runtime configuration until firewalld is reloaded.
For example, this opens HTTP temporarily:
sudo firewall-cmd --zone=public --add-service=http
This adds the rule permanently:
sudo firewall-cmd --zone=public --add-service=http --permanent
Apply permanent changes to the running configuration:
sudo firewall-cmd --reload
The separation between runtime and permanent rules makes it possible to test some changes before committing them. (firewalld)
Allow a Predefined Service
To allow HTTP in the public zone:
sudo firewall-cmd --zone=public --add-service=http --permanent
Allow HTTPS:
sudo firewall-cmd --zone=public --add-service=https --permanent
Allow SSH:
sudo firewall-cmd --zone=public --add-service=ssh --permanent
Reload the firewall:
sudo firewall-cmd --reload
Confirm the allowed services:
sudo firewall-cmd --zone=public --list-services
Where an appropriate predefined service exists, using it is usually clearer than opening individual ports. firewalld includes definitions for many common services and can display them with firewall-cmd --get-services. (firewalld)
Open a Specific Port
To open TCP port 8080:
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
Open a UDP port:
sudo firewall-cmd --zone=public --add-port=51820/udp --permanent
sudo firewall-cmd --reload
List open ports:
sudo firewall-cmd --zone=public --list-ports
Remove a Service or Port
Remove HTTP access:
sudo firewall-cmd --zone=public --remove-service=http --permanent
Remove TCP port 8080:
sudo firewall-cmd --zone=public --remove-port=8080/tcp --permanent
Then reload:
sudo firewall-cmd --reload
Assign an Interface to a Zone
List network interfaces:
ip address
Move an interface into the internal zone:
sudo firewall-cmd --zone=internal --change-interface=ens192 --permanent
sudo firewall-cmd --reload
Check the result:
sudo firewall-cmd --get-active-zones
Before moving a remote server’s main interface, confirm that the destination zone allows SSH or whichever service you use for administration.
Create a Rule for One Trusted Address
Rich rules provide more detailed matching.
For example, allow SSH from one IP address:
sudo firewall-cmd --zone=public \
--add-rich-rule='rule family="ipv4" source address="203.0.113.25" service name="ssh" accept' \
--permanent
Reload:
sudo firewall-cmd --reload
List rich rules:
sudo firewall-cmd --zone=public --list-rich-rules
Remove the rule by repeating it with --remove-rich-rule:
sudo firewall-cmd --zone=public \
--remove-rich-rule='rule family="ipv4" source address="203.0.113.25" service name="ssh" accept' \
--permanent
sudo firewall-cmd --reload
Rich rules are powerful, but the syntax must be entered carefully. Always verify the active configuration after making changes.
Checking Which Services Are Actually Listening
Opening a firewall port does not start the application behind it.
Similarly, closing a firewall port does not stop the service. It only prevents matching network traffic from reaching it through that path.
Check listening TCP and UDP sockets with:
sudo ss -tulpn
Useful fields include:
- The protocol
- The local listening address
- The port number
- The process using the socket
A service bound to 127.0.0.1 is normally available only from the local machine.
A service bound to 0.0.0.0 may be listening on all IPv4 interfaces, although firewall rules can still restrict access.
For IPv6, look for addresses such as :: and confirm that your firewall rules cover both address families as intended.
Test From Another Device
Do not rely entirely on the firewall’s status output. Test connectivity from another system.
For a web service:
curl -I http://server-address
For a TCP port:
nc -vz server-address 443
You can also scan systems you own or are authorised to assess with a tool such as Nmap:
nmap -sT server-address
A local test from the server itself may not accurately represent what a remote machine can reach.
Common Firewall Mistakes
Enabling the Firewall Before Allowing SSH
This is the classic remote-server mistake.
Always permit the correct management service first and keep a recovery console available.
Opening More Than the Application Needs
Avoid rules such as large port ranges unless the application genuinely requires them.
Instead of opening every database connection to the internet, restrict the database port to the application server, VPN subnet or management network that needs it.
Forgetting the Protocol
TCP and UDP are different protocols.
Opening:
sudo ufw allow 53/tcp
does not automatically allow:
53/udp
Some services require one protocol, while others may require both.
Forgetting firewalld’s Permanent Configuration
A runtime rule can appear to work perfectly and then disappear after a reload or reboot.
Check both the runtime and permanent configuration:
sudo firewall-cmd --zone=public --list-all
sudo firewall-cmd --zone=public --list-all --permanent
Reloading Before Confirming Remote Access
When using firewalld, a temporary runtime rule may be keeping your session alive. Reloading can replace that runtime configuration with the permanent configuration.
Confirm that the permanent rules include your remote management access before running:
sudo firewall-cmd --reload
Assuming the Firewall Is the Only Filter
Traffic may be filtered by several layers, including:
- A cloud security group
- A hosting provider firewall
- A broadband router
- A corporate perimeter firewall
- A VPN
- A container platform
- The host firewall itself
- The application’s own access controls
Container platforms, virtualisation systems and VPN software may also create their own firewall rules, which can lead to unexpected interactions. (Ubuntu Documentation)
Allowing a Port Without Securing the Service
A firewall can reduce exposure, but it cannot fix an insecure application.
If you open SSH to the internet, the SSH service still needs secure authentication.
If you open HTTPS, the web server still needs updates, appropriate TLS settings and secure application code.
If you expose a database, it still needs strong credentials and carefully configured user permissions.
A Simple UFW Server Baseline
For a basic Ubuntu web server managed through SSH:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
A more restrictive configuration could permit SSH only from a trusted office address:
sudo ufw delete allow OpenSSH
sudo ufw allow from 203.0.113.25 to any port 22 proto tcp
Only make this change after confirming that the trusted public IP address is correct and stable.
A Simple firewalld Server Baseline
For a basic web server using the public zone:
sudo systemctl enable --now firewalld
sudo firewall-cmd --zone=public --add-service=ssh --permanent
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --list-all
Before assuming the rules are correct, also verify which interface is assigned to the public zone:
sudo firewall-cmd --get-active-zones
Which Firewall Tool Should You Learn?
For a single Ubuntu desktop, small server or simple virtual machine, UFW is often the more approachable choice.
For systems that use network zones, multiple interfaces or more dynamic network configurations, firewalld may provide a cleaner structure.
The most important lessons are the same whichever tool you choose:
- Start with a restrictive incoming policy.
- Allow only the services that are required.
- Limit sensitive services to trusted source addresses.
- Confirm both IPv4 and IPv6 behaviour.
- Test from another device.
- Document why every exception exists.
- Remove rules when services are retired.
- Keep a recovery method available when changing a remote firewall.
Final Thoughts
A firewall does not need to be complicated to be valuable. Even a small ruleset that blocks unsolicited incoming connections and exposes only necessary services can significantly reduce a system’s attack surface.
The real danger is not usually having too few complicated rules. It is having old, undocumented or overly broad rules that nobody remembers creating.
Whether you choose UFW or firewalld, keep the configuration deliberate, review it regularly and verify that the exposed services still match the machine’s purpose.
Need Help Securing Your Linux Systems?
Hamilton Group can help your organisation review Linux servers, firewall rules, remote-access controls and wider network security.
We can identify unnecessary exposed services, tighten administrative access and help build a practical security configuration that protects your systems without disrupting legitimate users.
Call 0330 043 0069 or visit hgmssp.com to speak with one of our IT and cybersecurity specialists.