网关服务器的主要作用有二:1、路由 2、nat。考虑到网关是公司的核心服务,决定使用keepalived实现网关的双机热备。

    使用keepalived实现只监控主机的存活非常简单,而且在本次需求中并不需要监控服务。然后看似双机做成了,但是问题来了。

    网关上跑的全是iptables脚本,而且主要是状态跟踪和snat,最突出的一个问题是,keepalived发出的vrrp广播的源地址有时被转换成了外网地址,而且这个还不决定什么时候转换成外网地址。

    配置文件如下:

 

[root@gw-175 ~]# cat /etc/keepalived/keepalived.conf 

! Configuration File for keepalived

 

global_defs {

   notification_email {

     [email protected]

   }

   notification_email_from [email protected]

   smtp_server xxxxxxxx

   smtp_connect_timeout 30

   router_id gw_ha_175

}

 

#vrrp_sync_group VG1 {

# group {

# VI_1

#     }

#}

 

vrrp_script check_run {

script "/data/sbin/checkgw.sh"

weight -5

interval 5

}

 

vrrp_instance VI_1 {

state BACKUP

# nopreempt

interface eth0

virtual_router_id 150

priority 150

advert_int 1

track_script {

check_run

     }

track_interface {

        eth0

        }

authentication {

        auth_type PASS

        auth_pass 12345678

    }

notify_master "/data/sbin/master.sh"

notify_backup "/data/sbin/backup.sh"

# notify_fault "/data/sbin/backup.sh"

# smtp_alert

mcast_src_ip eth0 192.168.8.175

virtual_ipaddress {

        192.168.8.254/24 dev eth0

        192.168.9.254/24 dev eth0

        192.168.7.254/24 dev eth0

        192.168.6.254/24 dev eth0

        192.168.5.254/24 dev eth0

        192.168.4.254/24 dev eth0

        192.168.2.254/24 dev eth0

        192.168.1.254/24 dev eth0

        192.168.10.254/24 dev eth0

        192.168.100.254/24 dev eth0

        192.168.16.254/24 dev eth0

        192.168.33.254/24 dev eth0

        192.168.38.254/24 dev eth0

        192.168.39.254/24 dev eth0

    }

}

另外一台机器配置文件除了mcast_src_ip eth0 192.168.8.175和上面的不一样外,其余都一样。

我使用tcpdump抓到的包应该是这样,

 

[root@gw-174 ~]# tcpdump vrrp

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

09:34:28.681948 IP 192.168.8.175 > 224.0.0.18: VRRPv2, Advertisement, vrid 150, prio 150, authtype simple, intvl 1s, length 72

09:34:29.682389 IP 192.168.8.175 > 224.0.0.18: VRRPv2, Advertisement, vrid 150, prio 150, authtype simple, intvl 1s, length 72

但实际情况确是,

 

[root@gw-174 ~]# tcpdump vrrp

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

09:34:28.681948 IP 1.1.1.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 150, prio 150, authtype simple, intvl 1s, length 72

09:34:29.682389 IP 1.1.1.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 150, prio 150, authtype simple, intvl 1s, length 72

在进行了各种研究,发现是状态跟踪导致的,

[root@gw-175 ~]# grep src=192.168.8.175 /proc/net/ip_conntrack

unknown  112 599 src=192.168.8.175 dst=224.0.0.18 packets=11662 bytes=1072904 [UNREPLIED] src=1.1.1.1 dst=224.0.0.18 packets=0 bytes=0 mark=0 secmark=0 use=2

iptables会对每一个连接进行连接跟踪,除非这个连接断开或者/proc/net/ip_conntrack表中的记录超时才回重新跟踪。而vrrp广播是不停的发,所以连接不会断开,表中记录也不会超时,一直会匹配这个错误的记录。(至于这条记录是如何产生的,应该刚开始运行的时候iptables的nat表中还没添加相应的vrrp规则)

对于这种情况,尝试删除这个表中条目,失败!!!停止keepalived,等待表中条目超时,不可能!(停止后vip就会消失,就会断网)

在研究后决定对vrrp广播包就行取消状态跟踪,在filter表中添加UNTRACKED状态,

 

iptables -I FORWARD -m state --state ESTABLISHED,RELATED,UNTRACKED -j ACCEPT

iptables -I INPUT -m state --state ESTABLISHED,RELATED,UNTRACKED -j ACCEPT

在raw中,添加如下:

iptables -t raw -A OUTPUT -s 192.168.8.175 -d 224.0.0.0/8 -j NOTRACK

抓到的变为包如下:

 

[root@gw-174 ~]# tcpdump vrrp

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

09:34:28.681948 IP 192.168.8.175 > 224.0.0.18: VRRPv2, Advertisement, vrid 150, prio 150, authtype simple, intvl 1s, length 72

09:34:29.682389 IP 192.168.8.175 > 224.0.0.18: VRRPv2, Advertisement, vrid 150, prio 150, authtype simple, intvl 1s, length 72

等待表中条目超时后,在nat中添加对应vrrp的规则即可!

参考连接http://linuxnet527.blog.163.com/blog/static/172982867201151395821550/

http://wangcong.org/articles/learning-iptables.cn.html