防火牆之firewalld


本文轉載,以備查閱,僅僅在閱讀時根據自己的一些理解稍作修改。原文地址:http://www.excelib.com/article/286/show

你真的理解防火牆嗎

“防火牆”到底是什么

“防火牆”在我國最早是一種建築,他又叫“封火牆”,其主要作用就是防火,因為那時候的建築都是以木質結構為主,而且又非常密集,所以一個住宅着火就很容易傳播到鄰近的住宅,最初的防火牆就是在這種木質結構上塗上灰泥從而達到將火源隔斷的目的。

網絡中的防火牆來源於英文單詞“firewall”的翻譯,有時候也叫“網絡防火牆”,不過這個詞使用的並不是非常准確,這也就導致了對防火牆的普遍誤解。

一想到防火牆大家的第一印象大概就是“隔離”,而且很多防火牆的資料也是這么介紹的,比如“將內網和外網進行隔離”、“將本地電腦和外部網絡隔離”等等, 而且有時候還會配一張示意圖,圖中的防火牆就是一堵牆。以前學生在剛接觸防火牆的時候心里就產生了一些疑問:既然防火牆已經將網絡給隔斷了,那么正常的通信是怎么進行的呢?是可以穿牆而過還是需要從其他通道進入呢?而且,當時學生甚至認為防火牆是用來防病毒的!

其實這一切的根源都來自對“防火牆”這個詞本身的理解,實際上“網絡防火牆”所起的並不是牆的作用,而是門衛的作用,如果按門衛去理解很多問題就迎刃而解了。

牆和門衛有哪些區別呢?這個問題雖然看起來有些可笑,不過對於理解網絡防火牆還是有好處的。首先,牆所起的作用是隔斷,無論誰都過不去,但是門衛就不一樣 了,他的職能是檢查和判斷是否可以通過,只要符合條件就可以通過;其次,牆是死的,而門衛是活的,所以門衛還可以完成很多更加靈活的功能,比如有人要到A部門辦事,但A部門搬到新的辦公地址去了,這時門衛就可以告訴來人“你要去的部門換地方了,你到XXX去吧”,再比如有的人並不是要進去辦事,只是想從里邊穿過去抄近道,這種情況門 衛也能處理,但是牆是無論如何都辦不到的。

理解防火牆本質的好處

可能有的讀者會想:你這是在咬文嚼字,不就是個名詞嗎,理解不理解又有什么關系呢?會用不就行了?而且這么多年大家用的不也挺好的嘛!

其實並不是這樣,我們以前如果要使用一個防火牆一般都是先看他都具有哪些功能,其中我們能用到哪些,怎么去用,然后再去找文檔、找例子。。。。。。這其實是一 種被動的用法,因為這里我們其實是將防火牆當做一個新事物來學習和使用的(雖然我們一般剛開始都會將其理解為牆,但是慢慢會發現他跟牆的模型並不相符,所以就會將其當做一個新的事物來學習),但是理解了防火牆的本質就是門衛之后就不一樣了,這時我們在使用防火牆的時候首先就要想:我要給我的服務器(或者自 己的PC)找個門衛,這個門衛需要做什么,然后再去找防火牆、查具體某功能的配置方法等等,這樣就主動了。

不僅如此,在理解了其本質之后還有更大的好處,比如你想好了想找的“門衛”都需要有哪些功能之后又去找防火牆,然而卻發現沒有一款防火牆可以滿足你的需求,這時候創新的機會就來了!也就是說通過防火牆和門衛功能的類別更容易設計出更加合理和易用的防火牆。我們來看個例子,比如一個門衛應該可以有按時間段放行的功能,但是現有防火牆卻很少有這個功能,其實這個功能很多地方都是可以用得到的,比如每天要定時遠程備份一下日志,那么只要在每天在特定的時間段開放端口就行了,而不需要一直開着,當然這種需求可以通過定時任務很容易地解決,不過只要從“門衛”的角度去思考,這樣的需求還有很多。

真正好的創意其實是建立在扎實的基本功和對事物本質的深層次理解上的,而不是為了創新而創新出來的。

防火牆與殺毒軟件

對於不了解防火牆的用戶來說很多時候都分不清防火牆和殺毒軟件之間的關系,而且往往會認為防火牆就是用來防病毒的,其實這是對防火牆非常大的誤解,這也許跟大家心目中防火牆的“牆”、“保護”、“安全”等特征有關系,但是防火牆其實並不能防病毒。

我們上面說了,防火牆所起的是門衛的作用,不過這個門衛的邏輯非常簡單,他主要關心的只有兩樣東西:1、從哪來的2、到哪里去,別的東西他一概不管(實際上還 有一些東西,比如是有預約的——TCP,還是無預約的——UDP,如果是有預約的還會判斷是剛要去預約還是已經預約好了等內容)。而病毒是屬於所攜帶的內容方面的東西,這部分並不是門衛的職責范圍,而是應該有專人去負責,這就好像有人跟門衛說要去市場部,而且門衛所接到的指令是“所有到市場部的全部放行”,所以門衛就放行了,但是沒想到此人是到市場部去吵架的!不過這就不是門衛應該管的事情,而是保安所應該管的事情了。其實不僅如此,我們的防火牆這個“門 衛”即使見到來的人拿着刀、拿着槍,也一樣會放行,因為他只關心兩樣東西:從哪里來和到哪里去。

這種結構雖然“分工明確”,但是我們總會覺得這種門衛有點不近人情,至少算不上一個好門衛。那么能不能讓他包含查毒、防毒甚至殺毒的功能呢?當然沒問題,因為防火牆就是一個軟件,軟件都是人寫的, 只要我們把相應的功能給加進去就可以了,非常簡單!不過事實上並非如此,我們還拿門衛的例子來給大家解釋,因為門衛需要負責檢查所有進出的人,而要想知 道某個人是否攜帶了違禁物品(病毒)就需要對其進行收身,如果門衛要對所有人都進行收身,那么大家可以想象一下在上下班這種人流高峰期會是一種什么場景!而 且對於服務器來說一秒鍾就可能會有成千上萬的訪問,所以哪怕每次檢查多用一點點時間,累計起來就非常可怕了!而且以我們現在這種特征碼的檢查方式來說檢查病毒所用的並不是“一點點時間”,所以這種想法雖然技術上沒有問題,但是並不可行,至少從現在的技術來看是不可行的。

我們來總結一下,防火牆就像一個門衛,他的職能是負責讓不讓進出,而進去之后干什么那就不是他需要管的事情了,這應該是保安(殺毒軟件)或者其他相關部門的人所需要負責的。

 

理解了防火牆的本質之后再來學習、使用防火牆就容易了,不過對於Centos7新的防火牆firewalld來說還有一個很多人沒有真正理解透的概念,那就是zone,學生下節再給大家詳細介紹。

Firewalld的結構

firewalld簡介

Centos7中默認將原來的防火牆iptables升級為了firewalld,firewalld跟iptables比起來至少有兩大好處:

1、firewalld可以動態修改單條規則,而不需要像iptables那樣,在修改了規則后必須得全部刷新才可以生效;

2、firewalld在使用上要比iptables人性化很多,即使不明白“五張表五條鏈”而且對TCP/IP協議也不理解也可以實現大部分功能。

 

多知道點

iptables實際包含五張表

大部分iptables的資料都介紹說iptables包含四張表、五條鏈,不過實際上iptables還有第五張表——security表,但是這張表需要和selinux結合使用,而selinux雖然已經發布了十多年了但是直到現在還有很多人對他的理解不夠透徹,甚至有很多人會將其關閉!

其實selinux的設計理念在安全上來說是非常優秀的,而且理解了其設計理念之后再去使用也沒那么復雜,只不過其內置的規則是非常復雜的,等有機會學生專門給大家介紹一下selinux,現在還回到iptables的五張表,他們分別是filter、nat、mangle、raw和security。

filter表就是我們最常使用的過濾表;nat表主要用於數據包轉發,比如局域網的電腦如果想連接互聯網,那么就可以使用nat給轉發一下;mangle表的規則可以對數據包進行修改,比如修改ttl值等;raw表主要是為了提高效率使用的,raw本身的含義是指“原生的”、“未經過加工的”,符合raw表所對應規則的數據包將會跳過一些檢查,這樣就可以提高效率,當然,raw表的優先級也是最高的;security是跟selinux相關的MAC模式的安全過濾。

當然,這些內容大家了解一下就行,即使不理解也可以使用將firewalld使用的很好。

 

firewalld和iptables的關系

