防火牆配置dnat原理分析

我們通過一個例子來大致理解一 下它是如何工作的。比如,我想通過Internet連接發佈我們的網站,但是HTTP server在我們的內網裏,而 且我們對外只有一個合法的IP,就是防火牆那個對外的IP——$INET_IP。防火牆還 有一個內網的IP——$LAN_IP,HTTP server的IP是$HTTP_IP (這當然是內網的了)。爲了完成我們的設想,要做的第一件事就是把下面的這個簡單的規則加入到nat表 的PREROUTING鏈中:

iptables -t nat -A PREROUTING --dst $INET_IP -p  tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP    

現在,所有從Internet來的、到防火牆的80端口去的包都會被轉發(或稱做被DNAT )到在內網的HTTP服務器上。如果你在Internet上試驗一下,一切正常吧。再從內網裏試驗一下,完全 不能用吧。這其實是路由的問題。下面我們來好好分析這個問題。爲了容易閱讀,我們把在外網上訪問我們 服務器的那臺機子的IP地址記爲$EXT_BOX

  1. 包從地址爲$EXT_BOX的機子出發,去往地址爲$INET_IP 的機子。

  2. 包到達防火牆。

  3. 防火牆DNAT(也就是轉發)這個包,而且包會經過很多其他的鏈檢驗及處理。

  4. 包離開防火牆向$HTTP_IP前進。

  5. 包到達HTTP服務器,服務器就會通過防火牆給以迴應,當然,這要求把防火牆作爲HTTP到達$EXT_BOX的網關。一般情況下,防火牆就是HTTP服務器的缺省網關。

  6. 防火牆再對返回包做Un-DNAT(就是照着DNAT的步驟反過來做一遍),這樣就 好像是防火牆自己回覆了那個來自外網的請求包。

  7. 返回包好象沒經過這麼複雜的處理、沒事一樣回到$EXT_BOX

現在,我們來考慮和HTTP服務器在同一個內網(這裏是指所有機子不需要經過路由器而可以直接互相訪 問的網絡,不是那種把服務器和客戶機又分在不同子網的情況)的客戶訪問它時會發生什麼。我們假設客戶 機的IP爲$LAN_BOX,其他設置同上。

  1. 包離開$LAN_BOX,去往$INET_IP

  2. 包到達防火牆。

  3. 包被DNAT,而且還會經過其他的處理。但是包沒有經過SNAT 的處理,所以包還是使用它自己的源地址,就是$LAN_BOX(譯者注:這就是IP 傳輸包的特點,只根據目的地的不同改變目的地址,但不因傳輸過程中要經過很多路由器而隨着路由器改變 其源地址,除非你單獨進行源地址的改變。其實這一步的處理和對外來包的處理是一樣的,只不過內網包的 問題就在於此,所以這裏交待一下原因)。

  4. 包離開防火牆,到達HTTP服務器。

  5. HTTP服務器試圖回覆這個包。它在路由數據庫中看到包是來自同一個網絡的一臺機子,因此它會把回 復包直接發送到請求包的源地址(現在是回覆包的目的地址),也就是$LAN_BOX

  6. 回覆包到達客戶機,但它會很困惑,因爲這個包不是來自它訪問的那臺機子。這樣,它就會把這個包 扔掉而去等待“真正”的回覆包。

針對這個問題有個簡單的解決辦法,因爲這些包都要進入防火牆,而且它們都去往需要做DNAT才能到達 的那個地址,所以我們只要對這些包做SNAT操作即可。比如,我們來考慮上面的例子,如果對那些進入防火 牆而且是去往地址爲$HTTP_IP、端口爲80的包做SNAT操作,那麼這些包就好象是從$LAN_IP來的了,也就是 說,這些包的源地址被改爲$LAN_IP了。這樣,HTTP服務器就會把回覆包發給防火牆,而防火牆會再對包做  Un-DNAT操作,並把包發送到客戶機。解決問題的規則如下:

iptables -t nat -A POSTROUTING -p tcp --dst $HTTP_IP --dport 80 -j SNAT \ --to-source $LAN_IP    

要記住,按運行的順序POSTROUTING鏈是所有鏈中最後一個,因此包到 達這條鏈時,已經被做過DNAT操作了,所以我們在規則裏要基於內網的地址$HTTP_IP(包的目的地)來匹配 包。

 

警告:我們剛纔寫的這條規則會對日誌產生很大影響,這種影響應該說是很不好的。因爲來自 Internet包在防火牆內先後經過了DNAT和SNAT處理,才能到達HTTP服務器(上面的例子),所以HTTP服務器 就認爲包是防火牆發來的,而不知道真正的源頭是其他的IP。這樣,當它記錄服務情況時,所有訪問記錄的 源地址都是防火牆的IP而不是真正的訪問源。我們如果想根據這些記錄來了解訪問情況就不可能了。因此上 面提供的“簡單辦法”並不是一個明智的選擇,但它確實可以解決“能夠訪問”的問題,只是沒有考慮到日 志而已。

其他的服務也有類似的問題。比如,你在LAN內建立了SMTP服務器,那你就要設置防火牆以便能轉 發SMTP的數據流。這樣你就創建了一個開放的SMTP中繼服務器,隨之而來的就是日誌的問題了。

一定要注意,這裏所說的問題只是針對沒有建立DMZ或類似結構的網絡,並且內網的用戶訪問的是 服務器的外網地址而言的。(譯者注:因爲如果建立了DMZ,或者服務器和客戶機又被分在不同的子網裏, 那就不需要這麼麻煩了。因爲所有訪問的源頭都不在服務器所在的網裏,所以就沒必要做SNAT去改變包的源 地址了,從而記錄也就不是問題了。如果內網客戶是直接訪問服務器的內網地址那就更沒事了)

較好的解決辦法是爲你的LAN在內網建立一臺單獨的DNS服務器(譯者注:這樣,內網的客戶使用網站名 訪問HTTP服務器時,DNS就可以把它解析成內網地址。客戶機就可以直接去訪問HTTP服務器的內網地址了, 從而避免了通過防火牆的操作,而且包的源地址也可以被HTTP服務器的日誌使用,也就沒有上面說的日誌問 題了。),或者乾脆建立DMZ得了(這是最好的辦法,但你要有錢哦,因爲用的設備多啊)。   

對上面的例子應該考慮再全面些,現在還有一個問題沒解決,就是防火牆自己要訪問HTTP服務器時會發 生什麼,能正常訪問嗎?你覺得呢:)很可惜,現在的配置還是不行,仔細想想就明白了。我們這裏討論的基 礎都是假設機子訪問的是HTTP服務器的外網地址,但這個外網地址其實就是防火牆對外的地址,所以當防火 牆訪問這個外網地址時,就是訪問它自己。防火牆上如果有HTTP服務,那客戶機就會看到頁面內容,不過這 不是它想看到的(它想要的在DNAT上了),如果沒有HTTP服務,客戶就只能收到錯 誤信息了。前面給出的規則之所以不起作用是因爲從防火牆發出的請求包不會經過那兩條鏈。還記得防火牆 自己發出的包經過哪些鏈吧:)我們要在nat表的OUTPUT鏈中添加下面的規則:

iptables -t nat -A OUTPUT --dst $INET_IP -p  tcp --dport 80 -j DNAT \ --to-destination $HTTP_IP    

有了最後這條規則,一切都正常了。和HTTP服務器不在同一個網的機子能正常訪問服務了,和它在一個 網內的機子也可以正常訪問服務了,防火牆本身也能正常訪問服務了,沒有什麼問題了。這種心情,套用 《大話西遊》裏的一句話,就是“世界又清淨了”。(

發佈了144 篇原創文章 · 獲贊 12 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章