SNAT 下使用 keepalived 做雙機熱備的問題

1 問題表現

SNAT 下,使用 keepalived 做雙機熱備,會出現了 ip 衝突的 問題。

2 網絡拓撲

2.1 主機 FW1 的配置:

在這裏插入圖片描述

2.1.1 主機的 iptables 配置

將所有 192.168.8.0/24,地址轉換爲出口 ip 10.10.10.254。

iptables -t nat -A POSTROUTING -s 192.168.8.0/24 -j SNAT --to-source 10.10.10.254

2.1.2 主機的 keepalived.conf 配置

vrrp_group mcast_src_ip 虛擬 ip
VI_1 10.101.101.1/24 10.10.10.254/24
VI_2 192.168.8.1/24 192.168.8.254/24
! Configuration File for keepalived

global_defs {
   vrrp_sync_group G1{
       group{
           VI_1 
           VI_2
       }
   }
   router_id localhost.localdomain
}


vrrp_instance VI_1 {
    state BACKUP
    interface vEth0
     track_interface {
            vEth0     
            vEth1
    }
    mcast_src_ip 10.101.101.1
    virtual_router_id 10
    priority 200
    advert_int 3

    virtual_ipaddress {
        10.10.10.254/24
    }
    
}

vrrp_instance VI_2 {
    state BACKUP
    interface vEth1
     track_interface { 
            vEth0     
            vEth1
         }
    mcast_src_ip 192.168.8.1
    virtual_router_id 20
    priority 200
    advert_int 3
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    
    virtual_ipaddress {
        192.168.8.254/24
    }

}

2.2 備機 FW2 的配置:

2.2.1 備機 的 iptables 配置

將所有 192.168.8.0/24,地址轉換爲出口 ip 10.10.10.254。

iptables -t nat -A POSTROUTING -s 192.168.8.0/24 -j SNAT --to-source 10.10.10.254

2.2.2 備機的 keepalived.conf 配置

vrrp_group mcast_src_ip 虛擬 ip
VI_1 10.101.101.2/24 10.10.10.254/24
VI_2 192.168.8.2/24 192.168.8.254/24
! Configuration File for keepalived

global_defs {
   vrrp_sync_group G1{
       group{
           VI_1
           VI_2
       }

   }

   router_id localhost.localdomain
}

vrrp_instance VI_1 {
    state BACKUP
    interface vEth0
     track_interface {
          
            vEth0     
            vEth1
         }
    mcast_src_ip 10.101.101.2
    virtual_router_id 10
    priority 100
    advert_int 3

    virtual_ipaddress { 
        10.10.10.254/24
    }
}

vrrp_instance VI_2 {
    state BACKUP
    interface vEth1
     track_interface {
            vEth0     
            vEth1
         }
    mcast_src_ip 192.168.8.2
    virtual_router_id 20
    priority 100
    advert_int 3
    
    virtual_ipaddress {
        192.168.8.254/24
    }
}

3 故障重現

  1. 拔出主機的 vEth0 口的網線。等待主機上的 虛擬ip地址,遷移到備機。
  2. 插上主機的 vEth0 口的網線。等待備機上的 虛擬ip地址,遷移回主機。
  3. 查看 備機上的 ip。發現 vEth1 口的 虛擬ip地址 (192.168.8.254/24)沒有完全刪除。造成 ip 衝突。

3.1 主機 ip 查看結果

ip address show
>	8: vEth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
>		link/ether 00:10:f3:51:40:2e brd ff:ff:ff:ff:ff:ff
>		inet 10.101.101.1/24 scope global vEth0
>		   valid_lft forever preferred_lft forever
>		inet 10.10.10.254/24 scope global vEth0
>		   valid_lft forever preferred_lft forever
>		inet6 fe80::210:f3ff:fe51:402e/64 scope link 
>		   valid_lft forever preferred_lft forever
>	9: vEth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
>		link/ether 00:10:f3:51:40:2f brd ff:ff:ff:ff:ff:ff
>		inet 192.168.8.1/24 scope global vEth1
>		   valid_lft forever preferred_lft forever
>		inet 192.168.8.254/24 scope global secondary vEth1			# <-- 主機機的 虛擬ip 
>		     ^^^^^^^^^^^^^^^^
>		   valid_lft forever preferred_lft forever
>		inet6 fe80::210:f3ff:fe51:402f/64 scope link 
>		   valid_lft forever preferred_lft forever

3.2 備機 ip 查看結果

ip address show
	16: vEth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
		link/ether 00:10:f3:66:20:0b brd ff:ff:ff:ff:ff:ff
		inet 10.101.101.2/24 scope global vEth0
		   valid_lft forever preferred_lft forever
		inet6 fe80::210:f3ff:fe66:200b/64 scope link 
		   valid_lft forever preferred_lft forever
	17: vEth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
		link/ether 00:10:f3:66:20:0c brd ff:ff:ff:ff:ff:ff
		inet 192.168.8.2/24 scope global vEth1
		   valid_lft forever preferred_lft forever
		inet 192.168.8.254/24 scope global secondary vEth1			# <-- 備機的 虛擬ip 沒有完全刪除,造成 ip 衝突。
		     ^^^^^^^^^^^^^^^^
		   valid_lft forever preferred_lft forever
		inet6 fe80::210:f3ff:fe66:200c/64 scope link 
		   valid_lft forever preferred_lft forever

4 問題分析

爲了分析故障的原因。使用 tcpdump 查看 vrrp 報文。

tcpdump -nn -i any vrrp
>	tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
>	listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
>	19:54:11.106503 IP 10.10.10.254 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 200, authtype simple, intvl 3s, length 20
>                      ^^^^^^^^^^^^   abnormal, should be 192.168.8.1
>	19:54:12.105473 IP 10.101.101.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 200, authtype simple, intvl 3s, length 40
>	19:54:14.107528 IP 10.10.10.254 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 200, authtype simple, intvl 3s, length 20
>                      ^^^^^^^^^^^^   abnormal, should be 192.168.8.1
>	19:54:15.106532 IP 10.101.101.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 200, authtype simple, intvl 3s, length 40
>	19:54:17.108558 IP 10.10.10.254 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 200, authtype simple, intvl 3s, length 20
>                      ^^^^^^^^^^^^   abnormal, should be 192.168.8.1
>	19:54:18.107585 IP 10.101.101.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 200, authtype simple, intvl 3s, length 40
>	19:54:20.109579 IP 10.10.10.254 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 200, authtype simple, intvl 3s, length 20
>                      ^^^^^^^^^^^^   abnormal, should be 192.168.8.1
>	19:54:21.108639 IP 10.101.101.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 200, authtype simple, intvl 3s, length 40

上述報文有問題如下:

  1. 從 192.168.8.1 發送出來的 vrrp 報文。其中的源地址,因爲 SNAT 的原因 (iptables -t nat -A POSTROUTING -s 192.168.8.0/24 -j SNAT --to-source 10.10.10.254),都變換爲了 10.10.10.254。
  2. 由於主機的 keepalived 在配置中,是使用 192.168.8.1 作爲 mcast_src_ip 的。所以經過 SNAT 後,備機無法得知主機 正確的 mcast_src_ip 地址。
  3. 同樣道理,備機上 使用 192.168.8.2 作爲 mcast_src_ip 的。經過 SNAT 後,主機也是無法得知備機機 正確的 mcast_src_ip 地址。

5 處理目標

在主備機器中,源地址爲 mcast_src_ip 所 發送出的 vrrp 報文,都需要避免進行 SNAT。

6 處理方法

6.1 主機 的 iptables 配置

# 避免 10.101.101.1/32 進行 SNAT
iptables -t nat -A POSTROUTING -s 10.101.101.1/32 -d 224.0.0.0/8 -j ACCEPT
# 避免 192.168.8.1/32 進行 SNAT
iptables -t nat -A POSTROUTING -s 192.168.8.1/32 -d 224.0.0.0/8 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.8.0/24 -j SNAT --to-source 10.10.10.254

6.2 備機 的 iptables 配置

# 避免 10.101.101.2/32 進行 SNAT
iptables -t nat -A POSTROUTING -s 10.101.101.2/32 -d 224.0.0.0/8 -j ACCEPT
# 避免 192.168.8.2/32 進行 SNAT
iptables -t nat -A POSTROUTING -s 192.168.8.2/32 -d 224.0.0.0/8 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.8.0/24 -j SNAT --to-source 10.10.10.254

7 修復後的驗證

修復後,再次觀察主備機器上的 vrrp 報文:

  1. vrrp 報文恢復正常。
  2. 拔插網線後,也沒有虛擬ip 沒有完全刪除的情況出現。

主機上的 vrrp 報文:

tcpdump -nn -i any vrrp
>	tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
>	listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
>	19:56:59.760086 IP 192.168.8.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 200, authtype simple, intvl 3s, length 20
>	                   ^^^^^^^^^^^   normal
>	19:57:00.761498 IP 10.101.101.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 200, authtype simple, intvl 3s, length 40
>	19:57:02.760174 IP 192.168.8.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 200, authtype simple, intvl 3s, length 20
>	                   ^^^^^^^^^^^   normal
>	19:57:03.761584 IP 10.101.101.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 200, authtype simple, intvl 3s, length 40
>	19:57:05.760225 IP 192.168.8.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 20, prio 200, authtype simple, intvl 3s, length 20
>	                   ^^^^^^^^^^^   normal
>	19:57:06.761670 IP 10.101.101.1 > 224.0.0.18: VRRPv2, Advertisement, vrid 10, prio 200, authtype simple, intvl 3s, length 40
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章