firewalld自身並不具備防火牆的功能,而是和iptables一樣需要通過內核的netfilter來實現,也就是說firewalld和iptables一樣,他們的作用都是用於維護規則,而真正使用規則干活的是內核的netfilter,只不過firewalld和iptables的結構以及使用方法不一樣罷了。

 

  • 規則生效的方式不同:使用  iptables service,每一個單獨更改意味着清除所有舊有的規則和從 /etc/sysconfig/iptables里讀取所有新的規則(靜態防火牆),然而使用 firewalld 時卻不會再清除所有規則,僅僅運行與原先不同的新的規則。因此,firewalld 可以在運行時改變設置而不丟失現行連接(動態防火牆)。

從上圖可以看到,iptables服務和firewalld都是通過iptables命令與內核的netfilter進行交互的。在centos7中,我們仍然可以使用iptables命令來管理我們的防火牆。唯一不同的是當我們重啟服務器或重啟firewalld時,iptables命令管理的規則不會自動加載,反而會被firewalld的規則代替。

 

firewalld的結構

我們這里所說的結構並不是firewalld軟件的結構,而是配置文件的結構。

在具體介紹firewalld配置文件結構之前學生先來給大家介紹一下firewalld的配置模式,firewalld的配置模式設計的非常巧妙,而且這種設計思路也非常值得我們借鑒和學習。

firewalld的配置模式

firewalld的配置文件以xml格式為主(主配置文件firewalld.conf例外),他們有兩個存儲位置

/etc/firewalld/
/usr/lib/firewalld/

使用時的規則是這樣的:當需要一個文件時firewalld會首先到第一個目錄中去查找,如果可以找到,那么就直接使用,否則會繼續到第二個目錄中查找。換而言之,/etc/firewalld/中的配置會覆蓋/usr/lib/firewalld/中的配置。

 

firewalld的這種配置文件結構的主要作用是這樣的:在第二個目錄中存放的是firewalld給提供的通用配置文件,如果我們想修改配置,那么可以copy一份到第一個目錄中,然后再進行修改。這么做有兩個好處:首先我們日后可以非常清晰地看到都有哪些文件是我們自己創建或者修改過的,其次,如果想恢復firewalld給提供的默認配置,只需要將自己在第一個目錄中的配置文件刪除即可,非常簡單,而不需要像其他很多軟件那樣在修改之前還得先備份一下,而且時間長了還有可能忘掉之前備份的是什么版本。

當然,這種配置模式也並不是firewalld的首創,在其他很多地方也都有用到,比如java中用於記錄日志的logback也是這種模式,他在查找配置文件時會首先在根目錄下找logback-test.xml文件,如果可以找到就直接使用,如果找不到就會接着找logback.xml文件,如果還找不到就會使用自己包里邊自帶的配置文件,這樣使用起來就非常方便了,比如我們可以把logback-test.xml和logback.xml兩個文件都創建出來,在開發機上使用logback-test.xml文件,然后在往服務器部署的時候直接將其刪掉就可以了!當然還有很多產品也使用了這種配置模式,spring的很多子框架也使用的是這種模式,比如spring MVC中的組件配置也是這樣,如果沒有配置的話就會使用默認的配置,當然,我們這里不是在講Spring MVC所以就不展開了,如果想了解更多細節大家可以參考學生編寫的《看透Spring MVC:源代碼分析與實踐》一書。

配置文件結構

firewalld的配置文件結構非常簡單,主要有兩個文件和三個目錄:

文件:firewalld.conf、lockdown-whitelist.xml

目錄:zones、services、icmptypes

另外,如果使用到direct,還會有一個direct.xml文件。我們要注意,在保存默認配置的目錄“/usr/lib/firewalld/”中只有我們這里所說的目錄,而沒有firewalld.conf、lockdown-whitelist.xml和direct.xml這三個文件,也就是說這三個文件只存在於“/etc/firewalld/”目錄中。

下面學生分別來給大家介紹一下這些文件和目錄的作用

  • firewalld.conf:firewalld的主配置文件,是鍵值對的格式,不過非常簡單,只有五個配置項

    • DefaultZone:默認使用的zone,關於zone學生稍后給大家詳細介紹,默認值為public;

    • MinimalMark: 標記的最小值,linux內核會對每個進入的數據包都進行標記,目的當然是為了對他們進行區分,比如學生在前面給大家補充iptables五張表相關的內容時候介紹說符合raw表規則的數據包可以跳過一些檢查,那么是怎么跳過的呢?這里其實就是使用的標記,當然對數據包的標記還有很多作用。這里所設置的 MinimalMark值就是標記的最小值,默認值為100,一般情況下我們不需要對其進行修改,但是如果我們有特殊需要的時候就可以通過對其進行修改來告訴linux所使用標記的最小值了,比如我們需要給符合某條件的數據包標記為123,這時候為了防止混淆就需要將MinimalMark設置為一個大於123的值了;

    • CleanupOnExit:這個配置項非常容易理解,他表示當退出firewalld后是否清除防火牆規則,默認值為yes;

    • Lockdown: 這個選項跟D-BUS接口操作firewalld有關,firewalld可以讓別的程序通過D-BUS接口直接操作,當Lockdown設置為yes的時候就可以通過lockdown-whitelist.xml文件來限制都有哪些程序可以對firewalld進行操作,而當設置為no的時候就沒有限制了,默認值為 no;

    • IPv6_rpfilter:其功能類似於rp_filter,只不過是針對ipv6版的,其作用是判斷所接受到的包是否是偽造的,檢查方式主要是通過路由表中的路由條目實現的,更多詳細的信息大家可以搜索uRPF相關的資料,這里的默認值為yes。

  • lockdown-whitelist.xml:當Lockdown為yes的時候用來限制可以通過D-BUS接口操作firewalld的程序

  • direct.xml:通過這個文件可以直接使用防火牆的過濾規則,這對於熟悉iptables的用戶來說會非常順手,另外也對從原來的iptables到firewalld的遷移提供了一條綠色通道

  • zones:保存zone配置文件

  • services:保存service配置文件

  • icmptypes:保存和icmp類型相關的配置文件

 

在firewalld的使用中最基礎也是最重要的就是對zone的理解,不過現在還普遍理解的不是很透徹,下面學生就來給大家詳細介紹一下zone到底是什么。

zone

firewalld默認提供了九個zone配置文件:block.xml、dmz.xml、drop.xml、external.xml、home.xml、internal.xml、public.xml、trusted.xml、work.xml,他們都保存在“/usr/lib/firewalld/zones/”目錄下。這些zone之間是什么關系?他們分別適用用哪些場景呢?

為了弄明白這些問題大家需要先明白zone的本質含義。學生在上一節給大家介紹防火牆時說過防火牆就相當於一個門衛,門衛對具體某個來訪的人判斷是否應該放行是依靠規則來判斷的,而我們這里的zone其實就是一套規則集,或者說是一套判斷的方案。

理解了這層含義firewalld就容易了,比如上面的九個zone其實就是九種方案,而且起決定作用的其實是每個xml文件所包含的內容,而不是文件名,所以大家不需要對每種zone(每個文件名)的含義花費過多的精力,比如trusted這個zone會信任所有的數據包,也就是說所有數據包都會放行,但是public這個zone只會放行其中所配置的服務,其他的一律不予放行,其實我們如果將這兩個文件中的內容互換一下他們的規則就換過來了,也就是public這個zone會放行所有的數據包,下面我們來看一下這兩個文件的內容

public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer.
Only selected incoming connections are accepted.</description> <service name="ssh"/> <service name="dhcpv6-client"/> </zone>

 trusted.xml

<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <short>Trusted</short>
  <description>All network connections are accepted.</description>
</zone>

我們要特別注意trusted.xml中zone的target,就是因為他設置為了ACCEPT,所以才會放行所有的數據包,而public.xml中的zone沒有target屬性,這樣就會默認拒絕(reject)通過,所以public這個zone(這種方案)只有其中配置過的服務才可以通過。

其他的zone大家可以自己打開xml文件來看一下,這里學生就不一一介紹了,關於zone配置文件的詳細結構及含義后面學生再給大家進行講解,下面學生再給大家介紹一下firewalld中的service。

附錄:9個區域配置文件

drop.xml

 

<?xml version="1.0" encoding="utf-8"?>
<zone target="DROP">
  <short>Drop</short>
  <description>Unsolicited incoming network packets are dropped. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
</zone>

 

block.xml

<?xml version="1.0" encoding="utf-8"?>
<zone target="%%REJECT%%">
  <short>Block</short>
  <description>Unsolicited incoming network packets are rejected. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
</zone>

public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
</zone>

external.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>External</short>
  <description>For use on external networks. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <masquerade/>
