当电信宽带不下发ipv6地址,但是我们又有ipv4的公网地址的时候,就可以使用公网ipv4地址生成一个唯一的ipv6地址,使得一个ipv6数据包可以在ipv4的网络中传输时,这就是ipv6的6to4协议.

1、6to4原理


5-Openwrt ipv6 6to4_udp

路由器A及B分别是两个站点(站点A与站点B的出口路由器,并且都是IPv4及IPv6双栈路由器)。两边都申请到一个IPv4公网地址,使用这个公网IPv4地址进行映射得到全球唯一的6to4 IPv6地址,这个IPv6地址 /48位,空间非常大,用于相应站点内的IPv6用户。

如此一来,当站点A内的IPv6用户访问站点B的IPv6用户时,IPv6数据包发送到A,那么A根据IPv6数据报头中的目的IPv6地址,得到对应的目的IPv4全局IP,那么就将原始的IPv6数据包进行封装,套上6to4隧道的IPv4的头,然后将这个数据包放入IPv4网络进行路由,直到到达B。

数据包交互的详细过程:
5-Openwrt ipv6 6to4_udp_02

A拿到的IPv4公网地址是132.214.1.10,而B是206.123.31.200。
A和B分别使用这个IPv4公网地址来映射得到6to4地址空间(地址池),6to4地址空间使用2002::/16,而6to4地址的形成如下:

2002:IPv4地址:子网ID::接口ID
上面的IPv4地址,就是A或B拿到的那个公网IPv4地址,注意,这个公网IP非常重要,此公网IP的变化,有可能导致IPv6站点内IPv6不得不重新编址。得到6to4 IPv6地址空间后,这个地址空间是16+32=48bits,也就是/48的,因此空间非常大,你可以进一步的进行子网的划分,这个IPv6的地址空间就将用于站点内网。

数据交互过程如下:

1、上面的例子,A拿到的IPv4公网地址:132.214.1.10,映射得到2002:84d6:010a::/48,这个地址空间的一部分最终被用在了PC1上。现在,PC1要给PC2发送一个IPv6的数据。这个数据的源IP是PC1的IPv6全局唯一地址:2002:84d6:010a:1::1,目的IP为PC2的IPv6全局唯一地址:2002:ce7b:1fc8:2::2,这个IPv6报文被送到了PC1的默认网关也就是路由器。

2、A是一台6to4路由器,它会查看这个IPv6数据包的包头里的目的IPv6地址,它发现这个IPv6目的地地址是一个6to4地址,因此,它计算得出这个6to4 IPv6地址对应的IPv4公网IP,然后,为这个原始的IPv6数据进行封装,加上一个新的IPv4的头,而这个IPv4的头源地址是132.214.1.10,目的地址刚才通过计算得出的那个IPv4地址,正是206.123.31.200。然后,这个新的IPv4数据包进入因特网,最终被传送到B

3、B将报文的IPv4头除去,得到原始的IPv6数据,转发给PC2。

2、6to4配置


查看package下面已经有了6to4的协议脚本,位于package/network/ipv6/6to4/files/6to4.sh

和netifd下面的其他脚本一样,属于network.proto的一种

root@zihome:/lib/netifd/proto# ls
6to4.sh    dhcp.sh    dhcpv6.sh  ppp.sh

所以我们只需要配置uci后,重启/etc/init.d/network restart就可以

config interface 'wan6'
        option def_ifname 'eth1'
        option web_proto '6to4'
        option proto '6to4'
        option web_enabled '1'

ps可以观察到,6to4是没有像odhcp6c或pppoe那样,有一个进程一直再请求ipv6地址,而是在6to4.sh脚本里面,获取ipv4地址,判断是否为公网,如果是旧生成一个ipv6地址,如果不是那也就没有然后了。

这样如果中途ipv4掉了重新夺取到一个ipv4地址,上面生成的ipv6地址就是不对的,需要重新拉下6to4.sh脚本生成下。

所以在/etc/hotplug.d/iface/下添加了一个03-6to4脚本,获取到wan口IP的时候,重新ifup wan6一下。

#!/bin/sh

[ "$ACTION" = ifup ] && {
        if [ "$INTERFACE" = wan ]; then
                local ipv6_enabled=$(uci -q get network.wan6.web_enabled)
                local ipv6_proto=$(uci -q get network.wan6.proto)
                # 6to4 proto need ifup wan6 again
                if [ $ipv6_enabled == 1 -a x"$ipv6_proto" == x"6to4" ]; then
                        ifup wan6
                fi
        fi
}

查看官网可以看到6to4还有其他一些uci配置值,这边就不过多介绍

Name Type Default Description
ipaddr IPv4 address Current WAN IPv4 address Local IPv4 endpoint address
defaultroute boolean 1 Whether to create an IPv6 default route over the tunnel
ttl integer 64 TTL used for the tunnel interface
tos string (none) Type Of Service : either “inherit” (the outer header inherits the value of the inner header) or an hexadecimal value (Chaos Calmer and later only)
mtu integer 1280 MTU used for the tunnel interface
metric integer 0 Specifies the default route metric to use

3、6to4测试


实际测试

root@zihome:/# ifconfig pppoe-wan
pppoe-wan Link encap:Point-to-Point Protocol  
          inet addr:183.49.45.171  P-t-P:183.49.44.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1480  Metric:1
          RX packets:4826182 errors:0 dropped:137 overruns:0 frame:0
          TX packets:733858 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3 
          RX bytes:6436609082 (5.9 GiB)  TX bytes:108697921 (103.6 MiB)

root@zihome:/# ifconfig br-lan
br-lan    Link encap:Ethernet  HWaddr DC:4B:DD:1D:FB:6C  
          inet addr:192.168.3.1  Bcast:192.168.3.255  Mask:255.255.255.0
          inet6 addr: 2002:b731:2dab::1/60 Scope:Global
          inet6 addr: fe80::de4b:ddff:fe1d:fb6c/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:741126 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4849491 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:108828123 (103.7 MiB)  TX bytes:6544994763 (6.0 GiB)

root@zihome:/# ip -6 route
default from :: via ::192.88.99.1 dev 6to4-wan6  proto static  metric 1024 
default from 2002:b731:2dab::/48 via ::192.88.99.1 dev 6to4-wan6  proto static  metric 1024 
default from 2002::/16 via ::192.88.99.1 dev 6to4-wan6  proto static  metric 1024 
::/96 dev 6to4-wan6  metric 256 
2002:b731:2dab::/64 dev br-lan  proto static  metric 1024 
unreachable 2002:b731:2dab::/48 dev lo  proto static  metric 2147483647  error -128
2002::/16 dev 6to4-wan6  proto kernel  metric 256 
fe80::/64 dev br-lan  proto kernel  metric 256 

https://oldwiki.archive.openwrt.org/doc/uci/network

https://openwrt.org/docs/guide-user/network/ipv6/barrier.breaker.ipv6.6to4