又愛又恨的iptables


一、iptables簡介


iptables 的前身叫ipfirewall (內核1.x時代),這是一個從freeBSD上移植過來的,能夠工作在內核當中的,對數據包進行檢測的一款簡易訪問控制工具。但是 ipfirewall工作功能極其有限(它需要將所有的規則都放進內核當中,這樣規則才能夠運行起來,而放進內核,這個做法一般是極其困難的)。當內核發 展到2.x系列的時候,軟件更名爲ipchains,它可以定義多條規則,將他們串起來,共同發揮作用,而現在,它叫做iptables,可以將規則組成一個列表,實現絕對詳細的訪問控制功能。

iptables和netfilter的關係是一個很容易讓人搞不清的問題。很多的知道iptables卻不知道 netfilter。其實iptables只是Linux防火牆的管理工具而已,位於/sbin/iptables。真正實現防火牆功能的是 netfilter,它是Linux內核中實現包過濾的內部結構。



二、iptables基礎


規則(rules)其實就是網絡管理員預定義的條件,規則一般的定義爲“如果數據包頭符合這樣的條件,就這樣處理這個數據包”。規則存儲在內核空間的信息 包過濾表中,這些規則分別指定了源地址、目的地址、傳輸協議(如TCP、UDP、ICMP)和服務類型(如HTTP、FTP和SMTP)等。當數據包與規 則匹配時,iptables就根據規則所定義的方法來處理這些數據包,如放行(accept)、拒絕(reject)和丟棄(drop)等。配置防火牆的 主要工作就是添加、修改和刪除這些規則。



三、iptables傳輸數據包的過程


① 當一個數據包進入網卡時,它首先進入PREROUTING鏈,內核根據數據包目的IP判斷是否需要轉送出去。 
② 如果數據包就是進入本機的,它就會沿着圖向下移動,到達INPUT鏈。數據包到了INPUT鏈後,任何進程都會收到它。本機上運行的程序可以發送數據包,這些數據包會經過OUTPUT鏈,然後到達POSTROUTING鏈輸出。 
③ 如果數據包是要轉發出去的,且內核允許轉發,數據包就會如圖所示向右移動,經過FORWARD鏈,然後到達POSTROUTING鏈輸出。

wKioL1cht9TxIUWkAAFDRpSsZJI919.png



四、iptables的規則和鏈


上圖中的五個位置也被稱爲五個鉤子函數(hook functions),也叫五個規則鏈。

1.PREROUTING (路由前)

2.INPUT (數據包流入口)

3.FORWARD (轉發管卡)

4.OUTPUT(數據包出口)

5.POSTROUTING(路由後)

 這是netfilter規定的五個規則鏈,任何一個數據包,只要經過本機,必將經過這五個鏈中的其中一個鏈。

iptables包含4個表,5個鏈。其中表是按照對數據包的操作區分的,鏈是按照不同的Hook點來區分的,表和鏈實際上是netfilter的兩個維度。     

(1)4表:

   filter,nat,mangle,raw,默認表是filter(沒有指定表的時候就是filter表)

    filter:一般的過濾功能

    nat:用於nat功能(端口映射,地址映射等)

    mangle:用於對特定數據包的修改

    raw:有限級最高,設置raw時一般是爲了不再讓iptables做數據包的鏈接跟蹤處理,提高性能

(2)5鏈:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING。

    PREROUTING:數據包進入路由表之前

    INPUT:通過路由表後目的地爲本機

    FORWARDING:通過路由表後,目的地不爲本機

    OUTPUT:由本機產生,向外轉發

    POSTROUTING:發送到網卡接口之前。


(3)規則表:
1.filter表——三個鏈:INPUT、FORWARD、OUTPUT
作用:過濾數據包  內核模塊:iptables_filter.
2.Nat表——三個鏈:PREROUTING、POSTROUTING、OUTPUT
作用:用於網絡地址轉換(IP、端口) 內核模塊:iptable_nat
3.Mangle表——五個鏈:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
作用:修改數據包的服務類型、TTL、並且可以配置路由實現QOS內核模塊:iptable_mangle(別看這個表這麼麻煩,咱們設置策略時幾乎都不會用到它)
4.Raw表——兩個鏈:OUTPUT、PREROUTING
作用:決定數據包是否被狀態跟蹤機制處理  內核模塊:iptable_raw


