本实例中通过在两台VMWare虚拟机之间创建ipip6隧道,实现IPv4 over IPv6通信。

两台VMWare虚拟机通过NAT DHCP服务器连通,并手动配置静态IPv6地址。

网络环境

在VMWare中安装了两台虚拟机Ubuntu18.04和Ubuntu24.04,其中Ubuntu18.04的internet口和Ubuntu24.04的ens33口连接VMWare的NAT DHCP服务器。

下面是Ubuntu24.04的ens33口的配置信息:

$ sudo cat /etc/netplan/50-cloud-init.yaml
# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    ethernets:
        ens33:
            addresses:
            - 192.168.100.128/24
            - 2001:db8::1/64
            dhcp4: true
            optional: true
    version: 2

$ ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.100.128  netmask 255.255.255.0  broadcast 192.168.100.255
        inet6 fe80::20c:29ff:fe54:b940  prefixlen 64  scopeid 0x20<link>
        inet6 2001:db8::1  prefixlen 64  scopeid 0x0<global>
        ether 00:0c:29:54:b9:40  txqueuelen 1000  (Ethernet)
        RX packets 13290201  bytes 14862347751 (14.8 GB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6009878  bytes 2955096378 (2.9 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

可以看到ens33口配置了静态IPv4地址192.168.100.128和IPv6地址2001:db8::1

接下来是Ubuntu18.04的internet口的配置信息:

root@ubuntu:~# cat /etc/netplan/01-network-manager-all.yaml
# Let NetworkManager manage all devices on this system
network:
  version: 2
  renderer: NetworkManager
  ethernets:
          internet:
                  dhcp4: yes
                  dhcp6: yes
                  addresses: ["2001:db8::2/64"]
                  #addresses: [8.8.8.8/32, 8.8.4.4/32]
          wan:
                  dhcp4: no
                  dhcp6: no
                  addresses: [192.168.202.254/24,8.8.8.8/32,8.8.4.4/32,"2020::ff/64","2020::fe/64"]
root@ubuntu:~# ifconfig internet
internet: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.100.134  netmask 255.255.255.0  broadcast 192.168.100.255
        inet6 2001:db8::2  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::250:56ff:fe2c:f5ed  prefixlen 64  scopeid 0x20<link>
        ether 00:50:56:2c:f5:ed  txqueuelen 1000  (Ethernet)
        RX packets 280234  bytes 320719568 (320.7 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 125452  bytes 18174330 (18.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

可以看到Ubuntu18.04的internet口的IPv4地址是由NAT DHCP服务器动态分配的,为192.168.100.134,和Ubuntu24.04的IPv4地址在同一网段。其IPv6地址为手动指定的,值为2001:db8::2/64

拓扑介绍完毕,接下来创建IPv4 Over IPv6隧道。

隧道创建

首先在Ubuntu24.04上创建隧道,创建脚本create_tunnel.sh内容如下:

#!/bin/bash

# 判断隧道是否存在,如果存在则删除
if ifconfig | grep tun0 >/dev/null ;then
        ip -6 tunnel del tun0
fi
# 创建隧道,指定隧道接口名称tun0 隧道模式ipip6 远端IPv6地址和本地IPv6地址
ip -6 tunnel add tun0 mode ipip6 remote 2001:db8::2 local 2001:db8::1
# 给隧道添加IPv4地址
ip addr add 10.0.0.1/24 dev tun0
# 启用隧道接口
ip link set tun0 up
# 添加IPv4路由
route add -net 10.0.0.0/24 dev tun0
# 显示隧道
ip -6 tunnel show

执行结果如下:

$ sudo ./create_tunnel.sh
ip6tnl0: ipv6/ipv6 remote :: local :: encaplimit 0 hoplimit inherit tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000)
tun0: ip/ipv6 remote 2001:db8::2 local 2001:db8::1 encaplimit 4 hoplimit 64 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000)
$ ifconfig tun0
tun0: flags=209<UP,POINTOPOINT,RUNNING,NOARP>  mtu 1452
        inet 10.0.0.1  netmask 255.255.255.0  destination 10.0.0.1
        inet6 fe80::4427:f1ff:fe8e:d94a  prefixlen 64  scopeid 0x20<link>
        unspec 20-01-0D-B8-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 1000  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 2157 (2.1 KB)
        TX errors 2  dropped 2 overruns 0  carrier 0  collisions 0

 route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.2   0.0.0.0         UG    100    0        0 ens33
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 tun0

接下来在Ubuntu18.04上创建脚本create_tunnel_peer.sh内容如下:

#!/bin/bash

# 判断隧道是否存在,如果存在则删除
if ifconfig | grep tun0 >/dev/null ;then
        ip -6 tunnel del tun0
fi
# 创建隧道,指定隧道接口名称tun0 隧道模式ipip6 远端IPv6地址和本地IPv6地址
ip -6 tunnel add tun0 mode ipip6 remote 2001:db8::1 local 2001:db8::2
# 给隧道添加IPv4地址
ip addr add 10.0.0.2/24 dev tun0
# 启用隧道接口
ip link set tun0 up
# 添加IPv4路由
route add -net 10.0.0.0/24 dev tun0
# 显示隧道
ip -6 tunnel show

注意IPv6地址需要互换,同时IPv4地址需要保证在同网段。

执行结果如下:

root@ubuntu:~# ./create_tunnel.sh
ip6tnl0: ipv6/ipv6 remote :: local :: encaplimit 0 hoplimit inherit tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000)
tun0: ip/ipv6 remote 2001:db8::1 local 2001:db8::2 encaplimit 4 hoplimit 64 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000)
root@ubuntu:~# ifconfig tun0
tun0: flags=209<UP,POINTOPOINT,RUNNING,NOARP>  mtu 1452
        inet 10.0.0.2  netmask 255.255.255.0  destination 10.0.0.2
        inet6 fe80::3caf:fff:fe95:67a2  prefixlen 64  scopeid 0x20<link>
        unspec 20-01-0D-B8-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 1000  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@ubuntu:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.100.2   0.0.0.0         UG    101    0        0 internet
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 tun0

