This guide shows how to configure a persistent native nftables firewall on a BinaryLane Ubuntu or Debian VPS. It explains how nftables relates to UFW and the BinaryLane External Firewall, provides a table-scoped baseline ruleset, and covers common rules, verification and recovery.


This article describes a customer-managed solution. BinaryLane cannot provide hands-on troubleshooting for operating system-level issues. See What support options are available? for more information.


Prerequisites:

  • Root access or a user with sudo privileges.
  • An Ubuntu or Debian VPS that uses the apt package manager and systemd.
  • A current backup or another tested recovery path.
  • A list of the services and ports that must remain reachable.
  • Your current public IP address if you plan to restrict SSH by source address.
  • Access to the mPanel Rescue Console in case a firewall rule blocks SSH.


Warning: A default-deny firewall can lock you out of the VPS. Keep your current SSH session open, open the mPanel Rescue Console before applying the rules, and verify a second SSH connection before closing the original session.




TABLE OF CONTENTS





Choose where to filter traffic

You can use the BinaryLane External Firewall, nftables inside the VPS, or both. The right choice depends on how much control you need and whether you want to manage one or two policy layers.


Approach How it works Best suited to Trade-off
BinaryLane External Firewall only Filters IPv4 traffic before it reaches the VPS. Broad rules such as allowing SSH, HTTP and HTTPS, then blocking other IPv4 traffic. Does not filter IPv6 and has less operating-system context.
nftables only Filters traffic inside Linux after it reaches the VPS. Fine-grained IPv4 and IPv6 rules, counters, logging and service-specific policy. A bad rule can block remote access and requires operating-system or console access to repair.
Both The External Firewall applies first, then nftables evaluates traffic that reaches the VPS. Broad platform-level filtering with more detailed rules inside Linux. Two policies must be kept aligned. Either layer can block a connection, which can make troubleshooting more involved.


A practical combined design is to use the External Firewall for broad rules and nftables for finer service or source restrictions. If the External Firewall blocks a packet, nftables will not see it. If the External Firewall allows a packet, nftables can still block it.


Important: BinaryLane External Firewall rules currently apply to IPv4 traffic only and do not filter IPv6 traffic. If IPv6 is enabled on your VPS, manage IPv6 access inside the server using an OS-level firewall such as nftables.


You can manage the platform firewall from the External Firewall page in mPanel.




Choose one OS firewall manager

Ubuntu provides UFW as its default firewall configuration tool, although UFW is initially disabled by default. UFW is a front end for iptables, and current Ubuntu installations commonly use the nftables compatibility backend for iptables. As a result, rules created by UFW or iptables may also appear in nft list ruleset.


Choose one manager inside the VPS: For a normal host firewall, use UFW, firewalld, native nftables or another firewall manager as the owner of the OS firewall policy. Do not independently manage the same policy with UFW and nftables.service unless you understand the combined rule order and reload behaviour.


Using the BinaryLane External Firewall together with one OS firewall manager is different. The External Firewall is a separate upstream layer and can be used for broad IPv4 filtering while nftables applies finer IPv4 and IPv6 rules inside the VPS.


Before choosing native nftables:

  • If UFW is active, review sudo ufw status numbered and translate every required rule before disabling it.
  • If firewalld or another firewall service is active, either continue using that service or plan a deliberate migration. Do not proceed with this template unchanged.
  • If Docker, Kubernetes, libvirt, Fail2ban, CrowdSec, a VPN or a hosting panel manages firewall rules, preserve the tables and chains it owns.
  • If iptables --version shows (legacy), those rules are separate from the nftables ruleset. Identify their owner before changing the firewall.


The template in this guide manages only a uniquely named inet host_filter table. It does not flush tables created by other software and it does not create a forward chain.




Understand BinaryLane Port Blocking

Important: BinaryLane Port Blocking is enabled by default on new servers and blocks outbound TCP connections to ports 22, 25 and 3389. It is separate from the External Firewall and nftables.


Port Blocking does not define which inbound services can reach the VPS and it does not appear in nft list ruleset. An nftables output rule cannot override a platform Port Blocking restriction.


If the VPS needs to make outbound SSH, SMTP or RDP connections on these ports, review the setting on the Port Blocking page in mPanel. Disabling Port Blocking requires account approval.




Update the VPS and confirm nftables

Before updating: Package updates can restart services and a kernel update can require a reboot. Use a maintenance window and confirm your backup or recovery plan first.


Update the package lists and installed packages:

sudo apt update
sudo apt full-upgrade


Check whether the nft command is already installed:

command -v nft