</zone>

dmz.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>DMZ</short>
  <description>For computers in your demilitarized zone that are publicly-accessible with limited access to your internal network. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
</zone>

work.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Work</short>
  <description>For use in work areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
</zone>

home.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Home</short>
  <description>For use in home areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="mdns"/>
  <service name="samba-client"/>
  <service name="dhcpv6-client"/>
</zone>

internal.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Internal</short>
  <description>For use on internal networks. You mostly trust the other computers on the networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="mdns"/>
  <service name="samba-client"/>
  <service name="dhcpv6-client"/>
</zone>

trusted.xml

<?xml version="1.0" encoding="utf-8"?>
<zone target="ACCEPT">
  <short>Trusted</short>
  <description>All network connections are accepted.</description>
</zone>

 

service

service是firewalld中另外一個非常重要的概念,不過其含義是非常簡單的。學生還是拿門衛的例子來給大家做解釋,在iptables的時代我們給門衛下達規則時需要告訴他“所有到22號樓的人全部予以放行”、“所有到80號樓的人全部予以放行”等等,不過到了firewalld的時代就不需要這樣了,而是可以直接下達像“到銷售部的全部予以放行”這樣的命令,然后門衛再一查發現銷售部在80號樓,那么所有到80號樓的人門衛就都會放行了。我們這里的樓牌號和端口號相對應,部門名和服務名相對應,這樣大家應該就可以理解service的作用了。

從端口號改為服務名主要有兩個好處:首先是使用服務名配置的語義清晰,不容易出錯;其次在對某個服務的端口號進行修改的時候只需要修改相應的service文件就可以了,而不需要再修改防火牆方案——zone。這其實跟DNS將ip地址和域名關聯了起來是一樣的道理。下面學生再來給大家介紹一下service的配置文件。

service配置文件的命名規則是<服務名>.xml,比如ssh的配置文件是ssh.xml,http的配置文件是http.xml等,他們默認保存在“/usr/lib/firewalld/services/”目錄下,常見的服務其中都可以找到,如果我們想修改某個服務的配置,那么可以復制一份到“/etc/firewalld/services/”目錄下然后進行修改就可以了,要想恢復默認配置直接將我們自己的配置文件刪除就可以了。我們來看一下ssh服務的ssh.xml文件

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>SSH</short>
  <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
  <port protocol="tcp" port="22"/>
</service>

可以看到這里配置了tcp的22號端口,所以將ssh服務配置到所使用的zone(默認public)中后tcp的22號端口就開放了。如果我們想將ssh的端口修改為222,那么只需要將ssh.xml復制一份到“/firewalld/services/”中,然后將端口號修改為222就可以了。當然直接修改“/usr/lib/firewalld/services/”中的配置文件也可以實現,但是強烈建議不要那么做,原因相信大家都明白。 

明白原理之后使用起來就可以非常靈活了,比如我們將“/etc/firewalld/services/ssh.xml”文件復制一份到“/etc/firewalld/services/”中,然后將名字改為abc.xml,並且將abc這個服務配置到所使用的zone中,這時22端口就會開放。也就是說在zone中所配置的服務其實跟實際的服務並不存在直接聯系,而是和相應配置文件中配置的內容有關系。

配置方法

firewalld的配置方法主要有三種:firewall-config、firewall-cmd和直接編輯xml文件,其中firewall-config是圖形化工具,firewall-cmd是命令行工具,而對於linux來說大家應該更習慣使用命令行方式的操作,所以firewall-config我們就不給大家介紹了。具體的配置方法學生在下一節給大家進行介紹。

Firewalld常用命令

Firewalld防火牆中所使用到的命令可以分為三大類:安裝卸載、維護和策略操作。

安裝

在Centos7中默認已經安裝了firewalld,如果需要自行安裝,可以直接使用yum安裝

[root@excelib.com ~]# yum install firewalld

如果需要使用圖形化配置工具還需要安裝firewall-config

[root@excelib.com ~]# yum install firewall-config

這樣firewalld就安裝完成了,不過要注意firewalld跟iptables不能同時使用,所以在使用firewalld之前首先需要將iptables停用。

維護命令

firewalld的維護相對來說是非常簡單的,其命令主要分為三大類:啟動停止和查詢狀態、設置開機自動啟動以及更新規則。

啟動停止和查詢狀態

在Centos7中默認將原來的服務管理工具service升級為了systemctl,其實原來的service只是一個腳本執行工具,而systemctl的功能非常強大,關於systemctl的詳細用法大家可以閱讀linux中國的一篇文章,地址是:https://linux.cn/article-5926-1.html,這篇文章寫的非常詳細,所以學生就不再給大家做補充了,下面來說一說怎么用它來操作firewalld。

啟動

[root@excelib.com ~]# systemctl start firewalld

停止

[root@excelib.com ~]# systemctl stop firewalld

重啟

[root@excelib.com ~]# systemctl restart firewalld

查詢狀態

[root@excelib.com ~]$ systemctl status firewalld


另外,對於firewalld來說還可以使用自身的firewall-cmd工具來查詢運行狀態

[root@excelib.com ~]$ firewall-cmd --state

 

設置開機自動啟動

設置開機自動啟動也是使用systemctl來操作的,命令如下

啟用開機自動啟動 

[root@excelib.com ~]$ systemctl enable firewalld

禁用開機自動啟動

[root@excelib.com ~]$ systemctl disable firewalld

查看自動啟動狀態

[root@excelib.com ~]$ systemctl is-enabled firewalld

當然,systemctl的這些命令不只適用於firewalld,也適用於其他服務,使用時只要將firewalld換成相應服務的名稱就可以了。

 

更新規則

直接使用firewall-cmd修改的規則是不需要更新就可以直接生效的,但是如果加了--permanent參數,或者直接編輯xml文件之后就需要我們手動reload了,firewall-cmd提供了兩個更新規則的參數:--reload和--complete-reload,前者只是更新需要更新規則,而且更新的過程中不會影響現有的連接,而后者在更新時會將所有的規則清除掉然后重建,而且為了安全考慮,在更新之前首先會將策略設置為DROP,等更新完成之后再恢復為ACCEPT,這樣就會對現有連接造成影響,所以如果沒有特殊需求我們應該盡量使用前者。具體命令如下 

[root@excelib.com ~]# firewall-cmd --reload
[root@excelib.com ~]# firewall-cmd --complete-reload 

策略操作

對於firewalld來說最重要的就是策略操作了,策略操作主要有三種方法:使用firewall-config操作、使用firewall-cmd操作和直接編輯xml文件,學生在上節已經給大家介紹過了,firewall-config是圖形化工具,firewall-cmd是命令行工具,我們這里主要以命令行工具為主來給大家介紹。

firewall-cmd中關於規則的命令非常多,如果在這里全部列出來再給大家解釋一遍應該效果也不會太好,所以學生在后面講到具體相關內容時再給大家講相應的命令,比如講到zone的時候給大家介紹跟zone相關的命令,這樣大家更容易理解和記憶。

firewall-cmd中的命令雖然非常多,但是有四大類使用頻率非常高的命令:

  --add-xxx

  --remove-xxx

  --query-xxx

  --get-xxx

  --list-xxx

這里前兩個非常容易理解,一個是添加一個是刪除,而后三個從名字上就不太容易區分了,下面學生給大家解釋一下。

  • --query-xxx主要用於布爾值的查詢,比如

[root@excelib.com ~]$ firewall-cmd --zone=public --query-service=ssh
  • --get-xxx主要用於獲取特定的內容,比如這個命令用於查詢在public這個zone中是否包含ssh這個服務。
[root@excelib.com ~]$ firewall-cmd --get-zones

這樣就可以獲取到預設的zones,默認情況下返回結果為

block dmz drop external home internal public trusted work
  • --list-xxx主要用於按一定條件進行查詢(不過有的list命名也不需要條件),比如 
[root@excelib.com ~]$ firewall-cmd --zone=public --list-services

  這個命令可以返回public這個zone中所包含的services。

query還是比較容易理解的,但是get和list從字面上並不容易區分,剛開始學生以為get命令用於獲取單個結果,list用於獲取多個結果,但后來發現並不是這樣。當然,我們在使用的時候按照文檔中的說明來使用就可以了。

 

另外,在firewall-cmd中有一個比較特殊的參數:--permanent他表示是否將修改后的規則保存下來,如果不加這個參數,那么所做的修改當時會立即生效,但是在firewalld重啟之后就會丟失,而加上這個參數后所做的修改就會永久保存下來,不過這時的修改不會立即生效而是需要reload后才可以生效。其實這個也非常容易理解,當不加--permanent修改規則時firewalld會實際修改運行時的規則,而如果加了這個參數firewalld其實是去修改的xml配置文件,和我們直接編輯xml文件一樣,所以就需要reload才可以生效。

