Easy to use: The UFW is easy to use for both developers and sysadmins.
Security: The UFW is a secure and well-tested product by millions of users. Out of the box, it sets deny by default firewall policy which is great to avoid accidentally exposing service to the world.
Flexibility: The UFW firewall is highly adaptable and can be configured to permit or block traffic based on various factors, such as source and destination IP addresses, port numbers, protocols, and more, as per your needs.
Integration with other tools : Integrating ufw with various apps like SSH, NFS, POP3, OpenVPN, and other applications profile is a snap. Scriptwriting is also possible, allowing for the effortless configuration of firewall access to these services through shell scripts or automated tools like Ansible.
Setup of ufw
Step 1 – Installing ufw on Debian Linux 12
First, update your APT repos and install any pending updates:
sudo apt update
sudo apt upgrade
Reboot the Debian Linux machine when a new Linux kernel version is installed using the reboot command or shutdown command. For example:
sudo reboot
Next, install UFW using the apt command or apt-get command:
sudo apt install ufw
Print ufw version:
sudo ufw version
Outputs:
ufw 0.36.2
Step 2 – Configure UFW to allow SSH connections
Ensures that you allow ssh access. All you have to do is type:
sudo ufw allow ssh
📝 Optional advanced ssh firewall rules customization is possible with ufw. Let us see a few use cases to fine-tune ssh firewall rules.
- If you are running ssh on TCP port 2240, enter:
sudo ufw allow 2240/tcp
- Some sysadmins or developers have a static IPv4/IPv6 address (such as 103.1.2.3) at home or office location. In that case, only allow ssh access from the static IP address such as 103.1.2.3 to Debian server IP address 139.144.1.2 at TCP port 22:
sudo ufw allow proto tcp from 103.1.2.3 to 139.144.1.2 port 22
Are you running HTTP and HTTPS services too? Let open those TCP 80/443 ports so that the firewall will not block them. Type:
sudo ufw allow http
sudo ufw allow https
Confirm they are open:
ufw show added
Enabling UFW service in Debian 12
Let us see the firewall status, run:
sudo ufw status
Here is what it says:
Status: inactive
Hence, enable UFW, run:
sudo ufw enable
You need to type y
to confirm that you need to enable the firewall:
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
Congratulations! You have successfully configured a firewall using UFW on Debian 12. That’s all for now. Let us explore enabling other services or blocking ports and IP addresses with ufw.
Viewing default policies
To print the default firewall policy, use the grep command to query the /etc/default/ufw
:
sudo grep -i '^default_' /etc/default/ufw
The following output indicates that by default firewall will block all incoming and forward connections options, but it will allow outgoing connections from your Debian Linux version 12:
DEFAULT_INPUT_POLICY=”DROP”
DEFAULT_OUTPUT_POLICY=”ACCEPT”
DEFAULT_FORWARD_POLICY=”DROP”
DEFAULT_APPLICATION_POLICY=”SKIP”
You can change default policy using the following syntax:
sudo ufw default default allow|deny|reject [incoming|outgoing|routed]
For example:
sudo ufw default deny incoming
sudo ufw default allow outgoing
Deny vs reject default firewall policy
Let us find the distinction between a deny policy and a reject policy. I found a helpful table that outlines the differences:
Attribute | deny policy | reject policy |
---|---|---|
Drops the packet | Yes | Yes |
Sends a response to the client/sender | No | Yes |
Provides more information to the client/sender | No | Yes |
Recommended policy for better security | Yes | No |
Understanding route
policy
The route
policy is employed for traffic that is not intended for the local host but for another host on the network. The firewall usually forwards this traffic to the appropriate destination. For example, you may need to route incoming traffic on port 80/443 to a Linux container running on the same host or another machine. If you don’t have advanced networking and sysadmin skills, feel free to skip the following rules. They’re included here for your reference when you need to use advanced features in the future. The following rule would allow all routed traffic from the 172.0.0.0/24 subnet on the VLAN eth1 interface: sudo ufw route allow in on eth1 to 172.0.0.0/24
The route keyword can also be used to specify the specific ports that are allowed or denied:
sudo ufw route allow in on eth1 to 172.0.0.0/24 port 80
In this example, allow all traffic for LXD container on a Debian Linux by lxdbr0 interface by default:
sudo ufw allow in on lxdbr0 comment 'lxdbr0 for LXD'
sudo ufw route allow in on lxdbr0 comment 'lxdbr0 for LXD'
sudo ufw route allow out on lxdbr0 comment 'lxdbr0 for LXD'
Controlling the ufw service
Use the systemctl command. The syntax is as follows to see the current status:
sudo systemctl status ufw.service
OR
sudo ufw status
sudo ufw status verbose
sudo ufw status numbered
If you need to stop the firewall and disable on system startup, run:
sudo ufw disable
Here is what I see:
Firewall stopped and disabled on system startup
To enables the firewall service again, type:
sudo ufw enable
The rest of the tutorial will now cover blocking or allowing ports, IP addresses, and applications using ufw.
Step 3 – Adding allow rules
It is possible to allow unlimited access to specific IP addresses. For example, sysadmin IP or your VPN IP address 1.2.3.4:
sudo ufw allow from 1.2.3.4
In this example, allow access 192.168.2.0/24 CIDR (sub/net):
sudo ufw allow from 192.168.2.0/24
# OR on 'eth3' interface only #
sudo ufw allow in on eth3 from 192.168.2.0/24
Limit full access for 1.2.3.4 to TCP port 80, 443, and 22 as follows with comment as follows:
ufw allow from 1.2.3.4 to any port 22 proto tcp comment 'Open TCP SSH PORT for VPN IP only'
OR
sudo ufw allow from 1.2.3.4 to any port 80
sudo ufw allow from 1.2.3.4 to any port 443
You can state multiport as follows to open TCP port 22, 80, and 443 in a single rule but only from 1.2.3.4 IP: sudo ufw allow proto tcp from 1.2.3.4 to any port 22,80,443
You can also state port ranges. For example, open TCP and UDP port ranges between 3000 and 4000:
sudo ufw allow 3000:4000/tcp
sudo ufw allow 3000:4000/udp
Try this example:
sudo ufw allow in on eth1 from 172.0.0.0/24 to 172.0.0.1 port 22 proto tcp comment 'Open TCP SSH PORT for VLAN and LXD users'
The above command allows incoming SSH connections on TCP port 22
from the 172.0.0.0/24
CIDR (subnet) to the 172.0.0.1
IP address. The eth1
interface is the network interface that the SSH connections will be coming from. The proto
keyword specifies that the connections should be TCP
connections. The comment
keyword specifies a comment that will be displayed when the rule is listed using the sudo ufw status
command at the CLI.
Step 4 – Denying or rejecting rules
Now let us see blocking examples. Say you want to block the attacker’s IP address 1.2.3.4, CIDR 192.168.5.0/24, or TCP/23 telnet port. Here is how to do it:
sudo ufw deny from 1.2.3.4
sudo ufw deny from 192.168.5.0/24
sudo ufw deny 23/tcp
OR
reject it (see Table 01 for deny vs reject firewall targets)
sudo ufw reject from 1.2.3.4
sudo ufw reject from 192.168.5.0/24
sudo ufw reject 23/tcp
Here is how it looks when you run the sudo ufw status verbose
command:
Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- ... .. Anywhere DENY IN 1.2.3.4 Anywhere DENY IN 192.168.5.0/24 23/tcp DENY IN Anywhere 23/tcp (v6) DENY IN Anywhere (v6) ...
Block port 25:
sudo ufw deny 25
You can block port 25 from CIDR 192.168.1.0/24 as follows:
sudo ufw deny proto tcp from 192.168.1.0/24 port 25
Block all protocols from CIDR 192.168.1.0/24:
sudo ufw deny from 192.168.1.0/24
Block TCP connections from CIDR 192.168.5.0/24:
sudo ufw deny proto tcp from 192.168.5.0/24
Here is how to block UDP connections from CIDR 192.168.10.0/24:
sudo ufw deny proto udp from 192.168.10.0/24
Want to block all ports from CIDR 192.168.11.0/24? Try:
sudo ufw deny all from 192.168.11.0/24
Block all ports from any source (be careful with the following rule):
sudo ufw deny all
Step 4 – Limiting rules
The ufw supports connection rate limiting, which is useful for protecting against brute-force login attacks. When a limit rule is used, ufw will normally allow the connection but will deny connections if an IP address attempts to initiate 6 or more connections within 30 seconds. Typical usage is:
ufw limit ssh/tcp
OR
limit TCP/22 ssh connect from CIDR 192.168.11.0/24 when using the eth0 interface:
sudo ufw limit in on eth0 proto tcp from 192.168.11.0/24 port 22
Step 5 – Delete rules
The syntax is as follows to list all of the current rules in a numbered list format:
sudo ufw status numbered
Outputs:
Status: active To Action From -- ------ ---- [ 1] 22/tcp LIMIT IN Anywhere [ 2] 80/tcp ALLOW IN Anywhere [ 3] 443 ALLOW IN Anywhere [ 4] 22,25,80,443,9000/tcp ALLOW IN Anywhere [ 5] 22,80,443/tcp ALLOW IN 1.2.3.4 [ 6] Anywhere REJECT IN 1.2.3.4 [ 7] Anywhere DENY IN 192.168.5.0/24 [ 8] 23/tcp REJECT IN Anywhere [ 9] 25 DENY IN Anywhere [10] Anywhere DENY IN 192.168.1.0/24 25/tcp [11] Anywhere DENY IN 192.168.10.0/24/udp [12] Anywhere on eth0 LIMIT IN 192.168.11.0/24/tcp [13] Anywhere on eth0 LIMIT IN 192.168.11.0/24 22/tcp [14] 22/tcp (v6) LIMIT IN Anywhere (v6) [15] 80/tcp (v6) ALLOW IN Anywhere (v6) [16] 443 (v6) ALLOW IN Anywhere (v6) [17] 22,25,80,443,9000/tcp (v6) ALLOW IN Anywhere (v6) [18] 23/tcp (v6) REJECT IN Anywhere (v6) [19] 25 (v6) DENY IN Anywhere (v6)
To delete 4th rule type the command:
sudo ufw delete 4
Verify it:
sudo ufw status numbered
Step 6 – Inserting rule at firewall
It’s crucial to understand the sequence of ufw rules in the system table, which includes PREROUTING, INPUT, FORWARD, OUTPUT, FORWARD, and POSTROUTING. The order of these rules determines which rule will be executed first when a packet matches. Therefore, it’s possible to add a rule at a specific location using ufw to ensure it’s applied correctly. The syntax is:
sudo ufw insert [position] [rule] Where, the position
is the position of the rule in the chain. The position can be a number, such as 1. The rule
is the rule that you want to insert or delete. The rule can be a simple rule, such as allow ssh, or a more complex rule as per your needs. In this example, insert a rule that allows incoming tcp/25 connections at the top of the INPUT chain, you would use the following command:
sudo ufw insert 1 allow 25/tcp
Say you have six rules, and you want to insert a new rule as rule number five, use:
sudo ufw insert 5 deny to any port 22 from 192.168.2.5 proto tcp
Step 7 – Prepend rule at top of the firewall
A special ufw prepend
command rule allows you to insert a rule before all other rules in a chain. This can be useful for adding a rule that will always be applied, regardless of the order of the other rule. For example, allow or deny access to specific IP address/CIDR can be done with ufw prepend as follows:
sudo ufw prepend deny from 1.2.3.4
sudo ufw prepend deny from 123.1.2.3/29
sudo ufw prepend allow from 192.168.1.0/24
Similarly, to add a rule before all other rules matching the rule’s IP type, use the prepend rule to deny access 1.2.2.2:
sudo ufw prepend deny from 1.2.2.2
Here is how to prepend in your custom script/shell and add Cloudflare IPv4/IPv6 address to your Debian or Ubuntu Linux server with ufw. The following shell function only allows full access to port 80/443 to Cloudflare reverse proxy:
#
# Open TCP port 80/443 only to CF IPv4/IPv6 reverse proxy ranges only
#
update_cf_ufw_rules(){
download_cf_ipv_sets
self_get_ipv4
self_get_ipv6
# always add rule at top #
while read -r line
do
ufw prepend allow in on "$_pub_if" proto tcp from "$line" port 80 to "$_self_ipv4" comment "CF:80:$line"
ufw prepend allow in on "$_pub_if" proto tcp from "$line" port 443 to "$_self_ipv4" comment "CF:443:$line"
done <"$_out/ipv4.txt"
while read -r line
do
ufw prepend allow in on "$_pub_if" proto tcp from "$line" port 80 to "$_self_ipv6" comment "CF:80:$line"
ufw prepend allow in on "$_pub_if" proto tcp from "$line" port 443 to "$_self_ipv6" comment "CF:443:$line"
done <"$_out/ipv6.txt"
}
#
# Flush/remove all UFW rules that allowed/opened TCP port 80/443 for CF IPv4/IPv6 ranges
#
flush_cf_ufw_rules(){
read -r -t 15 -N 1 -p "This command will delete all rules for TCP ports 80/443, affecting everyone including Cloudflare. Do you want to proceed (y|N)?" answer
if [ "${answer,,}" == "y" ]
then
ufw show added | grep -E 'CF:(80|443):.*' \
| awk '{ gsub("ufw","ufw delete",$0); system($0)}'
fi
}
#
# List rules
#
list_cf_ufw_rules(){
ufw status verbose | head -7
if ! ufw status verbose | grep -E '# CF:(80|443):.*'
then
echo "$_self: WARNING: TCP ports 80 and 443 are blocked, even for Cloudflare IPv4/IPV6 ranges. Please run '$_self --update' to open these ports for Cloudflare IP ranges." 1>&2
fi
}
Step 8 – Application integration and management with ufw
To integrate applications, the ufw command can read profiles from /etc/ufw/applications.d/ directory. To view the names of known application profiles in ufw, simply use the command:
sudo ufw app list
Outputs:
Available applications: AIM Bonjour CIFS DNS Deluge IMAP IMAPS IPP KTorrent Kerberos Admin Kerberos Full Kerberos KDC Kerberos Password LDAP LDAPS LPD MSN MSN SSL Mail submission NFS OpenSSH POP3 POP3S PeopleNearby SMTP SSH Socks Telnet Transmission Transparent Proxy VNC WWW WWW Cache WWW Full WWW Secure XMPP Yahoo qBittorrent svnserve
Getting details about app
Details on the firewall profile for a given application can be seen with:
sudo ufw app info {name}
Where ‘{name}’ is one of the applications seen with the sudo ufw app list
command:
sudo ufw app list
sudo ufw app info 'WWW Cache'
Outputs:
Profile: WWW Cache Title: Web Server (8080) Description: Web Server (8080) Port: 8080/tcp
How do I use the app to open port?
The sytax is:
sudo ufw allow {name}
Try the extended syntax too sudo ufw allow from 192.168.0.0/16 to any app {name}
Let us open the NFS port using the NFS app so Linux or Unix clients can mount shared dirs using the mount command. On the NFS server type:
sudo ufw app info NFS
Open NFS ports: sudo ufw allow NFS
OR limit NFS server access to eth1 interface and CIDR 172.0.0.0/24:
sudo ufw allow in on eth1 from 172.0.0.0/24 to any app NFS comment 'Open NFS for VLAN users'
Verify it:
sudo ufw verbose
Outputs:
Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 25/tcp ALLOW IN Anywhere Anywhere DENY IN 8.0.0.0/24 ... ... 111,2049/tcp (NFS) on eth1 ALLOW IN 172.0.0.0/24 # Open NFS for VLAN users 111,2049/udp (NFS) on eth1 ALLOW IN 172.0.0.0/24 # Open NFS for VLAN users ... ..
Deleting app rule
Want to delete app rule? Try:
sudo ufw delete allow NFS
OR
complicated syntax as used earlier:
sudo ufw delete allow in on eth1 from 172.0.0.0/24 to any app NFS
With the app option, adding or deleting ufw firewall rules becomes effortless, even if you have limited TCP or UDP ports knowledge. The only drawback is not all apps are supported. Hence, knowing a little bit about networking concepts helps with the firewall.
Step 9 – Displaying firewall report
The syntax is
sudo ufw show {REPORT_TYPE}
The following {REPORT_TYPE}
(reports) are supported. Each is based on the live system and with the exception of the listening report, is in raw iptables format:
- raw
- builtins
- before-rules
- user-rules
- after-rules
- logging-rules
- listening
- added
Examples
Try the following examples at the Debian Linux 12 CLI: sudo ufw show raw | less
Try more, bat command or most command as pager: sudo ufw show builtins | more
Also try the following two reports: sudo ufw show listening
And: sudo ufw show added
Summing up
If you’re a new developer or sysadmin, installing and configuring firewalls on Debian Linux, v12 can be easy with ufw. It’s a user-friendly front-end for iptables or nftables that’s also recommended for experienced users. UFW is a great option for keeping your system secure while being easy to use. I suggest read the following UFW documenation online or offline using the man command/help command:
man ufw
ufw --help
Checking UFW Rules
The first step in troubleshooting is to ensure that the rules you added to UFW for Samba are correct. You can check the current UFW rules with the command:
sudo ufw status verbose
Adding Comments to UFW Rules
If the rules are correct but still not working, you can add a comment to the UFW command line. This will help you identify the purpose of the rule later. Here’s how to do it:
sudo ufw allow from any to any port 137,138,139,445 proto tcp comment 'passing samba from local'
In this command, from any to any port 137,138,139,445 proto tcp
specifies the rule, and comment 'passing samba from local'
adds a comment to the rule.
Creating a Custom UFW Profile for Samba
Another solution is to create a custom profile for Samba in UFW. Here’s how to do it:
Create a new file /etc/ufw/applications.d/samba4
with the necessary ports.
sudo nano /etc/ufw/applications.d/samba4
Add the following content to the file:
[Samba4]
title=Samba 4
description=Samba 4 Server
ports=137,138/udp|139,445/tcp
Save and close the file.
Now, add the profile to UFW with the following command:
sudo ufw allow from 192.168.192.0/24 to any app samba4
In this command, 192.168.192.0/24
specifies the network from which connections are allowed, and app samba4
specifies the application (Samba) for which the rule is being created.
Checking UFW Logs
If none of the above solutions work, you can check the UFW logs for any information on why the Samba service is still being blocked. Use the following command to monitor the logs in real-time:
tail -f /var/log/ufw.log
This command will display the most recent entries in the UFW log file and update in real-time as new entries are added.
Opening DHCP port using UFW in Linux
The commands are as follows when UFW:
sudo ufw allow bootps comment 'Allow 67/UDP'
sudo ufw allow bootpc comment 'Allow 68/UDP'
sudo ufw allow 53/udp comment 'Allow DNS_53/UDP'
sudo ufw allow 53/tcp comment 'Allow DNS_53/TCP'
Verify newly added UFW rules follows:
sudo ufw status verbose
Troubleshooting
Are DHCP and DNS traffic still blocked? See the UFW log as follows using the tail command in real-time:
sudo tail -f /var/log/ufw.log
You can query the /var/log/ufw.log
as follows:
sudo grep -w 'DPT={PORT_NUMBER_HERE}' /var/log/ufw.log
sudo grep -w 'DPT=67' /var/log/ufw.log
sudo grep -w 'DPT=67' /var/log/ufw.log
You can match both protocols (PROTO) and destination port (DPT)/source port (SPT) as follows:
sudo grep -Ew 'PROTO=UDP.*DPT=67' /var/log/ufw.log
sudo grep -Ew 'PROTO=UDP.*SPT={PORT_NUMBER_HERE}' /var/log/ufw.log
You can also use the journalctl command as follows:
journalctl | grep -i ufw
journalctl -g 'grep_regex_here'
journalctl -g 'ufw'
journalctl -g '\[ufw.*dpt=67'
journalctl -g '\[ufw.*dpt=68'
journalctl -g '\[ufw.*tcp=53'
The -g or --grep option filter output to entries where the MESSAGE= field matches the specified PERL-compatible regular expressions. Please note that if the pattern is all lowercase, matching is case insensitive. Otherwise, matching is case sensitive. This can be overridden with the --case-sensitive=<true|false>
option as follows:
journalctl -g '\[ufw.*DPT=53' --case-sensitive=false
Blocking DHCP and DNS traffic using the UFW
Do you need to block the DHCP and DNS traffic? The deny syntax is as follows:
sudo ufw deny bootps comment 'Block 67/UDP'
sudo ufw deny bootpc comment 'Block 68/UDP'
sudo ufw deny 53/udp comment 'Block DNS_53/UDP'
sudo ufw deny 53/tcp comment 'Block DNS_53/TCP'
Is UFW on Debian 12 frontend to IPtables or nftables?
It is a frontend to nftables which is the next version of IPtables. You can verify this using the following type command or command command or readlink command:
type -a iptables
readlink -f /usr/sbin/iptables
ls -l /usr/sbin/xtables-nft-multi
ls -l /usr/sbin/iptables
To maintain backward compatibility with iptables, /usr/sbin/xtables-nft-multi will execute all /usr/sbin/iptables commands. You can verify by this typing the following two commands, which dump all rules on the screen: sudo iptables -S
sudo nft list ruleset