nftables(iptables)/iproute2 ティップス

iptables

iptables for firewall

IPアドレスやポートのルーティング設定を行う iptables についてのティップス。
ルータのネットワーク設定、ファイヤーウォール、Docker, WireGuardなど iptables によってその挙動が決まります。iproute2 とセットで理解しましょう。
:warning:
"ifconfig", "netstat" の役割は iproute2 に置き換わっています。
"ip rule", "ip route"iproute2 に含まれるコマンドの一部です。
また iptablesnftables に置き換わっています。

netfilter.org:iptables, nftables ドキュメント

https://www.netfilter.org/documentation/index.html

Utilities obsoleted by iproute2

Legacy utility Replacement command Note
ifconfig ip addr, ip link, ip -s Address and link configuration
route ip route Routing tables
arp ip neigh Neighbors
iptunnel ip tunnel Tunnels
nameif, ifrename ip link set name Rename network interfaces
ipmaddr ip maddr Multicast
netstat ip -s, ss, ip route Show various networking statistics
brctl bridge Handle bridge addresses and devices

iptables - ArchWiki

https://wiki.archlinux.jp/index.php/Iptables

iptables Tutorial

https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#TRAVERSINGOFTABLES

注)iptables でのポート設定はプロセス上の設定ではないため netstat には反映されません。

マニュアルまたは $ man iptables コマンドで確認
https://man7.org/linux/man-pages/man8/iptables.8.html

SYNOPSIS         top
       iptables [-t table] {-A|-C|-D} chain rule-specification

       ip6tables [-t table] {-A|-C|-D} chain rule-specification

       iptables [-t table] -I chain [rulenum] rule-specification

       iptables [-t table] -R chain rulenum rule-specification

       iptables [-t table] -D chain rulenum

       iptables [-t table] -S [chain [rulenum]]

       iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]

       iptables [-t table] -N chain

       iptables [-t table] -X [chain]

       iptables [-t table] -P chain target

       iptables [-t table] -E old-chain-name new-chain-name

       rule-specification = [matches...] [target]

       match = -m matchname [per-match-options]

       target = -j targetname [per-target-options]


TABLES         top
       There are currently five independent tables (which tables are
       present at any time depends on the kernel configuration options
       and which modules are present).

       -t, --table table
              This option specifies the packet matching table which the
              command should operate on.  If the kernel is configured
              with automatic module loading, an attempt will be made to
              load the appropriate module for that table if it is not
              already there.

              The tables are as follows:

              filter:
                  This is the default table (if no -t option is passed).
                  It contains the built-in chains INPUT (for packets
                  destined to local sockets), FORWARD (for packets being
                  routed through the box), and OUTPUT (for locally-
                  generated packets).

              nat:
                  This table is consulted when a packet that creates a
                  new connection is encountered.  It consists of four
                  built-ins: PREROUTING (for altering packets as soon as
                  they come in), INPUT (for altering packets destined
                  for local sockets), OUTPUT (for altering locally-
                  generated packets before routing), and POSTROUTING
                  (for altering packets as they are about to go out).
                  IPv6 NAT support is available since kernel 3.7.

              mangle:
                  This table is used for specialized packet alteration.
                  Until kernel 2.4.17 it had two built-in chains:
                  PREROUTING (for altering incoming packets before
                  routing) and OUTPUT (for altering locally-generated
                  packets before routing).  Since kernel 2.4.18, three
                  other built-in chains are also supported: INPUT (for
                  packets coming into the box itself), FORWARD (for
                  altering packets being routed through the box), and
                  POSTROUTING (for altering packets as they are about to
                  go out).

              raw:
                  This table is used mainly for configuring exemptions
                  from connection tracking in combination with the
                  NOTRACK target.  It registers at the netfilter hooks
                  with higher priority and is thus called before
                  ip_conntrack, or any other IP tables.  It provides the
                  following built-in chains: PREROUTING (for packets
                  arriving via any network interface) OUTPUT (for
                  packets generated by local processes)

              security:
                  This table is used for Mandatory Access Control (MAC)
                  networking rules, such as those enabled by the SECMARK
                  and CONNSECMARK targets.  Mandatory Access Control is
                  implemented by Linux Security Modules such as SELinux.
                  The security table is called after the filter table,
                  allowing any Discretionary Access Control (DAC) rules
                  in the filter table to take effect before MAC rules.
                  This table provides the following built-in chains:
                  INPUT (for packets coming into the box itself), OUTPUT
                  (for altering locally-generated packets before
                  routing), and FORWARD (for altering packets being
                  routed through the box).
