iptables的觀念與使用

iptables的觀念與使用

1.前言

"iptables" 主要是第一層 : 封包過濾式的 netfilter 防火牆,他不是一種服務,是操作netfilter的命令。

Ubuntu server環境,防火牆有很多選擇,從最為易用便捷的 "ufw" 防火牆(Ubuntu預設),到較新的動態防火牆 " Firewalld ",再到較為專業的防火牆 "iptables"  一應俱全,如何選擇一款合適的防火牆呢?沒有標準答案,但肯定有最合適的選擇。

其中,iptables 這個工具功能全面強大,可以實現很多 ufw 及  Firewalld無 法完成的網絡功能,推薦有一定基礎的用戶使用。

2.理論與觀念

正確的觀念,才能理解,才能正確地應對不同的入侵方式。

iptables防火牆的結構

iptables 是Linux中功能最為強大的防火牆,使用靈活,可以對流入和流出伺服器的數據包進行很精細的控制,當然如果只是用來開啟或禁止某個網絡服務的某個網絡埠,它和 ufw 以及Firewalld都差不多

iptables的三大核心要素是表,鏈和規則。

一言以蔽之,iptables是表的集合,包含四張表(常用的三張 filter, nat, mangle),表則是鏈的集合,每個表都包含若干個鏈, 而鏈則是規則的集合,真正過濾規則是屬於鏈,iptables的處理流程如下圖所示:



從上圖可觀察到Kernel處理和過濾數據包的流程,描述了封包進入主機到離開主機,會經過哪些tables,這些tables裡面會寫規則,進行放行或攔截。

大致上你可以發現數據包在主機流通時有四張表、五個階段:

iptables 四張表(彩色的部分)

  • filter : 
    • 整個iptables最關鍵的表,實現封包的過濾,可以由INPUT,FORWARD,OUTPUT這三個能夠實現過濾功能的鏈組成。
  • nat  :  
    • 學過網路的人應該都知道NAT(Network Address Translation)網路地址轉換,正是應為有了這項技術才使得我們現今還能夠有IPv4可以使用,在iptables中也可以實現NAT的相關功能, 例如SNAT, DNAT, MASQUERADE等功能,nat表可以由PREROUTING, FORWARD, POSTROUTING組成
  • mangle : 
    • mangle可以對匹配到的報文的資料包進行拆解,做出修改,重新封裝等操作,一般我們用的很少,五個鏈都能實現mangle的功能。
  • raw  :  
    • 優先級最高,設置raw時一般是為了不再讓iptables做數據包的鏈接跟踪處理,raw關閉NAT的連線追蹤機制,防止在高並行的存取下伺服器的記憶體溢位導致故障,可由PREROUTING,OUTPUT實現。

五個階段(鏈)

  • PREROUTING  :  
    • 資料包文進入TCP/IP協定棧路由選擇前會被PREROUTING“鉤”住,分析其封包對其相應操作,注意:PREROUTING鏈不能對封包進行過濾,PREROUTING鏈是整個netfilter框架中的第一關。
  • INPUT  :  
    • 通過PREROUTING後進行路由選擇如果封包是進入本機內部,則轉發到INPUT鏈,INPUT鏈能夠通過實現定義好的規則對封包進行篩選如果被匹配則執行相應動作,INPUT鏈可以對封包進行過濾,INPUT鏈是資料包文進入使用者空間的必經之路。
  • FORWARD  :  
    • 通過PREROUTING後進行路由選擇如果封包只是通過本機進行轉發,則轉發到FORWARD鏈,FORWARD鏈能夠通過事先定義好的規則對封包進行匹配檢查並執行相應動作,INPUT鏈可以對封包進行過濾,正是有了FORWARD鏈iptables才能夠作為一個網路防火牆執行在網路邊緣對進出網路的資料包文進行過濾。
  • OUTPUT  :  
    • 封包從使用者空間的進程通過路由選擇特定的網絡卡介面後轉到OUTPUT鏈,OUTPUT鏈能夠通過實現定義好的規則對資料包文進行匹配檢查並執行相應動作,OUTPUT鏈可以對封包進行過濾。
  • POSTROUTING :  
    • 封包從OUTPUT或FORWARD轉發而來,到達netfilter框架中的最後一關,分析封包並執行對應動作,和POSTROUTING一樣不能對封包進行過濾。

