1. 程式人生 > >包過濾型防火牆iptables

包過濾型防火牆iptables

1、防火牆

Firewall:防火牆,隔離工具,工作於主機或網路邊緣,對於進出本主機或本網路的報文根據事先定義的檢查規則作匹配檢測,對於能夠被規則匹配到的報文作出相應處理的元件。防火牆分為主機防火牆和網路防火牆,從組成結構上分為軟體防火牆(軟體邏輯)和硬體防火牆(硬體和軟體邏輯)。
防火牆框架有:ipfw、ipchains等。

2、iptables(netfilter)

(1)netfilter是防火牆的kernel framework,iptables是編寫規則的CLI。
hook function:input、output、forward、prerouting、postrouting。
鏈(內建):PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING。
(2)功能表
filter:過濾作用,防火牆;
nat:network address translation,網路地址轉換,用於修改源IP或目標IP,也可以改埠;
mangle:拆解報文,做出修改,並重新封裝起來;
raw:關閉nat表上啟用的連線追蹤機制。
(3)功能所對應的鏈
raw:PREROUTING, OUTPUT;
mangle:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING;
nat:PREROUTING,[INPUT,]OUTPUT,POSTROUTING;
filter:INPUT,FORWARD,OUTPUT;
(4)報文流向
流入本機:PREROUTING --> INPUT;
由本機流出:OUTPUT --> POSTROUTING;
轉發:PREROUTING --> FORWARD --> POSTROUTING;
(5)路由功能發生的時刻:
報文進入本機後,以判斷目標主機是哪個;
報文離開本機之前,以判斷經由哪個介面送往下一站;

3、iptables規則

組成部分:根據規則匹配條件來嘗試匹配報文,一旦匹配成功,就由規則定義的處理動作作出處理;
匹配條件:基本匹配條件和擴充套件匹配條件;
處理動作:基本處理動作、擴充套件處理動作和自定義處理機制;
iptables的鏈:內建鏈和自定義鏈
內建鏈:對應於hook function;
自定義鏈:用於內建鏈的擴充套件和補充,可實現更靈活的規則管理機制;
新增規則時的考量點:
(1) 要實現哪種功能:判斷新增到哪個表上;
(2) 報文流經的路徑:判斷新增到哪個鏈上;
鏈:鏈上的規則次序,即為檢查的次序,因此,隱含一定的應用法則:
(1) 同類規則(訪問同一應用),匹配範圍小的放上面;
(2) 不同類的規則(訪問不同應用),匹配到報文頻率較大的放在上面;
(3) 將那些可由一條規則描述的多個規則合併起來;
(4) 設定預設策略;

4、iptables命令

iptables [-t table] {-A|-C|-D} chain rule-specification
iptables [-t table] -I chain [rulenum] rule-specification
iptables [-t table] -R chain rulenum rule-specification
iptables [-t table] -D chain rulenum
iptables [-t table] -S [chain [rulenum]]
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
iptables [-t table] -N chain
iptables [-t table] -X  [chain]
iptables [-t table] -P chain target
iptables [-t table] -E old-chain-name new-chain-name
rule-specification = [matches...]  [target]
match = -m matchname [per-match-options]
target = -j targetname [per-target-options]