OPTIONS         top
       The options that are recognized by iptables and ip6tables can be
       divided into several different groups.

   COMMANDS
       These options specify the desired action to perform. Only one of
       them can be specified on the command line unless otherwise stated
       below. For long versions of the command and option names, you
       need to use only enough letters to ensure that iptables can
       differentiate it from all other options.

       -A, --append chain rule-specification
              Append one or more rules to the end of the selected chain.
              When the source and/or destination names resolve to more
              than one address, a rule will be added for each possible
              address combination.

       -C, --check chain rule-specification
              Check whether a rule matching the specification does exist
              in the selected chain. This command uses the same logic as
              -D to find a matching entry, but does not alter the
              existing iptables configuration and uses its exit code to
              indicate success or failure.

       -D, --delete chain rule-specification
       -D, --delete chain rulenum
              Delete one or more rules from the selected chain.  There
              are two versions of this command: the rule can be
              specified as a number in the chain (starting at 1 for the
              first rule) or a rule to match.

       -I, --insert chain [rulenum] rule-specification
              Insert one or more rules in the selected chain as the
              given rule number.  So, if the rule number is 1, the rule
              or rules are inserted at the head of the chain.  This is
              also the default if no rule number is specified.

       -R, --replace chain rulenum rule-specification
              Replace a rule in the selected chain.  If the source
              and/or destination names resolve to multiple addresses,
              the command will fail.  Rules are numbered starting at 1.

       -L, --list [chain]
              List all rules in the selected chain.  If no chain is
              selected, all chains are listed. Like every other iptables
              command, it applies to the specified table (filter is the
              default), so NAT rules get listed by
               iptables -t nat -n -L
              Please note that it is often used with the -n option, in
              order to avoid long reverse DNS lookups.  It is legal to
              specify the -Z (zero) option as well, in which case the
              chain(s) will be atomically listed and zeroed.  The exact
              output is affected by the other arguments given. The exact
              rules are suppressed until you use
               iptables -L -v
              or iptables-save(8).

       -S, --list-rules [chain]
              Print all rules in the selected chain.  If no chain is
              selected, all chains are printed like iptables-save. Like
              every other iptables command, it applies to the specified
              table (filter is the default).

テーブルnatルールの確認

$ sudo iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A PREROUTING -i wg0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.8.0.3
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -o eth0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN

ルールの削除

$ sudo iptables -t nat -D PREROUTING -i wg0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.8.0.3

25 Most Frequently Used Linux IPTables Rules Examples

Iptables Essentials: Common Firewall Rules and Commands

firewallsetup

シンプルなステートフルファイアウォール

https://wiki.archlinux.jp/index.php/シンプルなステートフルファイアウォール

参考)パケットの流れ方:Netfilter

設定の保存とリストア・起動時の読込み

https://www.cyberciti.biz/faq/how-to-save-iptables-firewall-rules-permanently-on-linux/

ルールの保存

$ sudo /sbin/iptables-save > /etc/iptables/rules.v4
## IPv6 ##
$ sudo /sbin/ip6tables-save > /etc/iptables/rules.v6

保存したルールの確認

$ cat /etc/iptables/rules.v4

リストア

## Debian or Ubuntu ##
$ sudo /sbin/iptables-restore < /etc/iptables/rules.v4
$ sudo /sbin/ip6tables-restore < /etc/iptables/rules.v6
## CentOS/RHEL ##
$ sudo /sbin/iptables-save < /etc/sysconfig/iptables
$ sudo /sbin/ip6tables-save < /etc/sysconfig/ip6tables

再起動時に設定を読込む場合
:warning:
Please note that the following command will conflict with iptables frontends such as ufw command or firewall-cmd command. Avoid using the following packages if you are using those tools.

$ sudo apt install iptables-persistent
## OR ##
$ sudo apt-get install iptables-persistent

ポートフォワード

ホストマシン(ネットワークインターフェイス:eth0)のhttpsポート443 をLAN内のサーバマシン 10.8.0.3:443 へフォワーディング

$ sudo iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 443 -j DNAT --to-destination 10.8.0.3:443
$ sudo iptables -A FORWARD -p tcp -d 10.8.0.3 --dport 443 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

iproute2("ip rule", "ip route", etc...)

Wiki: iproute2
https://wiki.linuxfoundation.org/networking/iproute2

How To Use IPRoute2 Tools to Manage Network Configuration on a Linux VPS

$ ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 54:be:f7:08:c2:1b brd ff:ff:ff:ff:ff:ff
    inet 192.168.56.126/24 brd 192.168.56.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::56be:f7ff:fe08:c21b/64 scope link 
       valid_lft forever preferred_lft forever
