拓扑说明
A为外网任意一个用户
B为公网交换机,二层,保持wan口二层互通
CD 为某公司负载均衡(此次试验版本为6.5),组高可用集群,按照图示配置网络设置和DNAT,对于配置SNAT,路由等不在描述,按照普通常用配置即可
E为主流核心交换机,起三层路由,此次试验为华为NE40-X8A(数据中心级路由器)。
F为服务器1 对外提供服务,独立服务器与G无关联
G为服务器2 对外提供服务,独立服务器与F无关联
测试过程
测试1 由设备A 向202.0.0.3发起服务请求,数据包源ip 200.0.0.1 目的202.0.0.3,数据到达设备C,执行DNAT,数据包源200.0.0.1 目的192.168.0.2 到达设备F,设备F回应,源192.168.0.2 目的200.0.0.1 到达设备E,三层设备根据路由hash计算,将此数据包发往设备C,负载均衡根据连接跟踪,将数据包转换为源202.0.0.3 目的200.0.0.1,发往设备A,完成正常访问过程。
测试2由设备A 向202.0.0.4发起服务请求,数据包源ip 200.0.0.1 目的202.0.0.4,数据到达设备D,执行DNAT,数据包源200.0.0.1 目的192.168.0.3 到达设备G,设备G回应,源192.168.0.3 目的200.0.0.1 到达设备E,三层设备根据路由hash计算,将此数据包发往设备C(注:华为或者华三等厂商交换机是在交换机底层启动转发平面,数据包到达上行接口板以后由转发引擎查表转发,经交换网到下行接口板发出,并无连接跟踪功能,多路由实现负载路由时,只能通过源目iphash或者源iphash进行选择下一跳,)。此时问题出现了,由于数据流的首包是通过设备D进行的DNAT,设备C并没有发现首包。数据包要如何处理,这才是我们发现的问题所在。
问题分析
(此分析是结合自身工作经验自行分析,因为涉及底层操作系统问题,所以找不到人确认分析是否正确)
前提已知条件:AD设备在NAT数据包时依旧借用的linux自有的iptables/netfilter,在首包经过NAT时会产生一条连接跟踪记录了NAT转换的信息,在回包时会再次查询此连接跟踪将数据包转换回来。
为了能够进一步分析问题出现的原因,通过sniffer 发包工具模拟内外网,通过模拟测试TCP三次握手的流程分析问题原因。
通过xshell连接AD后台,由于人工发包速度较慢,所以vi /proc/sys/net/ipv4/netfilter/下的超时时间(由于是/proc 所以重启后会恢复),通过多次执行cat /proc/net/nf_conntrack | grep 200.0.0.1 查看2台AD关于200.0.0.1的链接跟踪记录。通过tcpdump –i eth1 host 200.0.0.1 –nn –c 1000 实时查看数据包的传入传出的过程。另外修改了网络拓扑,将内网精简成2层,并且不配置网关,在构造数据包时通过填写设备CD的mac控制数据向C 或者向D发送。
测试过程记录如下:
1.由A经D向F发送syn=1 ack=0后,设备D出现了链接跟踪,但是设备C未获得同步,由F经C向A 发送syn=1 ack=1,设备C收到数据包,在未配置snat时,通过路由直接转发,在启用防火墙并配置snat时,数据包被C丢弃。
2.由A经D向F发送syn=1 ack=0后,设备D出现了链接跟踪,但是设备C未获得同步,由F经D向A 发送syn=1 ack=1,由A经D向F发送syn=0 ack=1完成三次握手以后,设备C同步学习到了此链接跟踪。
3.通过发送UDP模拟测试, 由A经D向F 发送请求包,设备D获得了相应的链接跟踪,C未获得同步,由F经C向A 发送回应包,C设备在配置snat以后,认为此包为首包,进行了出站的snat,并产生了另一条snat的链接记录,未向D同步。由A经D向F 发送请求包,由F经D向A 发送回应包以后,C才能获得同步。
4.在较长时间差异下同时将完整的数据流经过设备D与设备C,发现C设备产生的新链接跟踪会刷新D设备旧的链接跟踪的老化时间,也就是说,链接跟踪是始终保持最新同步的。
测试小结
很简单,就一句话,只有在一次完整的数据流经过设备以后,才会向对端同步链接跟踪信息。
额外补充测试
从测试过程可以看到,对于半链接状态的链接跟踪是不会同步的,所以,尝试手动将D的链接记录添加到C的最后一条,此时链接是可以正常通讯的(前提条件,关闭所有的安全防护措施,毕竟这种传输方式在上下文检测过程中被认为攻击)。
另:通过手动同步链接跟踪,记录会被超时老化,而不是跟着数据包的发送保持实时刷新。
注:此次测试 在应用负载中未成功,在自己搭建的linux虚拟机中是可以的,初步猜测是应用负载有一些隐藏的安全防护,或者与session_id有关。
此类方案的优化建议
从以上测试可以看出,要想实现在来回路径不一致的环境下的高可用集群做网关的要求,需要从底层上修改linux机制,这是一个很复杂的事情,或者尝试通过编写shell脚本,实时同步链接跟踪。
在当前某公司未给出解决方案时,就需要自己想办法去解决这种部署环境方案所带来的问题。
其问题主要集中在数据包来回路径不一致上,即从一个方向进来的数据包,从另一条线路发出。
在当前条件下,问题核心集中在了设备E上,只要它能保证来回路径一致,就不需要对AD进行大改。
要想实现来回路径一致,我提出以下集中方案,并且附上我所能想象到的不足
1 将设备E换成支持来回路径一致的设备(应用负载中叫做对称路由),能提供这些功能的设备一般都是工作在四层或者七层的设备,无论接口数量,还是转发速度都无法与交换机或者路由器抗衡。
2 应用负载设备做双向地址转换,通过修改源地址来保证来回路径一致,缺陷就是内网中看不到公网地址,如果有审计或者安全设备,则会出现错误。
3通过逻辑上的主备,即将所有的浮动ip全部集中在一台设备上,表面上是高可用集群,其实就是主备部署。
4 在核心交换机上写PBR,将源地址为内网地址的,全部到一台设备,而端口映射的全部走另一台设备。也就是说,一台设备只负责上网,另一台设备只负责外部对内访问。缺陷是,内网用户通过公网地址访问的时候要写独立的PBR,有可能还有设备压力不均衡,毕竟上网的人更多,PBR 过多的时候,对于网络故障排除会造成困难。
5使用SDN,引导数据流向,这个就是属于网络大改的范畴了
暂时就写这么多吧。
最后感谢所有帮忙以及不帮忙的人,对于sniffer构建TCP连接的过程来说,简直了。