以前一直用印象笔记来做笔记的,第一次在cu上面写东西,希望不会被喷
记录一下最近遇到的一个问题的解决过程
1.网络环境和配置
ps:不知道在CU可以用什么样的图片格式的,这个图原来是viso画的,上传的时候不支持这种格式,
只好截图放上来了
s1和s2做了gre,而且在s1上面是通过eth0:1的公网地址来做gre的,eth0的地址是私网地址,
s1上面的路由配置如下:
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.118.1 0.0.0.0 UG 0 0 0 eth0
121.14.1.0 172.16.174.1 255.255.255.0 UG 0 0 0 gre1
即在s1上面默认走eth0,然后经过snat转换出去,只有121.14.1.0/24 网段的才通过gre1到s2出去
这样的配置运行了一段时间,一直没有问题的,直到有一天做了个conntrack -F 清除连接表的操作,就开始有部分网页访问不了了,但是部分还是正常的。s1重启后,一切又都正常了,再清一下连接表又不正常了,按道理来说,清空连接表最多只会对当前的连接有影响,如果是正在打开
的网页,有可能打不开了,打开了的网页,有可能卡死在那里了,但是新打开的网页不应该受影响的,真是奇怪了,于是分别s1的eth0和gre 抓包发现,不能正常访问的网页都是走gre的口出去的,看来是gre的这个网卡有问题了,而且数据包都经过了gre的口,就是没有经过eth0(要走
gre的数据包应该会先走gre口,然后再经过绑定的物理网卡出去,即eth0,抓包的时候应该gre和eth0都抓到才正确),那其实gre封包是完成了,到真实网卡发送的时候出问题了,重新研究了一下配置和数据包经过协议栈的顺序,觉得最有可能就是在SNAT,如果gre的数据包经过SNAT
是会改变saddr的,那么数据包就肯定出不去了。为了验证这个想法,分别在SNAT的前和后写了一个钩子函数,发现能正常访问的时候,经过gre出去的数据包,就算经过SNAT,数据包的saddr不会改变,不能正常访问的时候,经过SNAT的数据包的saddr会被改变,变成SNAT地址池中的一个,这就是为什么数据包能够出到gre,但是出不去eth0了,网页访问正常的时候经过gre出去而且经过SNAT出去的数据包是这样的:
网页访问不正常的时候经过gre而且经过了SNAT出去数据包是这样的
经过钩子函数的验证,可以发现gre的数据包确实也会SNAT的,但是为什么有些时候(清空连接表后)SNAT之后saddr会改变,有时候(重启之后)SNAT之后saddr有不会改变呢?
一开始怀疑是不是有什么开关之类的,可以控制gre的数据包不做SNAT的,查过源码,没有对应的开关,但是发现linux的nat对gre和icmp这种没有端口的之说的数据包是有做特殊处理的。ps:没事读读源码还是有收获的。
没有开关的话,就是gre的数据包一定会做SNAT的,那其实gre的数据包是不应该做SNAT的,这样的配置是不是有问题呢?但是为什么有时候正常有时候不正常呢?不正常的时候是因为清空了连接表的,难道连接有变化?一查连接表发现真的时候连接有变化,
多操作几次conntrack -F 清空连接表发现gre的连接有以下特点
正常的时候连接如下:
gre 47 599
src=115.x.x.x dst=119.x.x.x srckey=0x0 dstkey=0x0 src=119.x.x.x
dst=115.x.x.x srckey=0x0 dstkey=0x0 mark=0 use=1
不正常的连接如下:
gre 47 599 src=119.x.x.x dst=115.x.x.x srckey=0x0 dstkey=0x0 src=115.x.x.x dst=59.x.x.x srckey=0x0 dstkey=0x0 mark=0 use=1
从上面的连接结果正好能从侧面证实了自己写钩子函数验证到结果,gre的数据包会做SNAT的,
正常的时候是因为连接是s2先访问s1建立起来的,当s2先访问s1建立起连的时候在没有经过SNAT的时候,就已经把一条连接的original 和reply方向的src和dst决定了(就是一条连接中的两对src和dst),所以在经过SNAT 的时候数据包的saddr其实也是有被改变的,只不过根据连接,改变
后也跟原来是一样的,所以当重启后或者清空连接表后,如果s2的gre先发包到s1的话,就可以121.14.1.0/24 网段的网页就可以正常访问。不正常的时候,就不多解释了,根据正常的时候的表现就可以知道了。
结论:
1.如果要在同一个物理网卡上面既做gre有做snat的话,与gre绑定的公网地址,用snat的地址池中的一个(做过测试,如果数据包的saddr是snat地址池中的地址,是不会再做SNAT的了)
2.有做NAT的服务器,最好不要随便清空连接表,用户体验会不好
ps:linux的网络功能还是做得挺完善的,虽然经常觉得整个协议栈有时候太庞大了,太复杂了
阅读(3336) | 评论(0) | 转发(0) |