$ ip link

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 04:01:13:8a:a2:01 brd ff:ff:ff:ff:ff:ff
$ ip route show

default via 107.170.58.1 dev eth0  metric 100
107.170.58.0/24 dev eth0  proto kernel  scope link  src 107.170.58.162 
$ ip rule show

0:  from all lookup local 
32766:  from all lookup main 
32767:  from all lookup default

nftables

iptables と同様、netfilter.org のプロジェクトです。
https://www.netfilter.org/projects/nftables/index.html

nftables wiki
https://wiki.nftables.org/wiki-nftables/index.php/Main_Page

Ubuntu 20.04iptablesnftables のカーネルapiを利用した xtables-nft-multi で実質 nftables です。

xtables-nft-multi

https://manpages.debian.org/testing/iptables/xtables-nft-multi.8.en.html

iptablesnftables に置き換わっています。

nftables をインストールし、そのサービスデーモンを有効にすることでホスト起動時に自動的に設定したルールが読み込まれます(iptables-persistentはインストールする必要はありません)。

nftablesのインストール

$ sudo apt install nftables

ホストマシン起動時にnftablesのルールを読み込むサービスの有効化・サービス開始

$ sudo systemctl enable nftables
$ sudo systemctl start nftables

ステータス確認
ルールは /etc/nftables.conf で定義します。

$ sudo systemctl status nftables
● nftables.service - nftables
     Loaded: loaded (/lib/systemd/system/nftables.service; enabled; vendor preset: enabled)
     Active: active (exited) since Fri 2022-01-14 08:59:57 UTC; 2h 40min ago
       Docs: man:nft(8)
             http://wiki.nftables.org
    Process: 171 ExecStart=/usr/sbin/nft -f /etc/nftables.conf (code=exited, status=0/SUCCESS)
   Main PID: 171 (code=exited, status=0/SUCCESS)

Jan 14 08:59:57 ip-172-31-43-175 systemd[1]: Finished nftables.

Quick reference-nftables in 10 minutes

https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Rules

iptables から nftables への移行

https://wiki.nftables.org/wiki-nftables/index.php/Moving_from_iptables_to_nftables

iptables-translate

iptables による各コマンドを nftablesによるコマンドに変換します。

% iptables-translate -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
nft add rule ip filter INPUT tcp dport 22 ct state new counter accept

iptables で保存したルールセットは以下の iptables-restore-translate コマンドで変換出来ます。

iptables によるルールの保存

% iptables-save > save.txt
% cat save.txt
# Generated by iptables-save v1.6.0 on Sat Dec 24 14:26:40 2016
*filter
:INPUT ACCEPT [5166:1752111]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [5058:628693]
-A FORWARD -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Sat Dec 24 14:26:40 2016

iptables-restore-translate によるルールの変換

% iptables-restore-translate -f save.txt
# Translated by iptables-restore-translate v1.6.0 on Sat Dec 24 14:26:59 2016
add table ip filter
add chain ip filter INPUT { type filter hook input priority 0; }
add chain ip filter FORWARD { type filter hook forward priority 0; }
add chain ip filter OUTPUT { type filter hook output priority 0; }
add rule ip filter FORWARD tcp dport 22 ct state new counter accept
You should be able to directly give this to nftables:

変換したルールを nftables のファイル形式で保存、nftables でルールの読込み。

% iptables-restore-translate -f save.txt > ruleset.nft
% nft -f ruleset.nft

ルール一覧

% nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority 0; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority 0; policy accept;
		tcp dport ssh ct state new counter packets 0 bytes 0 accept
	}

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

ルールの消去

% nft flush ruleset

firewalld

nftables(ArchWiki)

https://wiki.archlinux.org/title/nftables

man page of NFT

https://www.netfilter.org/projects/nftables/manpage.html


iptables: The two variants and their relationship with nftables

$ iptables-legacy, $ iptables-nft, $ nft の関係図

+--------------+     +--------------+     +--------------+
|   iptables   |     |   iptables   |     |     nft      |   USER
|    legacy    |     |     nft      |     |  (nftables)  |   SPACE
+--------------+     +--------------+     +--------------+
       |                          |         |
====== | ===== KERNEL API ======= | ======= | =====================
       |                          |         |
+--------------+               +--------------+
|   iptables   |               |   nftables   |              KERNEL
|      API     |               |     API      |              SPACE
+--------------+               +--------------+
             |                    |         |
             |                    |         |
          +--------------+        |         |     +--------------+
          |   xtables    |--------+         +-----|   nftables   |
          |    match     |                        |    match     |
          +--------------+                        +--------------+

