华为USG防火墙DSVPN OSPF邻居状态停留exstart/exchange

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。

 

如果觉得本文对您有帮助,请扫描后面的二维码给予捐赠,您的支持是作者继续写出更好文章的动力!

 

posted @ 2022-03-29 02:56  foxgab  阅读(157)  评论(0编辑  收藏  举报