歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> 用IPIW實現BSD防火牆(中)

用IPIW實現BSD防火牆(中)

日期:2017/2/27 14:19:16   编辑:更多Linux

我們已經通過安裝帶缺省的禁止所有數據包出入的策略的ipfw,使所有的IP信息包都不能出入我的計算機系統,下面,我們再創建一個能被ipfw讀取的規則集,使所需要的信息包能夠出入計算機系統。 由於在創建規則集方面沒有所謂“最合適”的方法,因此我不能說明如何在規則集中添加“萬能”的規則,而只能說明一下在創建規則集時需要遵循的原則。在這裡,我假設你已經掌握了ipfw的語法,能夠理解我創建的規則。如果對這些知識不大理解,請參閱相關的資料。 在創建規則集時需要注意的是,規則是按給定數字行號的順序被系統讀取的,直到信息包符合一條規則,ipfw才會停止讀取規則,也就是說,如果規則400和規則800都適用於一個信息包,系統總是會用到規則400而不會讀取規則800。因此,在添加新的規則之前,需要仔細地審查原來的規則,確保新的規則不會被原來的規則所覆蓋。 此外,規則對所有的連接-也就是在ifconfig -a的輸出中所列出的所有連接都是適用的。如果在象我這樣只有一個連接的計算機上自然不會有什麼問題,但如果在有多個連接的計算機上,就會有所不同。例如,你的機器上可能有二個連接,一個是互聯網連接,一個是內部局域網連接,每個不同的連接需要不同的安全規則,這一點可以通過在ipfw的規則中指定連接的名字來實現。 我的機器是一台運行FreeBSD 4.2、配置有互聯網連接的單台計算機。由於這是我在家裡使用的計算機,因此可以對向互聯網上發送的信息包的類型不作任何限制,而只需要它能夠接收是對我發出的信息包有效響應的信息包。 要完成這一任務最好的方法之一是利用ipfw的動態功能。如果你對這一概念還不太熟悉,下面我將對它作一番詳盡的解釋。 如果使用“動態”的規則,當我向互聯網上發送一個信息包時,ipfw將在其狀態表中添加一個記錄,其中包括有發送的信息包的目標計算機的IP地址和使用的目標計算機的端口。當有信息包從互聯網上返回時,如果其IP地址、端口號與在狀態表中記錄得不一致,計算機就不會接收這一信息包。動態規則只適用於TCP信息包,而不適用於UDP信息包,原因是UDP不創建一個虛擬的連接,它被稱作是“無狀態”協議,也就不能使用“狀態表”。 ipfw手冊中的例子部分給出了三條用來創建這個動態信息包過濾裝置的規則。由於我決定在/etc/ipfw.rules中創建自己的規則,因此,需要以超級用戶的身份創建包含下面內容的文件: # 只允許向外發送信息包 add 00300 check-state add 00301 deny tcp from any to any in established add 00302 allow tcp from any to any out setup keep-state 由於規則100和規則200是預先包含在/etc/rc.firewall中的,因此,我自己添加的規則將從行號300開始。我將給相關的規則以300、301、302等行號,等規則越來越多或創建不相關的規則時,我就會把行號跳到400。不過,從理論上說你可以任意給規則指定行號,只要該行號沒有在該規則集文件中出現過就行。 你可能已經注意到規則集出現了幾個在ipfw手冊中定義的關健字: check-state:檢查信息包是否與動態規則集匹配。如果匹配則搜索中止,否則繼續搜索下一條規則。 keep-state:根據匹配情況,防火牆將創建一條動態規則,其功能是在源、目的IP地址/端口之間使用同一協議的流量,這一規則是具有一定的生命周期的(由一系列sysctl(8)變量控制),每當發現匹配協議時其生命周期都會刷新。 established:只適用於TCP信息包,與有RST或ACK位的信息包進行匹配。 setup:只適用於TCP信息包,與有SYN位但不具有ACK位的信息包進行匹配。 換句話說,當有信息包到達網絡連接後,ipfw將首先檢查它是否在狀態表中,如果在狀態表中,則允許它進入系統(行號為300的規則執行這一檢查工作)。如果它不在狀態表中,而且設置了RST或ACK位,ipfw將不允許它進入系統,因為它不是我創建的連接的有效響應(規則301完成這一工作)。只有當ACK標志沒有設置,(這意味著它要初始化連接)並且這一信息包是由系統向外發送的時,才允許它向外發送;如果有信息包符合這一規則,則它被加入狀態表中。 我們來看看添加上這些規則後對系統有什麼影響。對規則集進行檢查沒有錯誤後,保存文件,然後輸入下面的命令: killall init 敲Enter鍵,然後輸入: exit 然後仔細觀察啟動信息,確保規則在加載時沒有出現出錯信息。如果在規則加載過程中出現了錯誤信息,那麼可能是系統的安全級別被設置為3或更高了,必須首先在/etc/rc.conf文件中找到下面的這行內容,將kern_securelevel改為較小的值: kern_securelevel="3" 然後重新執行killall init命令。 重新登錄後,我將嘗試能否向外發送IP數據包並收到相應的應答數據包: ping www.freebsd.org