nftables.conf

Simple ruleset for a server

https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_server

/etc/nftables.conf

flush ruleset                                                                    
                                                                                 
table inet firewall {
                                                                                 
    chain inbound_ipv4 {
        # accepting ping (icmp-echo-request) for diagnostic purposes.
        # However, it also lets probes discover this host is alive.
        # This sample accepts them within a certain rate limit:
        #
        # icmp type echo-request limit rate 5/second accept      
    }

    chain inbound_ipv6 {                                                         
        # accept neighbour discovery otherwise connectivity breaks
        #
        icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept
                                                                                 
        # accepting ping (icmpv6-echo-request) for diagnostic purposes.
        # However, it also lets probes discover this host is alive.
        # This sample accepts them within a certain rate limit:
        #
        # icmpv6 type echo-request limit rate 5/second accept
    }

    chain inbound {                                                              

        # By default, drop all traffic unless it meets a filter
        # criteria specified by the rules that follow below.
        type filter hook input priority 0; policy drop;

        # Allow traffic from established and related packets, drop invalid
        ct state vmap { established : accept, related : accept, invalid : drop } 

        # Allow loopback traffic.
        iifname lo accept

        # Jump to chain according to layer 3 protocol using a verdict map
        meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 }

        # Allow SSH on port TCP/22 and allow HTTP(S) TCP/80 and TCP/443
        # for IPv4 and IPv6.
        tcp dport { 22, 80, 443} accept

        # Uncomment to enable logging of denied inbound traffic
        # log prefix "[nftables] Inbound Denied: " counter drop
    }                                                                            
                                                                                 
    chain forward {                                                              
        # Drop everything (assumes this device is not a router)                  
        type filter hook forward priority 0; policy drop;                        
    }                                                                            
                                                                                 
    # no need to define output chain, default policy is accept if undefined.

設定の分割定義

/etc/nftables.conf:

include "/etc/nft.conf.d/sets.d/main.conf" 
include "/etc/nft.conf.d/nftables.ip.filter.conf" 
include "/etc/nft.conf.d/nftables.ip.nat.conf" 
include "/etc/nft.conf.d/nftables.test1.conf" include "/etc/nft.conf.d/nftables.test2.conf"

Examples

Matching UDP/TCP headers in the same rule

The following example uses an anonymous l4proto set and a th (transport header) expression to match both TCP and UDP packets directed to port 53 (DNS):

% nft add rule filter input meta l4proto { tcp, udp } th dport 53 counter packets 0 bytes 0 accept comment "accept DNS"
https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_headers

Netfilter hooks

Netfilter hooks - nftables wiki

アプリケーションレイヤーにはSSH,Apache,Nginx, MySQLなどが該当します。

nft man page

Address Family
ip IPv4 address family.
ip6 IPv6 address family.
inet Internet (IPv4/IPv6) address family.
arp ARP address family, handling IPv4 ARP packets.
bridge Bridge address family, handling packets which traverse a bridge device.
netdev Netdev address family, handling packets on ingress and egress.

IPv4/IPv6/Inet address family hooks

Hook Description
prerouting All packets entering the system are processed by the prerouting hook. It is invoked before the routing process and is used for early filtering or changing packet attributes that affect routing.
input Packets delivered to the local system are processed by the input hook.
forward Packets forwarded to a different host are processed by the forward hook.
output Packets sent by local processes are processed by the output hook.
postrouting All packets leaving the system are processed by the postrouting hook.
ingress All packets entering the system are processed by this hook. It is invoked before layer 3 protocol handlers, hence before the prerouting hook, and it can be used for filtering and policing. Ingress is only available for Inet family (since Linux kernel 5.10).

Supported chain types

Type Families Hooks Description
filter all all Standard chain type to use in doubt.
nat ip, ip6, inet prerouting, input, output, postrouting Chains of this type perform Native Address Translation based on conntrack entries. Only the first packet of a connection actually traverses this chain - its rules usually define details of the created conntrack entry (NAT statements for instance).
route ip, ip6 output If a packet has traversed a chain of this type and is about to be accepted, a new route lookup is performed if relevant parts of the IP header have changed. This allows to e.g. implement policy routing selectors in nftables.

ホストマシンのネットワークインターフェイスへのパケットを処理するための幾つかの rule:ルール を一纏めにしたものが chain:チェーン であり、このルールの集合体である chain:チェーン はパケット経路の要所毎に幾つか設けられます。

chain:チェーン は1つの table:テーブル として包括されます。

nftables の設定ファイル /etc/nftables.conf に上記テーブルを複数定義することで、ネットワーク通信のファイヤーウォールとして機能させることが出来ます。

