dsvpn是基於mGRE實現點到多點自動建立連接和引入路由的實現,在啟用ipsec保護時,實質是一種gre over ipsec技術。dsvpn的ospf鏈路類型為p2mp。
問題現象
這次問題的主要現象,是dsvpn的中心節點(hub)與部分分支節點(spoke)之間建立的ospf鄰居狀態停留在exstart/exchange。dsvpn隧道兩端可以ping通,nhrp鄰居狀態正常。
初步嘗試
懷疑1:ipsec。因為dsvpn啟用了ipsec保護,ipsec偶爾會出現單向通的問題,因此嘗試reset ike sa,reset ipsec sa,重新建立ipsec sa,nhrp鄰居重新建立,問題依然存在。
懷疑2:MTU。看到ospf狀態停留exstart/exchange,首先想到的就是dbd報文mtu協商問題,這也是各種認證考試和排錯推薦的常見問題。不過Huawei USG默認關閉ospf-mtu檢查,也不需要像思科設備那樣配ignor mtu,使用命令查看鄰居和接口狀態,可以看到華為默認接口mtu是0。
懷疑3:防火牆策略。有一些安全設備是默認放行ospf、dhcp這類的網絡協議,華為防火牆再這個問題上特別糾結,到底是默認放行還是默認攔截有過多次反復(可見下圖)。不管三七二一直接配上 undo firewall packet-filter basic-protocol enable ,問題依然存在。
(上圖是firewall packet-filter basic-protocol enable命令在不同版本中的默認狀態,給華為防火牆升級版本的時候需要小心。)
懷疑4:router ID沖突。這也是可能造成這個問題的原因,檢查ospf error中router id沖突的計數,發現沒有增加。
深入排查
經過以上的排查和嘗試,要繼續解決這個問題就必須開debug和抓包了。
在鏈路兩端設備上分別debug ospf event和ospf package,發現發現exstart端發出的dd報文exchange端都可以收到,但是exchange端回復的報文,對端沒有收到,見下圖:
(spoke端,狀態為exstart)
(hub端,狀態為exchange)
debug過程中可以看到,hub和spoke端均有報文交互,但是唯獨長度1472的回應dd報文丟失,這也是debug過程中看到的最長的報文。因此懷疑網絡中存在真實的較低mtu,導致報文丟失。
兩端公網接口互ping,ping包設置df位。發現實際荷載可以達到1472,懷疑錯了?MTU沒問題??
流量經過ipsec加密,公網口抓包沒意義,因此嘗試在tunnel口上抓包,usg防火牆tunnel口抓包並不支持在web界面上操作,只能命令packet-capture,tunnel口抓到的報文也比較奇怪,似乎只有入向的,抓不到出向。抓包發現一個比較吃驚的事實,看似丟包了的那個長度1472 dd報文可以被抓到,雖然被分片了,但是是完整的,封裝在gre報文內層。
有點匪夷所思,為什么一個完整的包沒有被防火牆采用?而debug中明明就是丟包。
(spoke端tun口抓包顯示對方回復報文並沒有丟,只是被分片)
再次找了一台正常狀態的dsvpn兩端抓包,發現除了抓到分片且封裝在GRE中的dd報文外,還抓到了組裝在一起無gre封裝的報文。所以問題變成了,為什么出問題的那台設備上沒有看到解封裝且組裝好的報文呢??
問題的解決和分析
再仔細檢查存在問題設備上的抓包,發現其他報文,包括hello、lsu報文,都是同時可以看到gre封裝和解封裝的報文。唯獨這個被分片的dd報文沒有。報文有錯誤組裝失敗?仔細檢查了一遍,沒問題。難道是分片的部分識別不正常,被當成普通非gre包問攔截了?帶着這個疑問,嘗試把防火牆最末尾的默認策略改成permit,發現鄰居居然full了!!!
這個時候查看會話表,搜索目的域是local的會話,看到有一條源域是tunnel接口所在域,目的域是local,源目地址是兩邊防火牆公網地址,協議為gre的會話。
嘗試添加一條安全策略,匹配這個GRE會話的策略,默認策略改回deny,重新shutdown/undo shutdown tunnel接口,鄰居可以成功full。
你以為僅僅是單播的dd報文需要單獨放通的問題嗎?錯了,p2mp模式下lsu、lsr報文均是單播,都沒有被攔截,而且之前鄰居也是好好的,沒有dd報文丟失的問題,只是最近網絡規模稍有擴大才出現問題。也就是說沒有分片的報文都可以被undo firewall packet-filter basic-protocol enable這條命令,或者策略permit ospf放行,之前也一直好好的,只因為網絡規模擴大,導致dd報文需要分片,所以才出問題。
(不同網絡類型發送報文的方式)
總而言之,華為usg的處理流程是這樣的:沒有分片的報文被正常識別為ospf協議,放行;分片的報文識別為gre協議,需要多一次放行gre,gre解封裝后才能被當做ospf報文放行。
很難說這不是華為的bug。
如果覺得本文對您有幫助,請掃描后面的二維碼給予捐贈,您的支持是作者繼續寫出更好文章的動力!