ping: cannot resolve www.freebsd.org: Host name lookup failure lynx www.freebsd.org Alert!. Unable to Access document. 也許是我的系統上沒有安裝DNA域名解析功能的緣故,我再使用IP地址試一下: lynx 216.136.204.21 這次我發現自己在www.freebsd.org的主頁上了。我們再來試著ping一下這個IP地址吧: ping 216.136.204.21 PING 216.136.204.21 (216.136.204.21): 56 data bytes ping: sendto: Permission denied ping: sendto: Permission denied ping: sendto: Permission denied ^C --- 216.136.204.21 ping statistics --- 3 packets transmitted, 0 packets received, 100% packet loss 這裡我來解釋一下這一奇怪的現象吧。很明顯的是,一些數據包進入或發出了計算機系統,但一些則沒有。我們來仔細發分析一下我在上面的每個例子中使用的協議。 由於我只能使用其IP地址訪問www.freebsd.org的網站,因此域名解析沒有成功。當我使用DNS服務時,我會向我的ISP的DNS服務器發送域名查找請求,該DNS服務器應該向我的機器發送響應數據包。這些操作都是符合我們的規則的,由於我是在53端口發送請求的,也應該在端口53上接收到響應數據包。我將復查我發送請求的DNS服務器: more /etc/resolv.conf search kico1.on.home.com nameserver 24.226.1.90 nameserver 24.226.1.20 nameserver 24.2.9.34 似乎問題不是出在這兒,因此應該仔細地搞清楚域名解析的工作原理。我們來看一下能否從在線手冊上得到一點幫助: apropos resolve dnsquery(1) - 使用解析器查詢域名服務器 res_query(3), res_search(3), res_mkquery(3), res_send(3), res_init(3), dn_comp(3), dn_eXPand(3) - 解析器例程 resolver(5) - 解析器配置文件 man resolver 通過多次查看,下面的內容引起了我的興趣:RES_USEVC 在查詢中使用TCP而不是UDP連接;RES_STAYOPEN RES_USEVC用它來在多次查詢期間保持TCP連接。它只在需要進行多個查詢的的軟件中有用,UDP是最常用的模式。 我可能已經發現問題出在哪了。如果DNS使用的是UDP而不是TCP,而我的規則只允許TCP協議的數據包響應我的TCP連接,域名解析就會失敗。 man dnsquery <只顯示我們感興趣的部分> -s 使用流格式而非信息包。它使用一個帶名字服務器的TCP流式連接而不是UDP,這一選項會設置解析軟件選項字段的RES_USEVC位。(缺省狀態下使用UDP) 現在,我們來試試這個選項: dnsquery -s www.freebsd.org ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39772 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHOR99vY: 5, ADD99vIONAL: 5 ;; www.freebsd.org, type = ANY, class = IN www.freebsd.org. 49m21s IN CNAME freefall.freebsd.org. freebsd.org. 22m43s IN NS ns1.iafrica.com. freebsd.org. 22m43s IN NS ns2.iafrica.com. freebsd.org. 22m43s IN NS ns.gnome.co.uk.

freebsd.org. 22m43s IN NS ns0.freebsd.org. freebsd.org. 22m43s IN NS ns1.root.com. ns1.iafrica.com. 1h1m3s IN A 196.7.0.139 ns2.iafrica.com. 1h1m3s IN A 196.7.142.133 ns.gnome.co.uk. 12m37s IN A 193.243.228.142 ns0.freebsd.org. 11h9m9s IN A 216.136.204.126 ns1.root.com. 1h8m12s IN A 209.102.106.178 在我們使用TCP連接發出一個DNS請求時,名字解析過程運行得很好。我們再在沒有帶s選項的情況下看使用UDP時的情況如何: dnsquery www.freebsd.org Query failed (h_errno=2) : Host name lookup failure 現在我們明白了,DNS使用的是UDP數據包。由於我沒有在規則集中允許使用UDP數據包,因此DNS名字解析過程不能完成。 現在既然已經解決了這個問題,我們再來看看即使在使用IP地址時也ping不通的原因何在。我們知道,ping在其數據包中使用的是ICMP而非TCP協議。如果用ping發送ICMP數據包,不在防火牆的規則面前碰一鼻子灰才怪呢。 在向規則集中添加任何新的規則前,必須以超級用戶身份重新登錄。我們來看看ipfw的輸出:



dnsquery www.freebsd.org Query failed (h_errno=2) : Host name lookup failure 現在我們明白了,DNS使用的是UDP數據包。由於我沒有在規則集中允許使用UDP數據包,因此DNS名字解析過程不能完成。 現在既然已經解決了這個問題,我們再來看看即使在使用IP地址時也ping不通的原因何在。我們知道,ping在其數據包中使用的是ICMP而非TCP協議。如果用ping發送ICMP數據包,不在防火牆的規則面前碰一鼻子灰才怪呢。 在向規則集中添加任何新的規則前,必須以超級用戶身份重新登錄。我們來看看ipfw的輸出:



Copyright © Linux教程網 All Rights Reserved