テーブル、チェーン、ルールの作成、削除、追加方法は、設定ファイル /etc/nftables.conf を編集するか nftコマンド で行います。

table:テーブルnftコマンド

$ sudo nft list tables [<family>]
$ sudo nft list table [<family>] <name> [-n] [-a]
$ sudo nft (add | delete | flush) table [<family>] <name>

chain:チェーンnftコマンド

$ sudo nft (add | create) chain [<family>] <table> <name> [ { type <type> hook <hook> [device <device>] priority <priority> \; [policy <policy> \;] } ]
$ sudo nft (delete | list | flush) chain [<family>] <table> <name>
$ sudo nft rename chain [<family>] <table> <name> <newname>

rule:ルールnftコマンド

$ sudo nft add rule [<family>] <table> <chain> <matches> <statements>
$ sudo nft insert rule [<family>] <table> <chain> [position <position>] <matches> <statements>
$ sudo nft replace rule [<family>] <table> <chain> [handle <handle>] <matches> <statements>
$ sudo nft delete rule [<family>] <table> <chain> [handle <handle>]

ルールの <statements>counter を追加することによりルールを横切るパケット量が確認できます。これは、ルールが意図通りに適用されているかどうかの目安にもなります。


テーブルやチェーンの削除の場合、handleナンバーを指定して削除します。handleナンバーの表示には -a オプションを追加します(handleナンバーはカーネルによって自動的にアサインされます)。

% nft -a list table filter
table ip filter {
        chain input {
                 type filter hook input priority 0;
        }

        chain output {
                 type filter hook output priority 0;
                 ip daddr 192.168.1.1 counter packets 1 bytes 84 # handle 5
        }
}

上記handleナンバーを指定して削除

% nft delete rule filter output handle 5

Setting up nftables Firewall

以下用途に応じた nftables.conf ファイル例も参考にすること。
(サーバ用途とホームルータ用途)
https://wiki.nftables.org/wiki-nftables/index.php/Main_Page#Examples

サーバへのSSH接続制限.

filter input tcp dport 22 meter test { ip saddr ct count over 2 } reject

ルール適用の順序

ルール適用の順序はValuenft_Keywordにより決まります。
あるルールを優先して適用したい場合には、priorityに直接番号(マイナスの方が優先度高い)を指定します。

Priority within hook

Within a given hook, Netfilter performs operations in order of increasing numerical priority. Each nftables base chain and flowtable is assigned a priority that defines its ordering among other base chains and flowtables and Netfilter internal operations at the same hook. For example, a chain on the prerouting hook with priority -300 will be placed before connection tracking operations.

The following table shows Netfilter priority values, check the nft manpage for reference.

nftables Families Typical hooks nft Keyword Value Netfilter Internal Priority Description
prerouting -450 NF_IP_PRI_RAW_BEFORE_DEFRAG
inet, ip, ip6 prerouting -400 NF_IP_PRI_CONNTRACK_DEFRAG Packet defragmentation / datagram reassembly
inet, ip, ip6 all raw -300 NF_IP_PRI_RAW Traditional priority of the raw table placed before connection tracking operation
-225 NF_IP_PRI_SELINUX_FIRST SELinux operations
inet, ip, ip6 prerouting, output -200 NF_IP_PRI_CONNTRACK Connection tracking processes run early in prerouting and output hooks to associate packets with tracked connections.
inet, ip, ip6 all mangle -150 NF_IP_PRI_MANGLE Mangle operation
inet, ip, ip6 prerouting dstnat -100 NF_IP_PRI_NAT_DST Destination NAT
inet, ip, ip6, arp, netdev all filter 0 NF_IP_PRI_FILTER Filtering operation, the filter table
inet, ip, ip6 all security 50 NF_IP_PRI_SECURITY Place of security table, where secmark can be set for example
inet, ip, ip6 postrouting srcnat 100 NF_IP_PRI_NAT_SRC Source NAT
postrouting 225 NF_IP_PRI_SELINUX_LAST SELinux at packet exit
inet, ip, ip6 postrouting 300 NF_IP_PRI_CONNTRACK_HELPER Connection tracking helpers, which identify expected and related packets.
inet, ip, ip6 input, postrouting INT_MAX NF_IP_PRI_CONNTRACK_CONFIRM Connection tracking adds new tracked connections at final step in input & postrouting hooks.
bridge prerouting dstnat -300 NF_BR_PRI_NAT_DST_BRIDGED
bridge all filter -200 NF_BR_PRI_FILTER_BRIDGED
bridge 0 NF_BR_PRI_BRNF
bridge output out 100 NF_BR_PRI_NAT_DST_OTHER
bridge 200 NF_BR_PRI_FILTER_OTHER
bridge postrouting srcnat 300 NF_BR_PRI_NAT_SRC