規則格式:iptables [-t table] COMMAND chain [-m matchname [per-match-options]] -j targetname [per-target-options]
-t table:raw, mangle, nat, [filter]
COMMAND:
鏈管理:
-N:new, 自定義一條新的規則鏈;
-X: delete,刪除自定義的規則鏈;
-P:Policy,設定預設策略;對filter表中的鏈而言,其預設策略有:
ACCEPT(接受)、DROP(丟棄)、REJECT(拒絕);
-E:重新命名自定義鏈;引用計數不為0的自定義鏈不能夠被重新命名,也不能被刪除;
規則管理:
-A:append,追加;
-I:insert, 插入,要指明位置,省略時表示第一條;
-D:delete,刪除:(1) 指明規則序號;(2) 指明規則本身;
-R:replace,替換指定鏈上的指定規則;
-F:flush,清空指定的規則鏈;
-Z:zero,置零;
iptables的每條規則都有兩個計數器:
(1) 匹配到的報文的個數;
(2) 匹配到的所有報文的大小之和;
檢視:
-L:list, 列出指定鏈上的所有規則;
-n:numberic,以數字格式顯示地址和埠號;
-v:verbose,詳細資訊;-vv, -vvv;
-x:exactly,顯示計數器結果的精確值;
–line-numbers:顯示規則的序號;
chain:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING;
匹配條件:
基本匹配條件:無需載入任何模組,由iptables/netfilter自行提供;
[!] -s, --source address[/mask][,...]:檢查報文中的源IP地址是否符合此處指定的地址或範圍;
[!] -d, --destination address[/mask][,...]:檢查報文中的目標IP地址是否符合此處指定的地址或範圍;
[!] -p, --protocol protocol:protocol: tcp,udp,udplite,icmp,icmpv6,esp,ah,sctp,mh or “all”:{tcp|udp|icmp};
[!] -i, --in-interface name:資料報文流入的介面;只能應用於資料報文流入的環節,只能應用於PREROUTING,INPUT和FORWARD鏈;
[!] -o, --out-interface name:資料報文流出的介面,只能應用於資料報文流出的環節,只能應用於FORWARD、OUTPUT和POSTROUTING鏈;
擴充套件匹配條件: 需要載入擴充套件模組,方可生效;
隱式擴充套件:不需要手動載入擴充套件模組;因為它們是對協議的擴充套件,所以,但凡使用-p指明瞭協議,就表示已經指明瞭要擴充套件的模組;
tcp:
[!] --source-port, --sport port[:port]:匹配報文的源埠;可以是埠範圍;
[!] --destination-port,--dport port[:port]:匹配報文的目標埠,可以是埠範圍;
[!] --tcp-flags mask comp:mask is the flags which we should examine, written as a comma-separated list,例如 SYN,ACK,FIN,RST,comp is a comma-separated list of flags which must be set,例如SYN
--tcp-flags SYN,ACK,FIN,RST SYN表示,要檢查的標誌位為SYN,ACK,FIN,RST四個,其中SYN必須為1,餘下的必須為0;
[!] --syn:用於匹配第一次握手,相當於--tcp-flags SYN,ACK,FIN,RST SYN
udp:
[!] --source-port, --sport port[:port]:匹配報文的源埠;可以是埠範圍;
[!] --destination-port,--dport port[:port]:匹配報文的目標埠;可以是埠範圍;
icmp:
[!] --icmp-type {type[/code]|typename}
echo-request:8,echo-reply:0;
顯式擴充套件:必須要手動載入擴充套件模組,顯式地指明使用的擴充套件模組進行的擴充套件,語法格式:[-m matchname [per-match-options]]
處理動作:
-j targetname [per-target-options]
ACCEPT、DROP、REJECT、RETURN(返回呼叫鏈)、REDIRECT(埠重定向)、LOG(記錄日誌)、MARK(做防火牆標記)、DNAT(目標地址轉換)、SNAT(源地址轉換)、MASQUERADE(地址偽裝);
防火牆(服務)的啟動停止:
CentOS 6:
service iptables {start|stop|restart|status}
start:讀取事先儲存的規則,並應用到netfilter上;
stop:清空netfilter上的規則,以及還原預設策略等;
status:顯示生效的規則;
restart:清空netfilter上的規則,再讀取事先儲存的規則,並應用到netfilter上;
預設的規則檔案:/etc/sysconfig/iptables;
CentOS 7:
systemctl start|stop|restart|status firewalld.service
禁用防火牆:
systemctl disable firewalld.service
systemctl stop firewalld.service
使用幫助:
CentOS 6:man iptables
CentOS 7:man iptables-extensions

5、顯式擴充套件

(1)multiport擴充套件
以離散方式定義多埠匹配,最多指定15個埠;
[!] --source-ports,--sports port[,port|,port:port]...:指定多個源埠;
[!] --destination-ports,--dports port[,port|,port:port]...:指定多個目標埠;
[!] --ports port[,port|,port:port]...:指明多個埠;
~]# iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.67 -p tcp -m multiport --dports 22,80 -j ACCEPT
(2)iprange擴充套件
指明連續的(但一般不是整個網路)的IP地址範圍;
[!] --src-range from[-to]:源IP地址;
[!] --dst-range from[-to]:目標IP地址;
~]# iptables -A INPUT -d 172.16.100.67 -p tcp --dport 80 -m iprange --src-range 172.16.100.5-172.16.100.10 -j DROP
(3)string擴充套件
對報文中的應用層資料做字串模式匹配檢測;
--algo {bm|kmp}:字串匹配檢測演算法,bm:Boyer-Moore,kmp:Knuth-Pratt-Morris;
[!] --string pattern:要檢測的字串模式;
[!] --hex-string pattern:要檢測的字串模式,16進位制格式;
~]# iptables -A OUTPUT -s 172.16.100.67 -d 172.16.0.0/16 -p tcp --sport 80 -m string --algo bm --string "gay" -j REJECT
(4)time擴充套件
根據將報文到達的時間與指定的時間範圍進行匹配;
--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
--datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
--timestart hh:mm[:ss]
--timestop hh:mm[:ss]
[!] --monthdays day[,day...]
[!] --weekdays day[,day...]
--kerneltz:使用核心上的時區,而非預設的UTC;
~]# iptables -A INPUT -s 172.16.0.0/16 -d 172.16.100.67 -p tcp --dport 80 -m time --timestart 14:30 --timestop 18:30 --weekdays Sat,Sun --kerneltz -j DROP
(5)connlimit擴充套件
根據每客戶端IP做併發連線數數量匹配;
--connlimit-upto n:連線的數量小於等於n時匹配;
--connlimit-above n:連線的數量大於n時匹配;
~]# iptables -A INPUT -d 172.16.100.67 -p tcp --dport 21 -m connlimit --connlimit-above 2 -j REJECT
(6)limit擴充套件
基於收發報文的速率做匹配,令牌桶過濾器。
--limit rate[/second|/minute|/hour|/day]
--limit-burst number
~]# iptables -I INPUT -d 172.16.100.67 -p icmp --icmp-type 8 -m limit --limit 3/minute --limit-burst 5 -j ACCEPT
~]# iptables -I INPUT 2 -p icmp -j REJECT
(7)state擴充套件
根據“連線追蹤機制”去檢查連線的狀態;
conntrack機制:追蹤本機上的請求和響應之間的關係。狀態有如下幾種:
NEW:新發出請求,連線追蹤模板中不存在此連線的相關資訊條目,因此,將其識別為第一次發出的請求;
ESTABLISHED:NEW狀態之後,連線追蹤模板中為其建立的條目失效之前期間內所進行的通訊狀態;
RELATED:相關聯的連線;如ftp協議中的資料連線與命令連線之間的關係;
INVALID:無效的連線;
UNTRACKED:未進行追蹤的連線;
[!] --state state
~]# iptables -A INPUT -d 172.16.100.67 -p tcp -m multiport --dports 22,80 -m state --state NEW,ESTABLISHED -j ACCEPT
~]# iptables -A OUTPUT -s 172.16.100.67 -p tcp -m multiport --sports 22,80 -m state --state ESTABLISHED -j ACCEPT
調整連線追蹤功能所能夠容納的最大連線數量:/proc/sys/net/nf_contrack_max;
已經追蹤到到的並記錄下來的連線:/proc/net/nf_conntrack;
不同的協議的連線追蹤時長:/proc/sys/net/netfilter/;
iptables的連結跟蹤表最大容量為/proc/sys/net/ipv4/ip_conntrack_max,連結碰到各種狀態的超時後就會從表中刪除,當模板滿載時,後續的連線可能會超時。
解決方法一般有兩個:
1)加大nf_conntrack_max 值
vi /etc/sysctl.conf

net.ipv4.nf_conntrack_max = 393216
net.ipv4.netfilter.nf_conntrack_max = 393216

2)降低 nf_conntrack timeout時間
vi /etc/sysctl.conf

net.ipv4.netfilter.nf_conntrack_tcp_timeout_established = 300
net.ipv4.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.ipv4.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.ipv4.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120

iptables -t nat -L -n
如何開放被動模式的ftp服務?
1)裝載ftp連線追蹤的專用模組:
~]# modproble nf_conntrack_ftp
2)放行命令連線(假設Server地址為172.16.100.67):
~]# iptables -A INPUT -d 172.16.100.67 -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT
~]# iptables -A OUTPUT -s 172.16.100.67 -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPT
3)放行資料連線(假設Server地址為172.16.100.67):
~]# iptables -A INPUT -d 172.16.100.67 -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
~]# iptables -I OUTPUT -s 172.16.100.67 -m state --state ESTABLISHED -j ACCEPT

6、規則優化

伺服器端規則設定:任何不允許的訪問,應該在請求到達時給予拒絕;
1)可安全放行所有入站的狀態為ESTABLISHED狀態的連線;
2)可安全放行所有出站的狀態為ESTABLISHED狀態的連線;
3)謹慎放行入站的新請求;
4)有特殊目的限制訪問功能,要於放行規則之前加以拒絕;
如何使用自定義鏈:
自定義鏈:需要被呼叫才能生效,自定義鏈最後需要定義返回規則,返回規則使用的target叫做RETURN;
規則的有效期限:使用iptables命令定義的規則,手動刪除之前,其生效期限為kernel存活期限;
儲存規則至指定的檔案:
CentOS 6:
~]# service iptables save
將規則儲存至/etc/sysconfig/iptables檔案中;
~]# iptables-save > /PATH/TO/SOME_RULES_FILE
CentOS 7:
~]# iptables-save > /PATH/TO/SOME_RULES_FILE
重新載入預存規則檔案中規則:
~]# iptables-restore < /PATH/FROM/SOME_RULES_FILE
CentOS 6:
~]# service iptables restart
自動生效規則檔案中的規則:
1)用指令碼儲存各iptables命令,讓此指令碼開機後自動執行。
在/etc/rc.d/rc.local檔案中新增指令碼路徑:/PATH/TO/SOME_SCRIPT_FILE
2)用規則檔案儲存各規則,開機時自動載入此規則檔案中的規則。
在/etc/rc.d/rc.local檔案新增:
iptables-restore < /PATH/FROM/IPTABLES_RULES_FILE
CentOS 7:
引入了新的iptables前端管理工具firewalld,其管理工具有:firewalld-cmd,firewalld-config。

7、Target

iptables中的Target可以有以下動作:ACCEPT, DROP, REJECT, RETURN、LOG, SNAT, DNAT, REDIRECT, MASQUERADE;
LOG:--log-level level,--log-prefix prefix
NAT表的target:
SNAT:Source NAT,POSTROUTING,OUTPUT;
讓本地網路中的主機通過某一特定地址訪問外部網路時;
--to-source [ipaddr[-ipaddr]][:port[-port]]
--random
DNAT:Destination NAT,PREROUTING;
把本地網路中的某一主機上的某服務開放給外部網路中的使用者訪問時;
--to-destination [ipaddr[-ipaddr]][:port[-port]]
PNAT:Port NAT;
MASQUERADE:
--to-ports port[-port]
--random
SNAT示例:
~]# iptables -t nat -A POSTROUTING -s 192.168.12.0/24 -j SNAT --to-source 172.16.100.67
MASQUERADE示例:
源地址轉換:當源地址為動態獲取的地址時,MASQUERADE可自行判斷要轉換為的地址;
~]# iptables -t nat -A POSTROUTING -s 192.168.12.0/24 -j MASQUERADE
DNAT示例:
~]# iptables -t nat -A PREROUTING -d 172.16.100.67 -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77
~]# iptables -t nat -A PREROUTING -d 172.16.100.67 -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77:8080
~]# iptables -t nat -A PREROUTING -d 172.16.100.67 -p tcp --dport 22012 -j DNAT --to-destination 192.168.12.78:22
REDIRECT:埠重定向;

