Last updated on Oct 29, 2024
Nftables are a framework for packet filtering, firewalls and Network Address Translators (NATs). Support for nftables has been in the Linux Kernel since version 3.13. Nfables is the sucessor to iptables. In Debian 10 (buster - July 6, 2019), nftables replaced iptables. nftables has a compatibility mode for iptables.
To run nft commands requires root privillages. You can either prefix all nft commands with sudo or you can change to the root user:
sudo bash
To determine the verson of Nftables:
nft -v
At the top is a text file, /etc/nftables.conf. It contains one or more nftables. Nftables contains one or more chains, and chains contain one or more rules.
All of the nftables do not have to be inside of /etc/nftables.conf. You can include other nftables at the end of the file:
include "/Path/nftable_name.conf"
# | anything after the hash sign (#) is a comment |
; | more commands or parameters to follow |
\ | break a rule into mutliple lines |
There are six ntable types or address families:
ip | ip4 addresses - default if none specified |
ip6 | ip6 addresses |
inet | both ip4 & ip6 |
bridge | |
netdev | ingress filtering |
arp | Address Resolution Protocol |
Syntax: table [<address_family>] nft_table_name { }
There are two types of chains: base and non-base.
Base chains are the entry point for packets from the networking stack. Base chains specify a type, hook, priority and policy.
Syntax: chain chain_name {type <type> hook <hook> priority <priority>; [policy <policy>;]}
type: filter, route, and nat
priority: -300 to 300
policy: accept or drop
The lower the priority number the higher the priority is. Priority numbers can be negaive.
If no policy is explicitively give the default policy accept will be used.
Non-base chains are jump target to better organize rules. Non-base type chains do not have a type, hook and priority.
Rules are some expression to be matched followed by a verdict statement.
The following is an incomplet list of expressions that can be matched:
Common IPv4 Matches | ||
---|---|---|
saddr <ip source address> | Source addresses | ip saddr 192.168.1.0 ip saddr 192.168.1.0/24 |
daddr <ip destination address> | Destination addresses | ip daddr 192.168.1.0 ip daddr 192.168.1.0/24 |
protocol <protocol> | Upper layer protocol | ip protocol tcp ip protocol udp ip protocol icmp |
Common TCP Matches | ||
---|---|---|
sport <tcp source port> | Source port | tcp sport 22 tcp sport ssh |
dport <tcp destination port> | Destination port | tcp dport 22 tcp dport ssh |
Common UDP Matches | ||
---|---|---|
sport <udp source port> | Source port | udp sport 22 udp sport ssh |
dport <udp destination port> | Destination port | udp dport 22 udp dport ssh |
Common Meta Matches | ||
---|---|---|
iifname <input interface name> | Input interface name | meta iifname "lo" meta iifname "eth0" |
oifname <Output interface name> | Outout interface name | meta oifname "lo" meta oifname "eth0" |
iff <input interface index> | input interface index | meta iif lo meta iff eth0 |
oif <Ouput interface index> | output interface index | meta oif lo meta oif eth0 |
ifftype <input interface type> | input interface type | meta iiftype loopback meta iiftype ether meta iiftype ipip meta iiftype ipip6 |
oif <Ouput interface type> | output interface type | meta oiftype loopback meta oiftype ether meta oiftype ipip meta oiftype ipip6 |
* The prefix meta before the meta key is optional. See meta expressions - types qualified and unqualified in manpage.[]
Common Ether Matches | ||
---|---|---|
saddr <mac address> | Source MAC address | either saddr 00:0f:54:0c:11:04 |
Verdict statements include:
The follow is an ntable that accepts all IPv4 traffic with input source address 192.168.37.52, and its drops all other inputs, including all IPv6 traffic.
table inet FILTER {
chain INPUT {
type filter hook input priority 0; policy accept;
ip saddr 192.168.37.52 accept
drop
}
}
There are very few good tutorials on nftables. Nftables just does not have the same amount of documentation that iptables has. The nftables organization's (nftables.org) documentation is good; however, it is not a begginers guide. They want to show off their latest advances over iptables and how concise and succinct they can be. They have a simple ruleset for a home router [13], but it uses the concatenation operator (.) [14], vmap [15], and th (transport header) [16]. You have to dig through their documention to learn what these are. In the end, I found out that the th parameter requires both nftables 0.92 and Linux Kernnel 5.3. As of 11-29-22, the Raspberry Pi OS-64 still uses kernnel 5.15.
tcp dport 22 accept
Most all of these commands require root privilages. To become the root in the Raspberry Pi OS:
sudo bash
Notice that prompt changes to the hash sign (#), and that
whoami
says "root".
To determine if the the modulel is in the Linux Kernel:
modinfo nf_tables
To determine if nftables is installed, check the version:
nft -v
To determine if nftables is active
systemctl status nftables
My general purpose everyday RPi has firewald and fail2band installed. The "system status nftable" command say that it is unactive. However, the "nft list ruleset" command shows a table with the table_name firewalld. I do not understand this.
Raspberry Pi has everthing installed, but by default it is unactive.
For the current session, you can start or stop nftables (not persistent), with the following commands.
systemctl start nftables
systemctl stop nftables
To enabled or disabled nftables after a reboot (persistent), use one of the following commands:
systemctl enable nftables
systemctl mask nftables
To see errors:
systemctl status nftables
By defination, Nftables does not have defaults chains (like iptables). However, some Linux distributions have a default configuration file, which contains predefined chains. Also, some distrubtion have example nft script files. See table below:
Distribution | Config. Files | Script Files |
---|---|---|
Debian Raspberry Pi |
/etc/nftables.conf | /usr/share/doc/nftables/examples/ |
Red Hat Fedora |
/etc/sysconfig/nftables.conf | /etc/nftables/ |
Debian's default configuration file, which is listed below, contains three chains, an input chain, a forward chain, and an output chain. It accepts everything. It is just a skelton that can be added to.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter;
}
chain forward {
type filter hook forward priority filter;
}
chain output {
type filter hook output priority filter;
}
}
There are three ways to edit or create nftables.
The easest method, is to create and debug a script file wih method 3C, and to include the script file in the configuration file. Note, the configuration file can be just a single include statement.
Nft script files can have any name, but it is customary for them to have the .nft extension.
If you are going to pass a nft script file to the nft utility, it must have the folowing header:
#!/usr/sbin/nft -f
If you want to flush the existing ruleset then the next line after the header should be:
flush ruleset
To pass a script to the nft utility, enter:
nft -f your_script_filename.nft
To run a script directly, you have to make the script executable:
chmod +x your_script_filename.nft
In debugging nftables, the following command my be useful:
systemctl status nftables
Other than the extension, location and that the fact that the nftables.conf is ran at boot, there are no differences between the nftables.conf file and nftables script files.
To view all chains and rules in all tables:
nft list ruleset
To view chains and rules in a particuar table:
nft list table address_family table_name
To view the rules in a particuar chain:
nft list chain address_family table_name chain_name
Although you should never use firewalld and nftables together, you can use the nft utility to the view the nftables and rules generatated by firewalld:
nft list table inet firewalld
nft list table ip firewalld
nft list table ip6 firewalld
# | anything after the hash sign (#) is a comment |
; | more commands or parameters to follow |
\ | break a rule into mutliple lines |
Address Families
ip | ip4 addresses |
ip6 | ip6 addresses |
inet | both ip4 & ip6 |
bridge | |
netdev | ingress filtering |
arp |
Both iftables and iptables have chains with policy (accept/drop) and rules.
Both nf and ip table can filter:
prerouting | |
input | |
forward | |
output | |
postrouting | |
arp |
nft -v # version
/////////
sudo nft add table [address_famaily] example_table
sudo nft delete table [address_famaily] example_table
sudo nft flush table [address_famaily] example_table
The flush command deletes every rule in every chain in the table
sudo nft add chain inet example_table example_chain '{type filter hook input priority 0; }'
base chain | ||
type | is | filter |
hook | is | input |
priority | is | 0 |
Chains with lower priority numbers get procesed first.
Non-base chains aslo refered to as regular chains, do not have type, hook and priority
saddr | = | source address | e.g., 192.168.0.0/24 |
daddr | = | destination address | e.g., 192.168.0.2-192.168.0.59 |
iifname | = | input interface name | e.g., "eth0", "wlan0" |
oifname | = | output interface name | e.g., "eth0", "wlan0" |
ct | = | connection tracking |
Tables have chains, and chains have rules. A table can have more than one chain, and a chain can have more than one rule.
Common port aliases are:
Port No. | Alias |
---|---|
22 | ssh |
80 | http |
443 | https |
53 | domain (dns) |
To list all aliases: cat /etc/services.
Priority No.| | Alias |
---|---|
0 | filter |
I am not a fan of using keywords as aliases e.g., a type of rule is a filter (keyword), but the word "filter" can also be used as an alias for the rule priority number 0, and when they are in the same line, this makes it confusing for newcomers.
Example 1A: Only allow incoming from 192.168.37.52
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
# Allow all traffic from 192.168.37.52 - Don't lock myself out
ip saddr 192.168.37.52 accept
# Drop everything else
drop
}
}
Examble 1 does not allow loopback traffic that some services require. Modify it to allow loopback traffic.
Example 2:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
# Allow loopback traffic from this computer
meta iif lo accept
# Drop loopback traffic not from this computer
iif != lo ip daddr 127.0.0.1/8 drop # IPv4
iff != lo ip6 daddr ::1/128 drop # IPv6
# Allow all traffic from 192.168.37.52 - Don't lock myself out
ip saddr 192.168.37.52 accept
# Drop everything else
drop
}
}
References:
Example 1A: Allow all incoming tcp traffic to ports 22 (ssh) and 5900 (VNC).
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Allow SSH traffic
# matched by tcp and destination port 22 (alias ssh)
tcp dport ssh accept
# Allow VNC traffic
tcp dport 5900 accept # no alias for this port
# Drop everything else
drop
}
}
I am not a fan of keywords and/or aliases having multiple meaning. However, this seems to be the norm with nftable. For example, a type of chain is a "filter" (keyword), and "filter" is also used as an alias for the priority number 0. Furthermore, in this example the table name is "filter", and the chain name is "input", which is a type of hook (keyword). This is very confusing for newcomers.
Example 1B: To determine if this is working, you can add counters to count the number of packets and bytes. Counters should be paced immediately before accept or drop.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Allow SSH traffic
# mached by tcp and destination port 22 (alias ssh)
tcp dport ssh counter accept
# Allow VNC traffic
tcp dport 5900 counter accept # no alias for this port
# Drop everything else
drop
}
}
You can also defined named counters. Modify example 1a by naming the counter.
#!/usr/sbin/nft -f
flush ruleset
counter ssh_or_Vnc {}
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Allow SSH traffic
# mached by tcp and destination port 22 (alias ssh)
tcp dport ssh counter name ssh_or_vnc accept
# Allow VNC traffic
tcp dport 5900 counter name ssh_or_vnc accept
# Drop everything else
drop
}
}
Example 1C: Modify Example 1B to allow SSH and VNC traffic only from source addresses 192.168.37.45 and 192.168.37.45.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Allow SSH traffic
# mached by tcp and destination port 22 (alias ssh)
ip saddr 192.168.37.45 tcp dport ssh counter accept
ip saddr 192.168.37.46 tcp dport ssh counter accept
# Allow VNC traffic
ip saddr 192.168.37.45 tcp dport 5900 counter accept
ip saddr 192.168.37.46 tcp dport 5900 counter accept
# Drop everything else
drop
}
}
To use MAC addresses in lieu of IP addresses, prefix saddr with ether. For example:
ether saddr 04:0D:0A:3D:FE:06 tcp dport ssh counter accept
Sets are enclosed in brackets, and the elements are separated by commas. You can use sets to combine rules.
Example 1D: Modify Example 1C using sets.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Allow SSH and VNC traffic
# matched by source address and tcp protocol with destination port 22 or 5900.
ip saddr {192.168.37.45, 192.168.37.46} tcp dport {ssh, 5900} counter accept
# Drop everything else
drop
}
}
Example 1E: Modify Example 1D to use named sets.
#!/usr/sbin/nft -f
flush ruleset
# set_example.nft
table inet filter {
set allowable_ip_addresses{
typeof ip saddr
elements = {192.168.37.45, 192.168.37.46}
}
set allowable_dports{
typeof tcp dport
elements = {ssh, 5900}
}
chain input {
type filter hook input priority filter;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Only allow SSH & VNC traffic
# matched by source IP and tcp destination ports
ip saddr @allowable_ip_addresses tcp dport @allowable_dports accept
# Drop everything else
drop
}
}
Having to declare named sets in advance is more complicated than in-line sets. However, we have just touched on named sets. Named sets are more powerful than in-line sets. For example, as will be in "Advanced Named Sets", you can use nft rules to add elements to named sets.
For troubleshooting, you should accept pings but limit them
Example 1F: Modify Example 1E to accept pings.
#!/usr/sbin/nft -f
flush ruleset
# set_example.nft
table inet filter {
set allowable_ip_addresses{
typeof ip saddr
elements = {192.168.37.45, 192.168.37.46}
}
set allowable_dports{
typeof tcp dport
elements = {ssh, 5900}
}
chain input {
type filter hook input priority filter;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Only allow SSH & VNC traffic
# matched by source IP and tcp destination ports
ip saddr @allowable_ip_addresses tcp dport @allowable_dports accept
# allow pings without limits.
ip protocol icmp accept;
# Drop everything else
drop
}
}
Example 1G: Modify Example 1F to limit pings.
#!/usr/sbin/nft -f
flush ruleset
# set_example.nft
table inet filter {
set allowable_ip_addresses{
typeof ip saddr
elements = {192.168.37.45, 192.168.37.46}
}
set allowable_dports{
typeof tcp dport
elements = {ssh, 5900}
}
chain input {
type filter hook input priority filter;
# Don't lock myself out
ip saddr 192.168.37.52 accept
# Only allow SSH & VNC traffic
# matched by source IP and tcp destination ports
ip saddr @allowable_ip_addresses tcp dport @allowable_dports accept
# allow pings without limits.
ip protocol icmp limit rate 1/second accept;
# Drop everything else
drop
}
}
Thus far, all our chains have been "base" chains. Non-base chains do NOT have a type, hook, priority or default policy. They only contain rules. They are used to group your rules according to some criteria. Non-based chains are the targets of jump or goto actions.
Example 2A: Organize you rules according to the basic protocol (tcp, udp, icmp).
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
set allowable_ip_addresses {
typeof ip saddr
elements = {192.168.37.45, 192.168.37.46}
}
set allowable_dports{
typeof tcp dport
elements = {ssh, 5900}
}
chain INPUT {
type filter hook input priority filter; policy accept;
# don't look myself out
ip saddr 192.168.37.52 accept
# divide the traffic according to protocol
ip protocol tcp jump CHAIN_TCP
ip protocol udp jump CHAIN_UDP
ip protocol icmp jump CHAIN_ICMP
drop
}
chain CHAIN_TCP {
ip saddr @allowable_ip_addresses tcp dport @allowable_dports accept
}
chain CHAIN_UDP {
drop
}
chain CHAIN_ICMP {
ip protocol icmp limit rate 1/second accept
}
}
When your rules have criteria on the left and actions on the right, you can use verdict maps to consolidate rules.
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
set allowable_ip_addresses {
typeof ip saddr
elements = {192.168.37.45, 192.168.37.46}
}
set allowable_dports{
typeof tcp dport
elements = {ssh, 5900}
}
chain INPUT {
type filter hook input priority filter; policy accept;
# don't look myself out
ip saddr 192.168.37.52 accept
# divide the traffic according to protocol
ip protocol vmap {
tcp : jump CHAIN_TCP,
udp : jump CHAIN_UDP,
icmp: jump CHAIN_ICMP
}
drop
}
chain CHAIN_TCP {
ip saddr @allowable_ip_addresses tcp dport @allowable_dports accept
}
chain CHAIN_UDP {
counter drop
}
chain CHAIN_ICMP {
ip protocol icmp limit rate 1/second accept
}
}
TCP has connection tracking (ct) states. UDP does NOT have connection tracking states [1].
There are five (5) conntrack (ct) states [4]:
new | Netfilter has so far seen packets between this pair of hosts only in one direction. At least on of theses packets is part of a valid initialization sequence,e.g. SYN packet for a TCP Connection. |
established | Netfilter has seen valid packets travel in both directions between this pair of hosts. For TCP connections, the three-way-handshake has been successfully completed. |
related | This connection was initiated after the main connection, as expected from normal operation of the main connection. A common example is an FTP data channel established at the behest of an FTB control channel. |
invalid | Assigned to packets that do not follow the expected behavior of a connection. These include malformed, corrupted packets and maliceware. Another example, would be a late TCP packet that is received after retransmission has been performed [3]. These should be dropped. |
untracked | Dummy state assigned to packets. |
The following example uses connection tracking to only allow outbound DNS, HTTP, and HTTPS traffic and only allow inbound return traffic and loop back traffic.
#!/usr/bin/nft -f
flush ruleset
table ip transport {
chain INPUT {
type filter hook input priority filter; policy drop;
ct state established,related counter accept
iif lo ip daddr 127.0.0.1/8 counter accept
}
chain OUTPUT {
type filter hook output priority filter; policy drop;
# allow established and existing traffic
ct state established,related counter accept
# allow DNS out
udp dport 53 ct state new counter accept
tcp dport 53 ct state new counter accept
# allow HTTP/HTTS out
tcp dport { 80, 443 } ct state new counter accept
udp dport { 80, 443 } ct state new counter accept
# drop everyting else
}
}
The reasons for the two DNS statements and the two HTTP/HTTPS statements are:
Altought, tcp and udp are seperate protocols with their own headers, the raw location of dport is the same in both headers. This allows merging of dport statements that only differ in whether the protocol is tcp or udp.
For example the two statements:
tcp dport 53 accept
upd dport 53 accept
Can be replaced by the single statement:
meta l4proto {tcp,udp} th dport 53 accept
The first part of the statement, meta l4proto {tcp, udp}, ensures that it is a level 4 protocol - either tcp or udp and excludes other level 4 protocols. The second part of the statement, th dport 53, does a raw read of the transport header (th) and checks to see if dport matches 53.
With the transport header raw read feature, four lines in the previous example can be condensed to one line:
#!/usr/bin/nft -f
flush ruleset
table ip transport {
chain INPUT {
type filter hook input priority filter; policy drop;
ct state established,related counter accept
iif lo ip daddr 127.0.0.1/8 counter accept
}
chain OUTPUT {
type filter hook output priority filter; policy drop;
# allow established and existing traffic
ct state established,related counter accept
# allow DNS, HTTP and HTTP out
meta l4proto {udp,tcp} th dport { 53, 80, 443 } ct state new counter accept
# drop everyting else
}
}
This should be more efficent and faster than executng four sepearate tests.
References:
You can use variables:
define accepted_input_ports = {22,5900}
tcp dport $accepted_input_ports accept
As previously stated, you can used nft rules to add elements to a named set. The example below illustrates this and the use of timers.
Example 5 - If an IP address attemps to SSH into a machine more than twice in one minute, the IP address is locked out for 24 hours. This is the last example in referencet [1]. The code is below:
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
set stage1 {
typeof ip saddr
flags timeout
}
set stage2 {
typeof ip saddr
flags timeout
}
set stage3 {
typeof ip saddr
flags timeout
}
chain input {
type filter hook input priority filter; policy accept;
# allowed established and related traffic
ct state related,established accept
# do not lock yourself out
ct state new ip saddr 172.27.96.76 tcp dport 22 accept
# To understand the lockout code below, read it in the order of the comments numbers
ct state new ip saddr @stage2 tcp dport 22 add @stage3 { ip saddr timeout 1d } #3
ct state new ip saddr @stage1 tcp dport 22 add @stage2 { ip saddr timeout 1m } #2
ct state new tcp dport 22 add @stage1 { ip saddr timeout 1m } #1
ct state new ip saddr @stage3 tcp dport 22 drop #4
}
}
You can test this by trying to SSH into the machine, and when prompted for the password, type in an incorrect passwords three times. Then try to SSH into the machine a second time. Again type in an incorrect password three times. If you attempt to SSH into the machine for a third time, it wil NOT prompt you for a password. You are now locked out for 24 hours.
Thus if you know nftables, you do not need a program such as fail2ban that has dependaces.
You do not need to lock an IP address out for one day to prevent a brute force attach. Five minutes is probably sufficent. I belive the one day is so you can see that someone tried to attach this machine.
There is a Red Hat example that claims to limit login attempts. See reference [2]. The code us below:
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
set denylist {
type ipv4_addr
flags dynamic, timeout; timeout 5m;
}
chain input {
type filter hook input priority 0;
# I changed the rate from over 10/min to over 2/min for testing
# I am not sure what "untracked" does, if anything, in the statement below.
ip protocol tcp ct state new,untracked limit rate over 2/minute add @denylist {ip saddr}
ip saddr @denylist drop
}
}
When you attemp to remotely SSH into a machine, you usally get three (3) attemps to type in the correct password, before you have to SSH into the machine again. I was not able to type an incorrect password fast enought for my IP address to be placed in the denylist. However, when prompted for the password, you can hit Control-C, and then you will have to SSH again into the machine. This method took six (6) attemps before my IP address was put into the denylist. On at least one occassion it took seven (7).
The Youtube video in reference [3], uses the same code except he changed the rate to 3/minute. It took him seven (7) attemps before his IP address was placed into the denylist.
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
set ssh_clients {
type ipv4_addr
flags timeout
}
chain input {
type filter hook input priority filter; policy accept;
# do not lock myself out
ct state new ip saddr 192.168.37.45 tcp dport 22 accept
# accept loopback trafic
iif "lo" accept
# allowed established and related traffic
ct state related,established accept
tcp dport 10 add @ssh_clients {ip saddr timeout 30s}
ip saddr @ssh_clients tcp dport ssh accept
drop
}
}
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
# 11monitor.nft - version 11
#
# The following code helps you to idenify tcp, udp and icmp traffic
# on your local area network.
#
# For now (7-22-2022), I have decided to implement this only for IPv4 traffic
# and to drop, all IPv6 traffic.
set log_tcp_traffic { typeof ip saddr . tcp sport . ip daddr . tcp dport; }
set log_udp_traffic { typeof ip daddr . udp dport . ip saddr . udp sport; }
set log_ct_established_tcp { typeof ip daddr . tcp dport . ip saddr . tcp sport; }
set log_ct_established_udp { typeof ip daddr . udp dport . ip saddr . udp sport; }
set log_ct_invalid { typeof ip saddr; }
set log_loopback_traffic { typeof ip saddr; }
set log_loopback_bad { typeof ip saddr; }
set log_pings { typeof ip saddr; }
set log_dropped { typeof ip saddr; }
chain input {
type filter hook input priority filter; policy accept;
#log source ip of all input
add @log_tcp_traffic { ip daddr . tcp dport . ip saddr . tcp sport}
add @log_udp_traffic { ip daddr . udp dport . ip saddr . udp sport }
# do not lock myself out - allow local network
ct state new ip saddr 192.168.37.0/24 accept
# allowed established and related traffic
ct state related,established add @log_ct_established_tcp \
{ip daddr . tcp dport . ip saddr . tcp sport} accept
ct state related,established add @log_ct_established_udp \
{ip daddr . udp dport . ip saddr . udp sport} accept
ct state invalid add @log_ct_invalid {ip saddr} drop
# accept loopback trafic
iif "lo" add @log_loopback_traffic {ip saddr} accept
# loopback bad - I am currently working on this
# iff != lo ip daddr 127.0.0.1/8 add @loopback_bad {ip saddr} drop
# iff != lo ip6 daddr ::1/128 drop
# allow pings but limit the rate
ip protocol icmp limit rate 1/second add @log_pings {ip saddr} accept
# log dropped traffic
add @log_dropped {ip saddr} drop
}
chain forward {type filter hook forward priority filter; policy drop; }
chain output { type filter hook output priority filter; policy accept; }
}
# Drop all IPv6 Traffic:
table ip6 filter {
chain input { type filter hook forward priority filter; policy drop; }
chain forward { type filter hook forward priority filter; policy drop; }
chain output { type filter hook output priority filter; policy drop; }
}
References:
systemctl start nftables
nft list ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
# only routers should forward packets
counter drop
}
chain output {
type filter hook output priority filter; policy accept;
}
-- -- -- -- -- -- -- -- -- -- --
To stop nftables from doing anything, just drop all the rules:
nft flush ruleset
To uninstall it and purge any traces of nftables in your system:
aptitude purge nftables
///////////////////////////
modinfo nf_tables
lsmod | grep nf_tables
///////////////////////
iptables -F
ip6tables -F