LIMIT STATEMENT

データレート(単位時間当りのパケット数またはバイト容量で指定)の指定による通信量制限

limit rate [over] packet_number / TIME_UNIT [burst packet_number packets]
limit rate [over] byte_number BYTE_UNIT / TIME_UNIT [burst byte_number BYTE_UNIT]

TIME_UNIT := second | minute | hour | day
BYTE_UNIT := bytes | kbytes | mbytes

A limit statement matches at a limited rate using a token bucket filter. A rule using this statement will match until this limit is reached. It can be used in combination with the log statement to give limited logging. The optional over keyword makes it match over the specified rate.

over :データレートが上限を超えた場合に制限ルールを適用
burst:指定容量までは無制限

Table 62. limit statement values

Value Description Type
packet_number Number of packets unsigned integer (32 bit)
byte_number Number of bytes unsigned integer (32 bit)

ex)

limit rate 400/minute
limit rate 400/hour
limit rate over 40/day
limit rate over 400/week
limit rate over 1023/second burst 10 packets
limit rate 1025 kbytes/second
limit rate 1023000 mbytes/second
limit rate 1025 bytes/second burst 512 bytes
limit rate 1025 kbytes/second burst 1023 kbytes
limit rate 1025 mbytes/second burst 1025 kbytes
limit rate 1025000 mbytes/second burst 1023 mbytes

Limits

https://wiki.nftables.org/wiki-nftables/index.php/Limits
設定ファイル内で条件指定

table inet limit_demo {

   limit lim_400ppm { rate 400/minute ; comment "use to limit incoming icmp" ; }
   limit lim_1kbps  { rate over 1024 bytes/second burst 512 bytes ; comment "use to limit incoming smtp" ; }

   chain IN { 
      type filter hook input priority filter; policy drop;

      meta l4proto icmp limit name "lim_400ppm" accept
      tcp dport 25 limit name "lim_1kbps" accept
   }
}

Rate limiting matchings

nftコマンドによる条件設定
https://wiki.nftables.org/wiki-nftables/index.php/Rate_limiting_matchings

パケット数指定

% nft add rule filter input icmp type echo-request limit rate 10/second accept
% nft add rule filter input icmp type echo-request limit rate over 10/second drop

バイト容量指定

% nft add rule filter input limit rate 10 mbytes/second accept
% nft add rule filter input limit rate over 10 mbytes/second drop

バースト

% nft add rule filter input limit rate 10 mbytes/second burst 9000 kbytes accept
% nft add rule filter input icmp type echo-request limit rate 10/second burst 2 packets counter accept
% nft add rule netdev filter ingress pkttype broadcast limit rate over 10/second drop

Quota: データ容量の割当て

ポートやクライアントに割当てるデータ容量を指定。

https://wiki.nftables.org/wiki-nftables/index.php/Quotas

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

        udp dport 5060 quota until 100 mbytes accept
    }
}
table inet quota_demo {
   quota q_until_sip { until 100 mbytes used 0 bytes }
   quota q_over_http { over  500 mbytes ; comment "cap http (but not https)" ; }

   chain IN { 
      type filter hook input priority filter; policy drop;

      udp dport 5060 quota name "q_until_sip" accept
      tcp dport 80 quota name "q_over_http" drop
      tcp dport { 80, 443 } accept
   }

}

Maps, Vmaps

キー・バリューフォーマットにより条件・処理を設定

nft man : Maps

nft コマンド

add map [family] table map { type type | typeof expression [flags flags ;] [elements = { element[, ...] } ;] [size size ;] [comment comment ;] [policy 'policy ;] }
{delete | list | flush} map [family] table map
list maps [family]

Map specifications

Keyword Description Type
type data type of map elements string: ipv4_addr, ipv6_addr, ether_addr, inet_proto, inet_service, mark, counter, quota. Counter and quota can’t be used as keys
typeof data type of set element expression to derive the data type from
flags map flags string: constant, interval
elements elements contained by the map map data type
size maximum number of elements in the map unsigned integer (64 bit)
policy map policy string: performance [default], memory

Maps
https://wiki.nftables.org/wiki-nftables/index.php/Maps

ex) ポートフォワーディングを map で設定

% nft add rule ip nat prerouting dnat to tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 }

vmaps(verdict maps)
https://wiki.nftables.org/wiki-nftables/index.php/Verdict_Maps_(vmaps)

