nftables框架提供了數據包分類功能,它是iptables,ip6tables,arptables和ebtables的後繼產品。與以前的數據包過濾工具相比,它在便利性,功能和性能方面提供了許多改進,最值得注意的是:
-
查找表而不是線性處理
-
適用於IPv4和IPv6協議的單一框架
-
所有規則原子級應用,而不是獲取,更新和存儲完整的規則集
-
支持在規則集中(nftrace)進行調試和跟蹤,並監視跟蹤事件(在nft工具中)
-
更一致,更緊湊的語法,沒有特定於協議的擴展
-
用於第三方應用程序的Netlink API
與iptables相似,nftables使用tables來存儲chains。這些chains包含執行操作的各個規則。 nft工具取代了以前的數據包過濾框架中的所有工具。 libnftnl庫可用於通過libmnl庫與nftables Netlink API進行低級交互。
要顯示規則集更改的效果,請使用nft list ruleset命令。
由於這些工具將tables,chains,rules,sets和其他對象添加到nftables規則集中,因此請注意,nftables規則集操作(例如nft flush ruleset命令)可能會影響使用以前單獨的舊版命令安裝的規則集。
一、將iptables規則轉換爲nftables規則
redhat提供了iptables-translate和ip6tables-translate工具,可將現有iptables或ip6tables規則轉換爲適用於nftable的規則。
請注意,某些擴展名缺少翻譯支持。如果存在這樣的擴展名,則該工具會打印以#號爲前綴的未翻譯規則。 例如:
# iptables-translate -A INPUT -j CHECKSUM --checksum-fill nft # -A INPUT -j CHECKSUM --checksum-fill
此外,用戶可以使用iptables-restore-translate和ip6tables-restore-translate工具來轉換規則轉儲。
請注意,在此之前,用戶可以使用iptables-save或ip6tables-save命令來打印當前規則的轉儲。 例如:
# iptables-save >/tmp/iptables.dump # iptables-restore-translate -f /tmp/iptables.dump # Translated by iptables-restore-translate v1.8.0 on Wed Oct 17 17:00:13 2018 add table ip nat ...
二、編寫和執行nftables腳本
nftables框架提供了本機腳本編制環境,與使用shell腳本維護防火牆規則相比,它帶來了主要的好處:腳本的執行是原子級的。 這意味着系統將應用整個腳本,或者在發生錯誤時阻止執行。這樣可以確保防火牆始終處於一致狀態。
此外,nftables腳本環境使管理員能夠:
-
添加註釋
-
定義變量
-
包括其他規則集文件
2.1 nftables腳本中所需的腳本
與其他腳本相似,nftables腳本在設置解釋器指令的腳本第一行中需要一個shebang序列。
nftables腳本必須以下行開頭:
#!/usr/sbin/nft -f
支持的nftables腳本格式
2.2 nftables腳本環境支持以下格式的腳本
1) 使用與nft list ruleset命令顯示規則集相同的格式編寫腳本:
#!/usr/sbin/nft -f # Flush the rule set flush ruleset table inet example_table { chain example_chain { # Chain for incoming packets that drops all packets that # are not explicitly allowed by any rule in this chain type filter hook input priority 0; policy drop; # Accept connections to port 22 (ssh) tcp dport ssh accept } }
2) 使用與nft命令相同的語法:
#!/usr/sbin/nft -f # Flush the rule set flush ruleset # Create a table add table inet example_table # Create a chain for incoming packets that drops all packets # that are not explicitly allowed by any rule in this chain add chain inet example_table example_chain { type filter hook input priority 0 ; policy drop ; } # Add a rule that accepts connections to port 22 (ssh) add rule inet example_table example_chain tcp dport ssh accept
2.3 運行nftables腳本
要運行nftables腳本,該腳本必須是可執行的。僅當該腳本包含在另一個腳本中時,它纔不需要是可執行的。該過程描述瞭如何使腳本可執行並運行該腳本。
在/etc/nftables/example_firewall.nft文件中存儲了一個nftables腳本。
1) 僅需一次的步驟:
-
可選,將腳本的所有者設置爲root:
chown root /etc/nftables/example_firewall.nft
-
使腳本對於所有者可執行:
chmod u+x /etc/nftables/example_firewall.nft
2) 運行腳本
/etc/nftables/example_firewall.nft
如果未顯示任何輸出,則系統成功執行了腳本
2.4 在nftables腳本中使用註釋
nftables腳本環境將#字符右側的所有內容解釋爲註釋。
示例 nftables腳本中的註釋
註釋可以從一行的開頭開始,也可以在命令旁邊開始:
... # Flush the rule set flush ruleset add table inet example_table # Create a table ...
2.5 在nftables腳本中使用變量
要在nftables腳本中定義變量,請使用define關鍵字。 可以將單個值和匿名集存儲在變量中。對於更復雜的方案,請使用集合或判定圖。
1.具有單個值的變量
下面的示例定義一個名爲INET_DEV的變量,其值爲enp1s0:
define INET_DEV = enp1s0
在腳本中使用變量,方法是編寫$符號,後跟變量名稱:
... add rule inet example_table example_chain iifname $INET_DEV tcp dport ssh accept ...
2.包含匿名集的變量
以下示例定義了一個包含匿名集的變量:
define DNS_SERVERS = { 192.0.2.1, 192.0.2.2 }
在腳本中使用變量,方法是編寫$符號,後跟變量名稱:
add rule inet example_table example_chain ip daddr $DNS_SERVERS accept
2.6 在nftables腳本中包含文件
使用nftables腳本環境,管理員可以使用include語句來包含其他腳本。
如果僅指定沒有絕對或相對路徑的文件名,則nftables會包含來自默認搜索路徑的文件,該默認搜索路徑在/etc。
示例1 包括來自默認搜索目錄的文件
要包括來自默認搜索目錄的文件:
include "example.nft"
示例2 包括目錄中的所有*.nft文件
要包括所有以*.nft結尾的文件,這些文件存儲在/etc/nftables/rulesets/目錄中:
include "/etc/nftables/rulesets/*.nft"
請注意,include語句與以點開頭的文件不匹配
2.7 系統啓動時自動加載nftables規則
nftables systemd服務將加載/etc/sysconfig/nftables.conf文件中包含的防火牆腳本,nftables腳本存儲在/etc/nftables/目錄中。
1) 編輯/etc/sysconfig/nftables.conf文件
-
如果在安裝nftables軟件包時增強了在/etc/nftables/中創建的*.nft腳本,請取消註釋這些腳本的include語句。
-
如果從頭開始編寫腳本,請添加include語句以包含這些腳本。 例如,要在nftables服務啓動時加載/etc/nftables/example.nft腳本,請添加:
include "/etc/nftables/example.nft"
2) 啓用nftables服務,並啓動服務
# systemctl enable nftables # systemctl start nftables
三、創建和管理tables,chains和rules
3.1 標準chain優先級值和文本名稱
創建chain時,可以設置整數值或標準名稱來指定優先級,該標準名稱指定具有相同掛鉤值的chain遍歷順序。
名稱和值是根據xtables在註冊其默認鏈時使用的優先級定義的。
示例1.使用文本值設置優先級
以下命令使用標準優先級值50在example_table中創建一個名爲example_chain的鏈:
nft add chain inet example_table example_chain { type filter hook input priority 50 \; policy accept \; }
因爲優先級是一個標準值,所以也可以使用文本值:
nft add chain inet example_table example_chain { type filter hook input priority security \; policy accept \; }
-
標準優先級名稱,族和掛鉤兼容性矩陣
Name | Value | Families | Hooks |
---|---|---|---|
raw | -300 | ip , ip6 , inet |
all |
mangle | -150 | ip , ip6 , inet |
all |
dstnat | -100 | ip , ip6 , inet |
prerouting |
filter | 0 | ip , ip6 , inet , arp , netdev |
all |
security | 50 | ip , ip6 , inet |
all |
srcnat | 100 | ip , ip6 , inet |
postrouting |
所有系列都使用相同的值,但是網橋系列使用以下值:
-
標準優先級名稱,以及網橋系列的掛鉤兼容性
Name | Value | Hooks |
---|---|---|
dstnat | -300 | prerouting |
filter | -200 | all |
out | 100 | output |
srcnat | 300 | postrouting |
3.2 顯示nftables規則集
nftable的規則集包含tables, chains 和 rules。
# nft list ruleset table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport http accept tcp dport ssh accept } }
3.3 創建一個nftables表
nftables中的表是一個名稱空間,其中包含chains,rules,sets和其他對象的集合。 每個表都必須定義一個地址族。 表的地址族定義了表處理的地址類型。 創建表時,可以設置以下地址族之一:
-
ip:僅匹配IPv4數據包。 如果未指定地址族,則爲默認設置。
-
ip6:僅匹配IPv6數據包。
-
inet:匹配IPv4和IPv6數據包。
-
arp:匹配IPv4地址解析協議(ARP)數據包。
-
bridge:匹配通過網橋設備的數據包。
-
netdev:匹配入口的數據包。
1) 使用nft add table命令創建一個新表。 例如,創建一個名爲example_table的表來處理IPv4和IPv6數據包:
# nft add table inet example_table
2) 可選,列出規則集中的所有表:
# nft list tables table inet example_table
額外資源
-
有關地址族的更多詳細信息,請參見nft(8)手冊頁中的“Address families”部分。
-
有關可以在表上運行的其他操作的詳細信息,請參見nft(8)手冊頁中的“Tables”部分。
3.4 創建一個nftables鏈
鏈是規則的容器,存在以下兩種規則類型:
-
Base chain:將基鏈用作來自網絡堆棧的數據包的入口點。
-
Regular chain:將常規鏈用作跳轉目標並更好地組織規則。
該過程將基鏈添加到現有表,添加新鏈的表必須存在。
1) 使用nft add chain命令創建一個新chain。
例如,要在example_table中創建名爲example_chain的鏈:
# nft add chain inet example_table example_chain { type filter hook input priority 0 \; policy accept \; }
該鏈過濾傳入的數據包。 priority參數指定nftables處理具有相同鉤子值的鏈的順序。 較低的優先級值優先於較高的優先級值。 policy參數爲該鏈中的規則設置默認操作。
請注意,如果是遠程登錄服務器,並且將默認策略設置爲“丟棄”,則在沒有其他規則允許遠程訪問的情況下,連接會立即斷開。
2) 顯示所有chains
# nft list chains table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; } }
3.5 將規則附加到nftables鏈的末尾
1) 要添加新規則,請使用nft add rule命令。
例如,要將規則添加到example_table中的example_chain中,該規則允許端口22上的TCP通信:
# nft add rule inet example_table example_chain tcp dport 22 accept
除了端口號,還可以指定服務的名稱。 在該示例中,可以使用ssh代替端口號22。
請注意,服務名稱根據/etc/services文件中的條目解析爲端口號。
2) 在example_table中顯示所有鏈及其規則:
# nft list table inet example_table table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; ... tcp dport ssh accept } }
3.6 在nftables鏈的開頭插入規則
1) 要插入新規則,請使用nft insert rule命令
例如,要將規則插入到example_table中的example_chain中,該規則允許端口22上的TCP通信:
# nft insert rule inet example_table example_chain tcp dport 22 accept
2) 在example_table中顯示所有鏈及其規則
# nft list table inet example_table table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport ssh accept ... } }
3.7 在nftables鏈的特定位置插入規則
在nftables鏈中的現有規則之前和之後插入規則,這樣將新規則放在正確的位置
1) 使用nft -a list ruleset命令可在example_table中顯示所有鏈及其規則,包括其句柄:
# nft -a list table inet example_table table inet example_table { # handle 1 chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport 22 accept # handle 2 tcp dport 443 accept # handle 3 tcp dport 389 accept # handle 4 } }
使用-a將顯示句柄,需要此信息才能在下一步中放置新規則。
2) 將新規則插入到example_table中的example_chain鏈中:
-
要插入允許規則3之前的端口636上的TCP流量的規則,請輸入:
# nft insert rule inet example_table example_chain position 3 tcp dport 636 accept
-
要添加規則以允許句柄3之後在端口80上進行TCP通信,請輸入:
# nft add rule inet example_table example_chain position 3 tcp dport 80 accept
3) 在example_table中顯示所有鏈及其規則:
# nft -a list table inet example_table table inet example_table { # handle 1 chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport 22 accept # handle 2 tcp dport 636 accept # handle 5 tcp dport 443 accept # handle 3 tcp dport 80 accept # handle 6 tcp dport 389 accept # handle 4 } }
四、使用nftables配置NAT
使用nftables,可以配置以下網絡地址轉換(NAT)類型:
-
Masquerading
-
Source NAT(SNAT)
-
Destination NAT(DNAT)
4.1 不同的NAT類型:Masquerading,Source NAT和Destination NAT
Masquerading和Source NAT(SNAT)
使用這些NAT類型之一來更改數據包的源IP地址。例如,Internet提供商不會路由保留的IP範圍,例如10.0.0.0/8。如果在網絡中使用保留的IP範圍,並且用戶應該能夠訪問Internet上的服務器,則將數據包的源IP地址從這些範圍映射到公共IP地址。
Masquerading和SNAT都非常相似,不同之處在於:
-
Masquerading會自動使用傳出接口的IP地址。因此,如果傳出接口使用動態IP地址,請使用Masquerading。
-
SNAT將數據包的源IP地址設置爲指定的IP,並且不會動態查找傳出接口的IP。因此,SNAT比僞裝要快。如果傳出接口使用固定IP地址,請使用SNAT。
Destination NAT(DNAT)
使用此NAT類型將傳入流量路由到其他主機。例如,如果Web服務器使用保留IP範圍內的IP地址,因此不能直接從Internet訪問,則可以在路由器上設置DNAT規則以將傳入流量重定向到該服務器。
4.2 配置Masquerading
Masquerading使路由器能夠將通過接口發送的數據包的源IP動態更改爲接口的IP地址。 這意味着,如果接口分配了新的IP,則nftables在替換源IP時會自動使用新的IP。
以下示例將通過ens3接口離開主機的數據包的源IP替換爲ens3上設置的IP
1) 創建table
# nft add table nat
2) 將prerouting和postrouting鏈添加到表中:
# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
請注意,必須將 -- 選項傳遞給nft命令,以避免shell將負優先級值解釋爲nft命令的選項。
3) 將規則添加到與ens3接口上的傳出數據包匹配的postrouting鏈中:
# nft add rule nat postrouting oifname "ens3" masquerade
4.3 配置Source NAT
在路由器上,Source NAT(SNAT)可以將通過接口發送的數據包的IP更改爲特定的IP地址。
以下示例將通過ens3接口離開路由器的數據包的源IP替換爲192.0.2.1
1) 創建表
# nft add table nat
2) 將prerouting和postrouting鏈添加到表中
# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
3) 在postrouting鏈中添加一條規則,該規則將通過ens3的傳出數據包的源IP替換爲192.0.2.1:
# nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1
4.4 配置Destination NAT
通過Destination NAT,可以將路由器上的流量重定向到無法從Internet直接訪問的主機。
以下示例將發送到路由器端口80和443的傳入流量重定向到IP地址爲192.0.2.1的主機
1) 創建表
# nft add table nat
2) 將prerouting和postrouting鏈添加到表中
# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
3) 在prerouting鏈中添加一條規則,該規則將ens3接口上發送到端口80和443的傳入流量重定向到使用192.0.2.1的主機:
# nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1
4) 根據環境,添加SNAT或masquerading規則以更改源地址:
-
如果ens3接口使用了動態IP地址,請添加masquerading規則:
# nft add rule nat postrouting oifname "ens3" masquerade
-
如果ens3接口使用靜態IP地址,請添加SNAT規則。 例如,如果ens3使用198.51.100.1地址:
# nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1
五、在nftables命令中使用集
nftables框架本身支持集合。 例如,如果規則應匹配多個IP地址,端口號,網絡接口或任何其他匹配條件,則可以使用集。
5.1 在Nftable中使用匿名集
匿名集包含用大括號括起來的逗號分隔值,例如{22、80、443},可以在規則中直接使用這些值。 還可以將匿名集也用於IP地址或任何其他匹配條件。
匿名集的缺點在於,如果要更改集,則必須替換規則。
inet 家族中必須存在example_chain鏈和example_table表
1) 要將規則添加到example_table中的example_chain中,以允許到端口22、80和443的傳入流量:
# nft add rule inet example_table example_chain tcp dport { 22, 80, 443 } accept
2) 在example_table中顯示所有鏈及其規則:
# nft list table inet example_table table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport { ssh, http, https } accept } }
5.2 在nftable中使用命名集
nftables框架支持可變的命名集。命名集是可以在表中的多個規則中使用的元素的列表或範圍。相對於匿名集的另一個好處是,可以更新命名集而無需替換使用該集的規則。
創建命名集時,必須指定該集合包含的元素類型,可以設置以下類型:
-
ipv4_addr 包含IPv4地址或範圍的集合,例如192.0.2.1或192.0.2.0/24
-
ipv6_addr 包含IPv6地址或範圍的集合,例如2001:db8:1::1或2001:db8:1::1/64
-
ether_addr 包含物理地址(MAC)列表的集合,例如52:54:00:6b:66:42
-
inet_proto 包含Internet協議類型列表的集合,例如tcp
-
inet_service 包含Internet服務列表的集合, 例如ssh
-
mark 包含數據包標記列表的集合,數據包標記可以是任何正32位整數值(0到2147483647)
1) 創建一個空集。 以下示例爲IPv4地址創建了一個集合:
-
要創建一個可以存儲多個單獨的IPv4地址的集合,請執行以下操作:
# nft add set inet example_table example_set { type ipv4_addr \; }
-
要創建一個可以存儲IPv4地址範圍的集合,請執行以下操作:
# nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }
2) 創建使用集合的規則
例如,以下命令將一條規則添加到example_table中的example_chain中,該規則將丟棄來自example_set中IPv4地址的所有數據包。
# nft add rule inet example_table example_chain ip saddr @example_set drop
由於example_set仍爲空,因此該規則當前無效。
3) 將IPv4地址添加到example_set
-
如果創建一個存儲單個IPv4地址的集合,請輸入:
# nft add element inet example_table example_set { 192.0.2.1, 192.0.2.2 }
-
如果創建一個存儲IPv4範圍的集合,請輸入:
# nft add element inet example_table example_set { 192.0.2.0-192.0.2.255 }
指定IP地址範圍時,可以選擇使用無類域間路由(CIDR)表示法,例如上例中的192.0.2.0/24。
六、在nftables命令中使用判定映射
判定映射(也稱爲字典)使nft通過將匹配標準映射到動作來基於數據包信息執行動作。
6.1 在Nftable中使用文字映射
文字映射是直接在規則中使用的{match_criteria:action}語句。 該語句可以包含多個逗號分隔的映射。
文字映射的缺點是,如果要更改映射,則必須替換規則。
該示例使用文字映射將IPv4和IPv6協議的TCP和UDP數據包都路由到不同的鏈,以分別計算傳入的TCP和UDP數據包。
1) 創建example_table:
# nft add table inet example_table
2) 在example_table中創建tcp_packets鏈:
# nft add chain inet example_table tcp_packets
3) 將規則添加到tcp_packets中,以計算此鏈中的流量:
# nft add rule inet example_table tcp_packets counter
4) 在example_table中創建udp_packets鏈
# nft add chain inet example_table udp_packets
5) 將規則添加到udp_packets中,以計算此鏈中的流量:
# nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \; }
6) 創建傳入流量的鏈。 例如,要在example_table中創建一個名爲incoming_traffic的鏈以過濾傳入流量:
# nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
7) 將帶有文字映射的規則添加到incoming_traffic:
# nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
文字映射區分數據包,並根據其協議將其發送到不同的計數器鏈。
8) 列出流量計數器,顯示example_table:
# nft list table inet example_table table inet example_table { chain tcp_packets { counter packets 36379 bytes 2103816 } chain udp_packets { counter packets 10 bytes 1559 } chain incoming_traffic { type filter hook input priority filter; policy accept; ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets } } }
tcp_packets和udp_packets鏈中的計數器同時顯示已接收數據包的數量和字節。
6.2 在nftables中使用可變判定映射
nftables框架支持可變的判定映射,可以在一個表中的多個規則中使用這些映射。文字映射的另一個好處是,可以更新可變映射,而無需替換使用它的規則。
創建可變判定映射時,必須指定元素的類型:
-
ipv4_addr 匹配部分包含IPv4地址的映射,例如192.0.2.1
-
ipv6_addr 匹配項包含IPv6地址的映射,例如2001:db8:1 :: 1
-
ether_addr 匹配部分包含硬件網卡地址(MAC)的映射,例如52:54:00:6b:66:42。
-
inet_proto 匹配部分包含Internet協議類型的映射,例如tcp
-
inet_service 匹配部分包含Internet服務名稱端口號的映射,例如ssh或22
-
mark 匹配部分包含數據包標記的映射。數據包標記可以是任何正的32位整數值(0到2147483647)。
-
counter 匹配部分包含計數器值的映射。計數器值可以是任何正的64位整數值。
-
quota 匹配部分包含配額值的地圖的配額。配額值可以是任何正的64位整數值。
該示例會根據傳入數據包的源IP地址來允許或丟棄傳入數據包,使用可判定映射,只需一個規則即可配置此方案,而IP地址和操作將動態存儲在該映射中,該示例
在映射中添加和刪除條目。
1) 創建一個表。 例如,創建一個名爲example_table的表來處理IPv4數據包:
# nft add table ip example_table
2) 創建一個鏈。 例如,要在example_table中創建名爲example_chain的鏈:
# nft add chain ip example_table example_chain { type filter hook input priority 0 \; }
3) 創建一個空的映射。 例如,要創建IPv4地址的映射,請執行以下操作:
# nft add map ip example_table example_map { type ipv4_addr : verdict \; }
4) 創建使用映射的規則。 例如,以下命令將一條規則添加到example_table中的example_chain,該規則將操作應用於在example_map中定義的IPv4地址:
# nft add rule example_table example_chain ip saddr vmap @example_map
5) 將IPv4地址和相應的操作添加到example_map: 本示例定義了IPv4地址到操作的映射
# nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }
結合上面創建的規則,防火牆將接受來自192.0.2.1的數據包,並丟棄來自192.0.2.2的數據包。
6) 可選、通過添加另一個IP地址和操作語句來增強映射:
# nft add element ip example_table example_map { 192.0.2.3 : accept }
7) 可選、從映射上刪除一個條目:
# nft delete element ip example_table example_map { 192.0.2.1 }
8) 顯示規則集:
# nft list ruleset table ip example_table { map example_map { type ipv4_addr : verdict elements = { 192.0.2.2 : drop, 192.0.2.3 : accept } } chain example_chain { type filter hook input priority filter; policy accept; ip saddr vmap @example_map } }
七、使用nftables配置端口轉發
通過端口轉發,管理員可以將發送到特定目標端口的數據包轉發到其他本地或遠程端口。
例如,如果Web服務器沒有公用IP地址,則可以在防火牆上設置端口轉發規則,該規則將防火牆上端口80和443上的傳入數據包轉發到Web服務器。 使用此防火牆規則,Internet上的用戶可以使用防火牆的IP或主機名訪問Web服務器。
7.1 將傳入的數據包轉發到其他本地端口
下面示例將端口8022上的傳入IPv4數據包轉發到本地系統上的端口22。
1) 使用IP地址族創建一個名爲nat的表:
# nft add table ip nat
2) 將路由前和路由後鏈添加到表中:
# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
3) 在預路由鏈中添加一條規則,該規則會將端口8022上的傳入數據包重定向到本地端口22:
# nft add rule ip nat prerouting tcp dport 8022 redirect to :22
7.2 將特定本地端口上的傳入數據包轉發到其他主機
使用目標網絡地址轉換(DNAT)規則將本地端口上的傳入數據包轉發到遠程主機。 這使Internet上的用戶可以訪問在具有專用IP地址的主機上運行的服務。
下面示例將本地端口443上的傳入IPv4數據包轉發到IP地址爲192.0.2.1的遠程系統上的相同端口號。
1) 使用IP地址族創建一個名爲nat的表:
# nft add table ip nat
2) 將路由前和路由後鏈添加到表中:
# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
3) 在預路由鏈中添加一條規則,該規則會將端口443上的傳入數據包重定向到192.0.2.1上的同一端口:
# nft add rule ip nat prerouting tcp dport 443 dnat to 192.0.2.1
4) 在路由後鏈中添加一條規則,以僞裝外向流量:
# nft add rule ip daddr 192.0.2.1 masquerade
5) 啓用數據包轉發:
# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
八、使用nftable限制連接數量
使用nftable來限制連接數或阻止試圖建立給定數量的連接的IP地址,以防止它們使用過多的系統資源。
8.1 使用nftable限制連接數
使用nft實用程序的ct count參數,管理員可以限制連接數。
下面示例限制傳入連接
1) 添加一個規則,該規則只允許從IPv4地址同時連接到SSH端口(22)的兩個,並拒絕來自同一IP的所有其他連接:
# nft add rule ip example_table example_chain tcp dport ssh meter example_meter { ip saddr ct count over 2 } counter reject
2) 可選、顯示在上一步中創建的儀表:
# nft list meter ip example_table example_meter table ip example_table { meter example_meter { type ipv4_addr size 65535 elements = { 192.0.2.1 : ct count over 2 , 192.0.2.2 : ct count over 2 } } }
元素條目顯示當前與規則匹配的地址。 在此示例中,元素列出了與SSH端口具有活動連接的IP地址。 請注意,輸出不顯示活動連接數或連接被拒絕。
8.2 阻止在一分鐘內嘗試十個以上新的傳入TCP連接的IP地址
nftables框架使管理員可以動態更新集,本節說明如何使用此功能臨時阻止在一分鐘內建立十個以上IPv4 TCP連接的主機。 五分鐘後,nftables會自動從拒絕列表中刪除IP地址。
1) 使用ip地址系列創建過濾器表:
# nft add table ip filter
2) 將輸入鏈添加到過濾器表中:
# nft add chain ip filter input { type filter hook input priority 0 \; }
3) 將一個名爲denylist的集合添加到過濾器表中:
# nft add set ip filter denylist { type ipv4_addr \; flags dynamic, timeout \; timeout 5m \; }
此命令爲IPv4地址創建一個動態集。 5m超時參數定義了nftables在5分鐘後會自動從集合中刪除條目。
4) 添加一條規則,該規則會自動將嘗試在一分鐘內建立十個以上新TCP連接的主機的源IP地址添加到拒絕列表集中:
# nft add rule ip filter input ip protocol tcp ct state new, untracked limit rate over 10/minute add @denylist { ip saddr }
5) 添加一個規則,以刪除來自拒絕列表集中IP地址的所有連接:
# nft add rule ip filter input ip saddr @denylist drop
九、調試nftables規則
nftables框架爲管理員調試規則以及數據包是否匹配規則提供了不同的選項。
9.1 用計數器創建規則
要確定規則是否匹配,可以使用計數器。 本節介紹如何使用計數器創建新規則。
1) 將帶有counter參數的新規則添加到鏈中。 以下示例添加了一個帶有計數器的規則,該計數器允許端口22上的TCP通信並計算與該規則匹配的數據包和通信:
# nft add rule inet example_table example_chain tcp dport 22 counter accept
2) 要顯示計數器值:
# nft list ruleset table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport ssh counter packets 6872 bytes 105448565 accept } }
9.2 向現有規則添加計數器
要確定規則是否匹配,可以使用計數器。 本節介紹如何向現有規則添加計數器。
1) 顯示鏈中的規則及其句柄:
# nft --handle list chain inet example_table example_chain table inet example_table { chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport ssh accept # handle 4 } }
2) 通過替換規則但使用counter參數來添加計數器。 以下示例替換了上一步中顯示的規則,並添加了一個計數器:
# nft replace rule inet example_table example_chain handle 4 tcp dport 22 counter accept
3) 要顯示計數器值:
# nft list ruleset table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport ssh counter packets 6872 bytes 105448565 accept } }
9.3 監視與現有規則匹配的數據包
通過將nftables中的跟蹤功能與nft monitor命令結合使用,管理員可以顯示與規則匹配的數據包。 該過程描述瞭如何啓用對規則的跟蹤以及如何監視與該規則匹配的數據包。
1) 顯示鏈中的規則及其句柄:
# nft --handle list chain inet example_table example_chain table inet example_table { chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport ssh accept # handle 4 } }
2) 通過替換規則但使用meta nftrace set 1參數來添加跟蹤功能。 以下示例替換了上一步中顯示的規則,並啓用了跟蹤:
# nft replace rule inet example_table example_chain handle 4 tcp dport 22 meta nftrace set 1 accept
3) 使用nft monitor命令顯示跟蹤。 以下示例過濾命令的輸出,以僅顯示包含inet example_table example_chain的條目:
# nft monitor | grep "inet example_table example_chain" trace id 3c5eb15e inet example_table example_chain packet: iif "enp1s0" ether saddr 52:54:00:17:ff:e4 ether daddr 52:54:00:72:2f:6e ip saddr 192.0.2.1 ip daddr 192.0.2.2 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 49710 ip protocol tcp ip length 60 tcp sport 56728 tcp dport ssh tcp flags == syn tcp window 64240 trace id 3c5eb15e inet example_table example_chain rule tcp dport ssh nftrace set 1 accept (verdict accept) ...
十、備份和還原nftables規則集
10.1 將nftables規則集備份到文件
備份nftables規則:
-
採用nft列表規則集格式:
# nft list ruleset > file.nft
-
JSON格式:
# nft -j list ruleset > file.json
10.2 從文件還原nftables規則集
還原nftables規則:
-
如果要還原的文件爲nft列表規則集格式或包含nft命令:
# nft -f file.nft
-
如果要還原的文件爲JSON格式:
# nft -j -f file.json