network中发现的一个SNAT问题

网络设置采用的是单网络节点、flatDHCP,br100(ip:10.61.2.12)桥接到eth0作为flat interface,fixed_range=10.0.0.0/24,eth1(ip:10.61.5.1)作为public interface, floating_range=10.61.5.128/25,另有eth3(ip:10.17.20.254)连接到网络10.17.20.0/22(该网络中的机器有以下命令添加有永久路由保证对floating ip 的访问: route -p add 10.61.0.0 mask 255.255.0.0 10.17.20.254)

问题

1.实例间无法通过floating ip进行ssh登录而通过fixed ip是可以的。

2.网段10.17.20.0/22的机器可能通过floating ip ping通实例,反之则不通。

原因

flatDHCP模式下,实例通过DHCP从网络节点获取fixed ip,网络节点根据DHCP服务配置的MAC-IP对为实例分配fixed ip,至于floating ip网络节点通过iptables的DNAT和SNAT 实现floating ip与fixed ip的关联,可以说实例对于floating ip是完全不知情的。通过查看网络节点的iptables规则,发现SNAT的规则中指定了出去的接口为配置文件的 public_interface值,形如:-A nova-network-float-snat -s 10.0.0.6/32 -o eth1 -j SNAT --to-source 10.61.5.144;而DNAT是没有指定接口的。这样原因就清楚了。

问题一解释:以实例A(fixed_ip:10.0.0.6,floating_ip:10.61.5.144) ssh登录实例B(fixed_ip:10.0.0.18,floating_ip:10.61.5.153)为例,A发往B的包(sip:10.0.0.6,dip:10.61.5.153) 从br100进行网络节点通过DNAT变为(sip:10.0.0.6,dip:10.0.0.18)然后由br100转发给B,注意这里出口为br100故不进行SNAT,B收到请求后回包(sip:10.0.0.18,dip:10.0.0.6), 因为源地址和目的地址在同一网段,该包将直接发往A而不会经过网络节点,A收到回应后发现地址不对期望收到的包应该是(sip:10.61.5.153,dip:10.0.0.6)拒收,连接失败。

问题二解释:以刚才的实例A与C(ip:10.17.21.121)互ping为例。C ping A的包(sip:10.17.21.121,dip:10.61.5.144)从eth3进入网络节点经过DNAT变为(sip:10.17.21.121,dip:10.0.0.6) 经br100转发给A,A回应包(sip:10.0.0.6,dip:10.17.21.121)经br100进入网络节点作为前面DNAT的相关包进行逆转化为(sip:10.61.5.144,dip:10.17.21.121)然后经eth3发往C,ping成功。 现在反过来A ping C的包(sip:10.0.0.6,dip:10.17.21.121)从br100进入网络节点经eth3转发给C注意这里的出口为eth3不是eth1所以不会有SNAT。C收到后回应包(sip:10.17.21.121,dip:10.0.0.6) 但是C没有到10.0.0.6的正确路由,ping失败。

解决办法

有效的解决办法是去掉SNAT规则中对出口的限制这需要修改源代码,暂时我通过iptables-save各iptables-restore来实现这个功能,不过这样的话每次nova-network重启后创建新的实例都要重新运行这个命令, 命令为:

iptables-save | sed 's/-o eth1 //g' | iptables-restore

总结

这两个问题是由多网卡及SNAT规则综合导致的,如果是单网卡则两个问题都不会有,如果采用双网卡则会出现第一个问题,第二个问题主要是由于我这里网络的复杂性造成的,没有普遍性。

补充

刚看了下源代码 nova/network/linux_net.py,在Essex版中添加floating ip iptables转发规则的函数如下:

def floating_forward_rules(floating_ip, fixed_ip):
    return [('PREROUTING', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
            ('OUTPUT', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
            ('float-snat',
            '-s %s -j SNAT --to %s' % (fixed_ip, floating_ip))]

Folsom版中函数如下:

def floating_forward_rules(floating_ip, fixed_ip, device):
    rule = '-s %s -j SNAT --to %s' % (fixed_ip, floating_ip)
    if device:
        rule += ' -o %s' % device
    return [('PREROUTING', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
            ('OUTPUT', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
            ('float-snat', rule)]

可见SNAT规则中的出口参数是在F版中新添加的,并引起了我所遇到的两个问题,那为什么做这样的改动呢???git log

北方工业大学 | 云计算研究中心 | 姜永

linux

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/e47082df2e543411b4390cccd35b9f95.html