ex) プロトコル別によるルールを vmap で設定

% nft add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain }

設定(スクリプト)ファイル内 '.' でキーに該当する項目を追加

ip protocol . th dport vmap { udp . 53 : accept, tcp . 53 : accept, udp . 67 : accept}

Data Types

https://wiki.nftables.org/wiki-nftables/index.php/Data_types

inet_proto
Internet protocol (8 bit integer, with pre-defined symbolic constants):

  • tcp
  • udp
  • udplite
  • esp
  • ah
  • icmp
  • icmpv6
  • comp
  • dccp
  • sctp

inet_service
Network service port number (16 bit integer).

ipv4_addr
IPv4 address (32 bit integer).

ipv6_addr
IPv6 address (128 bit integer).

Sets

nft man

nft wiki

https://wiki.nftables.org/wiki-nftables/index.php/Sets

nftコマンド

add set [family] table set { type type | typeof expression ; [flags flags ;] [timeout timeout ;] [gc-interval gc-interval ;] [elements = { element[, ...] } ;] [size size ;] [policy policy ;] [auto-merge ;] }
{delete | list | flush} set [family] table set
list sets [family]
delete set [family] table handle handle
{add | delete} element [family] table set { element[, ...] }

Setsには2通りの記述方法があり、
1つ目は Anonymous Sets と呼ばれるもので、その名称を定義せずに複数の同一要素(ポート、IPアドレスなど)を { } 内で一纏めにしたもの。
ex)

define SIMPLE_SET = { 192.168.1.1, 192.168.1.2 }

define CDN_EDGE = {
    192.168.1.1,
    192.168.1.2,
    192.168.1.3,
    10.0.0.0/8
}

define CDN_MONITORS = {
    192.168.1.10,
    192.168.1.20
}

define CDN = {
    $CDN_EDGE,
    $CDN_MONITORS
}

# Allow HTTP(S) from approved IP ranges only
tcp dport { http, https } ip saddr $CDN accept
udp dport { http, https } ip saddr $CDN accept

2つ目はSet名称を定義して下記エレメントを { } 内で一纏めにしたもの。 @Set名称 で参照元として利用します。

Set specifications

Keyword Description Type
type data type of set elements string: ipv4_addr, ipv6_addr, ether_addr, inet_proto, inet_service, mark
typeof data type of set element expression to derive the data type from
flags set flags string: constant, dynamic, interval, timeout
timeout time an element stays in the set, mandatory if set is added to from the packet path (ruleset). string, decimal followed by unit. Units are: d, h, m, s
gc-interval garbage collection interval, only available when timeout or flag timeout are active string, decimal followed by unit. Units are: d, h, m, s
elements elements contained by the set set data type
size maximum number of elements in the set, mandatory if set is added to from the packet path (ruleset). unsigned integer (64 bit)
policy set policy string: performance [default], memory
auto-merge automatic merge of adjacent/overlapping set elements (only for interval sets)

ex)
https://wiki.nftables.org/wiki-nftables/index.php/Meters

table ip my_filter_table {
       set my_connlimit {
               type ipv4_addr
               size 65535
               flags dynamic
       }

       chain my_output_chain {
               type filter hook output priority filter; policy accept;
               ct state new add @my_connlimit { ip daddr ct count over 20 } counter packets 0 bytes 0 drop
       }
}

Meta

Matching packet metainformation

Matching packet metainformation - nftables wiki

Quick reference-nftables in 10 minutes - nftables wiki

ex)

meta iifname "eth0"
meta iifname != "eth0"
meta iifname {"eth0", "lo"}
meta iifname "eth*"

meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}
meta iiftype != ether
meta iiftype ether

meta nfproto ipv4
meta nfproto != ipv6
meta nfproto { ipv4, ipv6 }

meta l4proto 22
meta l4proto != 233
meta l4proto 33-45
meta l4proto { 33, 55, 67, 88 }
meta l4proto { 33-55 }

man meta

A meta expression refers to meta data associated with a packet.

There are two types of meta expressions: unqualified and qualified meta expressions.
Qualified meta expressions require the meta keyword before the meta key, unqualified meta expressions can be specified by using the meta key directly or as qualified meta expressions. Meta l4proto is useful to match a particular transport protocol that is part of either an IPv4 or IPv6 packet. It will also skip any IPv6 extension headers present in an IPv6 packet.

qualified meta expression

filter output meta oif eth0
filter forward meta iifkind { "tun", "veth" }

unqualified meta expression

filter output oif eth0

incoming packet was subject to ipsec processing

raw prerouting meta ipsec exists accept

Meta expression types