(4)規則鏈:
1.INPUT——進來的數據包應用此規則鏈中的策略
2.OUTPUT——外出的數據包應用此規則鏈中的策略
3.FORWARD——轉發數據包時應用此規則鏈中的策略
4.PREROUTING——對數據包作路由選擇前應用此鏈中的規則
(記住!所有的數據包進來的時侯都先由這個鏈處理)
5.POSTROUTING——對數據包作路由選擇後應用此鏈中的規則
(所有的數據包出來的時侯都先由這個鏈處理)

wKioL1chub7SfmmGAAI092k6rK8143.jpg(5)規則表之間的優先順序:

raw——mangle——nat——filter



五、iptables的命令管理



命令格式:iptables [-t table] SUBCOMMAND chain [matches...] [target]    

如圖示

   wKiom1chufPynWrRAAGdfGiCmc0986.jpg

   wKioL1chu2GD8Y_yAAJuOfLjfic539.jpg

詳細介紹:


(1)鏈管理
    -N: new,新增一條自定義鏈;
    -X:delete,刪除自定義的空鏈;
    -P:policy,設置鏈的默認策略;
         ACCEPT:接受
         DROP:丟棄
         REJECT:拒絕
    -E:rename,重命名自定義的未被引用(引用計數爲0)的鏈;


(2)規則管理
    -A:append,追加,默認爲最後一個;
    -I:insert,插入,默認爲第一個;
    -D:delete,刪除
        (1) rule specification
        (2) rule number
    -R:replace,替換
    -F:flush,清除規則
    -Z:zero,置0;
        iptables的每條規則都有兩個計數器:
             (1) 由本規則匹配到的所有的packets;
             (2) 由本規則匹配到的所有的bytes;
    -S:selected,以iptables-save命令的格式顯示鏈上的規則;


例:虛擬機ip地址爲192.168.1.108,已安裝httpd服務,編寫一條規則讓所有主機不可訪問

[root@bogon ~]# iptables -t filter -A INPUT -d 192.168.1.108 -p tcp --dport 80 -j REJECT

此時再通過瀏覽器就不能訪問apache測試頁面了

再編寫一條規則,讓192.168.1.X網段內的主機可以訪問

[root@bogon ~]# iptables -t filter -D INPUT 1 #先刪除之前的規則
[root@bogon ~]# iptables -t filter -I INPUT -s 192.168.1.0/24 -d 192.168.1.108 -j ACCEPT #添加規則
[root@bogon ~]# iptables -nvL --line-number #查看
Chain INPUT (policy ACCEPT 3 packets, 840 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1       72  5308 ACCEPT     all  --  *      *       192.168.1.0/24       192.168.1.108       

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 51 packets, 5708 bytes)
num   pkts bytes target     prot opt in     out     source               destination

修改本規則,讓本網段內的不能訪問apache測試頁面

[root@bogon ~]# iptables -t filter -R INPUT 1 -s 192.168.1.0/24 -d 192.168.1.108 -j REJECT

(3)查看
    -L: list,列出規則
    -n:numeric,以數字格式顯示地址和端口;
    -v:verbose,詳細信息;-vv, -vvv
    -x:exactly,顯示計數器的精確值而非單位換算後的結果;
    --line-numbers:顯示鏈上的規則的編號;           
    組合:-nvL

[root@bogon ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

    
匹配條件
(4)基本匹配:netfilter自帶的匹配機制
    [!] -s, --source address[/mask][,...]:原地址匹配
    [!] -d, --destination address[/mask][,...]:目標地址匹配
    [!] -i, --in-interface name:限制報文流入的接口,只能用於PREROUTING,INPUT及FORWARD;
    [!] -o, --out-interface name:限制報文流出的接口,只能用於OUTPUT,FORWARD及POSTROUTING;

(5)擴展匹配:經由擴展模塊引入的匹配機制,-m matchname
    隱式擴展:可以不用使用-m選項專門加載響應模塊;前提是要使用-p選項可匹配何種協議;

        tcp、udp、icmp

    顯式擴展:必須由-m選項專門加載響應模塊;
        multiport
        iprange
        string
        time
        connlimit
        limit
        state


(5.1)隱式擴展
    [!]  -p, --protocol PROTOCOL PROTOCOL:
    協議:tcp, udp, icmp, icmpv6, esp, ah, sctp, mh or "all"
                    
    tcp: 隱含指明瞭“-m tcp”,有專用選項:
    [!] --source-port,--sport  port[:port]:匹配報文中的tcp首部的源端口;可以是端口範圍;
    [!] --destination-port,--dport port[:port]:匹配報文中的tcp首部的目標端口;可以是端口範圍;
    [!] --tcp-flags mask comp:檢查報文中mask指明的tcp標誌位,而要這些標誌位comp中必須爲1;
        --tcp-flags  syn,fin,ack,rst  syn
        --tcp-flags  syn,fin,ack,rst  ack,fin
    [!] --syn:
        --syn相當於“--tcp-flags  syn,fin,ack,rst  syn”;tcp三次握手的第一次                      
    udp:隱含指明瞭“-m udp”,有專用選項:
    [!] --source-port,--sport  port[:port]:匹配報文中的udp首部的源端口;可以是端口範圍;
    [!] --destination-port,--dport port[:port]:匹配報文中udp首部的目標端口;可以是端口範圍
                        
    icmp:隱含指明瞭“-m icmp”,有專用選項:
    [!] --icmp-type {type[/code]|typename}
        type/code:
            0/0:echo reply   別人可以ping自己
            8/0:echo request 自己可以ping別人    

例:將虛擬機192.168.1.108設置爲,自己可以ping別人,而別人不能ping自己

對於ping這個協議,進來的爲8(ping),出去的爲0(響應).我們爲了達到目的,需要8出去,允許0進來

[root@bogon ~]# iptables -t filter -A INPUT -d 192.168.1.108 -p icmp --icmp-type 8 -j DROP #設置別人ping自己的數據包不能通過
[root@bogon ~]# iptables -t filter -A OUTPUT -s 192.168.1.108 -p icmp --icmp-type 0 -j ACCEPT #設置自己ping別人的數據包可以通過

               

       
(5.2)顯式擴展          
5.2.1 multiport:多端口匹配
    以離散方式定義多端口匹配,最多可以指定15個端口;          
    [!] --source-ports,--sports port[,port|,port:port]...
    [!] --destination-ports,--dports port[,port|,port:port]...
    [!] --ports port[,port|,port:port]...

 [root@bogon ~]# iptables -I INPUT -s 0/0 -d 192.168.1.108 -p tcp  -m multiport --dports 22,80 -j ACCEPT #允許所有主機訪問192.168.1.108的22和80端口
 [root@bogon ~]# iptables -I OUTPUT -d 0/0 -s 192.168.1.108 -p tcp  -m multiport --sports 22,80 -j ACCEPT #允許192.168.1.108的主機可以通過22和80端口發送數據包

5.2.2 iprange:指明一段連續的ip地址範圍做爲源地址或目標地址匹配;
    [!] --src-range from[-to]:源地址範圍
    [!] --dst-range from[-to]:目標地址範圍

 [root@bogon ~]# iptables -A INPUT -p tcp -m iprange --src-range 192.168.0.100-192.168.0.105 --dport 22 -j ACCEPT #匹配一組ip地址192.168.0.100-192.168.0.105

                
5.2.3 string:對報文中的應用層數據做字符串匹配檢測;
        --algo {bm|kmp}:指明算法
            (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris)
    [!] --string pattern:給定要檢查的字符串模式;
    [!] --hex-string pattern:給定要檢查的字符串模式;
                

[root@bogon ~]# iptables -I OUTPUT -s 192.168.1.108 -d 0/0 -p tcp --sport 80 -m string --algo bm --string "old" -j REJECT #有"old"字符串的拒絕訪問

                
5.2.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...]:匹配一個週中的哪些天; 

[root@bogon ~]# iptables -A INPUT -d 192.168.1.108 -p tcp --dport 23 -m iprange --src-range 192.168.1.1-192.168.1.100 -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 1,2,3,4,5 -j ACCEPT #讓192.168.1.1-192.168.1.100網段內的在工作日的09-18點可以通過23號端口訪問192.168.1.108

                
5.2.5 connlimit:根據每客戶端主機做併發連接數限制,即每客戶端最多可同時發起的連接數量;
    --connlimit-upto n:上限是多少。連接的數量小於等於n時匹配

    --connlimit-above n:下限是多少。最小連接數;           

[root@bogon ~]# iptables -A INPUT -s 0/0 -d 192.168.1.108 -p tcp --dport 23 -m connlimit --connlimit-upto 2 -j ACCEPT #每臺主機的最大連接數爲2個

                
5.2.6 limit:基於令牌桶算法對報文的速率做匹配;           
    --limit rate[/second|/minute|/hour|/day]
    --limit-burst number        

[root@bogon ~]# iptables -R INPUT 3 -d 192.168.1.108 -p icmp --icmp-type 8 -m limit --limit 20/minute --limit-burst 3 -j ACCEPT #表示,每分鐘組多可以有20個ping請求。開始時有3個請求。

5.2.7 state:是conntrack的子集,用於對報文的狀態做連接追蹤;      
    [!] --state state     

是一種顯式擴展,用於檢測會話之間的連接關係的,有了檢測我們可以實現會話間功能的擴展

什麼是狀態檢測?對於整個TCP協議來講,它是一個有連接的協議,三次握手中,第一次握手,我們就叫NEW連接,而從第二次握手以後的,ack都爲1,這是正常的數據傳輸,和tcp的第二次第三次握手,叫做已建立的連接(ESTABLISHED),還有一種狀態,比較詭異的,比如:SYN=1 ACK=1 RST=1,對於這種我們無法識別的,我們都稱之爲INVALID無法識別的。還有第四種,FTP這種古老的擁有的特徵,每個端口都是獨立的,21號和20號端口都是一去一回,他們之間是有關係的,這種關係我們稱之爲RELATED。

一共有5種狀態:
    INVALID:無法識別的連接;
    ESTABLISHED:連接追蹤模板當中存在記錄的連接;
    NEW:連接追蹤模板當中不存的連接請求;
    RELATED:相關聯的連接;
    UNTRACKED:未追蹤的連接;

[root@bogon ~]# iptables -A INPUT -s 192.168.1.0/24 -d 192.168.1.108 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT #允許192.168.1.X網絡內的主機通過22號端口,狀態爲NEW,ESTABLISHED,即新建的,已建立過連接的。
[root@bogon ~]# iptables -R OUTPUT 1 -m state --state ESTABLISHED -j ACCEPT #允許狀態爲ESTABLISHED的數據包通過

    已經追蹤到的並記錄下來的連接:
        /proc/net/nf_conntrack
                    
    連接追蹤功能所能夠記錄的最大連接數量(可調整):
        /proc/sys/net/nf_conntrack_max
                    
         sysctl -w net.nf_conntrack_max=300000
         echo  300000 > /proc/sys/net/nf_conntrack_max
                    
conntrack所能夠追蹤的連接數量的最大值取決於/proc/sys/net/nf_conntrack_max的設定;已經追蹤到的並記錄下來的連接位於/proc/net/nf_conntrack文件中,超時的連接將會被刪除;當模板滿載時,後續的新連接有可能會超時;解決辦法:
    (1) 加大nf_conntrack_max的值;
    (2) 降低nf_conntrack條目的超時時長;
    不同協議的連接追蹤時長:/proc/sys/net/netfilter/



(6)處理動作:
    -j targetname [per-target-options]
        ACCEPT, DROP, REJECT
        RETURN:返回調用的鏈
        REDIRECT:端口重定向
        LOG:日誌
        MARK:防火牆標記
        DNAT:目標地址轉換
        SNAT:源地址轉換
        MASQERADE:地址僞裝


規則的檢查次序:規則在鏈接上的次序即爲其檢查時的生效次序;因此,其優化使用有一定法則;

    (1) 同類規則(訪問同一應用),匹配範圍小的放前面;用於特殊處理;

    (2) 不同類的規則(訪問不同應用),匹配範圍大的放前面;

    (3) 應該將那些可由一條規則描述的多個規則合併爲一;

    (4) 設置默認策略;

規則的有效期限:

    iptables命令添加的規則,手動刪除之前,其生效期限爲kernel的生命週期;



七、SNAT和DNAT的實現


SNAT: source NAT 源地址轉換

    修改IP報文中的源IP地址;

    讓本地網絡中的主機可使用統一地址與外部主機通信,從而實現地址僞裝;

        請求:由內網主機發起,修改源IP,如果修改則由管理員定義;

        響應:修改目標IP,由nat自動根據會話表中追蹤機制實現相應修改;

DNAT: destination NAT 目的地址轉換

    修改IP報文中的目標IP地址;

    讓本地網絡中服務器使用統一的地址向外提供服務(發佈服務),但隱藏了自己的真實地址;

        請求:由外網主機發起,修改其目標地址,由管理員定義;

        響應:修改源地址,但由nat自動根據會話表中的追蹤機制實現對應修改;


SNAT: POSTROUTING(要在POSTROUTING鏈上添加規則)

DNAT: RPEROUTING(要在PREROUTING鏈上添加規則)


SNAT和DNAT誕生的本意是想隱藏本機ip的,但是無心插柳柳成蔭,由於我們現在IP地址十分緊俏,已經分配完了,這就導致我們必須要進行地址轉換,來節約我們僅剩的一點IP資源。如何通過iptables實現NAT的地址轉換呢?

現在大部分家庭使用的上網模式就是源地址轉換模式,即多臺內網主機-->路由器。共用一個外網地址。

1.SNAT基於源地址的轉換

基於原地址的轉換一般用在我們的許多內網用戶通過一個外網的口上網的時候,這時我們將我們內網的地址轉換爲一個外網的IP,我們就可以實現連接其他外網IP的功能。

所以我們在iptables中就要定義到底如何轉換:

定義的樣式:

比如我們現在要將所有192.168.10.0網段的IP在經過的時候全都轉換成172.18.100.1這個假設出來的外網地址:

[root@bogon ~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT --to-source 172.16.100.1


這樣,只要是來自本地網絡的試圖通過網卡訪問網絡的,都會被統統轉換成172.16.100.1這個IP.

那麼,如果172.16.100.1不是固定的怎麼辦?

我們都知道當我們使用聯通或者電信撥號上網的時候,一般它都會在每次你開機的時候隨機生成一個外網的IP,意思就是外網地址是動態變換的。這時我們就要將外網地址換成 MASQUERADE(動態僞裝):它可以實現自動尋找到外網地址,而自動將其改爲正確的外網地址。所以,我們就需要這樣設置:

       

 [root@bogon ~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE

這裏要注意:地址僞裝並不適用於所有的地方。

 

2.DNAT目標地址轉換

對於目標地址轉換,數據流向是從外向內的,外面的是客戶端,裏面的是服務器端通過目標地址轉換,我們可以讓外面的ip通過我們對外的外網ip來訪問我們服務器不同的服務器,而我們的服務卻放在內網服務器的不同的服務器上。


服務器爲內網192.168.10.18,假設有一個外網ip爲172.16.100.2

    如何做目標地址轉換呢?:

[root@bogon ~]# iptables -t nat -A PREROUTING -d 172.16.100.2 -p tcp --dport 80 -j DNAT --to-destination 192.168.10.18

    目標地址轉換要做在到達網卡之前進行轉換,所以要做在PREROUTING這個位置上


八、控制規則的存放以及開啓


注意:你所定義的所有規則,當你重啓的時候都會失效,要想能夠開機生效,需要使用一個命令將它保存起來

    1.service iptables save 命令

        它會保存在/etc/sysconfig/iptables這個文件中

    2.iptables-save 命令

        iptables-save > /etc/sysconfig/iptables 

    3.iptables-restore 命令

開機的時候,它會自動加載/etc/sysconfig/iptabels

如果開機不能加載或者沒有加載,而你想讓一個自己寫的配置文件(假設爲iptables.2)手動生效的話(可以將此寫入到一個腳本中,開機自動執行一次即可/etc/rc.d/rc.local/iptables.sh):

iptables-restore < /etc/sysconfig/iptables.2

則完成了將iptables中定義的規則手動生效

 

 


九、總結



    iptables是一個非常重要的工具,它是每一個防火牆上幾乎必備的設置,也是我們在做大型網絡的時候,爲了很多原因而必須要設置的。學好iptables,可以讓我們對整個網絡的結構有一個比較深刻的瞭解,同時,我們還能夠將內核空間中數據的走向以及linux的安全給掌握的非常透徹。

    由於時間倉促和能力問題,可能有不正之處,請大家不吝賜教,共同學習,進步!





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章