Set up a firewall on Debian 11 or newer using nftables

Nftable is the new tool for firewall configuration in newer Debian releases.


Having a functional firewall on the server is an important step in security work. In this guide, we will create a basic firewall that you can later extend with your own rules. The guide assumes a newly installed Cloud VM running Debian 11. If you want to set up a firewall on Ubuntu 22.04, we have a guide for that here: "Set up a firewall on Ubuntu 22.04 or newer using UFW".

In Debian 11 and newer, iptables has been replaced by nftables. There are several advantages to nftables, including the ability to create rules that apply to both IPv4 and IPv6. The syntax in nftables is also somewhat simplified. Another benefit is that there is a ready‑made file where we can place the rules, and a ready‑made systemd unit to start and stop the firewall.

Activate the firewall

All the required programs are already installed on Debian 11. However, you still need to enable and start the firewall. Do this with the following two commands:

Multiple commands
sudo systemctl enable nftables.service
sudo systemctl start nftables.service

Now you can test that the firewall is working by listing the rules. By default, nothing is filtered, but Debian provides a basic configuration for input, forward, and output. List the rules with the command:

Command
sudo nft list ruleset

The output should look similar to this:

Output
table inet filter {
        chain input {
                type filter hook input priority filter; policy accept;
        }

        chain forward {
                type filter hook forward priority filter; policy accept;
        }

        chain output {
                type filter hook output priority filter; policy accept;
        }
}

The basic configuration we see above comes from the file /etc/nftables.conf, confirming that nftables is working. If you display the contents of that file, it will match the output from the command you just ran. You can try this with cat /etc/nftables.conf. The output should be:

Create firewall rules

Now it’s time to add some firewall rules. The rules we’ll create here, in this example, allow incoming traffic for SSH, HTTP, and HTTPS. We'll also permit ICMP ("ping") and traceroute. To make IPv6 work, we'll allow both ICMP and the "next header". For the local loopback interface (lo), we'll allow all traffic. To ensure that the traffic we initiate ourselves—from the server—works correctly, we'll also allow incoming traffic that is related to or part of an already established connection.

For outbound traffic from the server, we'll also allow HTTP, HTTPS, ICMP ("ping"), and traceroute. To enable name resolution, we'll allow DNS queries on UDP port 53. We'll also allow NTP queries on UDP port 123 for time synchronization.

The final rule for both inbound and outbound traffic is a rule that drops (drop) all traffic. Rules are evaluated in the order they appear, so the rules that allow traffic will be processed before the final rule that blocks everything.

All of these rules apply to both IPv4 and IPv6—except for the special rules for ICMPv6 and "next header," which apply only to IPv6.

Add the rules to the file /etc/nftables.conf. Open the file with nano or vi and edit it so that it looks like the example below (the file is owned by root, so you need to open it with sudo nano /etc/nftables.conf or sudo vi /etc/nftables.conf).

After you have added all the rules and saved the file, reload the firewall rules for them to take effect. Do this with the systemctl command:

Now, let's verify that it works with sudo nft list ruleset. The output should be:

In some of the lines of the output, you’ll see counter packets 2 bytes 84. This counter tracks how many packets have matched that rule and their total size. If you don’t need to count packets, remove the keyword counter from the rules in /etc/nftables.conf. If you don’t want to open nftables.conf in a text editor and edit it manually, you can do it automatically with the following sed command:

If you make changes to the /etc/nftables.conf file, you must reload the firewall rules again with sudo systemctl reload nftables.service for the changes to take effect.

Make temporary changes

Changes you make in /etc/nftables.conf are permanent and are loaded automatically when the server reboots. However, sometimes you might need to create temporary rules—for example, during testing or when experimenting with new services. In those cases, you can use the nft add rule command. These rules are temporary; they disappear after a reboot.

New rules added with nft add rule are placed at the end of the list, i.e., after the rule that blocks all traffic. Therefore, you need to be able to insert rules at specific positions in the list. Start by listing all the rules again, this time adding the -a flag.

The output now includes numbered handles that you can use:

In this example, we'll add a new rule to allow incoming traffic on TCP port 8080 (http‑alt), then remove it again. Place the rule after the traceroute rule—that is, after handle 10. Do this with:

Let's list the rules again, but this time limit the list to the input rules. The new rule should be placed after handle 10:

To delete the rule again, use its handle, 22:

If you lock yourself out by mistake

Be careful when loading new firewall rules so you don’t lock yourself out of the SSH service (TCP port 22). If you do accidentally lock yourself out, you can log in through the console in Glesys Cloud. You’ll find it under ComputerVirtual machines. Click Actions next to your server’s name and select Console. Once you’re logged in, you can edit the /etc/nftables.conf file and fix the issue.

For more information on logging in to the console and booting the server in single-user mode, see Connect to the VM console.

Last updated

Was this helpful?