問題產生原因分析:
網絡環境介紹:
公司內網有一台web服務器,地址是192.168.100.100,web服務端口為80,並且為這台web服務器申請了DNS A記錄的域名解析服務,解析記錄是公司出口ip地址100.100.100.100。在辦公區網絡環境里,還有內網192.168.10.0網段,需要通過申請的域名來訪問公司內網的192.168.100.100的web服務。
做法是在防火牆的出口,做一條端口映射,100.100.100.100:80到192.168.100.100:80的端口映射。
問題來了,做好端口映射以后,其他外部網絡通過域名訪問公司的web服務是正常的,但是公司內網用戶通過域名訪問公司自己的web服務,卻無法訪問;而公司內網用戶通過192.168.100.100:80私有地址訪問,是正常的。這種情況,就是因為做好端口映射以后,訪問web服務的流量在響應的時候流量沒有回流到防火牆導致的。
原因分析:
如上圖,假如是192.168.10.10通過申請的域名訪問192.168.100.100的web服務。這里假設訪問的源端口是10000,目標端口是80,數據包分析如下:
C2主機發起web請求.因為通過域名訪問的,DNS解析服務正常,那么訪問目標就是100.100.100.100:80
192.168.10.10:10000--->100.100.100.100:80
數據包最終會被路由到防火牆上,防火牆檢查訪問的目的地址,匹配到它的端口映射策略,將目標地址改為對192.168.100.100的訪問,建立起一個針對目標ip地址轉換的NAT會話表
192.168.10.10:10000--->192.168.100.100:80
然后數據包到會被轉發到192.168.100.100服務器上並會響應192.168.10.10主機的請求,將上述訪問的源目ip地址及端口進行倒轉,並將數據包交給它的網關處理,圖中就是R1路由器
192.168.100.100:80--->192.168.10.10:10000
R1路由器檢查訪問者的源ip和目標ip地址,發現目標ip地址是192.168.10.10,是R1路由器一個可路由的內網ip地址,就會將數據包直接路由到C2主機上
C2主機接收到數據包,檢查數據包的源ip和端口是192.168.100.100:80,發現其本身並沒有這樣一個http會話與之相匹配,就是說C2主機並沒有主動發起對192.168.100.100:80的訪問,發起的是對100.100.100.100:80的訪問,那么C2主機就會丟棄這個數據包,導致內網用戶通過域名或者公網ip地址訪問自己的內網服務器不通的現象。
192.168.100.100:80--->192.168.10.10:10000
上述就是造成我們開頭所說問題的原因。發生上述問題的原因,就是因為其R1路由器發現響應數據包的目的ip地址是內網一個可直接路由的地址,就會直接在內網進行路由轉發,而不是將數據包交給防火牆進行路由轉發。
不要認為這是bug,這是正常現象,任何設備只要做了端口映射,都繞不開這個問題,因為TCP/IP協議棧就是這樣工作的。你要推倒重來,除非自己去設計一套網絡協議標准,況且在現有的TCP/IP的協議框架下,這個問題又不是說不能解決。那為何有的設備不用做端口回流呢?那是因為有的設備在你做端口映射的時候,偷偷地把端口回流的問題也給你解決了。然而你也不要以為它們幫你做了端口回流,你就認為那些設備是好設備,感覺好高端,那你錯了,我很少見企業級設備偷偷地幫你解決這個問題的(不是說沒有,一般是應用層網絡設備有這個),都是需要你主動去處理解決,這也體現了它們設備高度可定制性及擴展性。
你要高度可定制性和擴展性,那就要犧牲人性化的設計,需要專業人員去幫你做業務上的定制;你要人性化,自己點點鼠標就能把問題解決,那它就不可能在可定制性和擴展性上給你太多,這個世界上的事情也是如此,沒有十全十美。
解決方法:
這里介紹下思科防火牆和華為防火牆上如何解決這個問題。至於其他廠家的設備或者路由器等網絡設備,如何解決,可以自行查閱相關資料,解決的原理都一樣
這里只介紹其中一個解決方法,還有其他方法,可以自行查閱相關資料
解決方法的思路:內網主機在訪問的時候,將web服務的響應流量回流到防火牆上來,接受防火牆的處理。就是說,在流量經過防火牆的時候,將源地址做一個修改,使得R1路由器在路由數據包的時候,還把這個數據包路由到防火牆上來,而不是在內網直接路由;防火牆上有記錄它所做的相應修改(做源地址轉換,並維護這個NAT會話表即可),再把之前的修改給改回來,再轉發給內網主機即可。
內網主機對通過公網對內網服務器訪問的時候,流量在經過防火牆時,將內網主機的ip地址修改為一個外網ip地址(源NAT轉換),並做好及維護相應的NAT會話的記錄,這樣服務器在接收到數據包之后,發現源ip地址是一個外網ip地址,這樣數據流量會回流到防火牆,防火牆檢查相應的源NAT轉換策略,發現可以匹配,則進行源NAT的還原,並經數據包路由到內網的主機中
思科防火牆在做端口映射的時候,分為static(inside,outside)和static(inside,inside),方向不同。但是華為防火牆沒有這個問題,因此思科在解決這個問題時,有下面兩個關鍵步驟,而華為防火牆只需要下面第一步(准確來說,華為防火牆只是用的第一步的思路,實現方式和思科防火牆略微有些區別)即可。
第一步:內網192.168.10.0網段對100.100.100.100的訪問的時候,將源地址做一個轉換,轉換為防火牆內網口inside對100.100.100.100的訪問。
這一步你可以理解為用防火牆的內網inside接口的地址去訪問100.100.100.100。
之前做的全局NAT的轉換,內網192.168.10.10對所有外網的訪問,是轉換為防火牆outside口對外網的訪問,即防火牆outside代理防火牆內網中的所有主機去訪問外網,例如百度
第二步:內網192.168.10.0網段對100.100.100.100:80的訪問,將目標地址做一個轉換,轉換為對內網192.168.100.100:80的訪問。
這一步是做LAN到LAN的端口映射
思科防火牆:這里是基於思科防火牆8.2系統版本的配置,新版本配置有所改變,但是解決方法的原理類似
先做最基礎的配置,這里是我們平時上網說必須要的配置
1、全局的NAT源地址轉換,注意下面數字要對應。這一步主要是為了讓內網用戶可以正常訪問外網用的
# nat (inside) 1 0.0.0.0 0.0.0.0 //這條命令匹配了所有ip地址
# global (outside) 1 interface //對上面匹配的IP地址訪問外網的流量,做源地址轉換,源地址是interface outside接口的ip地址,即100.100.100.100
2、做端口映射(目的ip地址轉換):我們做的web服務是為我們的用戶提供服務的,因此我們需要做一個端口映射,能夠讓用戶訪問我們的web服務
# static (inside,outside) tcp 100.100.100.100 80 192.168.100.100 80 netmask 255.255.255.255 //外網outside區域網絡訪問100.100.100.100:80的時候,將轉換對192.168.100.100:80的訪問
3、內網192.168.10.0網段訪問100.100.100.100的時候,也做源地址轉換,但是區別上面的第1步,這里將源地址改為防火牆的內網口inside口
# access-list 100 extended permit ip 192.168.10.0 255.255.255.0 host 100.100.100.100 //匹配公司內網192.168.10.0/24訪問公網ip100.100.100.100的流量
# nat (inside) 10 access-list 100
# global (inside) 10 interface //對捕獲的流量做源地址轉換,轉換成interface inside接口的ip地址。就是說內網訪問100.100.100.100的流量的源地址,轉換為防火牆內網口的地址,變為防火牆inside口對web服務的訪問。
注意:如果這里是路由器或者其他網關設備的話,需要將interface換成這台路由器或者網關設備真實的ip地址,這里思科防火牆可以使用接口名稱代替
4、內網192.168.10.0網段對100.100.100.100:80的訪問,做目的ip地址及端口的轉換,但是這里區別上面的第二步,這里將目的地址改為內網服務器的ip地址,即192.168.100.100:80
# static (inside,inside) tcp 100.100.100.100 80 192.168.100.100 80 netmask 255.255.255.255 // //內網(inside區域)的網絡對100.100.100.100:80的訪問轉換為對192.168.100.100:80的訪問
5、允許相同安全級別之間的接口可以互相轉發數據
# same-security-traffic permit intra-interface
防火牆多一個這個步驟,路由器等其他網關設備沒有
華為防火牆
1、全局NAT地址轉換。這一步主要是為了讓內網用戶可以正常訪問外網用的
# nat-policy interzone trust untrust outbound // 注意NAT策略方向
# policy 0
# action source-nat // 是做源地址轉換
# policy source 192.168.0.0 mask 255.255.0.0 // 匹配內網所有主機ip
# easy-ip GigabitEthernet0/0/1 // 將源地址轉換為防火牆GigabitEthernet0/0/1接口的ip地址(在企業,一般這個接口都是企業出口ip地址)
2、端口映射:
# nat server 6 protocol tcp global 100.100.100.100 www inside 192.168.100.100 www
3、創建地址池
# nat address-group 1 1.1.1.1 1.1.1.2 // ip地址為1.1.1.1-1.1.1.2。咨詢過華為工程師,這里的地址池可以任意寫,但是必須保證在全網內唯一,數據可被路由到防火牆即可。不可以和上面的easy-ip重復
4、做域內NAT,注意和上面第二步NAT的區別,策略方向不一樣
# nat-policy zone trust
# policy 1
# action source-nat
# policy source 192.168.0.0 mask 16 // 這里匹配需要通過公網訪問的所有內網主機ip
# policy destination 192.168.100.100 mask 32 // 這里匹配,內網主機訪問哪個ip的時候,執行這個NAT(可以和上面一樣,寫地址段)
# address-group 1 // 匹配以后,將源地址轉換成這個地址池里的地址,注意1和上面的地址池索引相對應
說明:華為防火牆做好域間的策略,保證網絡訪問正常,這屬於其他防火牆的知識范圍,不做過多討論。
上述華為防火牆端口回流最好以后,內網主機用戶通過公網訪問,還是不行。具體也咨詢了華為工程師,把配置信息也發給他們看了下,他們檢查配置也說配置沒問題,找不出問題所在。通過測試並查看防火牆的會話表,發現內網主機發起訪問的時候,主機的源地址沒有執行轉換,就是上面的第4步沒有生效,估計是防火牆版本的一個bug吧。有華為防火牆大神的,可以幫忙指出問題所在。
說下華為防火牆和思科防火牆解決這個問題的思路上的一點不同:
思科防火牆:
思科防火牆在內網通過公網訪問內網web服務的時候,當流量到達防火牆以后,防火牆偷偷地數據包的源地址改成防火牆inside接口的地址了,這樣web服務器收到數據包的時候,就會響應這個數據包,把這個數據包響應給防火牆,而不是內網的主機。防火牆收到響應數據包以后,再偷偷地將數據包的源ip地址(此時已經變成目的ip地址了)改成內網主機的ip地址,然后轉發給內網主機。
華為防火牆:
華為防火牆在內網通過公網訪問內網web服務的時候,當流量到達防火牆后,防火牆像思科防火牆一樣,也會偷偷將數據包的源地址改成配置好的地址池中的一個ip地址(一般是一個公網地址,只要全局唯一即可);web服務器收到數據包的時候,就會響應這個數據包,因為是地址池內的地址,在內網不可路由,數據就會被路由到防火牆上,防火牆再次偷偷地將數據包的源ip地址(此時也應變成目的ip地址了)修改成內網主機的ip地址,然后再發給內網主機。
思科防火牆和華為防火牆在處理這個問題的時候,思路上有點不同。但是都是內網主機通過公網訪問內網web服務的時候,偷偷將主機ip地址修改成一個在內網必須路由到防火牆的一個ip地址(就是說接受防火牆的控制),然后web服務響應數據會回流到防火牆,最后經防火牆處理,轉發給內網主機。
台上十分鍾,台下十年功。在控制台上敲的幾下鍵盤,寫的幾行命令,台下的你可能要花上大半年甚至一兩年的時間,去了解它背后實現的原理和遇到問題的解決方法。你可能要去了解整個TCP/IP協議棧的工作方式、防火牆的工作方式及工作原理、廣域網以及局域網技術原理等等。總之,學無止境,越學越感覺自己之前無知。