簡介
前面文章主要介紹的是nftables的基本原理和基礎的配置,如nftables基本的表、鏈、規則的創建和管理。本篇文章主要介紹的是表達式EXPRESSIONS。
在網絡安全和數據處理中,表達式(Expressions)扮演著非常重要的角色。它們用于表示值,這些值可以是常量(如網絡地址、端口號等),也可以是在規則集評估過程中從數據包中收集的數據。表達式可以通過二進制、邏輯、關系和其他類型的表達式組合來形成復雜或關系(匹配)表達式。此外,表達式還用作某些類型操作(如網絡地址轉換NAT、數據包標記等)的參數。
每個表達式都有其數據類型,這決定了符號值的大小、解析方式、表示形式以及與其他表達式進行類型兼容性檢查的方式。數據類型對于確保表達式的正確執行和結果的準確性至關重要。
?通過description命令顯示表達式的類型及其數據類型的信息。還可以給出一個數據類型,nft將在其中顯示有關該類型的更多信息。
describe expression | data type

數據類型
數據類型(Data Types)是極其重要的概念,它們決定了符號值的大小、解析方式、表示形式以及表達式之間的類型兼容性。一下我們介紹幾種常見的數據類型:
INTEGER TYPE(整數類型)
Name | Keyword | Size | Base type |
Integer | integer | variable | - |
整數類型用于表示數值,可以是以十進制、十六進制或八進制形式指定的數字。整數類型的大小不是固定的,而是取決于它被使用的上下文或表達式。例如,在某些編程語言或系統中,整數可以是8位、16位、32位或64位,這取決于系統架構、編譯器選項或程序員的指定。
BITMASK TYPE(位掩碼類型)
Name | Keyword | Size | Base type |
Bitmask | bitmask | variable | integer |
位掩碼類型用于表示一組位(bit),其中每個位都可以獨立地設置為開(1)或關(0)。位掩碼常用于控制選項或設置狀態,因為它們允許在一個單獨的值中存儲多個布爾值。位掩碼類型基于整數類型,因為整數提供了存儲和操作位所需的底層機制。
STRING TYPE(字符串類型)
Name | Keyword | Size | Base type |
String | string | variable | - |
字符串類型用于表示文本數據,即一系列字符。字符串的開頭通常是一個字母字符(a-zA-Z),后面可以跟零個或多個字母數字字符或特定字符(如/、-、_、.)。此外,任何被雙引號(")包圍的內容都被視為字符串。這允許在字符串中包含那些可能被視為特殊字符的字符。
#例如如何在網絡過濾規則中指定接口名稱。
# Interface name
filter input iifname eth0
# Weird interface name
filter input iifname "(eth0)"
LINK LAYER ADDRESS TYPE(鏈路層地址類型)
Name | Keyword | Size | Base type |
Link layer address | lladdr | variable | integer |
鏈路層地址類型(lladdr
)用于表示鏈路層地址,如以太網MAC地址。這些地址通常由一系列以冒號(:)分隔的兩位十六進制數字組成,數量是可變的。盡管其大小是可變的,但每個MAC地址通常由6個八位字節(即48位)組成,但在指定時,格式上的冒號不計入實際大小。
#以太網目標MAC地址:這條規則指定了數據包輸入過濾時,目標以太網MAC地址應為 00:0c:29:0f:37:05
filter input ether daddr 00:0c:29:0f:37:05
IPV4 ADDRESS TYPE(IPv4地址類型)
Name | Keyword | Size | Base type |
IPV4 address | ipv4_addr | 32 bit | integer |
IPv4地址類型(ipv4_addr
)用于表示IPv4地址。這些地址通常是32位的,并可以通過多種方式指定,包括點分十進制、點分十六進制、點分八進制、十進制、十六進制、八進制表示法或作為主機名。如果指定為主機名,則使用標準系統解析器進行解析。
#點分十進制表示法:這條規則指定了數據包輸出過濾時,目標IPv4地址應為127.0.0.1(即本地回環地址)。
filter output ip daddr 127.0.0.1#主機名表示法:這條規則指定了數據包輸出過濾時,目標IPv4地址應通過主機名localhost解析得出。
filter output ip daddr localhost
IPV6 ADDRESS TYPE(IPv6地址類型)
Name | Keyword | Size | Base type |
IPv6 address | ipv6_addr | 128 bit | integer |
IPv6地址類型(ipv6_addr
)用于表示IPv6地址。這些地址是128位的,并可以指定為主機名或一系列由冒號分隔的十六進制半字(每個半字通常為4位十六進制數)。為了與端口號區分,IPv6地址有時會被方括號([]
)包圍。
#縮寫回環地址:這條規則指定了數據包輸出過濾時,目標IPv6地址應為縮寫形式的回環地址::1
filter output ip6 daddr ::1#帶方括號的IPv6地址:這條規則指定了在IPv6地址轉換的預路由階段,如果TCP目標端口為20000,則將其目的地址轉換為[1df::d0],并指定目標端口為22。方括號的使用確保了1df::d0被正確解析為IPv6地址,而不是與端口號混淆
ip6 nat prerouting tcp dport 20000 dnat to [1df::d0]:22
BOOLEAN TYPE(布爾類型)?
Name | Keyword | Size | Base type |
Boolean | boolean | 1 bit | integer |
布爾類型(boolean
)在用戶空間中是一個語法輔助類型,主要用于在(通常是隱式的)關系表達式的右側,將左側表達式轉換為布爾檢查(通常用于檢查存在性)。盡管布爾類型在底層實現上可能占用更多的存儲空間(比如一個字節或更多),但在邏輯上它被視為1位大小,即只能存儲兩個值:0(假)或1(真)。在大多數上下文中,布爾類型被映射到整數類型,其中0表示假,非0值(如1)表示真。
關鍵字與值
Keyword | Value |
exists表示存在,對應值為1(真) | 1 |
missing表示不存在,對應值為0(假) | 0 |
表達式支持布爾比較(boolean comparison)
表達式(expressions)支持布爾比較(boolean comparison)是一種非常常見且重要的特性。布爾比較允許你根據兩個或多個值之間的關系來評估表達式的結果為真(true)或假(false)。這種機制在條件語句(如if語句)、循環控制(如while循環)以及很多其他需要基于條件邏輯進行決策的場景中都是不可或缺的。
Expression | Behaviour |
fib | 檢查路由是否存在。這通常用于過濾規則中,以確定數據包是否匹配特定的路由。 |
exthdr | 檢查IPv6擴展頭是否存在。這允許在IPv6流量中根據擴展頭的存在性來過濾數據包。 |
tcp option | 檢查TCP選項頭是否存在。這允許基于TCP選項(如時間戳選項)的存在性來過濾TCP數據包。 |
#匹配存在的路由:這條規則表示如果輸入的數據包存在匹配的路由(即fib daddr表達式為真),并且指定的入接口(iif)和出接口(oif)也匹配,則該數據包將被匹配。注意這里的exists關鍵字用于將fib daddr的結果轉換為布爾值。
filter input fib daddr . iif oif exists#僅匹配IPv6非分片數據包:這條規則表示如果輸入的數據包是IPv6數據包,并且沒有分片擴展頭(即frag擴展頭不存在),則該數據包將被匹配。
filter input exthdr frag missing#匹配包含TCP時間戳選項的數據包:這條規則表示如果輸入的數據包是TCP數據包,并且包含時間戳選項(即tcp option timestamp存在),則該數據包將被匹配。這允許基于TCP數據包的特定選項來過濾流量
filter input tcp option timestamp exists
ICMP TYPE TYPE(ICMP類型)
Name | Keyword | Size | Base type |
ICMP Type | icmp_type | 8 bit | integer |
ICMP(Internet Control Message Protocol,互聯網控制消息協議)類型是一個用于方便指定ICMP頭部類型字段的類型。ICMP是IP網絡中的一個重要協議,用于發送控制消息,如錯誤報告、路由信息請求等。ICMP類型字段定義了ICMP消息的具體類型,每種類型都有其特定的用途和含義。
Keyword | Value | 解釋 |
echo-reply | 0 | 表示ICMP回顯應答消息,通常是對echo-request (ping請求)的響應 |
destination-unreachable | 3 | 表示目的不可達消息,用于通知發送方數據包無法到達其目的地 |
source-quench | 4 | 已廢棄,原用于擁塞控制,但現在已被新的機制所取代 |
redirect | 5 | 表示重定向消息,用于指導發送方將數據包發送到更好的路由 |
echo-request | 8 | 表示ICMP回顯請求消息,通常用于生成ping請求 |
router-advertisement | 9 | 路由器通告消息,用于動態地通知主機有關路由器的信息 |
router-solicitation | 10 | 路由器請求消息,用于請求路由器發送其通告。 |
time-exceeded | 11 | 表示生存時間(TTL)超過消息,用于通知發送方數據包在到達目的地之前已被丟棄,因為其TTL已減至0 |
parameter-problem | 12 | 表示參數問題消息,用于通知發送方其數據包中的某個字段有錯誤 |
timestamp-request | 13 | 時間戳請求消息,用于請求接收方記錄并返回數據包的接收時間 |
timestamp-reply | 14 | 時間戳應答消息,是對timestamp-request 的響應,包含接收時間 |
info-request | 15 | 用于請求關于網絡或主機的特定信息 |
info-reply | 16 | 是對info-request (信息請求)消息的響應。它包含了請求方所請求的信息 |
address-mask-request | 17 | 信息請求消息,用于請求有關地址掩碼的信息(在某些實現中可能稱為地址掩碼請求) |
address-mask-reply | 18 | 信息應答消息,是對info-request 的響應,包含請求的信息 |
#匹配ping數據包:這條規則表示匹配輸出方向上的ICMP數據包,其類型字段為echo-request(ping請求)或echo-reply(ping應答)。這通常用于允許或過濾ping操作,以測試網絡連通性或進行故障排查。
filter output icmp type { echo-request, echo-reply }
ICMP CODE TYPE(ICMP代碼類型)?
Name | Keyword | Size | Base type |
ICMP Code | icmp_code | 8 bit | integer |
ICMP(Internet Control Message Protocol,互聯網控制消息協議)代碼類型用于方便地指定ICMP頭部的代碼字段。ICMP消息不僅由類型字段標識其大致的類別,還通過代碼字段提供更具體的錯誤或信息類型。這使得接收方能夠更準確地了解發送ICMP消息的原因。
Keyword | Value | 解釋 |
net-unreachable | 0 | 表示網絡不可達。這通常意味著沒有到達目標網絡的路由 |
host-unreachable | 1 | 表示主機不可達。這通常意味著目標主機在指定的網絡上不存在或無法訪問 |
prot-unreachable | 2 | 表示協議不可達。這表示目標主機不支持發送方嘗試使用的協議 |
port-unreachable | 3 | 表示端口不可達。這表示目標主機上的特定端口沒有監聽或無法訪問 |
frag-needed | 4 | 表示需要分片但DF(Don't Fragment)位被設置。這通常發生在數據包太大而無法通過某個網絡段時,但發送方已請求不進行分片 |
net-prohibited | 9 | 表示網絡被禁止。這通常是由于設置的策略,阻止數據包進入或離開指定的網絡 |
host-prohibited | 10 | 表示主機被禁止。這通常表示目標主機已明確拒絕接收數據包,可能是出于安全或配置的原因 |
admin-prohibited | 13 | 表示管理禁止。這是一個更通用的“被禁止”代碼,可能用于表示由于管理策略而阻止數據包傳遞的多種情況 |
ICMP代碼的作用
ICMP代碼與ICMP類型字段結合使用,提供了關于ICMP消息的更詳細信息。這有助于接收方理解為什么發送了ICMP消息,并據此采取相應的行動。例如,如果接收到一個destination-unreachable
(類型3)和port-unreachable
(代碼3)的ICMP消息,接收方就知道數據包無法到達目標端口,并可能嘗試使用不同的端口或協議重新發送數據包。
注意事項
- 并非所有ICMP類型都有對應的代碼字段。有些ICMP類型可能只使用類型字段,而不使用代碼字段。
- ICMP代碼的具體含義可能因不同的系統和網絡實現而異。因此,在編寫依賴于特定ICMP代碼的邏輯時,需要仔細考慮這些因素。
- ICMP消息本身并不攜帶原始數據包的全部內容,而是包含有關原始數據包的一些關鍵信息(如IP頭部和至少前8個字節的數據)。這有助于接收方了解哪些數據包遇到了問題,但可能不足以完全重建原始數據包。
ICMPv6 TYPE TYPE(ICMPv6 類型)
Name | Keyword | Size | Base type |
ICMPv6 Type | icmpx_code | 8 bit | integer |
ICMPv6(Internet Control Message Protocol version 6)類型用于方便地指定ICMPv6頭部的類型字段。ICMPv6是IPv6協議棧中的一部分,用于發送控制消息,如錯誤報告、信息請求和響應等。與ICMPv4相比,ICMPv6在消息類型和目的上有所擴展,以支持IPv6網絡的特定需求。
Keyword | Value | 解釋 |
destination-unreachable | 1 | 表示目的不可達消息,用于通知發送方數據包無法到達其目的地 |
packet-too-big | 2 | 表示數據包太大,無法通過網絡段而不進行分片。這通常與路徑MTU發現過程相關 |
time-exceeded | 3 | 表示生存時間(TTL)或跳數限制(Hop Limit)超過,數據包在到達目的地之前已被丟棄 |
parameter-problem | 4 | 表示ICMPv6頭部中的某個字段存在錯誤 |
echo-request | 128 | 表示ICMPv6回顯請求消息,通常用于生成ping請求 |
echo-reply | 129 | 表示ICMPv6回顯應答消息,是對echo-request 的響應 |
mld-listener-query | 130 | 組播偵聽器發現(Multicast Listener Discovery, MLD)查詢消息,用于發現網絡上的組播偵聽器 |
mld-listener-report | 131 | 組播偵聽器報告消息,由組播偵聽器發送以響應MLD查詢或主動報告其存在 |
mld-listener-done | 132 | mld-listener-done ?和?mld-listener-reduction :均標記為132,但mld-listener-reduction 可能是對mld-listener-done 的一個補充或特定用途的變體,用于指示組播偵聽器數量的減少 |
mld-listener-reduction | 132 | |
nd-router-solicit | 133 | 鄰居發現(Neighbor Discovery, ND)路由器請求消息,用于請求路由器發送其通告 |
nd-router-advert | 134 | 鄰居發現路由器通告消息,包含有關網絡配置的信息 |
nd-neighbor-solicit | 135 | 鄰居發現鄰居請求消息,用于請求鄰居的鏈路層地址 |
nd-neighbor-advert | 136 | 鄰居發現鄰居通告消息,包含鄰居的鏈路層地址 |
nd-redirect | 137 | 鄰居發現重定向消息,用于指導發送方將數據包發送到更好的路由 |
router-renumbering | 138 | 路由器重編號消息,用于在IPv6網絡中重新分配地址 |
ind-neighbor-solicit | 141 | 無組播鄰居發現協議中的鄰居請求報文 |
ind-neighbor-advert | 142 | 無組播鄰居發現協議中的鄰居通告報文 |
mld2-listener-report | 143 | MLD2 協議中的監聽器報告 |
#匹配ICMPv6 ping數據包:這條規則表示匹配輸出方向上的ICMPv6數據包,其類型字段為echo-request(ICMPv6 ping請求)或echo-reply(ICMPv6 ping應答)。這通常用于允許或過濾ICMPv6 ping操作,以測試IPv6網絡的連通性或進行故障排查。
filter output icmpv6 type { echo-request, echo-reply }
ICMPv6 CODE TYPE(ICMPv6代碼類型)
Name | Keyword | Size | Base type |
ICMPv6 Code | icmpv6_code | 8 bit | integer |
ICMPv6代碼(Code)類型用于方便地指定ICMPv6頭部的代碼字段。這個字段提供了關于ICMPv6消息類型的進一步細分,以更精確地指示發生了什么問題或需要什么樣的響應。
Keyword | Value | 解釋 |
no-route | 0 | 表示沒有到目標地址的路由。這通常是由于路由表中沒有匹配的條目導致的 |
admin-prohibited | 1 | 表示由于管理策略,數據包被禁止傳輸。這通常是由網絡管理員設置的規則所觸發的 |
addr-unreachable | 3 | 表示目標地址不可達。這可能是因為目標地址不存在于鏈路上,或者地址是一個多播地址但當前沒有偵聽器 |
port-unreachable | 4 | 表示目標端口不可達。這意味著數據包已到達目標主機,但目標端口沒有監聽或無法訪問 |
policy-fail | 5 | 表示由于路由策略失敗,數據包被丟棄。這可能與路由策略、流量工程或安全策略有關 |
reject-route | 6 | 表示數據包被拒絕,因為存在一條明確拒絕該數據包的路由。這通常是為了防止某些類型的數據包進入網絡而設置的 |
ICMPv6代碼的作用
ICMPv6代碼與ICMPv6類型字段結合使用,為接收方提供了關于為什么發送ICMPv6消息的詳細信息。這有助于接收方理解數據包未能成功傳輸的原因,并據此采取相應的行動。例如,如果接收到一個destination-unreachable
(類型1)和no-route
(代碼0)的ICMPv6消息,接收方就知道數據包無法到達其目的地,因為沒有到目標地址的路由。
CONNTRACK TYPES
在Linux網絡子系統中,conntrack
(連接跟蹤)是一個重要的組件,用于跟蹤和記錄通過網絡接口進出的網絡連接。這有助于實現如NAT(網絡地址轉換)、防火墻規則等網絡功能。您提供的表格概述了conntrack
表達式和語句中使用的幾種類型及其關鍵字和值。
conntrack 類型
Name | Keyword | Size | Base type | 解釋 |
conntrack state | ct_state | 4 byte | bitmask | 表示連接的狀態,如新建、已建立、相關等 |
conntrack direction | ct_dir | 8 bit | integer | 表示數據包的方向,是原始數據包還是回復數據包 |
conntrack status | ct_status | 4 byte | bitmask | 提供有關連接狀態的額外信息,如是否已確認、是否進行了NAT等 |
conntrack event bits | ct_event | 4 byte | bitmask | 標記連接跟蹤過程中的事件,如新建連接、連接銷毀等 |
conntrack label | ct_label | 128 bit | bitmask | 用于給連接分配標簽,這些標簽可以在運行時從配置文件中讀取 |
conntrack state (ct_state)
Keyword | Value | 解釋 |
invalid | 1 | 連接無效或已過期 |
established | 2 | 連接已建立 |
related | 4 | 連接與已建立的連接相關(如FTP數據連接) |
new | 8 | 新建的連接 |
untracked | 64 | 連接未被跟蹤(可能由于配置或策略) |
conntrack direction (ct_dir)
Keyword | Value | 解釋 |
original | 0 | 原始數據包的方向(從客戶端到服務器) |
reply | 1 | 原始數據包的方向(從客戶端到服務器) |
conntrack status (ct_status)
Keyword | Value | 解釋 |
expected | 1 | 預期中的連接(如FTP主動模式下的數據連接) |
seen-reply | 2 | ?已看到回復數據包 |
assured | 4 | 連接已得到保證 |
confirmed | 8 | 連接已確認 |
snat | 16 | ?進行了源地址NAT |
dnat | 32 | 進行了目標地址NAT |
dying | 512 | 連接正在消亡(如超時后) |
conntrack event bits (ct_event)
這些事件位用于在連接跟蹤過程中標記不同的事件
Keyword | Value | 解釋 |
new | 1 | ?新建連接事件 |
related | 2 | 相關連接事件 |
destroy | 4 | 連接銷毀事件 |
reply | 8 | 回復數據包事件 |
assured | 16 | ?連接得到保證的事件 |
protoinfo | 32 | 協議信息更新事件 |
helper | 64 | 使用了連接跟蹤輔助模塊的事件 |
mark | 128 | 連接被標記的事件 |
seqadj | 256 | 序列號調整事件(如TCP序列號調整) |
secmark | 512 | 安全標記更新事件 |
label | 1024 | 連接標簽更新事件 |
conntrack label (ct_label)
ct_label
?允許給連接分配一個或多個標簽,這些標簽可以在運行時從配置文件中讀取,如?/etc/connlabel.conf
。這對于基于標簽的過濾和策略實施非常有用。
這些conntrack
類型和關鍵字是網絡編程和系統管理中的重要工具,它們允許開發者和管理員更精細地控制網絡流量的處理和路由。
DCCP PKTTYPE TYPE
Name | Keyword | Size | Base type |
DCCP packet type | dccp_pkttype | 4 bit | integer |
在DCCP(Datagram Congestion Control Protocol,數據報擁塞控制協議)中,包類型(Packet Type)是一個4位的字段,用于指示DCCP數據包的不同類型和目的。這個字段位于DCCP頭部中,并根據RFC 4340標準定義了不同的值。這些值幫助網絡中的節點理解和處理不同類型的DCCP數據包。
Keyword | Value | 解釋 |
request | 0 | 表示這是一個連接請求包,用于初始化一個新的DCCP連接 |
response | 1 | 是對request包的響應,表示接受或拒絕連接請求 |
data | 2 | 包含應用層數據,但不包含確認信息 |
ack | 3 | 是一個純確認包,不包含應用層數據,僅用于確認收到的數據 |
dataack | 4 | 同時包含應用層數據和確認信息,用于減少網絡中的包數量 |
closereq | 5 | 用于請求關閉一個已經建立的DCCP連接 |
close | 6 | 是對closereq包的響應,表示同意關閉連接 |
reset | 7 | 用于異常終止一個DCCP連接,比如當檢測到嚴重錯誤時 |
sync | 8 | 用于在連接建立時或連接過程中同步雙方的狀態信息 |
syncack | 9 | 是對sync包的確認,表示收到了同步信息并準備繼續 |
值得注意的是,值10到15是保留的,根據RFC 4340,這些值不應該被使用。在iptables中,這些保留值被標記為INVALID,意味著如果匹配到這些值,將被視為無效或不被識別的DCCP包類型。而在nftables中,你可以直接匹配這些數值范圍(即10-15),但通常不推薦這樣做,因為它們沒有定義的具體用途。
總結
以上就是我們介紹的一些主要的數據類型,通過數據類型和表達式相互配合,可以幫助用戶根據特定的需求構建和評估規則集,從而實現對數據包的精確控制和處理。通過結合不同類型的表達式,用戶可以更靈活地管理網絡流量和執行各種網絡操作。