之前幾篇文章已經(jīng)談及了firewalld最常用的配置,之前的所有命令行只是firewalld實(shí)用程序?qū)ptables/ntable的規(guī)則做了預(yù)封裝處理,每個(gè)區(qū)域的底層都有預(yù)設(shè)規(guī)則來處理入站/出站的數(shù)據(jù)包,如果你需要實(shí)現(xiàn)更細(xì)粒度的數(shù)據(jù)包過濾操作/轉(zhuǎn)發(fā)操作,那么你必須對iptables更深入的了解,而本章談?wù)摰降膁irect規(guī)則,實(shí)際上就是iptables規(guī)則的外殼語法。
實(shí)驗(yàn)拓?fù)?/h3>
我們?nèi)匀煌ㄟ^下面的拓?fù)?,通過direct規(guī)則將我們的Linux主機(jī)配置成一個(gè)路由器。

在開始前,我這里先給大家列出firewalld的初始狀態(tài)。
- external:ens33網(wǎng)絡(luò)接口位于外部區(qū)域
-
internal:ens34網(wǎng)絡(luò)接口位于內(nèi)部區(qū)域
direct規(guī)則應(yīng)用注意事項(xiàng)
注意以下示例僅適用于CentOS 7,7之前的內(nèi)核還是以netfilter作為iptalbes的操作實(shí)體,我們可以使用lsmod命令查看CentOS Linux 7加載的模塊來驗(yàn)證我們的想法

iptables在Linux 7中有好幾個(gè)子模塊,熟悉iptables的同學(xué)應(yīng)該都知道filter,nat,mangle等幾個(gè)表分別裝載著不同的鏈(Chain),而不同的鏈又分別可以定義著特定用途的規(guī)則。
- iptable_security,
- iptable_filter
- iptables_mangle
- iptables_nat
- iptables_raw.
而這些規(guī)則,正是firewalld中的direct規(guī)則。direct規(guī)則就是帶了套iptables規(guī)則。紅帽官方的firewalld手冊頁指出,只有在無法使用例如-add-rich-Rule=‘Rule’時(shí),才應(yīng)使用direct規(guī)則作為最后手段。因此有如下建議
- 我個(gè)人建議如果你對iptables有深入的理解,就使用direct規(guī)則
- rich規(guī)則與direct規(guī)則最好不要混用。
firewall-cmd
--permanent \
--direct \
--add-rule { ipv4 | ipv6 | eb } \
<表(table)> <鏈(chain)> <優(yōu)先級(priority)> args
Linux NAT系統(tǒng)
在使用direct規(guī)則配置nat系統(tǒng)之前,我們復(fù)習(xí)一下iptables的運(yùn)行機(jī)制,下圖是在前人的基礎(chǔ)上加以匯總的

我們假設(shè)external區(qū)域外有一臺主機(jī)(202.43.72.56)需要通過MS遠(yuǎn)程桌面服務(wù)連接到內(nèi)網(wǎng)的一臺主機(jī)10.10.10.1,那么對應(yīng)的數(shù)據(jù)包有如下細(xì)節(jié)信息。
- 源地址117.34.25.26,
- 目的地址:202.43.72.56(假設(shè)這是我們防火墻的公網(wǎng)IP)
- 源端口7345(隨機(jī)端口)
- 目的端口 3389
那么這個(gè)數(shù)據(jù)包會如上圖iptables的操作流程
數(shù)據(jù)包來到入站的網(wǎng)卡接口時(shí)候會先通過mangle表的PREROUTING,mange表通常給數(shù)據(jù)包的加上頭部字段加上特殊標(biāo)識,用于在后續(xù)其他鏈中對該數(shù)據(jù)包做精準(zhǔn)的控制(通常情況下,會略過mangle表的PREROUTING鏈)。
接著來到nat表的PREROUTING鏈中,目的地址轉(zhuǎn)換(Destination NAT ,簡稱DNAT)會在這里發(fā)生,也就是說入站數(shù)據(jù)包202.43.72.56:3389會被替nat表的PREROUTING鏈的規(guī)則替換成10.10.10.1:3389,被修改后的數(shù)據(jù)包在離開這里時(shí),之前的202.43.72.56的源端口和目的端口,以及內(nèi)網(wǎng)10.10.10.1的對應(yīng)信息會寫入一張NAT映射表。
接著10.10.10.1:3389的數(shù)據(jù)包,會被系統(tǒng)內(nèi)核的路由系統(tǒng)依據(jù)它的目標(biāo)IP(查看路由表),這里的10.10.10.1:3389這個(gè)數(shù)據(jù)包的接收對象顯然不是防火墻的本機(jī)地址,此時(shí)數(shù)據(jù)包會進(jìn)入FORWARD鏈。
在FORWARD鏈中,此時(shí)數(shù)據(jù)包會依次由mangle->filter兩張表的FORWARD鏈內(nèi)規(guī)則進(jìn)行過濾。由于在第一步的mangle表沒做任何處理,所以會快速略過mangle表,并且filter表的FORWARD鏈?zhǔn)悄J(rèn)ACCEPT的。值得一提的是,CentOS 7/8在安裝之初,如果主機(jī)本身不少于兩張網(wǎng)卡并且是已連接狀態(tài),系統(tǒng)內(nèi)核會默認(rèn)激活I(lǐng)P數(shù)據(jù)包轉(zhuǎn)發(fā)功能。
POSTROUTING鏈?zhǔn)怯糜谔幚頂?shù)據(jù)包在離開防火墻的出站數(shù)據(jù)包后的最后一個(gè)操作,當(dāng)10.10.10.1:3389這個(gè)數(shù)據(jù)包離開之前,POSTROUTING的規(guī)則會對數(shù)據(jù)包的源IP地址替換為10.10.10.254,這正是SNAT操作,同理這些對應(yīng)的IP和端口信息會被寫入NAT映射表中.對于10.10.10.1的主機(jī)接收到該數(shù)據(jù)包,該主機(jī)只知道這個(gè)數(shù)據(jù)包是防火墻的出站接口10.10.10.254發(fā)給它的,而對最初117.34.25.26的源地址,該主機(jī)是一無所知的。
此時(shí)源IP為10.10.10.254,目標(biāo)IP是10.10.10.1:3389的數(shù)據(jù)包已經(jīng)離開了防火墻,此時(shí)的數(shù)據(jù)包已經(jīng)被封裝成鏈路層中的數(shù)據(jù)幀,并且經(jīng)由二層交換設(shè)備到達(dá)10.10.10.1的主機(jī)。
對于上面NAT執(zhí)行原理的細(xì)節(jié),我只是提及到防火墻向內(nèi)網(wǎng)主機(jī)發(fā)送的過程,如果你對NAT原理不理解的話,建議找本類似CCNA的書籍,惡補(bǔ)一下路由交換與NAT的基礎(chǔ)。
Lab:配置NAT路由器

