簡介?
direct
?是?firewalld
?服務的一個功能,它允許用戶以更直接的方式配置防火墻規則,繞過通常的?firewalld
?區域(zone)和服務的抽象層。然而,這個功能已經被棄用(deprecated),并將在未來的版本中移除。
棄用原因:直接配置可能導致與?firewalld
?的其他功能(如區域和服務)發生沖突或混淆。因此,推薦使用?firewalld
?的策略(policies)和區域(zones)來配置防火墻。
替代方案:可以通過policies來替代direct
direct命令結構

文件結構
<?xml version="1.0" encoding="utf-8"?>
<direct>[ <chain ipv="ipv4|ipv6|eb" table="table" chain="chain"/> ][ <rule ipv="ipv4|ipv6|eb" table="table" chain="chain" priority="priority"> args </rule> ][ <passthrough ipv="ipv4|ipv6|eb"> args </passthrough> ]
</direct>
chain
它用于定義額外鏈的名稱。一個鏈條條目具有三個屬性:
-
ipv="ipv4|ipv6|eb"
:將創建鏈的 IP 家族。可以是 ipv4、ipv6 或 eb。 -
table="table"
:鏈將被創建的表名。這可以是 iptables、ip6tables 或 ebtables 可用的表之一。 -
chain="chain"
:將被創建的鏈的名稱。請確保沒有其他同名鏈存在。
請記得添加一條規則或者帶有 --jump
或 --goto
選項的穿透規則,將該鏈與另一個鏈連接起來。這個與我們iptables中的自定義鏈和關聯自定義鏈到對應的表是一樣的。
rule
它用于向內置或添加的鏈中添加規則。一個規則條目具有四個屬性:
-
ipv="ipv4|ipv6|eb"
:將添加規則的 IP 家族。可以是 ipv4、ipv6 或 eb。 -
table="table"
:規則將被添加到的表的名稱。這可以是 iptables、ip6tables 或 ebtables 可用的表之一。 -
chain="chain"
:將添加規則的鏈的名稱。這可以是內置鏈或使用chain
標簽創建的鏈。如果鏈名稱是內置鏈,則規則將被添加到chain_direct
,否則使用提供的鏈名稱。chain_direct
在所有內置鏈中內部創建,以確保添加的規則不會與 firewalld 創建的規則發生沖突。 -
priority="priority"
:優先級用于排序規則。優先級為 0 表示在鏈的頂部添加規則。具有相同優先級的規則處于同一級別,這些規則的順序不固定且可能更改。如果想確保一個規則在另一個規則之后添加,為第一個規則使用較低的優先級,為后續規則使用較高的優先級。
passthrough
passthrough
?是?firewalld
?中?direct.xml
?文件的一個可選元素標簽,用于向內置或添加的鏈中添加規則。。當你使用?passthrough
?時,你需要確保添加的規則與?firewalld
?自動創建的其他規則沒有沖突。
注意事項:
當使用firewalld
時,根據配置的FirewallBackend
(在firewalld.conf
中設置),直接規則的行為會有所不同。主要的后端有兩個:iptables
和nftables
數據包接受/丟棄優先級
- 如果使用了
FirewallBackend=nftables
,直接規則中ACCEPT數據包并不會立即導致數據包被系統接受。這些數據包仍然需要遵守firewalld
的nftables規則集。這基本上意味著有兩個獨立的防火墻,數據包必須同時被兩者接受(iptables和nftables)。 - 對于DROP規則,數據包會立即被丟棄,無論
FirewallBackend
的值是什么。 - 為了解決nftables中ACCEPT數據包的問題,用戶可以:
- 使用富規則(Rich Rules),它們會被轉換成啟用的后端規則。
- 在nftables規則集中明確接受數據包,這可以通過將接口或源添加到受信任的區域來實現。注意,這意味著
firewalld
將不會對這些數據包進行任何過濾。 - 在適當的區域中僅啟用相關的服務、端口、地址等。
- 可以通過設置
FirewallBackend=iptables
來回退到iptables后端。但是,應該意識到firewalld
的開發重點是nftables后端。
配置直接規則
命令參考
irect Options--direct --指定將要使用直接規則--get-all-chains --獲取所有的鏈--get-chains {ipv4|ipv6|eb} <table> --獲取表中的鏈--add-chain {ipv4|ipv6|eb} <table> <chain> --添加鏈到表中(自定義的)--remove-chain {ipv4|ipv6|eb} <table> <chain> --移除表中的某條鏈--query-chain {ipv4|ipv6|eb} <table> <chain> --返回鏈是否已被添加到表--get-all-rules --獲取所有的策略規則--get-rules {ipv4|ipv6|eb} <table> <chain> --獲取指定表中指定鏈中的規則--add-rule {ipv4|ipv6|eb} <table> <chain> <priority> <arg>... --在指定表中的指定鏈添加規則--remove-rule {ipv4|ipv6|eb} <table> <chain> <priority> <arg>... --優先從指定表中的指定鏈刪除規則條目--remove-rules {ipv4|ipv6|eb} <table> <chain> --從表中刪除規則條目--query-rule {ipv4|ipv6|eb} <table> <chain> <priority> <arg>... --返回是否優先的規則已被添加到鏈表中--passthrough {ipv4|ipv6|eb} <arg>... --直接傳遞iptables的命令--get-all-passthroughs --獲取所有直接傳遞的規則--get-passthroughs {ipv4|ipv6|eb} <arg>... --獲取跟蹤直通規則--add-passthrough {ipv4|ipv6|eb} <arg>... --添加一個直接規則--remove-passthrough {ipv4|ipv6|eb} <arg>... --移除一個直接規則--query-passthrough {ipv4|ipv6|eb} <arg>... --查詢直接規則是否添加
增加直接規則
firewall-cmd --direct --add-chain { ipv4 | ipv6 | eb } <table> [自定義鏈表名] <args>firewall-cmd --direct --add-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>
刪除直接規則
firewall-cmd --direct --remove-chain { ipv4 | ipv6 | eb } <table> [自定義鏈表名] <args>firewall-cmd --direct --remove-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>
firewalld與iptables表對比
修改firewall的后端為iptables
編輯/etc/firewalld/firewalld.conf,將FirewallBackend=修改為iptables,默認為nftables

此時查看我們的firewalld? zone

查看iptables
此時會發現我們的iptables有非常多的規則,我這里只列出與我們前面配置的trusted zone相關的規則。




測試1
配置直接規則,允許192.168.140.248訪問140.250的80端口,在firewalld中,我們已經配置了2條規則,第一條禁止第二條放行,但是禁止的優先級高,所以禁止優先。



測試2
我們現在要限制192.168.140.248對250的icmp訪問,每5秒放行一個數據包。這個在我們上篇文章介紹rich rule的時候是沒有實現的,那么我們這里通過--direct來實現

上面配置的詳細原理可以參考iptables常用擴展模塊和iptables自定義鏈的配置方式。配置完成后通過--runtime-to-permanent從runtime永久化然后重新加載。
此時在192.168.140.248上ping可以實現我們想要的功能嗎?

查看iptables





總結:
? ? ? ? 當我們使用--direct參數后,并且將后端改為iptables后,那么數據包的處理方式就和iptables是一樣的。我們可以直接修改iptables也可以通過firewalld-cmd進行配置。這個時候如果使用--direct命令去配置的話,需要我們對iptables有一定程度的了解。更多的iptables的使用大家可以看我前面與iptables有關的文章。