本文最后更新于:August 10, 2021 pm
                
              
            
            
              本文主要介绍基于CentOS7.9系统部署DPVS的FullNAT模式的各种部署方式和配置管理,包括IPv4-IPv4、bonding、IPv6-IPv6、IPv6-IPv4(NAT64)和keepalived模式这五种方案。
 
以下的配置全部基于双臂模式,并且RS机器上面已经安装了DPVS相应的toa模块。我们先从单个网卡的IPv4简单配置开始,接着再做bonding配置,然后再进行IPv6简单配置,NAT64配置以及最后使用keepalived配置主备模式。
本文中安装的DPVS版本为1.8-10,dpdk版本为18.11.2,详细安装过程已在之前的文章DPVS-FullNAT模式部署篇 - TinyChen’s Studio 中叙述过,这里不做赘述。
 
1、IPv4简单配置 1.1 架构图 首先是最简单的配置方式,直接使用ipvsadm的命令行操作来实现一个IPv4网络的FullNat模式,架构图如下:
这里我们使用dpdk2网卡作为wan口,dpdk0网卡作为lan口
1.2 配置过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47  $ dpip addr add 10.0.96.204/32 dev dpdk2 $ dpip route add 10.0.96.0/24 dev dpdk2 $ dpip route add 192.168.229.0/24 dev dpdk0 $ dpip route add default via 10.0.96.254 dev dpdk2 $ ipvsadm -A -t 10.0.96.204:80 -s rr $ ipvsadm -a -t 10.0.96.204:80 -r 192.168.229.1 -b $ ipvsadm --add-laddr -z 192.168.229.204 -t 10.0.96.204:80 -F dpdk0 $ dpip route show inet 192.168.229.204/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope host metric 0 proto auto inet 10.0.96.204/32 via 0.0.0.0 src 0.0.0.0 dev dpdk2 mtu 1500 tos 0 scope host metric 0 proto auto inet 10.0.96.0/24 via 0.0.0.0 src 0.0.0.0 dev dpdk2 mtu 1500 tos 0 scope link  metric 0 proto auto inet 192.168.229.0/24 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope link  metric 0 proto auto inet 0.0.0.0/0 via 10.0.96.254 src 0.0.0.0 dev dpdk2 mtu 1500 tos 0 scope global metric 0 proto auto $ dpip addr show inet 10.0.96.204/32 scope global dpdk2      valid_lft forever preferred_lft forever inet 192.168.229.204/32 scope global dpdk0      valid_lft forever preferred_lft forever $ ipvsadm  -ln  IP Virtual Server version 0.0.0 (size=0) Prot LocalAddress:Port Scheduler Flags   -> RemoteAddress:Port           Forward Weight ActiveConn InActConn TCP  10.0.96.204:80 rr   -> 192.168.229.1:80              FullNat 1      0          0 $ ipvsadm  -G VIP:VPORT            TOTAL    SNAT_IP              CONFLICTS  CONNS 10.0.96.204:80    1                               192.168.229.204       0          0
 
然后我们在RS上面启动一个nginx,设置返回IP和端口号,然后直接对VIP使用ping和curl命令进行测试:
$ ping -c4 10.0.96.204 PING 10.0.96.204 (10.0.96.204) 56(84) bytes of data. 64 bytes from 10.0.96.204: icmp_seq=1 ttl=54 time=47.2 ms 64 bytes from 10.0.96.204: icmp_seq=2 ttl=54 time=48.10 ms 64 bytes from 10.0.96.204: icmp_seq=3 ttl=54 time=48.5 ms 64 bytes from 10.0.96.204: icmp_seq=4 ttl=54 time=48.5 ms --- 10.0.96.204 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 8ms rtt min/avg/max/mdev = 47.235/48.311/48.969/0.684 ms $ curl 10.0.96.204 Your IP and port is 172.16.0.1:62844
 
1.3 小结 该模式非常的简单,可以快速配置检验自己机器上的DPVS能否正常工作,不过由于是单点,往往较少使用。
2、bonding配置 目前DPVS支持配置bonding4和bonding0,两者的配置基本相同,配置方式可以参考dpvs/conf/dpvs.conf.single-bond.sample这个文件。
配置bonding模式的时候,不需要对slave网卡(如dpdk0等)指定kni_name这个参数,而是要在bonding中指定对应的kni_name,同时还要注意primary参数指定的网卡的MAC地址一般就是bonding网卡的MAC地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 ! netif  config netif_defs {     <init> pktpool_size      1048575      <init> pktpool_cache    256      <init> device dpdk0 {         rx  {             max_burst_size       32              queue_number        16              descriptor_number   1024              rss                 all         }         tx {             max_burst_size       32              queue_number        16              descriptor_number   1024          }         fdir {             mode                 perfect             pballoc             64k              status              matched         }         ! mtu                   1500          ! promisc_mode         ! kni_name              dpdk0.kni     }     <init> device dpdk1 {         rx  {             max_burst_size       32              queue_number        16              descriptor_number   1024              rss                 all         }         tx {             max_burst_size       32              queue_number        16              descriptor_number   1024          }         fdir {             mode                 perfect             pballoc             64k              status              matched         }         ! mtu                   1500          ! promisc_mode         ! kni_name                dpdk1.kni     }     <init> device dpdk2 {         rx  {             max_burst_size       32              queue_number        16              descriptor_number   1024              rss                 all         }         tx {             max_burst_size       32              queue_number        16              descriptor_number   1024          }         fdir {             mode                 perfect             pballoc             64k              status              matched         }         ! mtu                   1500          ! promisc_mode         ! kni_name              dpdk2.kni     }     <init> device dpdk3 {         rx  {             max_burst_size       32              queue_number        16              descriptor_number   1024              rss                 all         }         tx {             max_burst_size       32              queue_number        16              descriptor_number   1024          }         fdir {             mode                 perfect             pballoc             64k              status              matched         }         ! mtu                   1500          ! promisc_mode         ! kni_name              dpdk3.kni     }     <init> bonding bond1 {         mode                     4          slave                   dpdk0         slave                   dpdk1         primary                 dpdk0         kni_name                bond1.kni     }     <init> bonding bond2 {         mode                     4          slave                   dpdk2         slave                   dpdk3         primary                 dpdk2         kni_name                bond2.kni     } }
 
随后在配置每个worker-cpu的时候要注意port要选择对应的bond网卡
<init> worker  cpu1 {     type     slave     cpu_id  1      port    bond1 {         rx_queue_ids      0          tx_queue_ids     0      }     port    bond2 {         rx_queue_ids      0          tx_queue_ids     0      } }
 
DPVS的bonding配置和在Linux中直接操作一样。bonding配置成功后只需要对生成的bonding网卡操作即可,使用dpip命令可以查看对应网卡的工作状态:如下面的网卡就工作在全双工、20000 Mbps速率的模式下,MTU为1500,并且在DPVS中配置了16个收发队列。
$ dpip link  show 5: bond1: socket 0 mtu 1500 rx-queue 15 tx-queue 16     UP 20000 Mbps full-duplex auto-nego     addr AA:BB:CC:11:22:33 6: bond2: socket 0 mtu 1500 rx-queue 15 tx-queue 16     UP 20000 Mbps full-duplex auto-nego     addr AA:BB:CC:12:34:56
 
3、IPv6简单配置 3.1 DPVS配置过程 IPv6的简单配置方法和IPv4一样,只是把对应的IPv4地址换成了IPv6地址,同时还需要额外注意一下IPv6地址指定端口的时候需要使用[]将IP地址括起来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36  $ dpip addr add 2001::201/128 dev bond2 $ dpip route -6 add 2001::/64 dev bond2 $ dpip route -6 add 2407::/64 dev bond1 $ dpip route -6 add default via 2001::1 dev bond2 $ ipvsadm -A -t [2001::201]:80 -s rr $ ipvsadm -a -t [2001::201]:80 -r [2407::1]:80 -b $ ipvsadm -a -t [2001::201]:80 -r [2407::2]:80 -b $ ipvsadm --add-laddr -z 2407::201 -t [2001::201]:80 -F bond1 $ dpip addr show inet6 2407::201/128 scope global bond1      valid_lft forever preferred_lft forever inet6 2001::201/128 scope global bond2      valid_lft forever preferred_lft forever       $ dpip route -6 show inet6 2001::201/128 dev bond2 mtu 1500 scope host inet6 2407::201/128 dev bond1 mtu 1500 scope host inet6 2407::/64 dev bond1 mtu 1500 scope link  inet6 2001::/64 dev bond2 mtu 1500 scope link  inet6 default via 2001::1 dev bond2 mtu 1500 scope global $ ipvsadm -Ln IP Virtual Server version 0.0.0 (size=0) Prot LocalAddress:Port Scheduler Flags   -> RemoteAddress:Port           Forward Weight ActiveConn InActConn TCP  [2001::201]:80 rr   -> [2407::1]:80 FullNat 1      0          0   -> [2407::2]:80 FullNat 1      0          0
 
3.2 效果检验 测试效果,确认RS上面的nginx能够正常返回用户端的真实IP和端口,则表明配置正常。
$  curl -6 "http://\[2001::201\]"  Your IP and port is [2408::1]:38383
 
4、NAT64配置 4.1 DPVS配置过程 架构图上和之前的两个并没太大的不同,只是IP略有差异
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37  $ dpip addr add 2001::201/128 dev bond2 $ dpip route -6 add 2001::/64 dev bond2 $ dpip route add 192.168.229.0/23 dev bond1 $ dpip route -6 add default via 2001::1 dev bond2 $ ipvsadm -A -t [2001::201]:80 -s rr $ ipvsadm -a -t [2001::201]:80 -r 192.168.229.1:80 -b $ ipvsadm -a -t [2001::201]:80 -r 192.168.229.2:80 -b $ ipvsadm --add-laddr -z 192.168.229.201 -t [2001::201]:80 -F bond1 $ dpip addr show inet6 2001::201/128 scope global bond2      valid_lft forever preferred_lft forever inet 192.168.229.201/32 scope global bond1      valid_lft forever preferred_lft forever       $ dpip route show inet 192.168.229.201/32 via 0.0.0.0 src 0.0.0.0 dev bond1 mtu 1500 tos 0 scope host metric 0 proto auto inet 192.168.229.0/23 via 0.0.0.0 src 0.0.0.0 dev bond1 mtu 1500 tos 0 scope link  metric 0 proto auto $ dpip route -6 show inet6 2001::201/128 dev bond2 mtu 1500 scope host inet6 2001::/64 dev bond2 mtu 1500 scope link  inet6 default via 2001::1 dev bond2 mtu 1500 scope global $ ipvsadm -ln  IP Virtual Server version 0.0.0 (size=0) Prot LocalAddress:Port Scheduler Flags   -> RemoteAddress:Port           Forward Weight ActiveConn InActConn TCP  [2001::201]:80 rr   -> 192.168.229.1:80              FullNat 1      0          0   -> 192.168.229.2:80              FullNat 1      0          0
 
测试效果
$  curl -6 "http://\[2001::201\]"  Your IP and port is 192.168.229.201:1035
 
从上面的测试结果来看,即使是安装了TOA模块,也无法获取NAT64模式下客户端的源IP地址,所有的客户端IP和端口都会变成LIP转发过来的时候的IP和端口。如果是对源IP没需求的话可以忽略这个问题,如果有需求的话则需要更改RS上面的客户端程序,下面我们以nginx为例。
4.2 NGINX支持NAT64 dpvs还为nginx提供了一个nat64的toa模块,当VIP为ipv6而RS为ipv4的时候,可以使用这个模块在nginx中获取用户真实的ipv6地址,需要我们在源码编译安装nginx之前先打上这个补丁。
从官方的文件名我们可以看出应该是基于1.14.0版本制作的patch,首先我们使用旧版的1.14.0版本能够正常打上补丁,后续的编译安装也能正常进行
$ pwd  /home/nginx-1.14.0 $ ls  auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  man  nginx-1.14.0-nat64-toa.patch  README  src $ cp  /home/dpvs/kmod/toa/example_nat64/nginx/nginx-1.14.0-nat64-toa.patch ./ $ patch -p 1 < nginx-1.14.0-nat64-toa.patch patching file src/core/ngx_connection.h patching file src/core/ngx_inet.h patching file src/event/ngx_event_accept.c patching file src/http/ngx_http_variables.c
 
使用最新的nginx-1.21.1版本的时候会有报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 $ cp  /home/dpvs/kmod/toa/example_nat64/nginx/nginx-1.14.0-nat64-toa.patch ./ $ pwd  /home/nginx-1.21.1 $ ls  auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  man  nginx-1.14.0-nat64-toa.patch  README  src $ patch -p 1 < nginx-1.14.0-nat64-toa.patch patching file src/core/ngx_connection.h Hunk  1 out of 1 hunk FAILED -- saving rejects to file src/core/ngx_connection.h.rej patching file src/core/ngx_inet.h Hunk  patching file src/event/ngx_event_accept.c Hunk  Hunk  Hunk  patching file src/http/ngx_http_variables.c Hunk  Hunk  Hunk 
 
仔细查看patch文件内容可以发现出现错误是因为1.21.1版本中对应部分移除了几行代码导致patch无法匹配,我们手动将那一行代码加上去
随后就能正常编译安装了,完成之后我们可以在日志中加入$toa_remote_addr和$toa_remote_port这两个变量来获取NAT64模式下的客户端真实IP。
4.3 效果检验 再次测试发现能够显示真正的客户端源IP地址和端口号。
$  curl -6 "http://\[2001::201\]"  Your remote_addr and remote_port is 192.168.229.201:1030 Your toa_remote_addr and toa_remote_port is [2408::1]:64920 toa_remote_addr=2408::1 | toa_remote_port=64920 | remote_addr=192.168.229.201 | remote_port=1030 
 
5、keepalived配置 5.1 架构图 使用keepalived配置有两大好处:
VIP、LIP、RS等配置参数可以固化在keepalived的配置文件中,无需每次都使用命令或脚本手动操作 
keepalived可以使用VRRP协议配置主备模式(master-backup),避免了单点问题 
 
官方的keepalived配置网络拓扑使用的是单臂模式,这里我们修改为双臂模式;同时需要注意DPVS使用的keepalived是修改过的版本,和原生版本的keepalived在配置语法和参数上稍有不同 。
和前面提到的一样,keepalived也支持IPv4-IPv4模式、IPv6-IPv6模式和NAT64模式(IPv6-IPv4)这三种模式,三者的不同只是在于路由的不同和keepalived的配置文件略有差异。
5.2 配置kni网卡 keepalived的配置需要在正常的Linux网络栈(非DPVS实现的简单用户态网络栈)中有一个能进行正常网络通信的kni网卡。kni网卡的配置和普通网卡的配置是完全一样的,只需要将配置文件中的DEVICE改为对应的kni网卡即可。
kni网卡的存在依赖于dpvs进程的存在,如果dpvs进程重启了,那么kni网卡不会跟着重启,而是处于DOWN状态直至我们手动将其启用(ifup)
 
$ cat  /etc/sysconfig/network-scripts/ifcfg-bond2.kni DEVICE=bond2.kni BOOTPROTO=static ONBOOT=yes  IPADDR=10.0.96.200 NETMASK=255.255.255.0 GATEWAY=10.0.96.254 $ ip a 32: bond2.kni: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000     link /ether a0:36:9f:f0:e4:c0 brd ff:ff:ff:ff:ff:ff     inet 10.0.96.200/24 brd 10.0.96.255 scope global bond2.kni        valid_lft forever preferred_lft forever     inet6 fe80::a236:9fff:fef0:e4c0/64 scope link         valid_lft forever preferred_lft forever
 
前面我们的dpvs.conf配置文件中会对每个dpdk网卡或者是bond网卡配置一个kni网卡(一般命名为dpdk0.kni或bond0.kni等),在前面的简单配置步骤中我们都是直接把VIP加到DPDK的网卡上,但是这样无法实现VIP的主备切换,因此这里我们需要将VIP交由keepalived程序控制。
5.3 配置路由 keepalived模式下,对于双臂网络模式的FullNAT,我们需要加的路由一般来说可以直观地分为三大部分:VIP网段的路由,RS/LIP网段的路由,默认路由 。
 $ dpip route add 10.0.96.0/24 dev bond2  $ dpip route add 192.168.229.0/23 dev bond1  $ dpip route add default via 10.0.96.254 dev bond2  $ dpip route -6 add 2001::/64 dev bond2  $ dpip route -6 add 2407::/64 dev bond1  $ dpip route -6 add default via 2001::1 dev bond2  $ dpip route -6 add 2001::/64 dev bond2  $ dpip route add 192.168.229.0/23 dev bond1  $ dpip route -6 add default via 2001::1 dev bond2 
 
5.4 配置keepalived 首先我们使用systemctl将keepalived管理起来,首先编写一个unit文件,配置中的路径要替换成DPVS定制版的keepalived二进制文件以及keepalived配置文件的路径(建议使用绝对路径)
$ cat  /usr/lib/systemd/system/keepalived.service [Unit] Description=DPVS modify version keepalived After=syslog.target network-online.target [Service] Type=forking PIDFile=/var/run/keepalived.pid KillMode=process ExecStart=/path/to/dpvs/bin/keepalived -f /etc/keepalived/keepalived.conf -D -d -S 0 ExecReload=/bin/kill -HUP $MAINPID  [Install] WantedBy=multi-user.target
 
随后我们修改keepalived的日志输出到指定的文件中方便我们定位问题
 local0.*                                                /path/to/keepalived.log
 
最后我们重启相关的rsyslog日志服务和keepalived
$ systemctl daemon-reload $ systemctl enable  rsyslog.service $ systemctl restart rsyslog.service
 
5.5 keepalived.conf 注意即使RS相同,NAT64模式和普通的IPv4模式也不能够在同一个vrrp_instance中同时定义IPv4地址和IPv6地址,因为两者使用的VRRP协议版本不同(VRRP和VRRP6)
以下以NAT64和IPv4网络两种配置为例,截取部分重点配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 ! Configuration  File for keepalived global_defs {     router_id  DPVS_TEST } local_address_group laddr_g1 {     192.168.229.201 bond1      } vrrp_instance VI_1 { 	     state  MASTER               interface bond2.kni          dpdk_interface bond2          virtual_router_id 201      priority 100      advert_int 1      authentication {         auth_type  PASS         auth_pass dpvstest     } 	     virtual_ipaddress {         10.0.96.201         10.0.96.202     } }vrrp_instance  VI_2 {     state  MASTER     interface bond2.kni     dpdk_interface bond2     virtual_router_id 202      priority 100      advert_int 1      authentication {         auth_type  PASS         auth_pass dpvstest     }     virtual_ipaddress {         2001::201         2001::202     } }virtual_server_group  10.0.96.201 -80  {     10.0.96.201 80     10.0.96.202 80 }virtual_server  group 10.0.96.201 -80  {     delay_loop  3      lb_algo rr     lb_kind FNAT     protocol TCP     laddr_group_name laddr_g1     real_server 192.168.229.1  80  {         weight  100          inhibit_on_failure         TCP_CHECK {             nb_sock_retry  2              connect_timeout 3              connect_port 80          }     }     real_server 192.168.229.2  80  {         weight  100          inhibit_on_failure         TCP_CHECK {             nb_sock_retry  2              connect_timeout 3              connect_port 80          }     } } virtual_server_group 10.0.96.201 -80 -6  {     2001::201 80     2001::202 80 }virtual_server  group 10.0.96.201 -80 -6  {     delay_loop  3      lb_algo rr     lb_kind FNAT     protocol TCP     laddr_group_name laddr_g1     real_server 192.168.229.1  80  {         weight  100          inhibit_on_failure         TCP_CHECK {             nb_sock_retry  2              connect_timeout 3              connect_port 80          }     }     real_server 192.168.229.2  80  {         weight  100          inhibit_on_failure         TCP_CHECK {             nb_sock_retry  2              connect_timeout 3              connect_port 80          }     } }
 
keepalived启动之后,我们就可以使用dpip命令查看到各个定义的VIP,ipvsadm命令中应该可以看到各组RS状态正常 
但是需要确保在keepalived运行过程中dpvs必须处于正常运行状态,并且配置文件中interface参数指定的kni网卡处于正常运行状态 
每个网卡和网段的相关路由还是需要自己手动添加(IPv4、IPv6) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51  $ dpip addr show inet 10.0.96.202/32 scope global bond2      valid_lft forever preferred_lft forever inet6 2001::202/128 scope global bond2      valid_lft forever preferred_lft forever inet6 2001::201/128 scope global bond2      valid_lft forever preferred_lft forever inet 10.0.96.201/32 scope global bond2      valid_lft forever preferred_lft forever inet 192.168.229.201/32 scope global bond1      valid_lft forever preferred_lft forever $ ipvsadm -ln  IP Virtual Server version 0.0.0 (size=0) Prot LocalAddress:Port Scheduler Flags   -> RemoteAddress:Port           Forward Weight ActiveConn InActConn TCP  10.0.96.201:80 rr   -> 192.168.229.1:80              FullNat 100    0          0   -> 192.168.229.2:80              FullNat 100    0          0 TCP  10.0.96.201:443 rr   -> 192.168.229.1:443             FullNat 100    0          0   -> 192.168.229.2:443             FullNat 100    0          0 TCP  10.0.96.202:80 rr   -> 192.168.229.1:80              FullNat 100    0          0   -> 192.168.229.2:80              FullNat 100    0          0 TCP  10.0.96.202:443 rr   -> 192.168.229.1:443             FullNat 100    0          0   -> 192.168.229.2:443             FullNat 100    0          0 TCP  [2001::201]:80 rr   -> 192.168.229.1:80              FullNat 100    0          0   -> 192.168.229.2:80              FullNat 100    0          0 TCP  [2001::201]:443 rr   -> 192.168.229.1:443             FullNat 100    0          0   -> 192.168.229.2:443             FullNat 100    0          0 TCP  [2001::202]:80 rr   -> 192.168.229.1:80              FullNat 100    0          0   -> 192.168.229.2:80              FullNat 100    0          0 TCP  [2001::202]:443 rr   -> 192.168.229.1:443             FullNat 100    0          0   -> 192.168.229.2:443             FullNat 100    0          0 $ curl -6 "http://\[2001::202\]"  Your remote_addr and remote_port is 192.168.229.201:1034 Your toa_remote_addr and toa_remote_port is [2408::1]:9684 $ curl 10.0.96.201 Your remote_addr and remote_port is 172.16.0.1:42254 Your toa_remote_addr and toa_remote_port is -:-
 
最后需要提醒的是,如果使用了NAT64模式,那么nginx是没办法直接获取真实的源端IP的,需要对XFF头进行设置,例如:
proxy_set_header  X-Forwarded-For "$real_remote_addr ,$proxy_add_x_forwarded_for " ;    map  $toa_remote_addr  $real_remote_addr  {        default  $toa_remote_addr ;        '-' $remote_addr;    }    map  $toa_remote_port  $real_remote_port  {        default  $toa_remote_port ;        '-' $remote_port;    }
 
6、总结 以上的多种配置中,基本上能在生产环境使用的最好就是keepalived的主备模式 ,此外还有一个需要交换机支持ECMP的多主模式这里因为条件有限暂时没有测试到,后面有条件了再补上。
至于NAT64模式和IPv6-IPv6模式的选择,如果RS是nginx,那么两种模式的区别在于是在nginx上做兼容还是在RS上面配置IPv6网络,具体看实际的网络条件和运维管理工具来判断;如果RS是其他的第三方程序,不想对源代码进行太多的侵入变更,最好就是直接使用IPv6-IPv6模式。