8、recent

利用iptables的recent模組來抵禦DOS攻擊(SSH 22號埠),建立一個列表,儲存有所有訪問過指定的服務的客戶端IP。

iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP
iptables -I INPUT  -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT  -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j LOG --log-prefix "SSH Attach: "
iptables -I INPUT  -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j DROP

注意:
1)利用connlimit模組將單IP的併發設定為3,會誤殺使用NAT上網的使用者,可以根據實際情況增大該值;
2)利用recent和state模組限制單IP在300s內只能與本機建立2個新連線,被限制五分鐘後即可恢復訪問。
3)第二句是記錄訪問tcp 22埠的新連線,記錄名稱為SSH;
–set 記錄資料包的來源IP,如果IP已經存在將更新已經存在的條目。
4)第三句是指SSH記錄中的IP,300s內發起超過3次連線則拒絕此IP的連線。
–update 是指每次建立連線都更新列表;
–seconds必須與–rcheck或者–update同時使用;
–hitcount必須與–rcheck或者–update同時使用;
5)iptables的記錄:/proc/net/xt_recent/SSH;
也可以使用下面的這句記錄日誌:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --name SSH --second 300 --hitcount 3 -j LOG --log-prefix "SSH Attack"

9、layer7

(1)layer7概述
layer7是一種第三方擴充套件模組,是iptables實現七層訪問過濾所用模組,用來識別應用層協議。

iptables/netfilter
iptables -m state, 
netfilter state

對核心中的netfilter,打補丁layer7,重新編譯核心,對iptables打補丁,補上layer7模組,重新iptables。
(2)diff:文字操作工具
diff是Unix系統的一個很重要的工具程式。它用來比較兩個文字檔案的差異,是程式碼版本管理的核心工具之一。其用法非常簡單:
# diff <變動前的檔案> <變動後的檔案>
由於歷史原因,diff有三種格式:正常格式(normal diff)、上下文格式(context diff)和合並格式(unified diff)。
1)正常格式的diff
例如,對file1(變動前的檔案)和file2(變動後的檔案)進行比較可使用如下命令:# diff file1 file2
顯示結果中,第一行是一個提示,用來說明變動位置。它分成三個部分:前面的數字,表示file1的第n行有變化;中間的"c"表示變動的模式是內容改變(change),其他模式還有"增加"(a,代表addition)和"刪除"(d,代表deletion);
2)上下文格式的diff
上個世紀80年代初,加州大學伯克利分校推出BSD版本的Unix時,覺得diff的顯示結果太簡單,最好加入上下文,便於瞭解發生的變動。因此,推出了上下文格式的diff。它的使用方法是加入-c選項(即context)。
# diff -c f1 f2
結果分成四個部分。第一部分的兩行,顯示兩個檔案的基本情況:檔名和時間資訊,"***“表示變動前的檔案,”—“表示變動後的檔案。第二部分是15個星號,將檔案的基本情況與變動內容分割開。第三部分顯示變動前的檔案,即file1。
另外,檔案內容的每一行最前面,還有一個標記位。如果為空,表示該行無變化;如果是感嘆號(!),表示該行有改動;如果是減號(-),表示該行被刪除;如果是加號(+),表示該行為新增。
第四部分顯示變動後的檔案,即file2。
3)合併格式的diff
如果兩個檔案相似度很高,那麼上下文格式的diff,將顯示大量重複的內容,很浪費空間。1990年,GNU diff率先推出了"合併格式"的diff,將f1和f2的上下文合併在一起顯示。它的使用方法是加入u引數(代表unified):# diff -u f1 f2
其結果的第一部分,也是檔案的基本資訊。”—“表示變動前的檔案,”+++“表示變動後的檔案。第二部分,變動的位置用兩個@作為起首和結束。第三部分是變動的具體內容。除了有變動的那些行以外,也是上下文各顯示3行。它將兩個檔案的上下文,合併顯示在一起,所以叫做"合併格式”。每一行最前面的標誌位,空表示無變動,減號表示第一個檔案刪除的行,加號表示第二個檔案新增的行。
(3)patch:打補丁工具
儘管並沒有指定patch和diff的關係,但通常patch都使用diff的結果來完成打補丁的工作,這和patch本身支援多種diff輸出檔案格式有很大關係。patch通過讀入patch命令檔案(可以從標準輸入),對目標檔案進行修改。通常先用diff命令比較新老版本,patch命令檔案則採用diff的輸出檔案,從而保持原版本與新版本一致。
patch的標準格式為:patch [options] [originalfile] [patchfile]
如果patchfile為空則從標準輸入讀取patchfile內容;如果originalfile也為空,則從patchfile(肯定來自標準輸入)中讀取需要打補丁的檔名。因此,如果需要修改的是目錄,一般都必須在patchfile中記錄目錄下的各個檔名。絕大多數情況下,patch都用以下這種簡單的方式使用:
patch命令可以忽略檔案中的冗餘資訊,從中取出diff的格式以及所需要patch的檔名,檔名按照diff引數中的"原始檔"、"目標檔案"以及冗餘資訊中的"Index:“行中所指定的檔案的順序來決定。
-p引數決定了是否使用讀出的原始檔名的字首目錄資訊,不提供-p引數,則忽略所有目錄資訊,-p0(或者-p 0)表示使用全部的路徑資訊,-p1將忽略第一個”/"以前的目錄,依此類推。如/usr/src/linux-2.4.15/Makefile這樣的檔名,在提供-p3引數時將使用linux-2.4.15/Makefile作為所要patch的檔案。
patch,-p,-R
(4)mockbuild
(5)使用layer7模組操作步驟
1)獲取並編譯核心