Firewalld的panic模式

Firewalld有一種Panic模式,Panic的單詞含義為“恐慌”、“驚慌”,在firewalld中他表示當發生緊急情況(比如遭到攻擊)時啟用的一種“禁行模式”,啟用這種模式后所有的進包和出包都會被丟棄,和panic模式相關的有三個命令

[root@excelib.com ~]# firewall-cmd --panic-on [root@excelib.com ~]# firewall-cmd --panic-off [root@excelib.com ~]# firewall-cmd --query-panic

這三個命令很容易理解,第一個是啟用panic模式,也就是“禁行模式”,第二個是禁用panic模式,第三個是查詢是否已啟用panic模式。

當啟用了panic模式后所有的進包和出包都會被丟棄,不過如果對於原來已經建立的連接並不會馬上斷開,只是雙方不能進行通信了而已,當達到設置的最長不活動(inactivity)周期后才會斷開,而如果在斷開前將panic模式關閉的話連接就不會受影響。

因為啟用panic模式后會丟棄所有進包和出包,所以使用時要格外謹慎,另外,如果是使用的ssh連接的話,啟動panic模式后ssh的連接也會被斷開(准確來說是不可通信了),這時更加需要注意。

多知道點

firewall-cmd的本質

大家現在應該對firewall-cmd命令已經比較熟悉的,但是他的本質到底是什么呢?學生在這里給大家介紹一下。

firewall-cmd其實是一個位於/usr/bin目錄下的Python腳本,大家如果想了解firewall-cmd命令的具體的細節而且又熟悉Python語言的話就可以直接打開這個文件進行代碼閱讀。

另外,這個命令有一個對於安全來說非常重要但是又很不容易引起注意的問題,首先我們來看一下這個腳本文件的屬性

[root@excelib.com~]# ll /usr/bin/firewall-cmd -rwxr-xr-w. 1 root root 62012 Nov 20 20:35 /usr/bin/firewall-cmd

 大家可以看到這里的權限是755,也就是說所有用戶都可以執行該命令,當然,這么設計主要是為了學生后面要給大家介紹的使用其他程序通過D-BUS接口來操作firewalld有關,而且在前面給大家說過可以通過whitelist來設置,不過只有將Lockdown配置為yes后whitelist才會生效,而且默認配置為no,也就是說默認情況下所有程序(用戶)都可以執行firewall-cmd命令,這當然是不安全的,如果大家不需要使用其他程序對其進行操作的話可以直接將其權限改為750,這樣更加安全

[root@excelib.com~]# chmod 750 /usr/bin/firewall-cmd

用活firewalld防火牆中的zone

firewalld中zone的含義學生前面已經給大家介紹過了,說白了一個zone就是一套規則集。可是什么時候該用哪個zone、每個zone中的規則具體是怎么設置呢?下面學生就來給大家詳細講解。

名詞解釋

在具體介紹zone之前學生先給大家介紹幾個相關的名詞,因為如果不理解這幾個名詞zone就無從入手。

  • target:目標,這個前面學生也已經給大家介紹過了,可以理解為默認行為。即當某個zone被設定為默認zone時,進入此zone中未匹配到任何規則到的報文將應用此target行為。有3個可選值:default、ACCEPT、%%REJECT%%、DROP,如果缺省則為%%REJECT%%。

  • service:這個在前面學生已經給大家解釋過了,他表示一個服務

  • port:端口,使用port可以不通過service而直接對端口進行設置

  • interface:接口,可以理解為網卡

  • source:源地址,可以是ip地址也可以是ip地址段

  • icmp-block:icmp報文阻塞,可以按照icmp類型進行設置

  • masquerade:ip地址偽裝,也就是按照源網卡地址進行NAT轉發

  • forward-port:端口轉發

  • rule:自定義規則

哪個zone在起作用

我們知道每個zone就是一套規則集,但是有那么多zone,對於一個具體的請求來說應該使用哪個zone(哪套規則)來處理呢?這個問題至關重要,如果這點不弄明白其他的都是空中樓閣,即使規則設置的再好,不知道怎樣用、在哪里用也不行。

對於一個接受到的請求具體使用哪個zone,firewalld是通過三種方法來判斷的:

1、source,也就是報文的源地址(如果某個zone中定義了source,那么這個zone會被優先啟用)

2、interface,接收請求的網卡(如果某個zone中定義了interface,那么這個zone會被第二優先啟用)

3、firewalld.conf中配置的默認zone(如果沒有以上兩種情況或者以上兩個情況都未匹配到的報文,會被默認zone處理)

這三個的優先級按順序依次降低,也就是說如果按照source可以找到就不會再按interface去查找,如果前兩個都找不到才會使用第三個,也就是學生在前面給大家講過的在firewalld.conf中配置的默認zone。此外,我們可以通過firewall-cmd --get-active-zones命令來 查看所有生效的zone(注意不會顯示默認zone),后面我們會介紹到。

好了,我們現在知道其原理了,下面學生就給大家介紹每一種方式所對應的配置方法。

配置source

source是在zone的xml文件中配置的,其格式為

<zone>
    <source address="address[/mask]"/>
</zone>

只要我們將source節點放入相應的zone配置文件中就可以了,節點的address屬性就是源地址,不過我們要注意相同的source節點只能在一個zone中進行配置,不能同時在多個zone中配置,也就是說同一個源地址只能對應於一個zone,另外,直接編輯xml文件之后還需要reload才可以起作用,這些學生前面已經給大家講過,這里就不再重述了。

另外,我們當然也可以使用firewall-cmd命令進行配置,這里主要有五個相關命令(參數)

firewall-cmd [--permanent] [--zone=zone] --list-sources
firewall-cmd [--permanent] [--zone=zone] --query-source=source[/mask]
firewall-cmd [--permanent] [--zone=zone] --add-source=source[/mask]
firewall-cmd               [--zone=zone] --change-source=source[/mask]
firewall-cmd [--permanent] [--zone=zone] --remove-source=source[/mask]

我們分別來介紹一下

  • --list-sources:用於列出指定zone的所有綁定的source地址

  • --query-source:用於查詢指定zone是否跟指定source地址進行了綁定

  • --add-source:用於將一個source地址綁定到指定的zone(只可綁定一次,第二次綁定到不同的zone會報錯)

  • --change-source:用於改變source地址所綁定的zone,如果原來沒有綁定則進行綁定,這樣就跟--add-source的作用一樣了

  • --remove-source:用於刪除source地址跟zone的綁定

 另外,大家可以看到上面的命令中有兩個可選參數:--permanent和--zone,--permanent學生在前面已經給大家介紹過了,表示是否存儲到配置文件中(如果存儲到配置文件中這不會立即生效),--zone用於指定所要設置的zone,如果不指定則使用默認zone。

我們來看個例子

[root@excelib.com ~]# firewall-cmd --zone=drop --change-source=1.2.3.4

這樣就可以將1.2.3.4綁定到drop這個zone中了,如果沒有修改過drop規則的話所有來自1.2.3.4這個ip的連接將會被drop。

至於什么時候使用add什么時候使用change,如果我們就是想將某源地址(已經綁定在其他zone時)綁定到指定的zone那么最好使用change;而如果想在源地址沒綁定的時候進行綁定,如果已經綁定過則不綁定那么就使用add。

換而言之:

如果源地址沒有在任何zone中綁定,此時change和add的作用是一樣的,都是綁定到指定zone中;如果源地址已經在其他zone中綁定了,想把該源地址從這個zone中刪除然后再綁定到指定的zone中,此時使用change;如果使用add,該源地址已經綁定在某個zone的情況下是不重新綁定到指定zone中。

 

配置interface

interface有兩個可以配置的位置:1、zone所對應的xml配置文件2、網卡配置文件(也就是ifcfg-*文件)。

第一種配置跟source大同小異,學生這里就不再細述了,interface在zone配置文件中的節點為

<zone>
    <interface name="string"/>
</zone>

相關的firewall-cmd命令為

firewall-cmd [--permanent] [--zone=zone] --list-interfaces
firewall-cmd [--permanent] [--zone=zone] --add-interface=interface
firewall-cmd        [--zone=zone] --change-interface=interface
firewall-cmd [--permanent] [--zone=zone] --query-interface=interface
firewall-cmd [--permanent] [--zone=zone] --remove-interface=interface

另外,我們還可以在網卡配置文件中進行配置,比如可以在ifcfg-em1文件中添加下面的配置

