Chinaunix首页 | 论坛 | 博客
  • 博客访问: 234917
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 296
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-22 11:52
文章分类

全部博文(31)

文章存档

2018年(3)

2017年(11)

2016年(12)

2015年(5)

我的朋友

分类: 网络与安全

2015-07-19 20:22:43

以前一直用印象笔记来做笔记的,第一次在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) |
0

上一篇:没有了

下一篇:网桥/ebtables在netfilter中的hook点分析

给主人留下些什么吧!~~