iptables其實是定義防火牆規則的工具,真正對數據報文處理的是內核中的netfilter模塊。netfilter對報文的處理方式通常有:過濾,地址轉換,鏈接追蹤。linux
防火牆其實是對進出本機的各類報文進行控制,因此瞭解常見報文的結構(格式)能夠精確的控制報文。web
ip報文的結構以下圖:vim
在這裏與防火牆關係最大的是源地址、目標地址、協議。源地址指明報文的來源,目標地址說明報文的去處,協議指明傳輸層所使用的協議。安全
補充:bash
ip報文在互聯網中傳輸的時候,要通過各類各樣的網絡設備,可是這些網絡設備的MTU(通常爲1500字節),因此ip報文在傳輸過程當中須要進行分段,每段都有一個分段標識。在目標地址的主機接收到,這些報文後,須要進行組裝,此時就須要靠段偏移來實現。有時候,在網絡中可能會造成迴環現象,爲了不諸如此類現象的發生,TTL(time-to-live)幫咱們解決這個問題,ip報文每通過一個網絡設備,其值會減小1。若是值爲0,咱們就認爲網絡不可達。服務器
這裏咱們使常關注的是:網絡
源地址端口:源地址進程的端口號併發
目標地址端口:目標地址進程對應的端口號ssh
FIN: 結束標識符,tcp斷開鏈接時,此標誌位爲1tcp
SYN: 請求標誌符,客戶端發起請求時,用於標識三次握手
ACK: 序列確認號,創建鏈接後,此標誌位是1。ACK=0,FIN=1一般用來肯定是第一次」握手」
補充:
RST:重置標識,從新創建鏈接的時候會用到
PSH: 此標誌位爲1時,代表在接受端不緩衝,直接處理
URG: 來講明緊急指針是否有效
窗口大小:目的告訴接收方在未收到「我」的確認時,接收方能夠容許發送的數據的最大字節數
原理以下圖所示:
Netfilte在內核中使用5個鉤子(Hook)函數來實現,對應netfilter的5個鏈,它們分別是PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING。對報文作出的動做有4張表raw,mangle,nat,filter來實現。
raw:目標是關閉nat表的鏈接追蹤功能;
mangle:自定義功能。
nat:實現地址轉換(SNAT,DNAT),啓用鏈接追蹤(connection_track)
filter: 實現數據包的過濾功能
PREROUTING:路由前,數據包最早到達的鏈
INPUT:到達本機內部的報文必經之路
FORWARD:由本機轉發的報文必經之路
OUTPUT:由本機發出的報文的必經之路
POSTROUTING:路由後,報文出本機的最後一個鏈
filter: INPUT, FORWARD, OUTPUT
nat: PREROUTING(DNAT),POSTROUTING(SNAT),OUTPUT(SNAT)
mangle: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING
raw: PREROUTING, OUTPUT
優先級從高到底的是:raw,mangle,nat,filter
跟本機內部進程通訊:
進入:PREROUTING, INPUT
出去:OUTPUT, POSTROUTING
由本機轉發:
PREROUTING, FORWARD, POSTROUTING
啓動腳本:/etc/init.d/iptables {start|stop|restart|save}
save是將寫好的規則保存到/etc/sysconfig/iptables,下次啓動時會去讀取此文件中的規則。也可以使用iptables-save重定向到某個文件中,下次可使用iptables-restore命令來導入規則。
iptables [-t TABLE] COMMAND CHAIN [RULE] [-j TARGET]
選項 | 意義 |
-t | 指明處理的表名,默認是filter |
-A|-D|-I|R | 增長、刪除、插入、替換匹配的規則,後面是對應要處理的鏈名 |
-F | 刷新規則庫 |
-Z | 清空計數器 |
-N|-X|-E | 本身 建立、刪除、重命名一個鏈 |
-P | 設置默認策略,常常用來設置黑名單、白名單 |
-L | 列出對應表的防火牆規則,可使用如下子選項 -n 以數字形式顯示ip地址和端口號 -v -vv -vvv 顯示信息的詳細程度 -x 精確顯示匹配到的包數和包的字節數 --line-numbers 列出每一個規則的序列號 --modprobe=command 能夠經過這個加載必要的模塊 |
說明,如下每一個選項前面均可以加 ! 來取反
1)通用的匹配條件
-s | 指明報文的源地址 |
-d | 指明報文的目的地址 |
-p | 指明報文的協議 |
-i | 指明報文的進入的網卡,與INPUT鏈一塊兒使用 |
-o | 指明報文出去的網卡,與OUTPUT一塊兒使用 |
2)擴展匹配
擴展匹配有隱式擴展和顯式擴展,隱式擴展是 -p 指定協議的補充說明,顯式擴展是用 -m 來指定特定的其餘擴展選項。
常見的隱式擴展以下:
tcp協議的擴展選項:
--sport | 指定源端口,udp協議也一樣適用 |
--dport | 指定目標端口,udp協議也一樣適用 |
--tcp-flags | 指明tcp報文中的狀態時,格式:--tcp-flags mask(要檢查的狀態值) comp(爲1的狀態值) 能夠設置的狀態值有SYN ACK FIN RST URG PSH ,ALL表示全部的狀態,NONE表示全部沒有設定 例如:--tcp-flags ALL ALL 檢查全部狀態都爲1 --tcp-flags ALL NONE 檢查全部狀態都爲0 |
--syn | 只檢查SYN狀態標誌位爲1 |
icmp協議的常見擴展:
icmp-type:icmp報文的類型,常見的有0和8,0表明響應報文,8表明請求報文。
常見的顯式擴展以下:
iprange:指明ip範圍的
--src-range | 指明源地址的範圍 用法:--src-range from[-to] 例如:--src-range 192.168.1.1-192.168.1.24 |
--dst-range | 指明目標地址的範圍,用法同--src-range相同 |
multiport:指明多端口,只能用於tcp和udp協議
--sports | 指明多個源端口 例如:--sports 21,22,80,53 |
--dports | 指明多個目標端口 |
--ports | 指明多個端口,這些端口包括源端口和目標端口 |
connlimit:限定鏈接的併發數
--connlimit-above | 同一客戶端的鏈接併發數 |
--connlimit-msak | 指明客戶端的有掩碼位數(prefix length) |
limit:限制傳輸速率的
--limit-rate | 限制傳輸速率的的 用法:--limit rate[/second|/minute|/hour|/day] |
--limit-brust | brust是令牌桶,裏面存放的是令牌的個數。簡單的來講,客戶端只用得帶令牌才能夠傳輸數據,此令牌數會累加 |
string:過濾字符串的
--algo | 指明匹配字符串的加密類型 kmp和bm(根據人名命名的) |
--string | 指明匹配的字符串 |
--hex-string | 匹配的字符串使用十六進制形式給出 |
--from | 指明匹配字符串的開始處,默認是0 |
--to | 指明匹配字符串的結束處,默認是65535 |
time:限定時間和日期
--datestart | 起始日期,格式:YYYY[-MM[-DD[Thh[:mm[:ss]]]]] |
--datestop | 截止日期,格式同上 |
--timestart | 起始時間,格式是:hh:mm[:ss] |
--timestop | 截止時間,格式同上 |
--weekdays | 指定星期數:Mon, Tue, Wed, Thu, Fri, Sat,Sun 也可使用1-7 |
--monthdays day | 指明一個月中的特定天數,1-31均可以使用 |
state:指明鏈接的狀態
--state | 指明鏈接狀態,狀態有: NEW:新創建的鏈接 ESTABLISHED: 已創建的鏈接 RELATED: 關聯的鏈接 INVILID:表示無效的狀態 |
recent: 阻擋大量的請求,例如能夠防止DOS的***
在內核裏面維護了地址列表,這個列表能夠經過--set, --rcheck, --update and --remove四種方法來修改列表。--set, --rcheck, --update and --remove 是相互排斥的,不可同時使用。recent模塊個規則有返回值(布爾值),爲真會執行 -j 指定的動做。
--set | 將地址添加到地址列表中,包含地址的時間戳 |
--name | 指定地址列表的名字,默認是DEFAULT |
--rsource --rdest | 指明當前的規則是應用到數據包的源地址仍是目標地址,默認是源地址 |
--rcheck | 檢查地址是否在地址列表中 |
--remove | 刪除地址列表中的 |
--update | 和rcheck做用同樣,但他會刷新時間戳 |
--hitcount | 指定時間內的命中數(在地址列表中匹配的次數) 必須與-rcheck和--update同時使用 |
--seconds | 用法:--seconds n 限制數據包裏的地址記錄到地址列表裏的時間要小於n 必須與-rcheck和--update同時使用 |
layre7:從應用層來協議來控制,不過CentOS6.5的內核不支持,此時咱們須要向內核打補丁,這一塊會在下面詳細的介紹。
通常有-j選項指定,常見的有:
DROP,ACCEPT,REJECT,DNAT,SNAT,MASQUERADE,RETRUN,MARK,LOG
DROP,ACCEPT,REJECT經常使用與過濾數據包
DNAT,SNAT,MASQUERADE用在地址轉換的模塊
DNAT常與--to-destination一塊兒使用,指明目標地址轉換的地址
SNAT常與--to-source一塊兒使用,指明目標地址轉換的地址,但有時這個地址是動態獲取的,因此就要藉助於MASQUERADE來動態指明要轉換的地址
RETRUN:是跳轉,一般用在自定義的鏈上,在自義鏈中沒法匹配報文時,將其返回主鏈
LOG:是定義日誌功能的
常見的選項有 --log-prefix (用於在日誌信息中標註信息) --log-level(用於指明日誌的級別)
INPUT和OUTPUT默認策略爲DROP,要求:
一、限制本地主機的web服務器在週一不容許訪問;新請求的速率不能超過100個每秒;web服務器包含了admin字符串的頁面不容許訪問;web服務器僅容許響應報文離開本機;
二、在工做時間,即週一到週五的8:30-18:00,開放本機的ftp服務給172.168.1.0 網絡中的主機訪問;數據下載請求的次數每分鐘不得超過5個;
三、開放本機的ssh服務給192.168.1.1-192.168.1.100中主機,新請求創建的速率一分鐘不得超過2個;僅容許響應報文經過其服務端口離開本機;
四、拒絕TCP標誌位所有爲1及所有爲0的報文訪問本機;
五、容許本機ping別的主機;但不開放別的主機ping本機;
# 設置防火牆規則機器的ip地址是192.168.1.99 iptables -A INPUT -p tcp --dport 80 -m time ! --weekdays Mon -m string \ --algo kmp ! --string "admin" -m limit --limit 100/second -j ACCEPT # ftp運行依賴於nf_conntrack_ftp 模塊,因此須要加載此模塊。 #在CerntOS中也能夠編輯/etc/sysconfig/iptables-config配置文件中的IPTABLES_MODULES選項修改 iptables -A INPUT -p tcp --dport 21 -m time --weekdays 1,2,3,4,5 --start-time 08:30 \ --stop-time 18:00 -m limit --climit-rate 5/minute \ --modprobe="modprobe nf_conntrack_ftp" -j ACCEPT iptables -A INPUT -p tcp --dport 22 -m iprange \ --src-range 192.168.1.1-192.168.10.100 -m limit --limit-rate 2/minute -j ACCEPT iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP # 把這條規則放入到INPUT鏈的第一條,對於已創建的鏈接直接放行,提升效率。 # RELATED是相關聯的狀態。例如ftp的被動鏈接 iptables -I INPUT 1 -m state --state ESTABLISED,RELATED -j ACCEPT iptables -A OUTPUT -s 192.168.1.99 -p icmp --icmp-type 8 -j ACCEPT iptables -P INPUT DROP iptables -P OUTPUT DROP # 對於各類響應報文,只要是能進入的數據包,而且是已創建或者相關聯的鏈接都予以放行 iptables -I OUTPUT 1 -m state --state ESTABLISED,RELATED -j ACCEPT
另外一種設置的方法:(使用自定義鏈)
iptables -N httpd_in iptables -A httpd_in -m time ! --weekdays Mon -m string --algo kmp \ ! --string "admin" -m limit --limit 100/second -j ACCEPT iptables -A httpd_in -j RETURN iptables -N ftp_in iptables -A INPUT -m time --weekdays 1,2,3,4,5 --start-time 08:30 \ --stop-time 18:00 -m limit --climit-rate 5/minute \ --modprobe="modprobe nf_conntrack_ftp" -j ACCEPT iptables -A ftp_in -j RETURN iptables -N ssh_in iptables -A ssh_in -m iprange --src-range 192.168.1.1-192.168.10.100 \ -m limit --limit-rate 2/minute -j ACCEPT iptables -A ftp_in -j RETURN iptables -A INPUT -p tcp --dport 80 -d 192.168.1.99 -j httpd_in iptables -A INPUT -p tcp --dport 21 -d 192.168.1.99 -j ftp_in iptables -A INPUT -p tcp --dport 22 -d 192.168.1.99 -j ssh_in iptables -A INPUT -d 192.168.1.99 -p icmp --icmp-type 8 -j DROP iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -p tcp --tcp-flags ALL NONE. -j DROP iptables -I INPUT -m state ESTABLISHED,RELEATED -j ACCEPT iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -I OUTPUT 1 -m state --state ESTABLISED,RELATED -j ACCEPT
情形以下:172.16.10.22經過192.168.1.99這臺主機做爲轉發訪問192.168.1.77的資源。
前提:192.168.1.99主機必須打開路由轉發功能,即內核參數net.ipv4.ip_forward=1
防火牆規則以下:
# 設置轉發策略,放行請求和響應的報文,可是每次這樣轉發效率就不是很高了 ## iptables -A FORWARD -d 192.168.1.77 -p tcp --dport 80 -j ACCEPT iptables -A FORWARD -s 192.168.1.77 -p tcp --sport 80 -j ACCEPT iptables -P FOREARD DROP # 優化策略以下,實現狀態匹配。但此種模式,要開啓鏈接追蹤的功能,很大程度上會消耗防火牆資源 iptables -I FORWARD 1 ESTABLISHED -j ACCEPT iptables -A FORWARD -s 192.168.1.77 -p tcp --sport 80 -m state --state NEW -j ACCEPT iptables -P FOREARD DROP
NAT實現網絡地址轉換,早期是爲了安全角度設置的,如今也可使用節約ip資源,實現內網共享地址上網。常見的地址轉換有:SNAT 源地址轉換,DANT 目的地址轉換,PNAT 端口轉換(一般原DNAT有關),FNAT (在虛擬局域網中會用到)源地址和目標地址轉換。
SNAT:在內網報文離開網絡防火牆以前,作源地址轉換。在外網接收到報文請求後,會先將報文發送到網絡防火牆處,網絡防火牆出會進行目標地址轉換,轉換到請求的內網主機。可是,這一步驟是由網絡防火牆中本身維護的地址映射表來完成的,不須要咱們參與。
前提:(在網絡防火牆處)
有路由功能:net.ipv4.ip_forward=1
FORWARD默認策略是DROP
在網絡防火牆處配置策略:
iptables -I FORWARD 1 -m state --state ESTABLISHED -j ACCEPT iptables -A FORWARD -s 192.168.1.77 -p tcp --dport 80 -m state \ --state NEW -j ACCEPT # 若是SNAT時,地址是不肯定的,可使用MASQUERADE iptables -t nat -A POSTROUTING -s 192.168.1.77 -p tcp --sport 80 \ -j SNAT --to-source 172.16.10.16
DNAT:我想訪問內網中的web服務,在麼辦?內網地址但是不能在公網上路由。因此,此時就須要DNAT轉換,直接請求172.16.10.16(在這裏模擬的是公網地址),由它轉換給內網主機。
前提:(在網絡防火牆處)
有路由功能:net.ipv4.ip_forward=1
FORWARD默認策略是DROP
在網絡防火牆處配置策略:
iptables -I FORWARD 1 -m state --state ESTABLISHED -j ACCEPT iptables -A FORWARD -d 192.168.1.77 -p tcp --dport 80 -m state --state NEW -j ACCEPT # 此時還能夠作端口轉換PNAT,真正的web服務是192.168.1.77:8080端口上 iptables -t nat -A PREROUTING -d 172.16.10.16 -p tcp --dport 80 -j SNAT \ --to-source 192.168.1.77:8080
限制一分鐘以內同一客戶端的ip訪問http協議請求最多10次
# 設置每一個IP的最大http併發請求 iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 10 -j DROP # 對於剛剛創建的請求時,記錄到HTTP的地址列表中,在/proc/net/xt_recent/HTTP iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set --name HTTP # 同一源地址在一分鐘以內請求到達11次時,會對它進行LOG記錄 iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update \ --seconds 60 --hitcount 11 --name HHTP -j LOG --log-prefix "HHTP Attach: " # 同一源地址在一分鐘以內請求到達11次時,會將其拒絕 iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update \ --seconds 60 --hitcount 11 --name SSH -j DROP
layer7是能夠識別應用層協議的模塊,可是CentOS6.5的內核是不支持這個模塊的,此時要對內核打補丁,從新編譯內核。對iptables打補丁,支持layer7模塊,從新編譯iptables。
diff:
diff是Unix系統的一個很重要的工具程序。它用來比較兩個文本文件的差別,是代碼版本管理的核心工具之一。其用法很是簡單:
# diff <變更前的文件> <變更後的文件>
patch:
儘管並無指定patch和diff的關係,但一般patch都使用diff的結果來完成打補丁的工做,這和patch自己支持多種diff輸出文件格式有很大關係。patch經過讀入patch命令文件(能夠從標準輸入),對目標文件進行修改。一般先用diff命令比較新老版本,patch命令文件則採用diff的輸出文件,從而保持原版本與新版本一致。
patch的標準格式爲:
patch [options] [originalfile] [patchfile]
常使用的選項:
-p參數決定了是否使用讀出的源文件名的前綴目錄信息,不提供-p參數,則忽略全部目錄信息,-p0(或者-p 0)表示使用所有的路徑信息,-p1將忽略第一個"/"之前的目錄,依此類推。如/usr/src/linux-2.4.15/Makefile這樣的文件名,在提供-p3參數時將使用linux-2.4.15/Makefile做爲所要patch的文件。
-R 相逆補丁,降級
下載real的源碼格式的rpm,下載地址http://ftp.redhat.com/pub/redhat/linux/enterprise/6Server/en/os/SRPMS/
具體步驟:
#一、獲取並編譯內核 useradd mockbuild rpm -ivh kernel-2.6.32-431.5.1.x86_64.el6.src.rpm tar -xf rpmbuild/SOURCES/linux-2.6.32-431.11.2.el6.tar.bz2 -C /usr/src/cd /usr/src cd /usr/src/ ln -sv linux-2.6.32-431.11.2.el6 linux #二、給內核打補丁 tar xf netfilter-layer7-v2.23.tar.bz2 -C /usr/src cd /usr/src/linux patch -p1 < ../netfilter-layer7-v2.23/kernel-2.6.32-layer7-2.23.patch cp /boot/config-* .config # 先肯定安裝 ncurses 包 make menuconfig 按以下步驟啓用layer7模塊 Networking support → Networking Options →Network packet filtering framework\ → Core Netfilter Configuration <M> 「layer7」 match support 關閉內核簽名功能: Enable loadable modules support -> [ ] Module signature verification Cryptographic API -> [ ] In-kernel signature checker #三、編譯並安裝內核 make make modules_install make install # 四、重啓系統,啓用新內核
具體步驟:
# 一、獲取iptables源碼的rpm包 rpm -ivh /root/iptables-1.4.7-11.el6.src.rpm tar xf /root/rpmbuild/SOURCES/iptables-1.4.7.tar.bz2 # 二、向iptables打補丁 cd /root/rpmbuild/SOURCES/iptables-1.4.7 cp /root/netfilter-layer7-v2.23/iptables-1.4.3forward-for-kernel-2.6.20forward/* ./extensions/ rm -rf iptables-1.4.7.tar.bz2 tar jcf iptables-1.4.7.tar.bz2 iptables-1.4.7/* # 三、修改rpm包的spec文件的下面內容 # vim /root/rpmbuild/SPECS/iptables.spec Release: 12%{?dist} ./configure --enable-devel --enable-libipq --bindir=/bin --sbindir=/sbin --sysconfdir=/etc --libdir=/%{_lib} --libexecdir=/%{_lib} --mandir=%{_mandir} --includedir= %{_includedir} --with-ksource=/usr/src/linux # 四、從新制做rpm包 rpmbuild -ba /root/rpmbuild/SPECS/iptables.spec # 五、升級iptables源碼包 rpm -Uvh /root/rpmbuild/RPMS/x86_64/iptables-1.4.7-12.el6.x86_64.rpm /root/rpmbuild/RPMS/x86_64/iptables-ipv6-1.4.7-12.el6.x86_64.rpm # 六、確認iptables打補丁成功,成功後會出現libxt_layer7.so的模塊 rpm -ql iptables | grep "layer" /lib64/xtables/libxt_layer7.so
具體步驟:
tar zxvf l7-protocols-2009-05-28.tar.gz cd l7-protocols-2009-05-28 make install
# 一、加載內核模塊 modprobe nf_conntrack modprobe xt_layer7 # 二、修改內核參數,此參數須要裝載nf_conntrack模塊後方能生效。 net.netfilter.nf_conntrack_acct = 1
至此,layer7模塊就可使用了。
用法以下:
iptables [specify table & chain] -m layer7 --l7proto [protocol name] -j [action]
例如:iptables -A FORWARD -m layer7 --l7proto qq -j REJECT # 在應用層放行qq協議的數據包
實驗拓撲圖:實現內網主機上網功能,可是不容許qq,xunlei協議的數據包。
前提:(在網絡防火牆處)
有路由功能:net.ipv4.ip_forward=1
FORWARD默認策略是ACCEPT
在網絡防火牆處配置策略:
iptables -A FORWARD -m layer7 --l7proto qq,xunlei -j REJECT iptables -t nat -A POSTROUTING -s 192.168.1.77 -j SNAT --to-source 172.16.10.16
RAW表只使用在PREROUTING鏈和OUTPUT鏈上,由於優先級最高,從而能夠對收到的數據包在鏈接跟蹤前進行處理。一但用戶使用了RAW表,在某個鏈上,RAW表處理完後,將跳過NAT表和 ip_conntrack處理,即再也不作地址轉換和數據包的連接跟蹤處理了。
RAW表能夠應用在那些不須要作nat的狀況下,以提升性能。如大量訪問的web服務器,可讓80端口再也不讓iptables作數據包的連接跟蹤處理,以提升用戶的訪問速度。
實際測試發現filter鏈仍然處理一些NOTRACK的包,但沒有進行connect tracking,因此filter鏈條裏必須將UNTRACKED狀態的包放行
iptables的連接跟蹤表最大容量爲/proc/sys/net/ipv4/ip_conntrack_max,連接碰到各類狀態的超時後就會從表中刪除。
因此解決方法通常有兩個:
(1) 加大 ip_conntrack_max 值
# vi /etc/sysctl.conf net.ipv4.ip_conntrack_max = 393216 net.ipv4.netfilter.ip_conntrack_max = 393216
(2): 下降 ip_conntrack timeout時間
#vi /etc/sysctl.conf net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 300 net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120 net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60 net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120
至此,iptables的基礎配置介紹完畢。