而且不是每個封包都會經過這五個階段,從主機內部出來的封包就會從output階段開始、通過主機把主機當router的封包就不會經過INTPUT和OUTPUT,反而會通過FORWARDING。

讓我們先不要管藍色的MANGLE,那是比較複雜的設定,也比較少用到。

我們可以更簡化的把「封包流動」觀念抽象成下圖:



表與鏈的包含關係:

  • filter :      INPUT、FORWARD、OUTPUT
  • nat :         PREROUTING(DNAT)、OUTPUT、POSTROUTING(SNAT)
  • mangle :  PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
  • raw  :       PREROUTING、OUTPUT

鏈與表的包含關係:

  • PREROUTING的規則可存在於:   nat、mangle、raw
  • INPUT的規則可存在於: mangle、filter
  • FORWARD的規則可存在於:mangle、filter
  • OUTPUT的規則可存在於:raw、mangle、nat、filter
  • POSTROUTING的規則可存在於:mangle、nat

iptables中規則的設定

有n張table,每張table內有m個chain,每個chain裡面有一系列的rule。

下面這張圖是iptables內建的table和chain。


每張table都有各自負責的工作,不要把規則隨意寫到任意table

  • Filter table  負責過濾進入主機或離開主機、還有經過主機做forward的封包。
  • NAT table   負責進行NAT,也就是更改source IP/port或destination IP/port。請不要在NAT table中進行過濾的工作。如果你做了,他會把你擋下來並且說你不行XD。
  • MANGLE  不講,因為少用而且我也不懂。

你可以自行在任意table的任意chain上添加或修改rule,也可以自己添加自定義的chain,再在裡面寫rule。

  • 規則由上往下依序比對,這些rule包含「accept, drop, reject, return」,只要一符合該規則,接下來該封包就會直接套用上去pass或丟棄或阻擋。
  • 你可以在內建的chain中指定跳到某個自訂的chain比對。如果比對成功會套用規則,如果失敗,那就會自動return回當初跳過去的chain的rule位置,並繼續比對下去。

3.應用

基礎

使用指令查看系統是否安裝防火牆

  • $whereis iptables

安裝 iptables:

  • $sudo apt install iptables

啟動 iptables 服務

  • $service iptables [start | restart | status]
    • 當啟動 iptables時,會讀入 /etc/sysconfig/iptables 的檔案內容,該檔案儲存之前對防火牆設定的內容,如此一來重開機時,原來的設定還繼續可用。bles 需先產生它

清除已有iptables規則

  • iptables -F     //刪除表中所有規則。
  • iptables -X     //刪除自定義鏈。
  • iptables -Z     //將表中數據包計數器和流量計數器歸零。

列出規則

  • $sudo iptables [-t Table] -L -n                     # 這可以列出你iptables現在的規則
    • -t Tables: 如果你沒有寫就代表預設指定Filter table
    • 如果你下 -t nat 代表使用nat Table,這樣該指令會列出nat這張tables下所有chain的規則
    • -L 代表List chain rule
    • -n 代表避開dns反查,這樣會直接列IP速度也比較快
Ubuntu 服務器默認不實施任何限制,但為了將來參考,請使用以下命令檢查當前的 iptable 規則。
  • $sudo iptables -L  #這將打印出三個鏈的列表,INPUT、FORWARD 、OUTPUT,就像下面的空規則表。

指令格式