The current BinaryLane Ubuntu 24.04 image includes the nftables package, but the service is not enabled by default. Package availability can differ on other images. If the command above returns no path, install nftables:

sudo apt install nftables


Confirm the installed version:

sudo nft --version


Check whether the update requires a reboot:

if [ -f /var/run/reboot-required ]; then
    cat /var/run/reboot-required
fi


If a reboot is required, reboot and reconnect before configuring the firewall:

sudo reboot




Inspect the current network state

Identify listening services, active firewall managers and the current Netfilter rules before making changes:

sudo ss -lntup
sudo ufw status verbose
sudo systemctl is-active firewalld
sudo iptables --version
sudo systemctl status nftables --no-pager
sudo nft list ruleset


An inactive service or an empty ruleset is not an error on a new server. Do not assume an existing server has the same state.


Stop if another firewall manager is active. Record the current rules, determine which application owns them, and translate every required inbound, outbound, forwarding and NAT rule before switching to native nftables. Disabling an existing firewall without reproducing its policy can expose services or break connectivity.


The nft list ruleset output can include rules created by UFW, iptables compatibility tools, Docker and other services. Seeing a rule in this output does not mean that nftables.service owns it.




Create a baseline ruleset

Back up the persistent nftables configuration if it exists:

if [ -f /etc/nftables.conf ]; then
    sudo cp -a /etc/nftables.conf "/etc/nftables.conf.backup-$(date +%F-%H%M%S)"
fi


Save the current active ruleset as a reference:

sudo nft list ruleset | sudo tee "/root/nftables-ruleset-$(date +%F-%H%M%S).nft" > /dev/null


The active-ruleset export can contain rules generated by other services. Use it for comparison and recovery planning rather than assuming it is a complete persistent configuration.


Open the persistent configuration file:

sudo nano /etc/nftables.conf


The following baseline permits established connections, loopback traffic, IPv4 ICMP, IPv6 ICMP, SSH, HTTP and HTTPS. Other inbound traffic is dropped and outbound traffic is allowed.

#!/usr/sbin/nft -f

add table inet host_filter
flush table inet host_filter

