====== 常見 iptables 的 firewall 設定配置問題 ====== 原文:http://phorum.study-area.org/viewtopic.php?t=41142 (需先連至 http://phorum.study-area.org) 作者: 小州 (kenduest) 最近更新時間: 11/20/2006 ========================================= ========================================= 標題列表項目: (一般本機的 firewall 配置問題) - 如何查詢我目前 iptables 的配置組態設定 ? - 如何關閉 Linux Distro 本身的 firewall 配置並讓規則清空不啟用? - 關於 RedHat 9, Fedora 與 RHEL 的 firewall 配置問題 - 如何使用手動方式清空與重置 iptables firewall rule? - iptables firewall 本身封包比對判斷流程圖為何? - iptables firewall 本身封包比對規則方式為何? - 使用 -P INPUT DROP 引起的主機本身對外連線不通問題? - 使用 -P INPUT DROP 導致本機存取自己服務也受到限制? - 使用 -P INPUT DROP 引起的網路存取正常,但是 ftp 連入卻失敗? - 使用 -P OUTPUT DROP 引起的網路不通問題? - 有無建議本機 firewall 服務只有開放對外項目,其餘禁止的配置方式? 標題列表項目: (提供 NAT 服務配置問題) - 一般建議單純化的 NAT 服務配置語法為何? - 透過 NAT 上網的內部 ip 主機,ftp 連結存取錯誤? - 如何配置連線到 NAT 主機某個對外 Port 時,可以轉送到內部某主機? - 使用 -j MASQUERADE 與 -j SNAT 於 NAT 使用差異 ? ========================================= 一般本機的 firewall 配置問題 ===== 1. 如何查詢我目前 iptables 的配置組態設定 ? iptables 本身提供了 iptables-save 這個程式檔案,執行後可以檢視目前的配置。 代碼: iptables-save 若是使用 iptables 該主要的程式的話,可以搭配 -L 選項列出規則清單。不過由於 iptables 過濾本身是可以針對不同 table 來處理,傳入 -t 可以查閱指定的 table,不指定時預設表示使用 filter table 項目。一般使用方式: 代碼: iptables -L iptables -t nat -L 不過 iptables 對於規則內有 ip 位址項目時會進行反查解析出主機名稱,這個也常導致反查時需要時間導致列出規則時卡住無法運作下去,所以實際上一般會搭配傳入 -n 選項,表示不顯示反查後主機名稱結果。 代碼: iptables -L -n iptables -t nat -L -n 當然,若是要查閱更詳細的資訊,可以再搭配 -v 選項。 代碼: iptables -L -n -v iptables -t nat -L -n -v ===== 2. 如何關閉 Linux Distro 本身的 firewall 配置並讓規則清空不啟用? 各家發行版本都會提供各自的 firewall script 於開機時自動帶入設定規則,所以並沒有一個統一的做法。 -- 在 RHEL 與 Fedora Linux 內的開機 script 本身為 /etc/init.d/iptables,所以關閉方式手動可以執行: 代碼: /etc/init.d/iptables stop 設定每次開啟不啟動該服務項目,可以使用 chkconfig 來關閉。 代碼: chkconfig iptables off -- 若是 SLES 的話,修改 /etc/sysconfig/network/config 配置,裡面可以找到: 代碼: # With this variable you can determine if the SuSEfirewall when enabled # should get started when network interfaces are starte FIREWALL="yes|no" 這可以設定每次啟動網路時是否啟用 firewall 配置。 ===== 3. 關於 RedHat 9, Fedora 與 RHEL 的 firewall 配置問題 系統本身提供配置 firewall 方式,文字模式是可以執行 setup 程式, 於 Firewall 項目進入後就可以選擇新增相關規則。最後所開放允許的組態都是儲存於 /etc/sysconfig/iptables 檔案內。 使用 /etc/init.d/iptables start 或者是 service iptables start 時,就會依據 /etc/sysconfig/iptables 設定的配置啟用 firewall 設定。 於 /etc/sysconfig/iptables 的格式結果,可以使用 iptables-restore 程式由標準輸入讀入後進行啟用。簡單說所謂開啟該服務,其實也就是: 代碼: iptables-restore < /etc/sysconfig/iptables 執行 /etc/init.d/iptables save 可以把目前系統正在運作執行配置的規則儲存至 /etc/sysconfig/iptables 檔案內,這底層其實也是呼叫 iptables-save 程式來達成該結果。簡單說也就是: 代碼: iptables-save > /etc/sysconfig/iptables 關於 /etc/sysconfig/iptables 本身只有包含給 firewall rule 的規則敘述,本身並沒有包含任何 iptables 相關 kernel module 載入配置, 若是需要載入額外的 module 的話可以修改 /etc/sysconfig/iptables-config。 /etc/sysconfig/iptables-config 本身或於 /etc/ini.d/iptables 該腳本檔案時讀入使用。依據該內容來看,提供相關變數定義可以指定載入必要的module 項目: 代碼: # Load additional iptables modules (nat helpers) # Default: -none- # Space separated list of nat helpers (e.g. 'ip_nat_ftp ip_nat_irc'), # which are loaded after the firewall rules are applied. Options for # the helpers are stored in /etc/modprobe.conf. IPTABLES_MODULES="" ===== 4. 如何使用手動方式清空與重置 iptables firewall rule? 若是純手動的方始清空所有規則設定,一般可以採用下列方式: 代碼: iptables -F # 若是沒有加上 -t 指定 table,預設是使用 -t filter iptables -X iptables -F -t nat iptables -X -t nat iptables -F -t mangle iptables -X -t mangle 其中 -F 表示清除指定 table 內所有 chain 項目內的規則清單設定。 -X 則是表示刪除使用者自訂的 chain 項目。 除了清除外,建議需要把過濾預設的政策設定為 ACCEPT,也就是允許任何封包的傳輸不會被阻擋。 代碼: iptables -P INPUT ACCEPT # 沒加上 -t 指定 table,預設使用 -t filter iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT iptables -t mangle -P PREROUTING ACCEPT iptables -t mangle -P POSTROUTING ACCEPT iptables -t mangle -P INPUT ACCEPT iptables -t mangle -P OUTPUT ACCEPT iptables -t mangle -P FORWARD ACCEPT 同時,後續若是手動打造 iptables firewall rule 的時候,該技巧也應該用上,也就是先清除之前規則外,包含把預設的政策都改成 ACCEPT,這樣配置 firewall 規則才不會混亂不堪。 ===== 5. iptables firewall 本身封包比對判斷流程圖為何? 詳細部份可以參閱這張表格: 代碼: http://ebtables.sourceforge.net/br_fw_ia/bridge3b.png ===== 6. iptables firewall 本身封包比對規則方式為何? 這個要區分成為幾點來說明: 1) 一般說法就是,first match,也就是符合規則敘述後就不再往下走 比方配置: 代碼: iptables -P INPUT ACCEPT iptables -A INPUT -s 192.168.1.1 -j ACCEPT iptables -A INPUT -s 192.168.1.0/24 -j DROP 這就是 192.168.1.0/24 中,只有允許 192.168.1.1 可以存取,其餘192.168.1.0/24 該網段 ip 都禁止存取。 常見設定觀唸錯誤如下: 代碼: iptables -P INPUT ACCEPT iptables -A INPUT -j ACCEPT iptables -A INPUT -s 192.168.1.0/24 -j DROP 為何 1921.68.1.0/24 還是可以存取不被禁止?這就是比對的符合就不會繼續往下走。 不過這邊到是要先註明的是,-j LOG 與 -j MARK 這類規則倒是會繼續往下比對,這個與 -j ACCEPT 與 -j DROP 就不相同情況。 2) 當比對規則都跑完了都沒有任何符合的敘述時,最後結果要看預設政策設定 代碼: iptables -P INPUT ACCEPT iptables -A INPUT -s 192.168.1.0/24 -j DROP ...... 上面規則來說,表示預設封包都允許連入存取的,只有禁止 192.168.1.0/24,也就是說比對流程規則跑完後都沒有任何符合敘述,最後就是允許存取。 代碼: iptables -P INPUT DROP iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT ...... 上面規則來說,表示預設封包都禁止連入存取的,只有允許 192.168.1.0/24,也就是說比對流程規則跑完後都沒有任何符合敘述,最後就是允許禁止。 把預設的政策調整為 DROP 基本上需要注意非常多流程,下面部份會談到這部份要注意事項。一般來說建議除非很清楚把預設存取設定為 DROP 帶來的結果,要不然請勿貿然配置使用。因為這樣設定的話,雖然是說只有開放 192.168.1.0/24 可以連入存取,但是卻會導致這台服務主機只可以連線到 192.168.1.0/24 網段的主機,其他的目的都被禁止了。 ===== 7. 使用 -P INPUT DROP 引起的主機本身對外連線不通問題? 為了更嚴厲的防火牆存取限制,一般初學者會這樣配配置: 代碼: iptables -P INPUT DROP iptables -A INPUT -p tcp --dport 22 -j ACCEPT 也就是主機只有打算開放 ssh 服務對外提供存取。 這樣乍看之下好像非常正確,但是設定好後外面是可以連到該 port 22 服務,但是卻導致了一個後續的問題,也就是 "該主機若是要主動對外要建立連線卻被禁止"。比方這台服務主機無法使用 ssh 登入到遠端主機,也無法用瀏覽器看其他主機 port 80 的 http 服務的。 引起該問題的原因呢? TCP/IP 本身是雙向的,也就是有出必有進,有進必有出。這個規則沒考慮到這點問題。 當主機對外要建立連線時,對方勢必也要回應封包到原主機,所以回應的封包是要被允許的。不過該配置來看卻沒考慮到這點問題,所以導致回應的封包被丟棄,所以連線根本建立失敗。 所以設定 -P INPUT DROP 時,一般正確方式應該考慮加上允許主機本身對外連線時對方回應封包項目,也就是: 代碼: iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT -m state --state ESTABLISHED 扮演很重要角色,那就是允許連線出去後對方主機回應進來的封包。 ===== 8. 使用 -P INPUT DROP 導致本機存取自己服務也受到限制? 代碼: iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT 不過上面規則通常應該考慮的是,主機本身對外只有提供可以連結存取port 22 該 ssh 服務,但是若是自己主機有開 port 80 與 port 25 等 服務項目的話,這樣配置卻也導致自己存取自己的主機服務也被限制住了。 基於該問題,一般會建議加上由 loopback interface 該介面不受到該 firewall 組態限制而被阻擋,一般會建議改成: 代碼: iptables -P INPUT DROP iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT ===== 9. 使用 -P INPUT DROP 引起的網路存取正常,但是 ftp 連入卻失敗? 依據前面介紹方式,只有開放 ftp port 21 服務,其他都禁止的話,一般會配置使用: 代碼: iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --dport 21 -j ACCEPT 這樣的配置,確認 ftp 用戶端是可以連到 ftp 主機並且看到歡迎登入畫面,不過後續要瀏覽檔案目錄清單與檔案抓取時卻會發生錯誤... ftp 協定本身於 data channnel 還可以區分使用 active mode 與 passive mode 這兩種傳輸模式,而就以 passive mode 來說,最後是協議讓 ftp client 連結到 ftp server 本身指定於大於 1024 port 的連接埠傳輸資料。 這樣配置在 ftp 傳輸使用 active 可能正常,但是使用 passive mode 卻發生錯誤,其中原因就是因為該主機firewall 規則配置不允許讓 ftp client 連結到 ftp server 指定的連結埠才引發這個問題。 要解決該問題方式,於 iptables 內個名稱為 ip_conntrack_ftp 的 helper,可以針對連入與連外目的 port 為 21 的 ftp 協定命令溝通進行攔截,提供給 iptables 設定 firwewall 規則的配置使用。開放做法為: 代碼: modprobe ip_conntrack_ftp iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp --dport 21 -j ACCEPT 其中 -m state 部分另外多了 RELATED 的項目,該項目也就是狀態為主動建立的封包,不過是因為與現有 ftp 這類連線架構會引發另外才產生的主動建立的項目。 不過若是主機 ftp 服務不在 port 21 的話,請使用下列方式進行調整: 代碼: modprobe ip_conntrack_ftp ports=21,30000 iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp --dport 21 -j ACCEPT iptables -A INPUT -p tcp --dport 30000 -j ACCEPT 也就是主機本身提供 ftp 服務分別在 port 21 與 30000 上,讓 ip_conntrack_ftp 這個 ftp helper 能夠正常提供 ftp 用戶端使用 passive mode 存取而不會產生問題。 ===== 10. 使用 -P OUTPUT DROP 引起的網路不通問題? 來看看這樣配置片段敘述: 代碼: iptables -P INPUT ACCEPT iptables -P OUTPUT DROP 這樣配置來看,感覺上就是主機對外完全開放沒有任何限制連入,但是該主機對外本身限制預設不可以連外,但是結果卻是不管外面也根本連不進來。 該問題 如同上面提到使用 -P INPUT DROP 的配置問題一樣,這樣也是根本沒有考慮到 TCP/IP 本身是雙向溝通的問題。 考慮連入封包後續主機要回應的項目,也是需要搭配傳入 -m state 來提供允許回應封包的項目,所以整個來看片段敘述為: 代碼: iptables -P OUTPUT DROP ip tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT 這樣設定好結果,就是該主機本身可以對自己主機服務連結存取,但是對外連結存取都會被禁止。 不過拉回來看,有必要配置 -P OUTPUT DROP 嗎?老實說個人倒是感覺通常都是多此一舉,因為實際應用部份通常不會限制自己主機對外連線的功能。 不過若是堅持要設定 -P OUTPUT DROP 的話,要考慮後續主動連外部份的開放描述可能可多了.... 比方這樣配置項目: 代碼: iptables -P OUTPUT DROP iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A OUTPUT -p tcp --dport 25 -j ACCEPT iptables -A OUTPUT -p udp --dport 53 -j ACCEPT iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT 這樣是不是有點找自己麻煩? 所以結論就是除非定真的是不想讓自己主機有主動連外的需求,那才考慮把 OUTPUT chain 的預設政策設定為 DROP,否則不要使用這種配置。 ===== 11. 有無建議本機 firewall 服務只有開放對外項目,其餘禁止的配置方式? 依據前面談到流程,若是預設 INPUT 的存取是禁止的話,提供如下配置參考: 代碼: modprobe ip_conntrack_ftp iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp --dport 21 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT 若是預設 INPUT 的存取是允許的話,提供如下配置參考: 代碼: modprobe ip_conntrack_ftp iptables -P INPUT ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p tcp --dport 21 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -m state --state NEW,INVALID -j DROP 若是需要允許主機可以接受 ping 程式測試這台機器是否可以存取的話,可以搭配使用: 代碼: iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT 當然請注意,搭配先使用 -F 與 -X 先把預先存在的 rule 清空後,避免 rule 混雜在一起而互相影響。 ===== 提供 NAT 服務配置問題 ===== 1. 一般建議單純化的 NAT 服務配置語法為何? 這邊是假設對外的介面為 eth0,對內介面為 eth1,該對內網段的 ip 範圍是 192.168.1.0/24。 若是預設的 FORWARD chain 本身為 ACCEPT 的話,配置語法使用為: 代碼: iptables -A POSTROUTING -t nat -s 192.168.1.0/24 -o eth0 -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward 若是預設的 FORWARD chain 本身為 DROP 的話,配置語法使用為: 代碼: iptables -A POSTROUTING -t nat -s 192.168.1.0/24 -o eth0 -j MASQUERADE iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT echo 1 > /proc/sys/net/ipv4/ip_forward 當然,請不要忘記前面談到的議題,也就是搭配先使用好 -F 與 -X 這類項目。還有預設 FORWARD chain 為 DROP 的話,考慮是否也開放允許 echo-request 這類 icmp 協定封包能夠允許由內部網段傳送出去。 ===== 2. 透過 NAT 上網的內部 ip 主機,ftp 連結存取錯誤? 該問題點與前面談到 ftp 問題與搭配使用 -m state --state RELATED 配置有關係。由於目前要的是 NAT 下 ftp 連線的追蹤功能,所以需要搭配掛入ip_nat_ftp 該 module 才可以正確提供追蹤機制。 所以經過該修改配置,於預設的 FORWARD chain 本身為 ACCEPT 的話,配置語法使用為: 代碼: modprobe ip_nat_ftp iptables -A POSTROUTING -t nat -o eth0 -s 192.168.1.0/24 -j MASQUERADE iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT echo 1 > /proc/sys/net/ipv4/ip_forward 搭配 ip_nat_ftp module 後,如此於 FORWARD chain 內使用的 RELATED 參數才會有效用。 ===== 3. 如何配置連線到 NAT 主機某個對外 Port 時,可以轉送到內部某主機? 一般語法配置為: 代碼: iptables -A PREROUTING -t nat -d 210.1.1.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.1:80 這邊是假設該 NAT 主機本身對外的 ip 為 210.1.1.1,設定外面連結存取到該 ip 的 port 80 時,將封包轉送到 192.168.1.1 的 port 80 上。 不過該配置常談到的問題就是,也許有人在 192.168.1.0/24 該內部網段連結 210.1.1.1 的 port 80 時,卻無法瀏覽實際 192.168.1.1:80 該服務項目。 該問題牽涉到 icmp 重導的問題,而且目前 netfilter iptables 發展已經不會有該問題。若是還有問題的話,可以考慮如下配置: 代碼: iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.1 --dport 80 -s 192.168.1.0/24 -j SNAT --to 192.168.1.254 其中 192.168.1.254 也就是 NAT 主機對內的 ip,這樣可以讓該內部的192.168.1.1 看到的存取來源為 192.168.1.254,如此可以解決該問題。 ===== 4. 使用 -j MASQUERADE 與 -j SNAT 於 NAT 使用差異 ? 這邊是假設該 NAT 主機本身對外的介面為 eth0,奇 ip 為 210.1.1.1;對內介面為 eth1,該對內網段的 ip 範圍是 192.168.1.0/24。 一般選擇提供 NAT 服務,讓內部 privae ip 可以存取連上 internet 的配置方式有: 代碼: iptables -A POSTROUTING -t nat -s 192.168.1.0/24 -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward 另外一種使用方式: 代碼: iptables -A POSTROUTING -t nat -s 192.168.1.0/24 -j SNAT --to 210.1.1.1 echo 1 > /proc/sys/net/ipv4/ip_forward 基本上最後的結果都是可以達成需求的,不過一般差別為: 1) 使用 -j SNAT 一般會比 -j MASQUERADE 效率來的好,因為這牽涉到封包傳送通過相關介面時的相關比對問題 2) 若是對外本身 ip 不是固定的,也就是撥接取得這類會非固定的環境之下,採用 -j MASQUERADE 會比較方便使用 ===== kenduest 在 星期二 十一月 21, 2006 11:46 pm 作了第 4 次修改 ====== PortNocking ====== 利用依序對特定 Port 送訊息之方式開啟服務之 Port http://hahahaha.cc/?p=92 :INTO-PHASE2 --A INTO-PHASE2 -m recent --name PHASE1 --remove-A INTO-PHASE2 -m recent --name PHASE2 --set -A INTO-PHASE2 -j LOG --log-prefix "INTO PHASE2: "-A INPUT -m recent --update --name PHASE1 -A INPUT -p tcp --dport 168 -m recent --set --name PHASE1 -A INPUT -p tcp --dport 978 -m recent --rcheck --name PHASE1 -j INTO-PHASE2 -A INPUT -p tcp -s YOUR_HOST_IP --dport 22 -m recent --rcheck --seconds 5 --name PHASE2 -j ACCEPT opendoor.sh 示意, opendoor.sh IP 168 978: #!/bin/bash # $1 host name or IP address telnet $1 $2 &> /dev/null telnet $1 $3 &> /dev/null ssh $1