ZONE=public

這行配置就相當於下面的命令

[root@excelib.com ~]# firewall-cmd --zone=public --change-interface=em1

這樣配置之后來自em1的連接就會使用public這個zone進行管理(如果source匹配了其他的zone除外)。

配置默認zone

默認zone的配置學生前面已經給大家介紹過了,他是通過firewalld.conf配置文件的DefaultZone配置項來配置的,當然也可以使用firewall-cmd命令來配置

firewall-cmd --set-default-zone=zone

另外還可以通過--get-default-zone來獲取默認zone的值。

查看當前起作用的zone

我們可以使用下面的命令來查看當前所有起作用的zone

firewall-cmd --get-active-zones

這個命令會返回所有綁定了source、interface以及默認的zone,並會說明在什么情況下使用。

反向查詢

firewalld還給我們提供了反向查詢的命令,也就是根據source或者interface查詢所對應的zone,其命令如下

firewall-cmd --get-zone-of-interface=interface firewall-cmd --get-zone-of-source=source[/mask]

有了這兩個命令我們就可以檢查我們的設置是否正確了。

 

好了,現在大家就明白了一個接收到的請求具體使用哪個zone了,那么zone具體的規則怎么配置呢?下面學生就來給大家詳細介紹。

zone規則配置

target

zone規則中首先最重要的是target的設置,他默認可以取四個值:default、ACCEPT、%%REJECT%%、DROP,其含義很容易理解,這里學生就不介紹了,需要說明的是,缺省時默認的target為DROP,下面來說怎么配置。

在xml文件中target是zone節點的一個屬性,比如drop.xml中為

<zone target="DROP">

block.xml中為

<zone target="%%REJECT%%">

如果使用firewall-cmd命令來操作,命令如下

firewall-cmd --permanent [--zone=zone] --get-target
firewall-cmd --permanent [--zone=zone] --set-target=target

我們要特別注意,這里的--permanent不是可選的,也就是說使用firewall-cmd命令也不可以讓他直接生效,也需要reload才可以。

service

service學生在前面也已經給大家介紹過了,他的配置和我們上面所介紹的source基本相同,只不過同一個service可以配置到多個不同的zone中,當然也就不需要--change命令了,他在zone配置文件中的節點為

<zone>
    <service name="string"/>
</zone>

相應的配置命令為

 

firewall-cmd [--permanent] [--zone=zone] --list-services
firewall-cmd [--permanent] [--zone=zone] --add-service=service [--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-service=service
firewall-cmd [--permanent] [--zone=zone] --query-service=service

 

具體每個命令的含義大家對照上面的source很容易就理解了,不過這里的--add命令中多了一個--timeout選項,學生這里給大家介紹一下。

--add-service中的--timeout的含義是這樣的:添加一個服務,但是不是一直生效而是生效一段時間,過期之后自動刪除。

這個選項非常有用,比如我們想暫時開放一個端口進行一些特殊的操作(比如遠程調試),等處理完成后再關閉,不過有時候我們處理完之后就忘記關閉了,而現在的--timeout選項就可以幫我們很好地解決這個問題,我們在打開的時候就可以直接設置一個時間,到時間之后他自動就可以關閉了。另外,這個參數還有更有用的用法,學生會在下面給大家講到。當然--timeout和--permanent是不可以一起使用的。

另外,這里我們主要講的是怎么在zone中使用service,而service自己的配置學生下節再給大家詳細介紹。

port

port是直接對端口的操作,他和service非常相似,所以這里也不詳細介紹了,port在zone中的配置節點為

<zone>
    <port port="portid[-portid]" protocol="tcp|udp"/>
</zone>

相應命令為

firewall-cmd [--permanent] [--zone=zone] --list-ports firewall-cmd [--permanent] [--zone=zone] --add-port=portid[-portid]/protocol [--timeout=seconds] firewall-cmd [--permanent] [--zone=zone] --remove-port=portid[-portid]/protocol firewall-cmd [--permanent] [--zone=zone] --query-port=portid[-portid]/protocol

icmp-block

icmp-block是按照icmp的類型進行設置阻塞,比如我們不想接受ping報文就可以使用下面的命令來設置

[root@excelib.com ~]# firewall-cmd --add-icmp-block=echo-request

當然,如果需要長久保存就需要加--permanent選項,不過那樣就需要reload才能生效。

icmp-block在zone配置文件中的節點為

<zone>
    <icmp-block name="string"/>
</zone>

相應操作命令為

firewall-cmd [--permanent] [--zone=zone] --list-icmp-blocks firewall-cmd [--permanent] [--zone=zone] --add-icmp-block=icmptype [--timeout=seconds] firewall-cmd [--permanent] [--zone=zone] --remove-icmp-block=icmptype firewall-cmd [--permanent] [--zone=zone] --query-icmp-block=icmptype

masquerade

masquerade大家應該都比較熟悉,其作用就是ip地址偽裝,也就是NAT轉發中的一種,具體處理方式是將接收到的請求的源地址設置為轉發請求網卡的地址,這在路由器等相關設備中非常重要,比如大家很多都使用的是路由器連接的局域網,而想上互聯網就得將我們的ip地址給修改一下,要不大家都是192.168.1.XXX的內網地址,那請求怎么能正確返回呢?所以在路由器中將請求實際發送到互聯網的時候就會將請求的源地址設置為路由器的外網地址,這樣請求就能正確地返回給路由器了,然后路由器再根據記錄返回給我們發送請求的主機了,這就是masquerade。

其設置非常簡單,masquerade在zone中是一個沒有參數(屬性)的節點

<zone>
    <masquerade/>
</zone>

操作命令為

firewall-cmd [--permanent] [--zone=zone] --add-masquerade [--timeout=seconds]
firewall-cmd [--permanent] [--zone=zone] --remove-masquerade
firewall-cmd [--permanent] [--zone=zone] --query-masquerade

forward-port

這項也非常容易理解,他是進行端口轉發的,比如我們要將在80端口接收到tcp請求轉發到8080端口可以使用下面的命令

[root@excelib.com ~]# firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080

forward-port還支持范圍轉發,比如我們還可以將80到85端口的所有請求都轉發到8080端口,這時只需要將上面命令中的port修改為80-85即可。

在zone配置文件中節點如下

<zone>
    <forward-port port="portid[-portid]" protocol="tcp|udp" [to-port="portid[-portid]"] [to-addr="ipv4address"]/>
</zone>

相關操作命令如下

firewall-cmd [--permanent] [--zone=zone] --list-forward-ports firewall-cmd [--permanent] [--zone=zone] --add-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]][--timeout=seconds] firewall-cmd [--permanent] [--zone=zone] --remove-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]] firewall-cmd [--permanent] [--zone=zone] --query-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]]

rule

rule可以用來定義一條復雜的規則,其在zone配置文件中的節點定義如下

<zone>
    <rule [family="ipv4|ipv6"]> [ <source address="address[/mask]" [invert="bool"]/> ] [ <destination address="address[/mask]" [invert="bool"]/> ] [ <service name="string"/> | <port port="portid[-portid]" protocol="tcp|udp"/> | <protocol value="protocol"/> | <icmp-block name="icmptype"/> | <masquerade/> | <forward-port port="portid[-portid]" protocol="tcp|udp" [to-port="portid[-portid]"] [to-addr="address"]/> ] [ <log [prefix="prefixtext"] [level="emerg|alert|crit|err|warn|notice|info|debug"]/> [<limit value="rate/duration"/>] </log> ] [ <audit> [<limit value="rate/duration"/>] </audit> ] [ <accept/> | <reject [type="rejecttype"]/> | <drop/> ] </rule>
</zone>

可以看到這里一條rule的配置的配置項非常多,比zone本身還多出了destination、log、audit等配置項。其實這里的rule就相當於使用iptables時的一條規則。rule的操作命令如下

firewall-cmd [--permanent] [--zone=zone] --list-rich-rules firewall-cmd [--permanent] [--zone=zone] --add-rich-rule='rule' [--timeout=seconds] firewall-cmd [--permanent] [--zone=zone] --remove-rich-rule='rule' firewall-cmd [--permanent] [--zone=zone] --query-rich-rule='rule'

這里的參數'rule'代表一條規則語句,語句結構就是直接按照上面學生給大家的節點結構去掉尖括號來書寫就可以了,比如要設置地址為1.2.3.4的source就可以寫成source address="1.2.3.4",也就是直接寫標簽名,然后跟着寫屬性就可以了,我們來看個例子

[root@excelib.com ~]# firewall-cmd --add-rich-rule='rule family="ipv4" source address="1.2.3.4" drop'

這條規則就會將1.2.3.4這個源地址的連接全部給drop掉。

使用rule結合--timeout我們可以實現一些非常好玩和有用的功能,比如我們可以寫個自動化腳本,當發現有異常的連接時就可以添加一條rule將其相應的地址drop掉,而且還可以使用--timeout給設置個時間段,過了之后再自動開放!

用活firewalld防火牆之service

前面學生已經給大家介紹了在firewalld中service的概念以及在zone中怎么使用service,但是service本身怎么配置我們還沒講,本節學生就來給大家介紹service本身的配置。

service配置文件

service相對於zone來說結構要簡單的多,其整體配置文件結構如下

<service [version="string"]> [<short>short description</short>] [<description>description</description>] [<port [port="portid[-portid]"] protocol="protocol"/>] [<module name="helper"/>] [<destination ipv4="address[/mask]" ipv6="address[/mask]"/>] </service>

firewall-cmd分別提供了兩個命令來創建和刪除service

firewall-cmd --permanent --new-service='service' firewall-cmd --permanent --delete-service='service'

不過我們如果直接編輯xml文件應該更簡單,前面學生給大家介紹service概念的時候已經給大家介紹過了操作service配置文件的方法了,大部分服務在“/usr/lib/firewalld/services/”目錄下都可以找到,不過我們不要直接修改而要復制一份到“/etc/firewalld/services/”中然后再進行修改,當然如果想自己創建一個服務也可以直接在“/etc/firewalld/services/”目錄中創建,另外,更好的做法是在“/usr/lib/firewalld/services/”中找一個類似的服務復制一份到“/etc/firewalld/services/”目錄中,然后修改文件名和其中的內容。

下面學生對service中的每個配置項給大家解釋一下

version

version是service節點的一個可選屬性,用於表示service的版本。

short

short在zone、icmptype等配置文件中也存在,其作用是簡介,主要是讓我們對所配置的內容有所了解,類似於注釋的作用。

description

作用跟short相同,不過描述信息更加詳細。

port

服務所對應的端口,這項是service中非常重要的一個配置項,大部分service主要就是對port進行綁定的,當一個service綁定了指定端口之后,該端口接收到的連接就會當成這個service,然后到所對應的zone中去查詢規則,從而判斷是否可以放行。

一個service中可以配置多個port節點,這在有的時候是非常有用的,比如

port節點有兩可個配置的屬性:port和protocol

port屬性

port用來配置所使用的端口號,可以是單個端口也可以是一個端口段,比如port=100-105表示100到105之間的端口號,另外,port屬性是個可選屬性,可以不進行設置。

protocol屬性

protocol屬性用於指定所對應的協議,如果port屬性不為空,那么protocol應該設置為tcp或者udp,如果port屬性為空(沒設置),那么protocol可以設置為/etc/protocols中所包含的任意協議。

module

module用於設置netfilter的helper。學生前面給大家介紹過,firewalld其實是基於netfilter進行工作的,netfilter中的helper主要用於連接的跟蹤,這樣就可以實現“有狀態的防火牆”,也就是將相關的連接管理到一起。一個典型的例子就是ftp的連接,我們知道一般來說ftp使用的是21號端口,不過21號端口主要是用來傳輸命令的,實際傳輸文件又會使用一個其他的端口,不過這兩個連接還有內在的聯系,這種情況就可以使用netfilter中的helper來處理,在我們這里service中就是module節點。我們看一下firewalld默認給我們提供的ftp的service配置文件ftp.xml

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>FTP</short>
  <description>FTP is a protocol used for remote file transfer. If you plan to make your FTP server publicly available, enable this option. You need the vsftpd package installed for this option to be useful.</description>
  <port protocol="tcp" port="21"/>
  <module name="nf_conntrack_ftp"/>
</service>

destination

destination非常簡單,他就表示目標地址,也就是根據目標地址來綁定服務,他有兩個屬性:ipv4和ipv6,分別用於綁定ipv4和ipv6的地址,可以使用單個地址也可以使用掩碼。

另外,在一個service中destination最多只能出現一次。

使用service

編輯完service配置文件后我們就可以在zone中使用了,具體使用方法學生在前面已經給大家介紹過,這里就不再重述了。

Firewalld中的whitelist並不是規則白名單

whitelist的含義

白名單跟防火牆結合在一起大家很容易將其理解為規則白名單,不過在Firewalld中whitelist卻並不是規則白名單的含義。

對於一個防火牆來說,最重要的當然就是規則了,Firewalld當然也不例外,學生前面也給大家介紹了很多規則相關的配置方法,不過大家有沒有意識到一個潛在的問題呢?當我們服務器中的某個服務(比如http)出現漏洞時,攻擊者如果可以執行命令那么是不是就可以使用firewall-cmd工具來修改我們防火牆的規則呢?如果真是這樣那么后果可想而知,攻擊者不但可以開放我們原來沒有開放的端口,甚至還可以搞惡作劇——將我們正常服務的端口給關閉!

Firewalld中whitelist就是來解決這個問題的,他可以限制誰能對防火牆規則進行修改,也就是說這里的whitelist其實使用用來配置可以修改防火牆規則的主體的白名單。

使用條件

在默認配置下whitelist是不啟用的,我們需要將Lockdown設置為yes才可以啟用,這些內容前面學生已經給大家介紹過了,另外,firewall-cmd工具也可以直接對其進行設置和查詢,命令如下

firewall-cmd --lockdown-on firewall-cmd --lockdown-off firewall-cmd --query-lockdown

第一個是開啟Lockdown,也就是讓whitelist起作用,第二個是關閉Lockdown,第三個是查詢當前Lockdown的狀態。

這三個命令非常容易理解,不過他們跟學生前面給大家介紹過的其他命令有一些使用上的區別,我們看到這三個命令都沒有--permanent選項,不過這並不表示他們不可以持久化保存,其實恰恰相反,在我們對Lockdown進行修改時配置文件和運行時環境會同時進行修改,也就是說當我們使用firewall-cmd命令對Lockdown的狀態進行修改后首先可以立即生效、其次在重啟后也不會失效。

另外,在使用--lockdown-on的時候大家要特別小心,要先看自己在不在whitelist范圍內,如果不在,啟用之后我們自己也不可以對防火牆進行操作了!

配置文件

whitelist的配置文件是位於/etc/firewalld目錄下的lockdown-whitelist.xml文件,其結構如下

<whitelist> [<selinux context="selinuxcontext"/>] [<command name="commandline[*]"/>] [<user {name="username"|id="userid"}/>] </whitelist>

我們看到這里面有三個可選的配置節點:selinux、command和user,每個配置節點都可以配置多個,配置進來的就表示可以修改防火牆規則,下面學生分別來給大家介紹一下這三個配置項。

selinux

一說到selinux可能有的人就會產生畏懼心,不過這里用到的非常簡單,只需要將某進程的content給設置進去就行了,具體某個進程的content大家可以使用“ps -e --context”命令來查找,找出來之后設置到context屬性中就可以了。

我們可以直接編輯xml配置文件,另外也可以使用firewall-cmd命令來操作,相關命令如下

firewall-cmd [--permanent] --add-lockdown-whitelist-context=context firewall-cmd [--permanent] --remove-lockdown-whitelist-context=context firewall-cmd [--permanent] --query-lockdown-whitelist-context=context firewall-cmd [--permanent] --list-lockdown-whitelist-contexts

這四個命令也非常容易理解,他們分別表示添加、刪除、查詢一個具體的selinuxcontenxt以及羅列出所有白名單中配置了的selinuxcontenxt,使用--permanent可以持久化保存,不使用可以立即生效。

command

通過command節點可以針對具體的command命令進行配置,配置之后此命令就可以被一般用戶執行了。比如我們想將之前講過的panic模式的開啟和關閉命令開放,這樣當遇到緊急情況時一般用戶也可以啟動panic模式,這種需求我們使用下面的配置即可

<whitelist>
    <command name="/usr/bin/python /bin/firewall-cmd --panic-on"/>
    <command name="/usr/bin/python /bin/firewall-cmd --panic-off"/>
</whitelist>

另外,command還可以使用通配符“*”,所以上面的配置還可以簡化為

<whitelist>
    <command name="/usr/bin/python /bin/firewall-cmd --panic-*"/>
</whitelist>

當然,command也可以使用firewall-cmd命令來操作,相關命令如下

firewall-cmd [--permanent] --add-lockdown-whitelist-command=command firewall-cmd [--permanent] --remove-lockdown-whitelist-command=command firewall-cmd [--permanent] --query-lockdown-whitelist-command=command firewall-cmd [--permanent] --list-lockdown-whitelist-commands

命令的含義跟上面的selinux差不多,大家可以很容易理解,學生就不再解釋了。

user

這里的user指的就是linux中的用戶,通過這項可以對指定的用戶開放配置權限,指定用戶的方法有兩種:通過userId和通過userName都可以,在默認的lockdown-whitelist.xml配置文件中就設置了id為0的user,也就是root用戶

<whitelist> ... <user id="0"/>
</whitelist>

當然,通過name屬性設置用戶名也是可以的,非常簡單,學生這里就不給大家舉例了。user也可以使用firewall-cmd命令來操作,而且uid和name是分開操作的,所以user相關的命令一共有八個

firewall-cmd [--permanent] --add-lockdown-whitelist-uid=uid firewall-cmd [--permanent] --remove-lockdown-whitelist-uid=uid firewall-cmd [--permanent] --query-lockdown-whitelist-uid=uid firewall-cmd [--permanent] --list-lockdown-whitelist-uids firewall-cmd [--permanent] --add-lockdown-whitelist-user=user firewall-cmd [--permanent] --remove-lockdown-whitelist-user=user firewall-cmd [--permanent] --query-lockdown-whitelist-user=user firewall-cmd [--permanent] --list-lockdown-whitelist-users

前四個是對uid進行操作,后四個是對username進行操作,具體含義大家應該很容易理解。

特別注意

在使用whitelist的時候我們要特別注意一點,那就是whitelist只是針對規則的修改(包括添加和刪除)起作用,但是不會限制查詢。如果大家是使用root配置好防火牆后一般很少修改,也沒有使用腳本動態修改等特殊需求的話可以直接將/bin/firewall-cmd的權限設置為750或者更低。

 Firewalld防火牆與ICMP攻擊

提到ICMP大家應該都很熟悉,可能有人會說:不就是ping嗎?但是說到ICMP攻擊以及相關防御措施可能就有的人不是非常清楚了。

ICMP的概念

要想理解ICMP攻擊以及防范我們還得從ICMP的概念說起,ICMP是“Internet Control Message Protocol”的縮寫,意思是“Internet控制消息協議”,他主要用於在不同主機、路由器等設備之間傳遞控制消息,比如網絡是否可以聯通、路由設備地址的發現、路由路徑是否合理等內容。

ICMP攻擊

ICMP協議被攻擊的方法有很多種,比如的“Ping of Death”、使用ICMP數據包發起DDOS攻擊、redirect攻擊等等,下面學生簡單給大家介紹一下。

“Ping of Death”的原理是當發送的數據包大小超過64KB(規定最大64KB)后接收信息的主機就會出現內存分配錯誤,進一步會導致TCP/IP堆棧崩潰,甚至主機死機!不過這一漏洞在新版的操作系統中已經解決了。

ICMP 的DDOS簡單來說就是一直不停地發送ICMP數據包從而占滿被攻擊主機的帶寬,當然,更進一步還可以使用一些手段將流量進行放大,比如將源地址設置為被 攻擊主機的“echo-request”類型報文廣播給很多第三方主機,這時這些接收到報文的主機就會給被攻擊目標主機返回“echo-replay”報 文,這樣流量就被放大了。

要理解redirect攻擊,首先要明白redirect的作用,學生給大家舉個例子大家就明白了,比如有個快遞 需要從北京發往廣州,結果北京發到沈陽的中轉站了,這時候沈陽就覺得不對呀,要往廣州發應該往南邊發才對怎么能往北邊發呢?所以沈陽站就會跟北京站聯系, 告訴他:你發的不對,你應該往南邊的XXX站發送才對。ICMP中的redirect就是起這個作用的,當路由設備發現某個數據包經過自己不是最優路徑時 就會給源地址發一個redirect數據包,告訴對方發的路徑不合適,並且指出應該發往的地址。這個功能是很有用的,不過如果被攻擊者使用情況就完全不一 樣了,他們可以使用這一功能將正常(合理)的路由地址給修改為一個不合理的甚至不存在的地址,這樣就會給通訊造成問題,另外,有一些還會將目標地址設置為 他們自己可以控制的主機的地址,這樣就可以截獲數據了!跟redirect相關的還有router-advertisement、router- solicitation等類型的ICMP數據包。

當然,除了這三種還有很多攻擊的類型,比如我們下面會說到的destination-unreachable、source-quench、time-exceeded等類型的攻擊。

可能看到這里有的讀者就覺得不容易理解了:echo-request、redirect、destination-unreachable等等到底是什么東西呢?其實這都是ICMP的類型,下面學生就來給大家介紹ICMP的類型。

ICMP的類型

ICMP 數據包主要包含三部分內容:類型、代碼和附加數據,其中的類型和代碼屬於包頭,代碼(code)相當於類型(type)下的細分子類型,我們也可以理解為 他們共同來決定一個ICMP包的類型,比如學生上面給大家講的redirect的type為5,不過5這個type下面還有4個code——0,、1、 2、3,他們所表示的含義如下表所示

表1:ICMP包Redirect類型表

type code 描述
5 0 Redirect for network——對網絡重定向
5 1 Redirect for host——對主機重定向
5 2 Redirect for TOS and network——對服務類型和網絡重定向
5 3 Redirect for TOS and host——對服務類型和主機重定向

具體更多的代碼學生就不在這里羅列了,大家很容易就可以找到。在ICMP數據包中type和code就像excel中的兩個單元格,只要將相應的數據填入,主機就可以知道這個ICMP包的類型了。

這里的type和code我們當然是不需要記的,在使用的時候只需要用名字就可以了,比如type為8的數據包我們直接寫Echo request、type為0的數據包我們直接寫Echo Reply就行了,下面學生簡單地給大家介紹幾個常見的類型

  • Echo request:需要回應的請求,也就是我們常說的ping請求

  • Echo Reply:對ping的回應報文(pong)

  • Destination Unreachable:目標不可達

  • Source Quench:源地址資源緊張,正常情況下當我們要發送數據的路由設備請求過多時就會發出這種ICMP包

  • Time Exceeded:超時,比如TTL用完后就會產生這種類型的數據包

Firewalld針對ICMP攻擊的防御方法

firewalld中有專門針對icmp報文的配置方法,而且使用起來也非常簡單,我們只需要將firewalld所支持的icmp類型配置到所使用的zone中就可以了,要查看firewalld所支持的icmp類型可以使用下面的命令

firewall-cmd [--permanent] --get-icmptypes

默認的返回結果如下

destination-unreachable echo-reply echo-request parameter-problem redirect router-advertisement router-solicitation source-quench time-exceeded

這里的類型前面學生基本都給大家介紹過了,下面來學生來給大家講怎么使用。跟icmptype相關的命令主要有四個

firewall-cmd [--permanent] [--zone=zone] --list-icmp-blocks firewall-cmd [--permanent] [--zone=zone] --add-icmp-block=<icmptype> firewall-cmd [--permanent] [--zone=zone] --remove-icmp-block=<icmptype> firewall-cmd [--permanent] [--zone=zone] --query-icmp-block=<icmptype>

他們分別用於列出zone中所阻止的所有icmp類型、添加、刪除和查詢某個具體的icmp類型,如果指定zone則對具體zone進行操作,否則對當前活動的zone進行操作。

icmp配置文件的結構也非常簡單,除了short和description外只有一個destination節點,可以設置對ipv4和ipv6的支持與否。

補充與建議

對於firewalld中的icmp設置大家要特別注意下面三點

1、firewalld只可以阻止指定類型的icmp包,沒有其他更多的配置選項

2、如果使用drop、reject這些zone的話,默認所有icmp類型都會阻塞

3、默認情況下firewalld中所配置的icmp類型主要是針對入包的,而對於主機發出的包是不會攔截的。另外,在前面學生跟大家說過firewalld是一款有狀態的防火牆,也就是說不同連接之間的關系firewalld在內部是有記錄的,所以即使我們將echo-reply設置到zone中之后再去使用本機ping其他主機也是可以收到回復的,這是因為firewalld底層可以識別出那個echo-reply是我們發生去請求的回應。

對於具體哪個類型應該阻止,哪個應該放行大家需要根據自己的實際情況來設定,學生下面給大家提供一些思考的方向和建議。

  • destination-unreachable:當收到這種類型數據包之后相應地址的連接將會被斷開,如果是攻擊者偽造的數據包,那么會將我們的很多正常連接斷開。當將其設置到zone中后我們本機發送的請求還是可以收到destination-unreachable類型回復的,只是直接發給我們的destination-unreachable數據包進不來了,所以建議大家可以阻止。

  • echo-request:主要用於接收ping請求,阻塞之后我們的主機將不可被ping,不過打開后又有可能被攻擊,有種慣用的做法是設置開通的頻率,比如1秒鍾只可以被ping一次,不過這種功能直接使用學生上面給大家介紹的方法是無法設置的,不過沒關系,當學習了學生下一節將要給大家介紹的firewalld中的direct之后就可以設置了。

  • echo-reply:這是回應ping信息的包,一般來說我們應該將其阻止,因為他跟destination-unreachable一樣,如果是我們本機發出的即使設置了阻止也還是可以接收到的。

  • parameter-problem:當接收到的報文參數錯誤,無法解析時會返回這種類型的報文。

  • redirect:這種報文學生在前面已經給大家詳細介紹過,這里就不再重述了。

  • router-advertisement和router-solicitation:這是一對報文,他們的作用是用來發現路由設備的地址,主機發出router-solicitation類型數據包來查找路由設備,路由設備可以發出router-advertisement類型ICMP數據包來告訴主機自己是路由設備

  • source-quench:這個學生也給大家介紹過了,當源地址設備(比如路由設備)資源緊張時就會發出這種數據包

  • time-exceeded:數據包超時。

 

最后還是那句話,沒有最優配置方法(否則就不需要配置了),大家需要根據自己的實際情況進行配置。

用活Firewalld防火牆之direct

學生在前面已經給大家介紹過了Firewalld中direct的作用,使用他可以直接使用iptables、ip6tables中的規則進行配置,下面學生就給大家介紹direct的具體用法。

direct結構

我們還是先從配置文件入手,direct的配置文件為/etc/firewalld/direct.xml文件,結構如下

<?xml version="1.0" encoding="utf-8"?>
<direct> [ <chain ipv="ipv4|ipv6" table="table" chain="chain"/> ] [ <rule ipv="ipv4|ipv6" table="table" chain="chain" priority="priority"> args </rule> ] [ <passthrough ipv="ipv4|ipv6"> args </passthrough> ] </direct>

大家可以看到這里的direct一共有三種節點:chain、rule和passthrough,他們都是可選的,而且都可以出現多次。

屬性

  • ipv:這個屬性非常簡單,表示ip的版本

  • table:chain和rule節點中的table屬性就是iptables/ip6tables中的table

  • chain:chain中的chain屬性用於指定一個自定義鏈的名字,注意,不可與已有鏈重名;rule中的chain屬性既可以是內建的(也就是iptables/ip6tables中的五條鏈),也可以是在direct中自定義的chain

  • priority:優先級,用於設置不同rule的優先級,就像iptables中規則的前后順序,數字越小優先級越高

  • args:rule和passthrough中的args就是iptables/ip6tables中的一條具體的規則,不過他們可以使用我們自定義的chain。

     

 

使用

因為direct的使用跟iptables/ip6tables非常相似,換句話說,想用好direct需要有iptables/ip6tables的基礎,而iptables/ip6tables並不是我們這套教程的重點,所以這里學生就不給大家詳細講解了。

direct中自定義chain跟iptables/ip6tables中使用-N新建chain類似,創建完之后就可以在規則中使用-j或者-g來使用了。

Firewalld中跟direct相關的命令如下

firewall-cmd [--permanent] --direct --get-all-chains firewall-cmd [--permanent] --direct --get-chains { ipv4 | ipv6 | eb } table firewall-cmd [--permanent] --direct --add-chain { ipv4 | ipv6 | eb } table chain firewall-cmd [--permanent] --direct --remove-chain { ipv4 | ipv6 | eb } table chain firewall-cmd [--permanent] --direct --query-chain { ipv4 | ipv6 | eb } table chain firewall-cmd [--permanent] --direct --get-all-rules firewall-cmd [--permanent] --direct --get-rules { ipv4 | ipv6 | eb } table chain firewall-cmd [--permanent] --direct --add-rule { ipv4 | ipv6 | eb } table chain priority args firewall-cmd [--permanent] --direct --remove-rule { ipv4 | ipv6 | eb } table chain priority args firewall-cmd [--permanent] --direct --remove-rules { ipv4 | ipv6 | eb } table chain firewall-cmd [--permanent] --direct --query-rule { ipv4 | ipv6 | eb } table chain priority args firewall-cmd --direct --passthrough { ipv4 | ipv6 | eb } args firewall-cmd --permanent --direct --get-all-passthroughs firewall-cmd --permanent --direct --get-passthroughs { ipv4 | ipv6 | eb } firewall-cmd --permanent --direct --add-passthrough { ipv4 | ipv6 | eb } args firewall-cmd --permanent --direct --remove-passthrough { ipv4 | ipv6 | eb } args firewall-cmd --permanent --direct --query-passthrough { ipv4 | ipv6 | eb } args

下面我們來看個文檔(firewalld.direct(5))中提供的例子

<?xml version="1.0" encoding="utf-8"?>
<direct>
    <chain ipv="ipv4" table="raw" chain="blacklist"/>
    <rule ipv="ipv4" table="raw" chain="PREROUTING" priority="0">-s 192.168.1.0/24 -j blacklist</rule>
    <rule ipv="ipv4" table="raw" chain="PREROUTING" priority="1">-s 192.168.5.0/24 -j blacklist</rule>
    <rule ipv="ipv4" table="raw" chain="blacklist" priority="0">-m limit --limit 1/min -j LOG --log-prefix "blacklisted: "</rule>
    <rule ipv="ipv4" table="raw" chain="blacklist" priority="1">-j DROP</rule>
</direct>

在這個例子中首先自定義了一個叫blacklist的鏈,然后將所有來自192.168.1.0/24和192.168.5.0/24的數據包都指向了這個鏈,最后定義了這個鏈的規則:首先進行記錄,然后drop,記錄的方法是使用“blacklisted: ”前綴並且限制1分鍾記錄一次。

當然,使用相似的方法大家也可以寫出來上一節學生給大家留下的那個問題:對ping請求進行限制。

實戰練習

1、允許訪問本機的redis服務(端口6379)

 

[root@www zones]# firewall-cmd --get-services  #查看是否有定義好的redis服務
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client ceph ceph-mon dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync freeipa-ldap freeipa-ldaps freeipa-replication ftp high-availability http https imap imaps ipp ipp-client ipsec iscsi-target kadmin kerberos kpasswd ldap ldaps libvirt libvirt-tls mdns mosh mountd ms-wbt mysql nfs ntp openvpn pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp ptp pulseaudio puppetmaster radius rpc-bind rsyncd samba samba-client sane smtp smtps snmp snmptrap squid ssh synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server
[root@www zones]# firewall-cmd --get-services|grep redis  #redis服務器未定義

方法一:通過端口,特點:直接快捷

[root@www zones]# firewall-cmd --zone=public --add-port=6379/tcp
success
[root@www zones]# firewall-cmd --zone=public --add-port=6379/tcp --permanent
success
[root@www zones]# cat public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="http"/>
  <service name="ssh"/>
  <port protocol="tcp" port="6379"/>
</zone>

方法二:通過服務

創建服務:(創建服務通過復制並修改配置文件的方法更加簡單)

[root@www zones]# cp /usr/lib/firewalld/services/mysql.xml /etc/firewalld/services/redis.xml
[root@www zones]# vim /etc/firewalld/services/redis.xml
[root@www zones]# cat /etc/firewalld/services/redis.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Redis</short>
  <description>Redis Database Server</description>
  <port protocol="tcp" port="6379"/>
</service>

 [root@www zones]# firewall-cmd --zone=public --add-service=redis

 success

2、取消(禁止)訪問本機的redis服務(端口6379)

[root@www zones]# firewall-cmd --zone=public --remove-port=6379/tcp
success
或者
[root@www zones]# firewall-cmd --zone=public --remove-service=redis
success

3、允許訪問本機的http服務,但是禁止58.56.88.22訪問。

[root@www zones]# firewall-cmd --add-service=http
success
[root@www zones]# firewall-cmd --zone=drop --change-source=58.56.88.22 --permanent  #永久生效,但是不實時生效
success
[root@www zones]# firewall-cmd --zone=drop --change-source=58.56.88.22
success     #實時生效。
或者使用firewall-cmd --reload來重讀規則  

4、查看當前生效的區域(接上題)

[root@www zones]# firewall-cmd --get-active-zones
drop
  sources: 58.56.88.22

5、只允許某個ip訪問指定端口

設置規則:
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="5432" accept"

查看配置結果

firewall-cmd --list-all

刪除規則

firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="5432" accept"

 

參考內容: 

http://www.firewalld.org/documentation/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM