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 updatesudo 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:

Table 1: deny and reject are both used to block traffic
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.serviceOR

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 | lessTry 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

Adding Samba and Windows Shares to ufw

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