一、什么是iptables
iptables是Linux的防火牆管理工具而已,真正實現防火牆功能的是Netfilter,我們配置了iptables規則后Netfilter通過這些規則來進行防火牆過濾等操作
Netfilter模塊:
它是主要的工作模塊,位於內核中,在網絡層的五個位置(也就是防火牆四表五鏈中的五鏈)注冊了一些鈎子函數,用來抓取數據包;把數據包的信息拿出來匹配各個各個鏈位置在對應表中的規則:匹配之后,進行相應的處理ACCEPT、DROP等等。
下面這張圖很明了的說明了Netfilter和iptables之間的關系
二、四表五鏈(重要)
四表五鏈:
鏈就是位置:共有五個 進路由(PREROUTING)、進系統(INPUT) 、轉發(FORWARD)、出系統(OUTPUT)、出路由(POSTROUTING);
表就是存儲的規則;數據包到了該鏈處,會去對應表中查詢設置的規則,然后決定是否放行、丟棄、轉發還是修改等等操作。
2.1. 具體的四表
- filter表——過濾數據包
- Nat表——用於網絡地址轉換(IP、端口)
- Mangle表——修改數據包的服務類型、TTL、並且可以配置路由實現QOS
- Raw表——決定數據包是否被狀態跟蹤機制處理
2.2. 具體的五鏈
- INPUT鏈——進來的數據包應用此規則鏈中的策略
- OUTPUT鏈——外出的數據包應用此規則鏈中的策略
- FORWARD鏈——轉發數據包時應用此規則鏈中的策略
- PREROUTING鏈——對數據包作路由選擇前應用此鏈中的規則(所有的數據包進來的時侯都先由這個鏈處理)
- POSTROUTING鏈——對數據包作路由選擇后應用此鏈中的規則(所有的數據包出來的時侯都先由這個鏈處理)
2.3. 四表五鏈之間的關系
三、iptables語法參數
3.1.iptables語法格式
iptables [-t 表名] 選項 [鏈名] [條件] [-j 控制類型]
3.2.iptables常用參數
-P 設置默認策略:iptables -P INPUT (DROP|ACCEPT) -F 清空規則鏈 -L 查看規則鏈 -A 在規則鏈的末尾加入新規則 -I num 在規則鏈的頭部加入新規則 -D num 刪除某一條規則 -s 匹配來源地址IP/MASK,加嘆號"!"表示除這個IP外。 -d 匹配目標地址 -i 網卡名稱 匹配從這塊網卡流入的數據 -o 網卡名稱 匹配從這塊網卡流出的數據 -p 匹配協議,如tcp,udp,icmp --dport num 匹配目標端口號 --sport num 匹配來源端口號
四、常用實例
以下例子大家都可以直接進行根據需求更改使用
1. 刪除已有規則 在開始創建iptables規則之前,你也許需要刪除已有規則。命令如下: iptables -F (or) iptables –flush 查看已有規則 iptables -nL 2.設置鏈的默認策略 鏈的默認政策設置為”ACCEPT”(接受),若要將INPUT,FORWARD,OUTPUT鏈設置成”DROP”(拒絕),命令如下: iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP 當INPUT鏈和OUTPUT鏈都設置成DROP時,對於每一個防火牆規則,我們都應該定義兩個規則。例如:一個傳入另一個傳出。在下面所有的例子中,由於我們已將DROP設置成INPUT鏈和OUTPUT鏈的默認策略,每種情況我們都將制定兩條規則。 當然,如果你相信你的內部用戶,則可以省略上面的最后一行。例如:默認不丟棄所有出站的數據包。在這種情況下,對於每一個防火牆規則要求,你只需要制定一個規則——只對進站的數據包制定規則。 3. 阻止指定IP地址 例:丟棄來自IP地址x.x.x.x的包 BLOCK_THIS_IP="x.x.x.x" iptables -A INPUT -s "$BLOCK_THIS_IP" -j DROP 注:當你在log里發現來自某ip地址的異常記錄,可以通過此命令暫時阻止該地址的訪問以做更深入分析 例:阻止來自IP地址x.x.x.x eth0 tcp的包 iptables -A INPUT -i eth0 -s "$BLOCK_THIS_IP" -j DROP iptables -A INPUT -i eth0 -p tcp -s "$BLOCK_THIS_IP" -j DROP 4. 允許所有SSH的連接請求 例:允許所有來自外部的SSH連接請求,即只允許進入eth0接口,並且目標端口為22的數據包 iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT 5. 僅允許來自指定網絡的SSH連接請求 例:僅允許來自於192.168.100.0/24域的用戶的ssh連接請求 iptables -A INPUT -i eth0 -p tcp -s 192.168.100.0/24 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT 6.允許http和https的連接請求 例:允許所有來自web - http的連接請求 iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT 例:允許所有來自web - https的連接請求 iptables -A INPUT -i eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT 7. 使用multiport 將多個規則結合在一起 允許多個端口從外界連入,除了為每個端口都寫一條獨立的規則外,我們可以用multiport將其組合成一條規則。如下所示: 例:允許所有ssh,http,https的流量訪問 iptables -A INPUT -i eth0 -p tcp -m multiport --dports 22,80,443 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp -m multiport --sports 22,80,443 -m state --state ESTABLISHED -j ACCEPT 8. 允許從本地發起的SSH請求 iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT 請注意,這與允許ssh連入的規則略有不同。本例在OUTPUT鏈上,我們允許NEW和ESTABLISHED狀態。在INPUT鏈上,我們只允許ESTABLISHED狀態。ssh連入的規則與之相反。 9. 僅允許從本地發起到一個指定的網絡域的SSH請求 例:僅允許從內部連接到網域192.168.100.0/24 iptables -A OUTPUT -o eth0 -p tcp -d 192.168.100.0/24 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT 10. 允許從本地發起的HTTPS連接請求 下面的規則允許輸出安全的網絡流量。如果你想允許用戶訪問互聯網,這是非常有必要的。在服務器上,這些規則能讓你使用wget從外部下載一些文件 iptables -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT 注:對於HTTP web流量的外聯請求,只需要將上述命令中的端口從443改成80即可。 11. 負載平衡傳入的網絡流量 使用iptables可以實現傳入web流量的負載均衡,我們可以傳入web流量負載平衡使用iptables防火牆規則。 例:使用iptables nth將HTTPS流量負載平衡至三個不同的ip地址。 iptables -A PREROUTING -i eth0 -p tcp --dport 443 -m state --state NEW -m nth --counter 0 --every 3 --packet 0 -j DNAT --to-destination 192.168.1.101:443 iptables -A PREROUTING -i eth0 -p tcp --dport 443 -m state --state NEW -m nth --counter 0 --every 3 --packet 1 -j DNAT --to-destination 192.168.1.102:443 iptables -A PREROUTING -i eth0 -p tcp --dport 443 -m state --state NEW -m nth --counter 0 --every 3 --packet 2 -j DNAT --to-destination 192.168.1.103:443 12. 允許外部主機ping內部主機 iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT 13. 允許內部主機ping外部主機 iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT 14. 允許回環訪問 例:在服務器上允許127.0.0.1回環訪問。 iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT 15. 允許內部網絡域外部網絡的通信 防火牆服務器上的其中一個網卡連接到外部,另一個網卡連接到內部服務器,使用以下規則允許內部網絡與外部網絡的通信。此例中,eth1連接到外部網絡(互聯網),eth0連接到內部網絡(例如:192.168.1.x)。 iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT 16. 允許出站的DNS連接 iptables -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT iptables -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT 17. 允許NIS連接 如果你使用NIS管理用戶帳戶,你需要允許NIS連接。如果你不允許NIS相關的ypbind連接請求,即使SSH連接請求已被允許,用戶仍然無法登錄。NIS的端口是動態的,先使用命令rpcinfo –p來知道端口號,此例中為853和850端口。 rpcinfo -p | grep ypbind 例:允許來自111端口以及ypbind使用端口的連接請求 iptables -A INPUT -p tcp --dport 111 -j ACCEPT iptables -A INPUT -p udp --dport 111 -j ACCEPT iptables -A INPUT -p tcp --dport 853 -j ACCEPT iptables -A INPUT -p udp --dport 853 -j ACCEPT iptables -A INPUT -p tcp --dport 850 -j ACCEPT iptables -A INPUT -p udp --dport 850 -j ACCEPT 注:當你重啟ypbind之后端口將不同,上述命令將無效。有兩種解決方案: 1)使用你NIS的靜態IP 2)編寫shell腳本通過“rpcinfo - p”命令自動獲取動態端口號,並在上述iptables規則中使用。 18. 允許來自指定網絡的rsync連接請求 例:允許來自網絡192.168.101.0/24的rsync連接請求 iptables -A INPUT -i eth0 -p tcp -s 192.168.101.0/24 --dport 873 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 873 -m state --state ESTABLISHED -j ACCEPT 19. 允許來自指定網絡的MySQL連接請求 很多情況下,MySQL數據庫與web服務跑在同一台服務器上。有時候我們僅希望DBA和開發人員從內部網絡(192.168.100.0/24)直接登錄數據庫,可嘗試以下命令: iptables -A INPUT -i eth0 -p tcp -s 192.168.100.0/24 --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 3306 -m state --state ESTABLISHED -j ACCEPT 20. 允許Sendmail, Postfix郵件服務 Sendmail和postfix都使用了25端口,因此我們只需要允許來自25端口的連接請求即可。 iptables -A INPUT -i eth0 -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT 21. 允許IMAP和IMAPS 例:允許IMAP/IMAP2流量,端口為143 iptables -A INPUT -i eth0 -p tcp --dport 143 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 143 -m state --state ESTABLISHED -j ACCEPT 例:允許IMAPS流量,端口為993 iptables -A INPUT -i eth0 -p tcp --dport 993 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 993 -m state --state ESTABLISHED -j ACCEPT 22. 允許POP3和POP3S 例:允許POP3訪問 iptables -A INPUT -i eth0 -p tcp --dport 110 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 110 -m state --state ESTABLISHED -j ACCEPT 例:允許POP3S訪問 iptables -A INPUT -i eth0 -p tcp --dport 995 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 995 -m state --state ESTABLISHED -j ACCEPT 23. 防止DoS攻擊 iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT 上述例子中: -m limit: 啟用limit擴展 –limit 25/minute: 允許最多每分鍾25個連接(根據需求更改)。 –limit-burst 100: 只有當連接達到limit-burst水平(此例為100)時才啟用上述limit/minute限制。 24. 端口轉發 例:將來自422端口的流量全部轉到22端口。 這意味着我們既能通過422端口又能通過22端口進行ssh連接。啟用DNAT轉發。 iptables -t nat -A PREROUTING -p tcp -d 192.168.102.37 --dport 422 -j DNAT --to 192.168.102.37:22 除此之外,還需要允許連接到422端口的請求 iptables -A INPUT -i eth0 -p tcp --dport 422 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 422 -m state --state ESTABLISHED -j ACCEPT 25. 記錄丟棄的數據表 第一步:新建名為LOGGING的鏈 iptables -N LOGGING 第二步:將所有來自INPUT鏈中的數據包跳轉到LOGGING鏈中 iptables -A INPUT -j LOGGING 第三步:為這些包自定義個前綴,命名為”IPTables Packet Dropped” iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: " --log-level 7 第四步:丟棄這些數據包 iptables -A LOGGING -j DROP 26. ip映射(NAT) 假設有一家ISP提供園區Internet接入服務,為了方便管理,該ISP分配給園區用戶的IP地址都是偽IP,但是部分用戶要求建立自己的WWW服務器對外發布信息。 我們可以再防火牆的外部網卡上綁定多個合法IP地址,然后通過ip映射使發給其中某一 個IP地址的包轉發至內部某一用戶的WWW服務器上,然后再將該內部WWW服務器響應包偽裝成該合法IP發出的包。 我們假設以下情景: 該ISP分配給A單位www服務器的ip為: 偽ip:192.168.1.100 真實ip:202.110.123.100 該ISP分配給B單位www服務器的ip為: 偽ip:192.168.1.200 真實ip:202.110.123.200 linux防火牆的ip地址分別為: 內網接口eth1:192.168.1.1 外網接口eth0:202.110.123.1 然后我們將分配給A、B單位的真實ip綁定到防火牆的外網接口,以root權限執行以下命令: ifconfig eth0 add 202.110.123.100 netmask 255.255.255.0 ifconfig eth0 add 202.110.123.200 netmask 255.255.255.0 首先,對防火牆接收到的目的ip為202.110.123.100和202.110.123.200的所有數據包進行目的NAT(DNAT): iptables -A PREROUTING -i eth0 -d 202.110.123.100 -j DNAT --to 192.168.1.100 iptables -A PREROUTING -i eth0 -d 202.110.123.200 -j DNAT --to 192.168.1.200 其次,對防火牆接收到的源ip地址為192.168.1.100和192.168.1.200的數據包進行源NAT(SNAT): iptables -A POSTROUTING -o eth0 -s 192.168.1.100 -j SNAT --to 202.110.123.100 iptables -A POSTROUTING -o eth0 -s 192.168.1.200 -j SNAT --to 202.110.123.200 這樣,所有目的ip為202.110.123.100和202.110.123.200的數據包都將分別被轉發給192.168.1.100和192.168.1.200;而所有來自192.168.1.100和192.168.1.200的數據包都將分 別被偽裝成由202.110.123.100和202.110.123.200,從而也就實現了ip映射。
五、iptables腳本
我們可以把我們的iptables規則寫到一個shell文件中,為了每次開機自啟動設置規則,我們可以加到開機自啟動的里面
下面的腳本需要根據需求進行更改不過腳本是一定可以用的
#!/bin/bash /sbin/iptables -F /sbin/iptables -X /sbin/iptables -F -t nat /sbin/iptables -X -t nat /sbin/iptables -P INPUT ACCEPT /sbin/iptables -P OUTPUT ACCEPT /sbin/iptables -A INPUT -i lo -j ACCEPT /sbin/iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT /sbin/iptables -A INPUT -s 192.168.0.0/24 -m state --state NEW -m tcp -p tcp --dport 10050 -j ACCEPT /sbin/iptables -A INPUT -s 172.17.0.0/16 -j ACCEPT /sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT /sbin/iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT /sbin/iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT /sbin/iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 10240 -j ACCEPT /sbin/iptables -t nat -A PREROUTING -i em1 -d 123.59.32.113 -p tcp --dport 10240 -j DNAT --to-destination 192.168.0.186:5011 /sbin/iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 808 -j ACCEPT /sbin/iptables -A INPUT -s 123.120.0.0/16 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT /sbin/iptables -A INPUT -s 123.120.0.0/16 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT /sbin/iptables -A INPUT -s 114.248.0.0/16 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT /sbin/iptables -A INPUT -s 221.222.0.0/16 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT /sbin/iptables -A INPUT -s 192.168.0.0/24 -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT IPLIST="117.122.219.0/24 61.164.149.0/24 122.228.208.0/24 221.222.0.0/16 114.248.0.0/16 123.120.0.0/16 111.201.0.0/16" for ip in ${IPLIST};do /sbin/iptables -A INPUT -s ${ip} -p tcp -m state --state NEW -m tcp --dport 5000:5100 -j ACCEPT /sbin/iptables -A INPUT -s ${ip} -p tcp -m state --state NEW -m tcp --dport 5600:5700 -j ACCEPT done nginx=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' synginx` /sbin/iptables -t nat -A PREROUTING -d 123.59.32.113 -p tcp -m tcp --dport 80 -j DNAT --to-destination ${nginx}:80 /sbin/iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE /sbin/iptables -A INPUT -p ICMP -j ACCEPT /sbin/iptables -A INPUT -j DROP