到此处为止,隧道已经创建完成。

验证

由于是IPv4 over IPv6隧道,因此首先需要验证IPv6地址是否通畅。

# 在Ubuntu24.04上ping Ubuntu18.04的IPv6地址
$ ping  2001:db8::2
PING 2001:db8::2 (2001:db8::2) 56 data bytes
64 bytes from 2001:db8::2: icmp_seq=1 ttl=64 time=0.247 ms
64 bytes from 2001:db8::2: icmp_seq=2 ttl=64 time=0.215 ms
64 bytes from 2001:db8::2: icmp_seq=3 ttl=64 time=0.533 ms
64 bytes from 2001:db8::2: icmp_seq=4 ttl=64 time=0.237 ms
64 bytes from 2001:db8::2: icmp_seq=5 ttl=64 time=0.358 ms
^C
--- 2001:db8::2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4056ms
rtt min/avg/max/mdev = 0.215/0.318/0.533/0.118 ms
# 反之亦然
root@ubuntu:~# ping 2001:db8::1
PING 2001:db8::1(2001:db8::1) 56 data bytes
64 bytes from 2001:db8::1: icmp_seq=1 ttl=64 time=0.268 ms
64 bytes from 2001:db8::1: icmp_seq=2 ttl=64 time=0.299 ms
64 bytes from 2001:db8::1: icmp_seq=3 ttl=64 time=0.722 ms
64 bytes from 2001:db8::1: icmp_seq=4 ttl=64 time=0.359 ms
^C
--- 2001:db8::1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3080ms
rtt min/avg/max/mdev = 0.268/0.412/0.722/0.181 ms

接下来验证IPv4地址是否通畅,这里通畅会存在问题,即未设置IPv4地址路由,导致IPv4 ping不通

$ ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.290 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.263 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.223 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.259 ms
^C                                                                                                                                                                                           --- 10.0.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3101ms
rtt min/avg/max/mdev = 0.223/0.258/0.290/0.023 ms

root@ubuntu:~# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.270 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.273 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.287 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.544 ms
^C
--- 10.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3070ms
rtt min/avg/max/mdev = 0.270/0.343/0.544/0.117 ms

下面是在Ubuntu24.04上的tun0口的抓包结果: Ubuntu24.04口的tun0抓包

tun0口的抓包结果显示只是普通的ICMP交互报文,这是以为IPv6报文被转发到该接口之前已经被解封装了。

下面是在ens33口的抓包结果,ens33口是和Ubuntu18.04连通的接口。

通过ens33接口抓包数据可以看到,IPv6报文的目的地选项中的下一个头部类型被设置为IPIP,因此可以确定ICMP报文是通过IPv4 over IPv6隧道传输的。

Ubuntu18.04的internet口的抓包结果和ens33口相同。