「指定某張table裡的某個chain,進行[添加/移除/修改] rule,而這些rule包含通過、阻擋、丟棄、跳到其他chain繼續比對、修改source/destination IP/port」...更多指令規則請自己man iptables,或是你喜歡網頁版的話,請參考wikibook-iptables

  • iptables -A [命令選項] -s [匹配條件] -ACCEOT[相應操作] [.....還有很多自己man]

    命令選項 : 

    • 用於指定iptables的執行方式,包括插入規則,刪除規則和添加規則
      • -A  some_chain : append rule到某個chain的最後面。
      • -I add some_chain : Insert rule到某個chain的最前面1條。
      • -I some_chain 3: Insert rule到某個chain的第三個rule。
      • -D:從規則列表中刪除1條規則。
      • -F:刪除表中所有規則。
      • -L:查看iptables規則列表。
      • -P:定義默認策略。
      • -R:替換規則列表中的某條規則。
      • -X:刪除自定義鏈。
      • -Z:將表中數據包計數器和流量計數器歸零。

    匹配條件 :

    • 匹配條件用來實現更為精細和具體的條件,如網絡接口名稱,協議名稱,源目的埠號等,
        • -i:網絡接口名稱 #指定數據包從哪個網絡接口進入
          • -m:匹配的模塊 #指定數據包規則所使用的過濾模塊
            • -o:網絡接口名稱 #指定數據包從哪個網絡接口輸出
              • -p:協議名稱 #指定數據包匹配的協議,如TCP、UDP和ICMP等
                • --state:數據包當前狀態 #指定ESTABLISHED,RELATED等
                  • --dport:目的埠號 #指定數據包匹配的目的埠號iptables規則的動作,match TCP或UDP封包的port,port的格式可以是 -dport 80或是 -dport 80:90
                  • --sport:源埠號 #指定數據包匹配的源埠號,格視同上 -dport
                    • -s 來源:source IP, 來源的格式可以是 192.168.1.1或是192.168.1.1/24,也可以是 -s ! source,這會排除所有source
                      • -d 目的地:敘述同上。
                        • -p 協定:協定可以是tcp, udp, icmp
                        • -j : 套用的rule , -j rule,這裡的rule其實是「target of rule」,也就是你可以是一個chain_name,或是「ACCEPT, DROP, QUEUE, RETURN, REJECT, LOG, DNAT, SNAT」

                      相應操作 : 

                      • -ACCEPT:接受數據包
                      • -DNAT:目標地址轉換,即改變數據包的目的地址。例如:將的廣域網IP(222.101.98.54/24) ==> 區域網的IP(.1/24),且在NAT表的PREROUTING鏈上進行該動作
                      • -DROP:丟棄數據包
                      • -LOG:日誌功能,將符合規則的數據包的相關信息記錄在日誌中,便於分析和排錯
                      • -MASQUERADE:IP偽裝,改寫數據包來源IP為防火牆的IP及埠,和SNAT不同的是,當進行IP偽裝時,不需指定要偽裝成哪個IP,IP會從網卡直接讀取
                      • -EDIRECT:與DROP基本一樣,區別在於它除了阻塞包之外,還向發送者返回錯誤信息
                      • -SNAT:源地址轉換,即改變數據包的源地址

                      進階指令

                      新增規則Add Rules

                      封鎖你討厭的人的IP,讓他永遠無法跟你連線,假設是140.113.235.151

                      • $sudo iptables -A INPUT -s 140.113.235.151 -d 你自己的IP -j REJECTED
                      內部機器無法連到特定IP: 如 140.1.1.1
                      • $sudo iptables -A FORWARD -d 140.1.1.1 -p tcp -j DROP
                        • 對內部機器連線到外部,定義在filter table(預設值,因此 -t filter 可省略) 中的FORWARD chain,因此指令如上。

                      刪除規則Delete Rules

                      你反悔了,你想要和他和好

                      • $sudo iptables -D INPUT n    #n填入由上往下數第幾個規則,第1個就填1第2個就填2...

                      設定NAT

                      設定NAT不能在Filter這張表中設定,要在nat這張表中設定,所以請一定要記得-t nat

                      先觀察nat這張表的預設規則是什麼

                      • $sudo iptables -t nat -L -n

                      我這台機器後面有192.168.2.0/24的子網域,我想讓這些人可以正常上網。

                      我想讓外面的人透過port 222連到我內部內網的port 192.168.2.1這台server的port 22,來進行ssh

                      • $sudo iptables -t nat -A PREROUTING  -d x.x.x.x(你家IP) -p tcp --dport 222  -j DNAT--to-destination 192.168.2.1:22
                        • 為什麼是改PREROUTING? 因為封包到你機器進行route前會先經過preroute,這時你就可以趁天賜良機(?)的時候改掉目的地。達成NAT的效果

                      預設的nat table規則是什麼?

                      • $sudo iptables -t nat -L -n

                      匯出/匯入設定檔

                      • $sudo iptables-save > 你電腦裡(例如:~/iptables_save_03062019.txt)
                      • $sudo iptables-restore < 你電腦裡(例如:~/iptables_save_03062019.txt)

                      你有一連串討厭的人,不想和他們連線

                      那我們最好另外開一條chain來管理所有你討厭的人

                      • $sudo iptables -N BLACKLIST   
                        • # 在Filter這個預設table下開一條新的chain叫做BLACKLIST
                      • $sudo iptables -A BLACKLIST  -s 140.113.235.151 -d 你自己的IP -j REJECTED  #
                        •  加入兩個你討厭的人
                      • $sudo iptables -A BLACKLIST  -s 140.113.235.152 -d 你自己的IP -j REJECTED
                      • $sudo iptables -A INPUT -j BLACKLIST 
                        • # 讓所有進入的封包都要經過BLACKLIST chain進行比對

                      指定一個IP range,不想讓這個IP range的所有人透過tcp連線到我的port 22

                      • $sudo iptables -A INPUT -p tcp --dport 22 -m iprange --src-range 192.168.1.100-192.168.1.200 -j REJECT
                        • -m 的意思是match,先match到的先得

                      你很害羞,不想讓所有人ping到你。

                      • $sudo iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
                        • ping是使用icmp protocal實作的,其他的機器會對你發出echo-request,這時你要選擇無視他(Drop)。

                      三個典型的iptables命令:

                      • $sudo iptables -A INPUT -i ens33 -p tcp --sport 22 -j ACCEPT
                      • $sudo iptables -A INPUT -i ens33 -p tcp --sport 80 -j ACCEPT
                      • $sudo iptables -A INPUT -i ens33 -p tcp --sport 443 -j ACCEPT

                      上述命令看似複雜,但將其拆開來看的話,其實真的很簡單。

                      • -A表示將此條規則附加到的iptables規則上,由於沒有指定鏈名,故採用默認的鏈Filter。
                      • -i參數指定了此規則所用的網絡接口 ens33,在編寫自己的規則時,由於伺服器網口眾多,請確保知道通過哪個網口連接到網絡。
                      • -p參數用於指定協議,以上這條規則適用於TCP協議,-m參數有點不同,用於判斷必須滿足的條件才能使流量不被拒絕,過濾條件是數據包的狀態。
                      • --state參數後接具體狀態名,如ESTABLISHED或RELATED等,還有就是--sport參數表示源埠,告訴iptables流量來自哪個埠,
                      • -j參數,它用於對符合此條iptables規則的數據包所執行的操作,如ACCEPT、DROP或REJECT等。

                      其他常用指令

                      我的主機只提供網站與郵件服務

                      由於郵件伺服器是透過SMTP port 25(TCP),Web服務是透過 HTTP port 80 (TCP),可用如下規則:
                      • $sudo iptables -A INPUT -p tcp --dport 25 -j ACCEPT
                      • $sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
                      • $sudo iptables -A INPUT -p tcp -i eth0 -j DROP
                      或是
                      • $sudo iptables -A INPUT -p tcp -m multiport 25,80 -j ACCEPT
                      • $sudo iptables -A INPUT -p tcp -i eth0 -j DROP

                      查看當前所有規則

                      • $sudo iptables -vnL

                      清除當前所有規則

                      清理當前所有規則的目的是防止當前的規則影響自己規則,並能夠按照自己的想法生效,建議先將老規則保存後再執行此命令比較穩妥。

                      • $sudo iptables -F 
                      • $sudo iptables -X 
                      • $sudo iptables -Z

                      允許迴路Loopback

                      Loopback是Linux系統所使用的內部接口,一定要允許迴路Loopback
                      • $sudo iptables -A INPUT -i lo -j ACCEPT

                      禁止其他主機Ping Ubuntu伺服器

                      通常伺服器不允許其他主機ping自己,實現方法如下:
                      • $sudo iptables -A INPUT -i ens33 -p icmp -j DROP
                      如果要禁止來自某一IP的ping,可以使用如下命令:
                      • $sudo iptables -A INPUT -i ens33 -p icmp -s 192.168.1.4 -j DROP
                        • #禁止192.168.1.4發出的ping

                      封殺指定IP

                      可使用iptables封殺指定IP,關鍵操作如下:
                      • $sudo iptables -I INPUT -i ens33 -s 192.168.1.4 -j DROP 
                        • #DROP掉來自192.168.1.4的所有數據包
                        • 在上述規則存在的添加下,要解封IP 192.168.1.23,只需將參數-I換成-D即可。
                      此外如果要想清空封掉的IP位址,可以運行如下命令:
                      • $sudo iptables -F

                      封殺指定網段

                      要添加IP段到封停列表中,使用下面的命令:
                      • $sudo iptables -I INPUT -i ens33 -s 192.168.1.0/24 -j DROP 
                        • #DROP掉所有來自192.168.1.0網段的數據包

                      封殺指定埠

                      可使用iptables封殺指定IP埠,關鍵操作如下:
                      • $sudo iptables -I INPUT -i ens33 -p tcp --dport 1234 -j DROP
                        • #封殺123埠
                      如果要放行某些IP的1234埠,可以進行如下操作:
                      • $sudo iptables -I INPUT -i ens33 -s 192.168.1.0/24 -p tcp --dport 1234 -j ACCEPT 
                        • #放行源地址來自192.168.1.0網段1234埠的所有數據包

                      允許SSH服務

                      伺服器大多需要SSH服務,iptables需要開啟SSH埠,具體操作如下:
                      • $sudo iptables -A INPUT -i ens33 -p tcp --dport 22 -j ACCEPT

                      允許域名服務

                      伺服器要啟用DNS服務,iptables需要開啟相應埠,關鍵操作如下:
                      • $sudo iptables -A INPUT -i ens33 -p tcp --dport 53 -j ACCEPT
                      • $sudo iptables -A INPUT -i ens33 -p udp --dport 53 -j ACCEPT 
                        • #大於512位元組的請求將使用TCP的53埠,因為UDP的最大長度為512位元組,而TCP的長度則可以超過512位元組

                      允許時間服務

                      需要允許的計算機連接到NTP伺服器以獲取時間,具體操作如下:
                      • $sudo iptables -A INPUT -i ens33 -p udp --dport 123 -j ACCEPT

                      允許Email服務

                      對於電子郵件的發送和接收比較麻煩,這裡採用默認和安全兩種方式,關鍵操作如下:

                      • SMTP
                        • $sudo iptables -A INPUT -i ens33 -p tcp --dport 25 -j ACCEPT
                        • $sudo iptables -A INPUT -i ens33 -p tcp --dport 465 -j ACCEPT
                      • POP3
                        • $sudo iptables -A INPUT -i ens33 -p tcp --dport 110 -j ACCEPT
                        • $sudo iptables -A INPUT -i ens33 -p tcp --dport 995 -j ACCEPT
                      • IMAP
                        • $sudo iptables -A INPUT -i ens33 -p tcp --dport 143 -j ACCEPT
                        • $sudo iptables -A INPUT -i ens33 -p tcp --dport 993 -j ACCEPT

                      如果是上述之外的服務,如MySQL或Postgre等,請用相應埠替換即可。

                      拒絕其它數據包

                      • $sudo iptables -A INPUT -j REJECT
                      • $sudo iptables -A FORWARD -j REJECT
                      • $sudo iptables -A OUTPUT -j REJECT

                      LOG通過該規則的封包

                      • $sudo iptables ....somerule... -j LOG
                        • 要如何觀察呢? 在ubuntu上是tail -f /var/log/kern.log

                      參考資料

                      特色、摘要,Feature、Summary:

                      關鍵字、標籤,Keyword、Tag:

                      • Ubuntu,Linux,Security,

                      留言

                      這個網誌中的熱門文章

                      Ubuntu 常用指令、分類與簡介

                      網路設定必要參數IP、netmask(遮罩)、Gateway(閘道)、DNS

                      了解、分析登錄檔 - log

                      Python 與SQLite 資料庫

                      Blogger文章排版範本

                      Pandas 模組

                      如何撰寫Shell Script

                      查詢指令或設定 -Linux 線上手冊 - man

                      下載網頁使用 requests 模組