Keyword Description Type
length Length of the packet in bytes integer (32-bit)
nfproto real hook protocol family, useful only in inet table integer (32 bit)
l4proto layer 4 protocol, skips ipv6 extension headers integer (8 bit)
protocol EtherType protocol value ether_type
priority TC packet priority tc_handle
mark Packet mark mark
iif Input interface index iface_index
iifname Input interface name ifname
iiftype Input interface type iface_type
oif Output interface index iface_index
oifname Output interface name ifname
oiftype Output interface hardware type iface_type
sdif Slave device input interface index iface_index
sdifname Slave device interface name ifname
skuid UID associated with originating socket uid
skgid GID associated with originating socket gid
rtclassid Routing realm realm
ibrname Input bridge interface name ifname
obrname Output bridge interface name ifname
pkttype packet type pkt_type
cpu cpu number processing the packet integer (32 bit)
iifgroup incoming device group devgroup
oifgroup outgoing device group devgroup
cgroup control group id integer (32 bit)
random pseudo-random number integer (32 bit)
ipsec true if packet was ipsec encrypted boolean (1 bit)
iifkind Input interface kind
oifkind Output interface kind
time Absolute time of packet reception Integer (32 bit) or string
day Day of week Integer (8 bit) or string
hour Hour of day String

Meta expression specific types

Type Description
iface_index Interface index (32 bit number). Can be specified numerically or as name of an existing interface.
ifname Interface name (16 byte string). Does not have to exist.
iface_type Interface type (16 bit number).
uid User ID (32 bit number). Can be specified numerically or as user name.
gid Group ID (32 bit number). Can be specified numerically or as group name.
realm Routing Realm (32 bit number). Can be specified numerically or as symbolic name defined in /etc/iproute2/rt_realms.
devgroup_type Device group (32 bit number). Can be specified numerically or as symbolic name defined in /etc/iproute2/group.
pkt_type Packet type: host (addressed to local host), broadcast (to all), multicast (to group), other (addressed to another host).
ifkind Interface kind (16 byte string). See TYPES in ip-link(8) for a list.
time Either an integer or a date in ISO format. For example: “2019-06-06 17:00”. Hour and seconds are optional and can be omitted if desired. If omitted, midnight will be assumed. The following three would be equivalent: “2019-06-06”, “2019-06-06 00:00” and “2019-06-06 00:00:00”. When an integer is given, it is assumed to be a UNIX timestamp.
day Either a day of week (“Monday”, “Tuesday”, etc.), or an integer between 0 and 6. Strings are matched case-insensitively, and a full match is not expected (e.g. “Mon” would match “Monday”). When an integer is given, 0 is Sunday and 6 is Saturday.
hour A string representing an hour in 24-hour format. Seconds can optionally be specified. For example, 17:00 and 17:00:00 would be equivalent.

time, day, hourによるスケジュール管理

https://git.netfilter.org/nftables/commit/?id=f8f32deda31df597614d9f1f64ffb0c0320f4d54

time < "2019-06-06 17:00" drop;
time < "2019-06-06 17:20:20" drop;
time < 12341234 drop;
day "Saturday" drop;
day 6 drop;
hour >= 17:00 drop;
hour >= "17:00:01" drop;
hour >= 63000 drop;

ex) 00:00-04:00の時間帯でポート25への通信を遮断

#!/usr/sbin/nft -f

table inet filter {
    chain input {
        type filter hook input priority 0; policy accept;
        tcp dport 25 hour 00:00-04:00 drop
    }
}

ロードバランス

https://wiki.nftables.org/wiki-nftables/index.php/Load_balancing

Round Robin
This method uses the nftables number generator : numgen.

The example below is distributing new connections in a round-robin fashion between 192.168.10.100 and 192.168.20.200.

% nft add rule nat prerouting dnat to numgen inc mod 2 map { \
               0 : 192.168.10.100, \
               1 : 192.168.20.200 }

You can also emulate flow distribution with different backend weights using intervals:

% nft add rule nat prerouting dnat to numgen inc mod 10 map { \
               0-5 : 192.168.10.100, \
               6-9 : 192.168.20.200 }

The distribution can be based on ports as well:

% nft add rule nat prerouting ip protocol tcp dnat to 192.168.1.100 : numgen inc mod 2 map {\
               0 : 4040 ,\
               1 : 4050 }

Support for random and probability-based distributions also exists:

% nft add rule nat prerouting numgen random mod 2 vmap { 0 : jump mychain1, 1 : jump mychain2 }
% nft add rule nat prerouting numgen random mod 100 vmap { 0-49 : jump mychain1, 50-99 : jump mychain2 }