在上面拓?fù)渲?我們要允許internal區(qū)域的vm與external的web主機(jī)通信,我們必須為防火墻配置IP偽裝,如果你的防火墻接口的IP地址經(jīng)常變動(dòng)的,那么使用下面指令:
firewall-cmd --permanent --direct --add-rule \
ipv4 nat POSTROUTING 0 -o ens33 -j MASQUERADE
注意:由于在寫本文時(shí),我在公司和家中搭建的網(wǎng)絡(luò)環(huán)境有差別,防火墻外部接口獲得的ip地址有所不同,因此配置命令和截圖會有所不同,這里特此說明。
或?qū)τ谟泄潭ㄍ饩W(wǎng)IP的情況,我們應(yīng)該明確在nat表的POSTROUTING中使用SNAT操作,本示例是192.168.50.19,因此如下命令所示
firewall-cmd --permanent --direct \
--add-rule ipv4 nat POSTROUTING 0 \
-s 10.10.10.0/24 -o ens33 \
-j SNAT --to 192.168.50.19
以下這條是可選的命令,如果你生產(chǎn)環(huán)境的信息安全要求比較嚴(yán)謹(jǐn),不妨將FORWARD鏈的默認(rèn)策略設(shè)定為DROP
iptables -P FORWARD DORP
這樣以后誰要訪問你的網(wǎng)站或者你公司的員工需要訪問外網(wǎng)就必須在FORWARD鏈中顯式添加基于源IP地址到目標(biāo)IP的轉(zhuǎn)發(fā)規(guī)則。
將所有ICMP請求從internal區(qū)域(ens34)轉(zhuǎn)發(fā)到external區(qū)域(enp33)
firewall-cmd --permanent --direct \
--add-rule ipv4 filter FORWARD 0 -i ens34 -o ens33 \
-p icmp -m state --state NEW,RELATED,ESTABLISHED \
-j ACCEPT
對所有HTTP和HTTPS流量執(zhí)行相同的操作:
firewall-cmd --permanent --direct \
--add-rule ipv4 filter FORWARD 0 -i ens34 -o ens33 \
-p tcp -m multiport --dport 80,443 \
-m state --state NEW,RELATED,ESTABLISHED \
-j ACCEPT
對所有dns流量執(zhí)行相同的操作:
firewall-cmd --permanent --direct \
--add-rule ipv4 filter FORWARD 0 -i ens34 -o ens33 \
-p udp --dport 53 \
-m state --state NEW,RELATED,ESTABLISHED \
-j ACCEPT
還允許internal區(qū)域訪問public區(qū)域外的SMTP和SMTPS服務(wù)器:
firewall-cmd --permanent --direct \
--add-rule ipv4 filter FORWARD 0 -i ens34 -o ens33 \
-p tcp -m multiport --dport 25,465 \
-m state --state NEW,RELATED,ESTABLISHED
-j ACCEPT
開放ssh端口
firewall-cmd --permanent --direct \
--add-rule ipv4 filter FORWARD 0 -i ens34 -o ens33 \
-p tcp --dport 22 \
-m state --state NEW,RELATED,ESTABLISHED \
-j ACCEPT
記錄所有轉(zhuǎn)發(fā)流量的日志
firewall-cmd --permanent --direct \
--add-rule ipv4 filter FORWARD 0 -i enp34 -o enp33 \
-j LOG --log-prefix "forward_traffic "
最后一條默認(rèn)規(guī)則
firewall-cmd --permanent --direct 、
--add-rule ipv4 filter FORWARD 0 -i ens34 -o ens33 \
-j REJECT
配置完以上規(guī)則,我們重新加載firewalld
firewall-cmd --reload
查看所有iptable規(guī)則
firewall-cmd --direct --get-all-rules
如下圖所示

我們從internal區(qū)域的vm中測試,剛才用direct規(guī)則配置的防火墻,嘗試打開一個(gè)網(wǎng)站以及做一個(gè)簡單的路有跟蹤,一切如常工作,那么我們本篇direct配置示例就到這里。

后文更新
參考文章:
