iptables & netfilter
1、簡介
netfilter/iptables(下文中簡稱為iptables)組成Linux核心下的包過濾防火牆,完成封包過濾、封包重定向和網路地址轉換(NAT)等功能。]
iptabels其實不是真正的防火牆,netfilter才是防火牆真正的安全框架(framework),netfilter位於核心空間。iptables其實是一個命令列工具,位於使用者空間,我們用這個工具操作真正的框架。
Netfilter是Linux作業系統核心層內部的一個數據包處理模組,它具有如下功能:
- 網路地址轉換(Network Address Translate)
- 資料包內容修改
- 資料包過濾的防火牆功能
2、iptables基礎
iptatble是按規則來辦事的,當資料包與規則匹配時,iptables就根據規則所定義的方法來處理這些資料包,如放行(accept)、拒絕(reject)和丟棄(drop)等。配置防火牆的主要工作就是新增、修改和刪除這些規則。
netfilter才是真正的防火牆,它是核心的一部分,所以,如果我們想要防火牆能夠達到”防火”的目的,則需要在核心中設定關卡,所有進出的報文都要通過這些關卡,經過檢查後,符合放行條件的才能放行,符合阻攔條件的則需要被阻止,於是,就出現了input關卡和output關卡,而這些關卡在iptables中不被稱為”關卡”,而被稱為”鏈”。
iptatbles中不僅有input
、output
關卡,還有prerouting
、forward
、postrouting
,當我們啟用了防火牆功能時,報文需要經過如下關卡,也就是說,根據實際情況的不同,報文經過”鏈”可能不同。如果報文需要轉發,那麼報文則不會經過input鏈發往使用者空間,而是直接在核心空間中經過forward鏈和postrouting鏈轉發出去的。
2.1、鏈
防火牆的作用就在於對經過的報文匹配”規則”,然後執行對應的”動作”,所以,當報文經過這些關卡的時候,則必須匹配這個關卡上的規則,但是,這個關卡上可能不止有一條規則,而是有很多條規則,當我們把這些規則串到一個鏈條上的時候,就形成了”鏈”。
這樣來說,把他們稱為”鏈”更為合適,每個經過這個”關卡”的報文,都要將這條”鏈”上的所有規則匹配一遍,如果有符合條件的規則,則執行規則對應的動作。
2.2、表
具有相同功能規則的集合叫做“表”,iptables定義來4種表,每種表對應了不同的功能,即我們定義的規則都逃脫不了這4種功能的範圍。
- filter表:過濾功能,防火牆;核心模組:iptable_filter
- nat表:網路地址轉換功能;核心模組:iptable_nat
- mangle表:拆解報文,修改,並重新封裝功能;核心模組:iptable_mangle
- raw表:關閉nat表上啟用的連線追蹤機制;核心模組:iptatble_raw
需要注意的是,某些“鏈”註定 不會包含“某類規則”,錶鏈的對應關係如下:
綜合上面描述,資料包經過防火牆的流程總結為下:
如果想要linux主機支援轉發,則需要開啟核心的IP_FORWARD功能,可以臨時修改對應檔案/proc/sys/net/ipv4/ip_forward。
在寫Iptables規則的時候,要時刻牢記這張路由次序圖,靈活配置規則。
2.3、規則
根據指定的匹配條件來嘗試匹配每個流經此處的報文,一旦匹配成功,則由規則後面指定的處理動作進行處理。
匹配條件分為
基本匹配條件:源IP、目的IP等
擴充套件匹配條件:源埠、目的埠等
處理動作(在iptatbles中被稱為target):
- ACCEPT:允許資料包通過
- DROP:丟棄資料包,不給任何迴應資訊
- REJECT:拒絕資料包通過,必要時傳送一個響應資訊
- SNAT:源地址轉換,解決內網使用者用同一個公網地址上網的問題
- MASOUERADE:SNAT的一種特殊形式,適用於動態的、臨時會變的ip上
- DNAT:目的地址轉換
- REDIRECT:在本機做埠對映
- LOG:在/var/log/messages檔案中記錄日誌資訊,然後將資料包傳遞給下一條規則。
3、使用
3.1、規則查詢
#檢視對應表所有規則,省略表名預設為filter表
iptables -t 表名 -L
#指定鏈的規則,-v:詳細資訊 -n:直接顯示IP地址 --line-numbers:顯示規則序號 -x:顯示計數器的精確值
iptables --line-numbers -t 表名 -nvxL 鏈名
3.2、規則管理
新增規則
命令語法:iptables -t 表名 -A 鏈名 匹配條件 -j 動作
示例:iptables -t filter -A INPUT -s 192.168.1.146 -j DROP
-I:在對應鏈開頭新增規則
-A:在末尾新增規則
規則是按照順序執行的,新增時候可以指定規則序號,這樣就可以在任意位置插入規則了.
命令語法:iptables -t 表名 -I 鏈名 規則序號 匹配條件 -j 動作
示例:iptables -t filter -I INPUT 5 -s 192.168.1.146 -j REJECT
---設定預設動作---
命令語法:iptables -t 表名 -P 鏈名 動作
示例:iptables -t filter -P FORWARD ACCEPT
刪除規則
命令語法:iptables -t 表名 -D 鏈名 規則序號
示例:iptables -t filter -D INPUT 3
---按照具體匹配條件與動作刪除規則--
命令語法:iptables -t 表名 -D 鏈名 匹配條件 -j 動作
示例:iptables -t filter -D INPUT -s 192.168.1.146 -j DROP
-F:清空對應鏈的規則,如果省略鏈名錶示刪除表中所有規則
修改規則
---規則原本的匹配條件不可省略!如果省略,源地址會變成0.0.0.0/0,此時如果是拒絕動作,那麼ssh就斷掉了---
命令語法:iptables -t 表名 -R 鏈名 規則序號 規則原本的匹配條件 -j 動作
示例:iptables -t filter -R INPUT 3 -s 192.168.1.146 -j ACCEPT
儲存規則
---儲存在/etc/sysconfig/iptables檔案中
service iptables save 或
iptables-save > /etc/sysconfig/iptables
---從檔案中重新載入規則
iptatbles-restore < /etc/sysconfig/iptables
3.3、基本匹配條件
當規則中同時存在多個匹配條件時,多個條件之間預設存在“與”的關係.
-s: 指定源ip,多個ip用逗號隔開,也可以指定一個網段
iptables -t filter -I INPUT -s 192.168.1.111,192.168.1.118 -j DROP
iptables -t filter -I INPUT -s 192.168.1.0/24 -j ACCEPT
iptables -t filter -I INPUT ! -s 192.168.1.0/24 -j ACCEPT
-d: 匹配目標地址,用法和-s一樣
-p: 匹配報文協議型別,可以匹配的協議型別tcp、udp、udplite、icmp、esp、ah、sctp等
-i: 匹配報文從哪個網絡卡介面流入本機,由於匹配條件只是用於匹配報文流入的網絡卡,所以在OUTPUT鏈與POSTROUTING鏈中不能使用此選項
-o: 匹配報文從哪個網絡卡介面流出本機
3.3、擴充套件匹配條件
tcp擴充套件模組
常用的擴充套件匹配條件如下:
-p tcp -m tcp –-sport 用於匹配tcp協議報文的源埠,可以使用冒號指定一個連續的埠範圍
-p tcp -m tcp –-dport 用於匹配tcp協議報文的目標埠,可以使用冒號指定一個連續的埠範圍
--tc-flages 用於匹配tcp頭部欄位標誌位,第一部分為需要匹配哪些標誌位,第二部分為哪些標誌位為1
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
--syn 相當於使用”–tcp-flags SYN,RST,ACK,FIN SYN
udp模組
當使用擴充套件匹配條件時,如果未指定擴充套件模組,iptables會預設呼叫與”-p”對應的協議名稱相同的模組,所以,當使用”-p udp”時,可以省略”-m udp”.udp只有sport和dport兩個匹配條件
mutiport擴充套件模組
常用的擴充套件匹配條件如下:
-p tcp -m multiport –-sports 用於匹配報文的源埠,可以指定離散的多個埠號,埠之間用”逗號”隔開
-p udp -m multiport –-dports 用於匹配報文的目標埠,可以指定離散的多個埠號,埠之間用”逗號”隔開
iprange模組
包含的擴充套件匹配條件如下
-m iprange –-src-range:指定連續的源地址範圍,用
-
指定一個連續的範圍-m iprange -–dst-range:指定連續的目標地址範圍
string模組
使用string擴充套件模組,可以指定要匹配的字串,如果報文中包含對應的字串,則符合匹配條件,常用擴充套件匹配條件如下
–-algo:指定對應的匹配演算法,可用演算法為bm、kmp,此選項為必需選項。
–-string:指定需要匹配的字串
time模組
常用擴充套件匹配條件如下
–-timestart:用於指定時間範圍的開始時間,不可取反
–-timestop:用於指定時間範圍的結束時間,不可取反
–-weekdays:用於指定”星期幾”,可取反
–-monthdays:用於指定”幾號”,可取反
–-datestart:用於指定日期範圍的開始日期,不可取反
–-datestop:用於指定日期範圍的結束時間,不可取反
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --datestart 2017-12-24 --datestop 2017-12-27 -j REJECT
connlimit模組
使用connlimit擴充套件模組,可以限制每個IP地址同時連結到server端的連結數量,注意:我們不用指定IP,其預設就是針對”每個客戶端IP”,即對單IP的併發連線數限制
–-connlimit-above:單獨使用此選項時,表示限制每個IP的連結數量。
–-connlimit-mask:此選項不能單獨使用,在使用–connlimit-above選項時,配合此選項,則可以針對”某類IP段內的一定數量的IP”進行連線數量的限制
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
limit模組
如果我想要限制單位時間內流入的包的數量,就能用limit模組,我們可以以秒為單位進行限制,也可以以分鐘、小時、天作為單位進行限制
常用的擴充套件匹配條件如下
–-limit-burst:類比”令牌桶”演算法,此選項用於指定令牌桶中令牌的最大數量
–-limit:類比”令牌桶”演算法,此選項用於指定令牌桶中生成新令牌的頻率,可用時間單位有second、minute 、hour、day。
iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT
icmp模組
–-icmp-type:匹配icmp報文的具體型別,可以使用type/code和description兩種方式表示
state模組
問題: 怎樣判斷這些報文是為了迴應我們之前發出的報文,還是主動向我們傳送的報文呢?
state模組可以讓iptables實現”連線追蹤”機制,”連線”其中的報文可以分為5種狀態,報文狀態可以為NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED.
--state
3.4、黑白名單機制
前文中一直在強調一個概念:報文在經過iptables的鏈時,會匹配鏈中的規則,遇到匹配的規則時,就執行對應的動作,如果鏈中的規則都無法匹配到當前報文,則使用鏈的預設策略(預設動作),鏈的預設策略通常設定為ACCEPT或者DROP。
所以,當鏈的預設策略為ACCEPT時,鏈中的規則對應的動作應該為DROP或者REJECT,表示只有匹配到規則的報文才會被拒絕,沒有被規則匹配到的報文都會被預設接受,這就是”黑名單”機制。
同理,當鏈的預設策略為DROP時,鏈中的規則對應的動作應該為ACCEPT,表示只有匹配到規則的報文才會被放行,沒有被規則匹配到的報文都會被預設拒絕,這就是”白名單”機制。
在對應的鏈中沒有設定任何規則時,這樣使用預設策略為DROP是非常不明智的,因為管理員也會把自己拒之門外,即使對應的鏈中存在放行規則,當我們不小心使用”iptables -F”清空規則時,放行規則被刪除,則所有資料包都無法進入,這個時候就相當於給管理員挖了個坑,所以,我們如果想要使用”白名單”的機制,最好將鏈的預設策略保持為”ACCEPT”,然後將”拒絕所有請求”這條規則放在鏈的尾部,將”放行規則”放在前面,這樣做,既能實現”白名單”機制,又能保證在規則被清空時,管理員還有機會連線到主機
iptables -P INPUT ACCEPT
iptabels -I INPUT -p tcp --dport 22 -j ACCEPT
iptabels -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -j ACCEPT
3.5、自定義鏈
當預設鏈中的規則非常多時,不方便我們管理。
想象一下,如果INPUT鏈中存放了200條規則,這200條規則有針對httpd服務的,有針對sshd服務的,有針對私網IP的,有針對公網IP的,假如,我們突然想要修改針對httpd服務的相關規則,難道我們還要從頭看一遍這200條規則,找出哪些規則是針對httpd的嗎?這顯然不合理。
但是需要注意的是,自定義鏈並不能直接使用,而是需要被預設鏈引用才能夠使用.
--建立自定義鏈
iptables -t filter -N IN_WEB
--引用自定義鏈
iptables -t filter -I INPUT -p tcp --dport 80 -j IN_WEB
--重新命名自定義鏈
iptables -E IN_WEB WEB
--刪除自定義鏈
刪除自定義鏈需要滿足兩個條件
1、自定義鏈沒有被引用
2、自定義鏈中沒有任何規則
iptables -D INPUT 1
iptables -F WEB
iptables -X WEB
3.6、網路防火牆
防火牆從邏輯上講,可以分為主機防火牆與網路防火牆。
主機防火牆:針對於單個主機進行防護。
網路防火牆:往往處於網路入口或邊緣,針對於網路入口進行防護,服務於防火牆背後的本地區域網。
iptables都是作為主機防火牆的角色出現的,如果想要使用iptables充當網路防火牆,iptables所在的主機則需要處於網路入口處,網路防火牆主要職責就是“過濾並轉發”,所以規則只能定義在FORWARD鏈中.
上圖中把C主機的閘道器指向B主機網絡卡1的IP,A主機閘道器設為B網絡卡2的地址.
A ping 10.1.0.1 是ping不通的,A主機通過路由表得知,發往10.1.0.0/16網段的報文的閘道器為B主機,當報文達到B主機時,B主機發現A的目標為10.1.0.1,而自己的IP是10.1.0.3,這時,B主機則需要將這個報文轉發給10.1.0.1(也就是C主機),但是,Linux主機在預設情況下,並不會轉發報文,如果想要讓Linux主機能夠轉發報文,需要額外的設定,這就是為什麼10.1.0.1沒有迴應的原因.
A ping 10.1.0.3可以ping通: 當報文到達B時,B主機發現自己既是192.168.1.146又是10.1.0.3,所以,B主機就直接回應了A主機,並沒有將報文轉發給誰,所以A主機得到了10.1.0.3的迴應。
臨時生效:把/proc/sys/net/ipv4/ip_forward檔案內容設定為1表示支援轉發報文.
永久生效:/etc/sysctl.conf新增net.ipv4.ip_forward=1
此時就可以ping通了
#如果想要iptables作為網路防火牆,iptables所在主機開啟核心轉發功能,以便能夠轉發報文。
#使用如下命令檢視當前主機是否已經開啟了核心轉發,0表示為開啟,1表示已開啟
cat /proc/sys/net/ipv4/ip_forward
#使用如下兩種方法均可臨時開啟核心轉發,立即生效,但是重啟網路配置後會失效。
方法一:echo 1 > /proc/sys/net/ipv4/ip_forward
方法二:sysctl -w net.ipv4.ip_forward=1
#使用如下方法開啟核心轉發功能,重啟網路服務後永久生效。
配置/etc/sysctl.conf檔案(centos7中配置/usr/lib/sysctl.d/00-system.conf檔案),在配置檔案中將 net.ipv4.ip_forward設定為1
#由於iptables此時的角色為"網路防火牆",所以需要在filter表中的FORWARD鏈中設定規則。
#可以使用"白名單機制",先新增一條預設拒絕的規則,然後再為需要放行的報文設定規則。
#配置規則時需要考慮"方向問題",針對請求報文與迴應報文,考慮報文的源地址與目標地址,源埠與目標埠等。
#示例為允許網路內主機訪問網路外主機的web服務與sshd服務。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 22 -j ACCEPT
#可以使用state擴充套件模組,對上述規則進行優化,使用如下配置可以省略許多"迴應報文放行規則"。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
3.7、動作總結
閘道器配置和上面一樣.
SNAT(服務在外網,內網主動訪問外網)
#主機B
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 192.168.1.146
此時內網主機ping A主機就能ping通, iptables會自動維護NAT表,並將響應報文的目標地址轉換回來.
DNAT(服務在內網,外網主動訪問內網)
#主機B
iptables -t nat -F
iptables -t nat -I PREROUTING -d 192.168.1.146 -p tcp --dport 3389 -j DNAT --to-destination 10.1.0.6:3389
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 192.168.1.146
表示報文目標地址為B公網IP,目標埠為3389的報文符合匹配條件,做DNAT轉換對映到10.1.0.6:3389上.
注:理論上只配置DNAT規則即可,但是如果在測試時無法正常DNAT,可以嘗試配置對應的SNAT,此處按照配置SNAT的流程進行。
MASQUERADE
MASQUERADE會動態的將源地址轉換為可用的IP地址,其實與SNAT實現的功能完全一致,都是修改源地址,只不過SNAT需要指明將報文的源地址改為哪個IP,而MASQUERADE則不用指定明確的IP,會動態的將報文的源地址修改為指定網絡卡上可用的IP地址.
iptables -t nat -I POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE
表示通過外網網絡卡出去的報文在經過POSTROUTING鏈時,會自動將報文的源地址修改為外網網絡卡上可用的IP地址,這時,即使外網網絡卡中的公網IP地址發生了改變,也能夠正常的、動態的將內部主機的報文的源IP對映為對應的公網IP,可以把MASQUERADE理解為動態的、自動化的SNAT,如果沒有動態SNAT的需求,沒有必要使用MASQUERADE,因為SNAT更加高效。
REDIRECT
使用REDIRECT動作可以在本機上進行埠對映
#將本機80埠對映到本機8080埠
iptables -i nat -A PREROUTING -o tcp --dport 80 -j REDIRECT --to-ports 8080
4、總結
規則順序很重要
如果報文已經被前面的規則匹配到,IPTABLES則會對報文執行對應的動作,通常是ACCEPT或者REJECT,報文被放行或拒絕以後,即使後面的規則也能匹配到剛才放行或拒絕的報文,也沒有機會再對報文執行相應的動作了(前面規則的動作為LOG時除外),所以,針對相同服務的規則,更嚴格的規則應該放在前面。
當規則中有多個匹配條件時,條件之間是“與”的關係
在不考慮1的情況下,應該將更容易被匹配的規則放在前面
比如,你寫了兩條規則,一條針對sshd服務,一條針對web服務。假設,一天之內,有20000個請求訪問web服務,有200個請求訪問sshd服務,那麼,應該將針對web服務的規則放在前面,針對sshd的規則放在後面,因為訪問web服務的請求頻率更高。如果將sshd的規則放在前面,當報文是訪問web服務時,sshd的規則也要白白的驗證一遍,由於訪問web服務的頻率更高,白白耗費的資源就更多。
當IPTABLES所在主機作為網路防火牆時,在配置規則時,應著重考慮方向性,雙向都要考慮,從外到內,從內到外。
在配置IPTABLES白名單時,往往會將鏈的預設策略設定為ACCEPT,通過在鏈的最後設定REJECT規則實現白名單機制,而不是將鏈的預設策略設定為DROP,如果將鏈的預設策略設定為DROP,當鏈中的規則被清空時,管理員的請求也將會被DROP掉。