本文主要介绍基于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中叙述过,这里不做赘述。
首先是最简单的配置方式,直接使用ipvsadm的命令行操作来实现一个IPv4网络的FullNat模式,架构图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIO6Gr21-1645782784634)(https://resource.tinychen.com/20210806163652.svg)]
这里我们使用dpdk2网卡作为wan口,dpdk0网卡作为lan口
# 首先我们把VIP 10.0.96.204 加到dpdk2网卡(wan)上
$ dpip addr add 10.0.96.204/32 dev dpdk2
# 接着我们需要添加两条路由,分为是wan口网段的路由和到RS机器网段的路由
$ dpip route add 10.0.96.0/24 dev dpdk2
$ dpip route add 192.168.229.0/24 dev dpdk0
# 最好再加一条到网关的默认路由保证ICMP数据包的回包能跑通
$ dpip route add default via 10.0.96.254 dev dpdk2
# 使用RR算法建立转发规则
# add service to forwarding, scheduling mode is RR.
# use ipvsadm --help for more info.
$ ipvsadm -A -t 10.0.96.204:80 -s rr
# 这里为了方便测试我们只添加一台RS
# add two RS for service, forwarding mode is FNAT (-b)
$ ipvsadm -a -t 10.0.96.204:80 -r 192.168.229.1 -b
# 添加LocalIP到网络中,FNAT模式这里需要
# add at least one Local-IP (LIP) for FNAT on LAN interface
$ 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
该模式非常的简单,可以快速配置检验自己机器上的DPVS能否正常工作,不过由于是单点,往往较少使用。
目前DPVS支持配置bonding4
和bonding0
,两者的配置基本相同,配置方式可以参考dpvs/conf/dpvs.conf.single-bond.sample
这个文件。
配置bonding模式的时候,不需要对slave网卡(如dpdk0
等)指定kni_name
这个参数,而是要在bonding中指定对应的kni_name
,同时还要注意primary
参数指定的网卡的MAC地址一般就是bonding网卡的MAC地址。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d2ypkdTT-1645782784636)(https://resource.tinychen.com/dpvs-two-arm-fnat-bond4-fakeip.drawio.svg)]
! netif config
netif_defs {
pktpool_size 1048575
pktpool_cache 256
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
}
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
}
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
}
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
}
bonding bond1 {
mode 4
slave dpdk0
slave dpdk1
primary dpdk0
kni_name bond1.kni
}
bonding bond2 {
mode 4
slave dpdk2
slave dpdk3
primary dpdk2
kni_name bond2.kni
}
}
随后在配置每个worker-cpu
的时候要注意port
要选择对应的bond
网卡
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
IPv6的简单配置方法和IPv4一样,只是把对应的IPv4地址换成了IPv6地址,同时还需要额外注意一下IPv6地址指定端口的时候需要使用[]
将IP地址括起来。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x8OGeT1u-1645782784636)(https://resource.tinychen.com/dpvs-two-arm-fnat-ipv6-fakeip.drawio.svg)]
# 添加VIP和相关路由
$ 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和RS
$ 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
# 添加IPv6 LIP
$ 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
测试效果,确认RS上面的nginx能够正常返回用户端的真实IP和端口,则表明配置正常。
$ curl -6 "http://\[2001::201\]"
Your IP and port is [2408::1]:38383
架构图上和之前的两个并没太大的不同,只是IP略有差异
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gQb1l7wO-1645782784637)(https://resource.tinychen.com/dpvs-two-arm-fnat-nat64-fakeip.drawio.svg)]
# 添加VIP和相关路由
$ 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和RS
$ 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
# 添加IPv6 LIP
$ 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为例。
dpvs还为nginx提供了一个nat64的toa模块,当VIP为ipv6而RS为ipv4的时候,可以使用这个模块在nginx中获取用户真实的ipv6地址,需要我们在源码编译安装nginx之前先打上这个补丁。
从官方的文件名我们可以看出应该是基于1.14.0版本制作的patch,首先我们使用旧版的1.14.0版本能够正常打上补丁,后续的编译安装也能正常进行
[root@tiny-centos7 nginx-1.14.0]# pwd
/home/nginx-1.14.0
[root@tiny-centos7 nginx-1.14.0]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man nginx-1.14.0-nat64-toa.patch README src
[root@tiny-centos7 nginx-1.14.0]# cp /home/dpvs/kmod/toa/example_nat64/nginx/nginx-1.14.0-nat64-toa.patch ./
[root@tiny-centos7 nginx-1.14.0]# 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版本的时候会有报错
[root@tiny-centos7 nginx-1.21.1]# cp /home/dpvs/kmod/toa/example_nat64/nginx/nginx-1.14.0-nat64-toa.patch ./
[root@tiny-centos7 nginx-1.21.1]# pwd
/home/nginx-1.21.1
[root@tiny-centos7 nginx-1.21.1]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man nginx-1.14.0-nat64-toa.patch README src
[root@tiny-centos7 nginx-1.21.1]# patch -p 1 < nginx-1.14.0-nat64-toa.patch
patching file src/core/ngx_connection.h
Hunk #1 FAILED at 144.
1 out of 1 hunk FAILED -- saving rejects to file src/core/ngx_connection.h.rej
patching file src/core/ngx_inet.h
Hunk #1 succeeded at 128 with fuzz 2 (offset 2 lines).
patching file src/event/ngx_event_accept.c
Hunk #1 succeeded at 17 (offset -5 lines).
Hunk #2 succeeded at 30 (offset -5 lines).
Hunk #3 succeeded at 172 (offset -5 lines).
patching file src/http/ngx_http_variables.c
Hunk #1 succeeded at 145 (offset 2 lines).
Hunk #2 succeeded at 398 (offset 15 lines).
Hunk #3 succeeded at 1311 (offset -11 lines).
仔细查看patch文件内容可以发现出现错误是因为1.21.1版本中对应部分移除了几行代码导致patch无法匹配,我们手动将那一行代码加上去
随后就能正常编译安装了,完成之后我们可以在日志中加入$toa_remote_addr
和$toa_remote_port
这两个变量来获取NAT64模式下的客户端真实IP。
再次测试发现能够显示真正的客户端源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
# 同时在nginx的日志中也能看到对应的字段
toa_remote_addr=2408::1 | toa_remote_port=64920 | remote_addr=192.168.229.201 | remote_port=1030
使用keepalived配置有两大好处:
官方的keepalived配置网络拓扑使用的是单臂模式,这里我们修改为双臂模式;同时需要注意DPVS使用的keepalived是修改过的版本,和原生版本的keepalived在配置语法和参数上稍有不同。
和前面提到的一样,keepalived也支持IPv4-IPv4模式
、IPv6-IPv6模式
和NAT64模式(IPv6-IPv4)
这三种模式,三者的不同只是在于路由的不同和keepalived的配置文件略有差异。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PWdhgSQJ-1645782784639)(C:\Users\tinychen\OneDrive\Blogs\pic_cache\20210810-dpvs-fullnat-management\dpvs-two-arm-fnat-keepalived-fakeip.drawio.svg)]
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
程序控制。
keepalived模式下,对于双臂网络模式的FullNAT,我们需要加的路由一般来说可以直观地分为三大部分:VIP网段的路由,RS/LIP网段的路由,默认路由。
# IPv4网络模式
$ dpip route add 10.0.96.0/24 dev bond2 # VIP网段的路由
$ dpip route add 192.168.229.0/23 dev bond1 # RS/LIP网段的路由
$ dpip route add default via 10.0.96.254 dev bond2 # 默认路由
# IPv6网络模式
$ dpip route -6 add 2001::/64 dev bond2 # VIP网段的路由
$ dpip route -6 add 2407::/64 dev bond1 # RS/LIP网段的路由
$ dpip route -6 add default via 2001::1 dev bond2 # 默认路由
# NAT64模式(IPv6-IPv4)
# 此模式的区别在于RS要换为IPv4网段的路由
$ dpip route -6 add 2001::/64 dev bond2 # VIP网段的路由
$ dpip route add 192.168.229.0/23 dev bond1 # RS/LIP网段的路由
$ dpip route -6 add default via 2001::1 dev bond2 # 默认路由
首先我们使用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的日志输出到指定的文件中方便我们定位问题
# 对于系统使用rsyslog服务来管理日志的,可以修改 /etc/rsyslog.conf 加入下列的配置
local0.* /path/to/keepalived.log
最后我们重启相关的rsyslog日志服务和keepalived
$ systemctl daemon-reload
$ systemctl enable rsyslog.service
$ systemctl restart rsyslog.service
注意即使RS相同,NAT64模式和普通的IPv4模式也不能够在同一个vrrp_instance
中同时定义IPv4地址和IPv6地址,因为两者使用的VRRP协议版本不同(VRRP和VRRP6)
以下以NAT64和IPv4网络两种配置为例,截取部分重点配置
! Configuration File for keepalived
global_defs {
router_id DPVS_TEST
}
# 配置LOCAL IP
# 网卡使用DPDK的lan网段网卡
local_address_group laddr_g1 {
192.168.229.201 bond1
}
# 配置IPv4模式的VIP
vrrp_instance VI_1 {
# 确定该VIP的状态为MASTER或者是BACKUP
state MASTER
# interface指定为Linux网络栈能识别到的、由dpvs虚拟出来的kni网卡
# keepalived模式需要确保该kni网卡处于up状态,此前的简单配置均不需要
interface bond2.kni
# dpdk_interface指定为wan口网卡,即VIP所在的dpdk网卡
dpdk_interface bond2
# 虚拟路由ID,需要全局唯一
virtual_router_id 201
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass dpvstest
}
# 配置VIP,可以多个一组,但是不可IPv6和IPv4混用
virtual_ipaddress {
10.0.96.201
10.0.96.202
}
}
# 配置IPv6模式的VIP
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
}
}
# 配置对应的VIP和RS
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
}
}
}
dpip
命令查看到各个定义的VIP,ipvsadm命令中应该可以看到各组RS状态正常# 检查配置的各个VIP和LIP是否生效
$ 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
# 检查各组RS服务是否正常
$ 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测试IPv6服务是否能够走通
$ 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测试IPv4服务是否能够走通
$ 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;
}
以上的多种配置中,基本上能在生产环境使用的最好就是keepalived的主备模式,此外还有一个需要交换机支持ECMP的多主模式这里因为条件有限暂时没有测试到,后面有条件了再补上。
至于NAT64模式
和IPv6-IPv6模式
的选择,如果RS是nginx,那么两种模式的区别在于是在nginx上做兼容还是在RS上面配置IPv6网络,具体看实际的网络条件和运维管理工具来判断;如果RS是其他的第三方程序,不想对源代码进行太多的侵入变更,最好就是直接使用IPv6-IPv6模式
。