# useradd mockbuild
# rpm -ivh kernel-2.6.32-431.5.1.x86_64.el6.src.rpm
# cd rpmbuild/SOURCES
# tar linux-2.6.32-*.tar.gz -C /usr/src
# cd /usr/src
# ln -sv 

2)給核心打補丁

# tar xf netfilter-layer7-v2.23.tar.bz2
# cd /usr/src/linux
# patch -p1 < /root/netfilter-layer7-v2.23/kernel-2.6.32-layer7-2.23.patch
# cp /boot/config-*  .config
# make menuconfig

3)按如下步驟啟用layer7模組
Networking support → Networking Options →Network packet filtering framework → Core Netfilter Configuration
“layer7” match support
4)編譯並安裝核心

# make
# make modules_install
# make install

5)重啟系統,啟用新核心
6)編譯iptables

# tar xf iptables-1.4.20.tar.gz
# cp /root/netfilter-layer7-v2.23/iptables-1.4.3forward-for-kernel-2.6.20forward/* /root/iptables-1.4.20/extensions/
# cp /etc/rc.d/init.d/iptales /root
# cp /etc/sysconfig/iptables-config /root
# rpm -e iptables iptables-ipv6 --nodeps
# ./configure  --prefix=/usr  --with-ksource=/usr/src/linux
# make && make install
# cp /root/iptables /etc/rc.d/init.d
# cp /root/iptables-config /etc/sysconfig

7)為layer7模組提供其所識別的協議的特徵碼

# tar zxvf l7-protocols-2009-05-28.tar.gz
# cd l7-protocols-2009-05-28
# make install	

8)使用layer7模組
ACCT的功能已經可以在核心引數中按需啟用或禁用。此引數需要裝載nf_conntrack模組後方能生效。
net.netfilter.nf_conntrack_acct = 1
l7-filter uses the standard iptables extension syntax

# iptables [specify table & chain] -m layer7 --l7proto [protocol name] -j [action] 
# iptables -A FORWARD -m layer7 --l7proto qq -j REJECT

9)編譯核心

make menuconfig
make -j #
make modules_install
make install

清理核心原始碼樹。
xt_layer7.ko依賴於nf_conntrack.ko模組。