table inet host_filter {
    chain input {
        type filter hook input priority filter; policy drop;

        ct state invalid counter drop
        ct state established,related counter accept
        iifname "lo" counter accept

        ip protocol icmp counter accept
        ip6 nexthdr ipv6-icmp counter accept

        tcp dport { 22, 80, 443 } ct state new counter accept

        counter drop
    }

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


The inet family handles both IPv4 and IPv6. Keep ICMPv6 allowed so IPv6 neighbour discovery, router advertisements and error handling continue to work.


The add table and flush table lines reset only the table managed by this guide. They do not remove unrelated tables created by UFW, Docker or other applications.


This host-firewall baseline does not create a forward chain. If the VPS routes traffic, hosts containers, provides a VPN gateway or performs NAT, identify which service owns forwarding and configure that traffic separately.




Check, apply and enable the ruleset

Check the complete file for syntax errors without applying it:

sudo nft --check --file /etc/nftables.conf


If UFW is active and you have decided to replace it with native nftables, confirm that the new rules reproduce every required UFW rule. Keep the Rescue Console and current SSH session open, then disable UFW immediately before loading the new configuration:

sudo ufw disable


Do not run this command when UFW is already inactive or when you intend to keep using UFW.


Load the configuration and enable the nftables service at boot:

sudo nft --file /etc/nftables.conf
sudo systemctl enable --now nftables


Keep the original session open. From a second terminal, confirm you can create a new SSH connection to the VPS. If IPv6 is enabled and you use it for administration, test an IPv6 SSH connection as well.


Verify the service and the table managed by this guide:

sudo systemctl is-enabled nftables
sudo systemctl is-active nftables
sudo nft list table inet host_filter


The first two commands should return enabled and active. The final command should show the inet host_filter table.


For a final persistence check, reboot during the maintenance window, reconnect and run the verification commands again.


Do not stop or restart nftables to apply routine changes. On Ubuntu 24.04, stopping nftables.service flushes the complete active nftables ruleset, including tables owned by other applications. After editing the table-scoped configuration in this guide, use sudo nft --check --file /etc/nftables.conf followed by sudo nft --file /etc/nftables.conf. You can also use sudo systemctl reload nftables while the service is active.




Common firewall configurations

Add persistent rules inside the input chain, above the final counter drop rule. After editing the file, check and load it using the commands from the previous section.


Restrict SSH by source address

Replace 203.0.113.10 and 2001:db8:1234::/64 with your real administration address or range. Remove port 22 from the broad TCP port rule, then use:

ip saddr 203.0.113.10 tcp dport 22 ct state new counter accept
ip6 saddr 2001:db8:1234::/64 tcp dport 22 ct state new counter accept
tcp dport { 80, 443 } ct state new counter accept


If your administration IP changes, update the rule before closing the current session. If you use both firewall layers, update the corresponding External Firewall source rule as well.


Allow a custom TCP service

tcp dport 8443 ct state new counter accept


Allow WireGuard

udp dport 51820 ct state new counter accept


Allow a DNS server

An authoritative or recursive DNS service normally needs both UDP and TCP port 53:

udp dport 53 ct state new counter accept
tcp dport 53 ct state new counter accept


Restrict database access

Do not broadly expose database ports. Replace 192.0.2.20 with the application server or trusted source address:

ip saddr 192.0.2.20 tcp dport { 3306, 5432 } ct state new counter accept


Log dropped input traffic

Place this rate-limited logging rule immediately before the final counter drop rule:

limit rate 5/minute burst 10 packets log prefix "nft input drop: " flags all counter


Rate limiting helps prevent routine scans from flooding the system log. Review disk and log-retention usage if you enable firewall logging.




Monitor and manage nftables

List the table and packet counters managed by this guide:

sudo nft list table inet host_filter


List the complete ruleset when you need to see tables created by other applications:

sudo nft list ruleset


Include rule handles when you need to remove a live rule:

sudo nft -a list chain inet host_filter input


View rate-limited drop logs if you enabled the logging rule:

sudo journalctl -k --grep 'nft input drop:' --since today


For temporary, source-restricted TCP access, quote the complete nftables expression so the shell does not alter it:

sudo nft 'insert rule inet host_filter input ip saddr 203.0.113.10 tcp dport 8080 ct state new counter accept comment "temporary app access"'


Find its handle:

sudo nft -a list chain inet host_filter input


Then remove it, replacing <HANDLE> with the displayed number:

sudo nft delete rule inet host_filter input handle <HANDLE>


Note: Rules added directly with the nft command are runtime changes. They are lost when the saved configuration is reloaded or the server reboots unless you also add them to /etc/nftables.conf.




Recover access

If a new rule blocks SSH, use the mPanel Rescue Console to sign in locally.


Recovery action: The next command immediately removes the active table created by this guide. It does not remove unrelated nftables tables owned by other applications.
sudo nft delete table inet host_filter


Prevent the same saved configuration from loading during a reboot while you repair it:

sudo systemctl disable nftables


Edit /etc/nftables.conf, then check and apply the corrected configuration:

sudo nft --check --file /etc/nftables.conf
sudo nft --file /etc/nftables.conf
sudo systemctl enable --now nftables


Confirm a new SSH connection works before closing the console. Do not blindly load the earlier active-ruleset export because it may contain dynamic rules generated by other services.







Troubleshooting

Problem What to check
nft command not found Install the package with sudo apt install nftables, then run sudo nft --version.
UFW or firewalld is active Choose which OS firewall manager will own the policy. Do not apply the native nftables template until all required rules have been translated and you have a safe migration plan.
nftables fails to load Run sudo nft --check --file /etc/nftables.conf, then review sudo systemctl status nftables --no-pager and sudo journalctl -u nftables -b --no-pager.
SSH times out after applying rules Use the mPanel Rescue Console and follow the recovery steps. If you use both firewall layers, confirm the External Firewall also permits your source address and TCP port 22.
A service port times out Check that the service is listening with sudo ss -lntup, inspect the host_filter counters, and review both firewall layers if both are in use.
A connection is refused instead of timing out The traffic may be reaching the VPS but no service is listening on that address and port. Check the service state and listening sockets.
IPv4 works but IPv6 does not The External Firewall does not filter IPv6. Check the VPS IPv6 address and route, keep ICMPv6 allowed, and confirm the nftables rule applies to IPv6.
Outbound SSH, SMTP or RDP is blocked Check BinaryLane Port Blocking in mPanel. The default platform control is separate from the nftables output policy.
Docker, a VPN or routed traffic stops working Inspect the complete ruleset and any existing forward chains. The baseline in this guide does not create a forward policy or remove other tables, but another firewall manager or older configuration may still affect forwarded traffic.
Rules disappear after a reboot Confirm nftables.service is enabled and that the required rules are present in /etc/nftables.conf. Runtime-only rules are not persistent.
iptables --version shows (legacy) Legacy iptables rules are not represented by the native nftables ruleset. Identify the application that owns them before changing firewall managers.



If you require assistance, submit a support ticket through the BinaryLane helpdesk.