IPv6来啦 (by quqi99)

版权声明:本文为博主原创文章,如需转载,请注明出处! https://blog.csdn.net/quqi99/article/details/81389399

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (作者:张华 发表于:2018-08-03)

问题

家里用的是中国移动的宽带, 一直挺稳定的, 而且昨天发现ISP下发了IPv6地址(不是子网, 形如: 2409:8a00:7805:xxxx:xxxx:xxxx:xxxx:xxxx/64, 打xxxx的部分是动态变化的). 好吧, 咱就用用.

路由器配置

  • 配置/etc/config/network使用’option ip6assign ‘64’
config interface 'lan'                    
        ...      
        option ip6assign '64'
  • 配置/etc/confignetwork删除config globals ‘globals’段中和 IPv6 ULA-Prefix相关的配置 (注: 使用IPv6 ULA-Prefix的话, LAN中机器就会得到一个以它打头的IPv6地址, 但如何从外网访问这个地址呢? 有三种方式: 一是使用我们现在使用的relay方式得到是ISP提供的全球可路由的IPv6地址;二是配置ULA-Prefix=2409:8a00:7805:1::/80之后再使用下列的neigh proxy的方法解决, 但这种一般是子网长度80比64大, 但ISP并没有给我们分配subnet, 只是分配了IPv6地址, 所以无法保证2409:8a00:7805:1::/80这个前缀与ISP分配的2409:8a00:7805:xxxx:xxxx:xxxx:xxxx:xxxx/64一致;三是ULA-Prefix配置一个与ISP分配的不同的路由然后通过配置路由的方式但前提是也得有全球可路由的IPv6 subnet啊. 所以这里我们选择了relay模式来实现外网访问内网的目的.
sysctl -w net.ipv6.conf.all.proxy_ndp=1
ip -6 neigh add proxy 2409:8a00:7805:1::430 dev pppoe-wan
ip -6 neigh show proxy
  • 配置/etc/config/dhcp使用relay模式, relay模式意味着openwrt通过默认的odhcpd作为中继自动为LAN的其他机器配置ISP的IPv6地址
config dhcp 'wan'                                                                                                                       
        option interface 'wan'                                                                                                          
        option ignore '1'                                                                                                               
        option dhcpv6 'disabled'                                                                                                        
        option ndp 'relay'                                                                                                              
        option ra 'relay'                                                                                                               
        option master '1'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
config dhcp 'lan'                                                                                                                       
        option interface 'lan'                                                                                                          
        option start '100'                                                                                                              
        option limit '150'                                                                                                              
        option leasetime '12h'                                                                                                          
        list dhcp_option '6,192.168.99.1'                                                                                               
        option ndp 'relay'                                                                                                              
        option ra 'relay'                                                                                                               
        option dhcpv6 'relay'

# actually I use 60, not 64
cat /etc/config/network
config interface 'lan'
    ...
    option ip6assign '60'

配置完之后就可以通过下列命令重启路由器服务就可以在br-lan与pppoe-wan上获得ISP分配的IPv6地址了.

/etc/init.d/network restart
/etc/init.d/odhcpd restart

内网机器直接通过’sudo /etc/init.d/network-manager restart’重启网络也会获取ISP分配的IPv6地址.

验证

  • 内网机器访问br-lan内网网关, 能通是因为下列路由的功能:
hua@t440p:~$ ip -6 route list |grep 2409:8a00:7805:b7df::/64
2409:8a00:7805:b7df::/64 dev eth0  proto ra  metric 100  pref medium

root@OpenWrt:~# route -A inet6 |grep ::/0
::/0                                        fe80::200:5eff:fe00:134                 UG    1024   0        0

注: 后面我们会看到::/0的默认路由会造成很多问题.
- 内网机器访问pppoe-wan外网网关
对于relay模式由于内网机器拿到的本来就是ISP分配的可路由的IP所以自然能通. 但对于nat模式由于内网机器分配的是和ISP不同网段的IP, 所以需要在路由器上做NAT6, 如:

#ip6tables -t nat -I POSTROUTING -o pppoe-wan -j MASQUERADE
ip6tables -t nat -I POSTROUTING -s `uci get network.globals.ula_prefix` -j MASQUERADE > /dev/null 2>&1
  • 外网访问内网机器
    如果使用relay由于内网机器使用的是全球可路由的IPv6地址, 外网直接就是可以访问内网机器的;但如果是不同子网需要做路由;如果只是前缀相同只是子网长度不同可以做neigh proxy
  • 但是此时我们发现内网机器无法访问外网(如ping6 ipv6.baidu.com), 但此时在路由器上却是可以访问外网的. 原因就在于上面使用::/0的默认路由似乎有问题(报这个错: Destination unreachable: Unknown code 5), 改成了2000::/3就好了:
route -A inet6 add 2000::/3 `route -A inet6 | grep ::/0 | awk 'NR==1{print"gw "$2" dev "$7}'`

或者:

ip -6 route add default from 2409:8a00:7805::48 dev pppoe-wan

但上面两种方法仍然遇到了不稳定的问题, 感觉是openwrt的odhcpd不稳定, 照下列方法更换为6relayd之后仍然不好使.

wget https://www.shintaku.cc/files/6relayd_2013-10-21_ar71xx.ipk
opkg install 6relayd_2013-10-21_ar71xx.ipk
vi /etc/config/6relayd
config relay
        option master 'wan'
        option network 'lan'
        option rd 'relay'
        option dhcpv6 'relay'
        option ndp 'relay'
/etc/init.d/odhcpd disable
/etc/init.d/odhcpd stop
/etc/init.d/6relayd enable
/etc/init.d/6relayd start

接着使用tcpdump查看好像是DHCPv6 reply包从pppoe-wan过不来br-lan口:

08:22:53.810272 IP6 2400:da00:2::29 > 2409:8a00:7805:b7df:8d79:6c9:315a:9ca3: ICMP6, echo reply, seq 7, length 64

所以接着, 在/etc/config/firewall文件的 Allow-ICMPv6-Forward项中添加了下列行后确认已经有了129(129就是reply)相关的iptables rules之后仍然不好使.

        list icmp_type 'router-solicitation'    
        list icmp_type 'neighbour-solicitation' 
        list icmp_type 'router-advertisement'   
        list icmp_type 'neighbour-advertisement'

root@OpenWrt:~# ip6tables-save |grep Allow-ICMPv6-Forward |grep 129
-A zone_wan_forward -p ipv6-icmp -m icmp6 --icmpv6-type 129 -m limit --limit 1000/sec -m comment --comment Allow-ICMPv6-Forward -j ACCEPT

google查到的和这个bug相同(https://github.com/openwrt/odhcpd/issues/37), 但里面的所有方法都试过了不成功.
似乎是ISP使用的是Statefull DHCPV6的方式, 6relayd可以把ra信息relay过来,但LAN端机器似乎无法跟DHCPV6服务器通信。

2018-0805更新

今天通过这个帖子(https://bbs.pku.edu.cn/v2/post-read.php?bid=35&threadid=15501646)解决了上面的问题:
OpenWRT默认是在wan口使用DHCPv6 Client, 在LAN口使用odhcpd开启RA和DHCPv6. 这个默认配置适用于国外主流ISP, 因为他们DHCPv6-PD (prefix delegation)把一个至少/64地址段分配给客户使用(还有的使用小于64的地址段给客户分配静态IP).
不过中国移动给客户分配的是SLAAC地址, 没有使用DHCPv6, 也就没使用DHCPv6-PD, 这样拿不到前缀(ISP分配的2409:8a00:7805:xxx::/64地址的第4段总是变化的), 所以odhcpd也就无法根据这个前缀设置路由, 所以我们需要手工设置确保可以在OpenWrt上ping通内网机器, 这样才能保证reply消息到达br-lan之后能到达内网机器, 如:
route -A inet6 add 2409:8a00:7805:d9b1::/64 dev br-lan
所以最终添加在/etc/firewall.user的内容如下:

# make ipv6 relay to work
PREFIX=`route -A inet6 |grep lo |grep 2409:8a00:7805 |grep ::/128 |awk -F '::/' '{print $1"::/64"}' |uniq`
ip -6 route del $PREFIX dev br-lan > /dev/null 2>&1
route -A inet6 add $PREFIX dev br-lan > /dev/null 2>&1                                    

# make ipv6 nat to work                                                                                        
#ip -6 route add default from $PREFIX dev pppoe-wan > /dev/null 2>&1                                           
#route -A inet6 add 2000::/3 `route -A inet6 | grep ::/0 | awk 'NR==1{print"gw "$2" dev "$7}'` > /dev/null 2>&1

再就是得配置replay消息能从pppoe-wan到达br-lan, 所以最终使用下列配置(也记得去掉IPv6 ULA-Prefix):

config dhcp 'wan'                                
        option interface 'wan'                   
        option ignore '1'                        
        option ndp 'relay'                       
        option ra 'relay'                        
        option master '1'                                      
config dhcp 'lan'             
        option interface 'lan'
        option start '100'    
        option limit '150'    
        option leasetime '12h'
        list dhcp_option '6,192.168.99.1'
        option ndp 'relay'               
        option ra 'relay'   

可新问题又来了, 这条路由总是过期, 如下:

2409:8a00:7805:da41::/64 dev br-lan  proto kernel  metric 256  expires 259019sec

重新执行一下上面的命令又能恢复, 太不稳定了, 还是转回ipv6 NAT模式吧.

20180902更新

上述静态路由过期的问题原因找到, 原因是需要添加metric
- route -A inet6 add 2409:8a00:7805:d9b1::/64 dev br-lan # 会有过期时间
- route -A inet6 add 2409:8a00:7805:d9b1::/64 dev br-lan metric 1 # 无过期时间
或者使用ip命令它添加的无过期时间 - ip -6 route del 2409:8a00:7805:d9b1::/64 dev br-lan

转试NAT6

上面使用replay时的bug解不了, 无奈之下, 只好使用NAT6, 外面访问不了内网就访问不了吧, 起码可以内网访问外网啊.
- 在/etc/config/network中配置了ula_prefix=2001:192:168:99::/64, 这时路由器上的br-lan除了ISP分配的IP之外, 也会多时我们这个自己配置的地址: 2001:192:168:99:0:0:0:1/64

config globals 'globals'
        option ula_prefix '2001:192:168:99::/64'
  • 修改/etc/config/dhcp将relay模式改到server模式即NAT模式
config dhcp 'lan'                                
        option interface 'lan'                   
        option start '100'                       
        option limit '150'                       
        option leasetime '12h'                   
        list dhcp_option '6,192.168.99.1'        
        option dhcpv6 'server'                   
        option ra_management '2'                 
        option ra 'server'                       
        option ra_default '1'
  • 在/etc/firewall.user中添加下列SNAT规则
ip6tables -t nat -I POSTROUTING -s `uci get network.globals.ula_prefix` -j MASQUERADE > /dev/null 2>&1 
route -A inet6 add 2000::/3 `route -A inet6 | grep ::/0 | awk 'NR==1{print"gw "$2" dev "$7}'` > /dev/null 2>&1

之后, 内网机器随便手动配置一个IP如2001:192:168:99:0:0:0:3/64并添加默认路由之后就可以访问外网了.
如果想外网访问2001:192:168:99::3/64, 是不能够使用下面的neigh proxy方式的, 因为网段和ISP分配的可路由网段根据就不一样嘛. 唯一的办法其实就是做DNAT

sysctl -w net.ipv6.conf.all.proxy_ndp=1
ip -6 neigh add proxy 2001:192:168:99:0:0:0:3 dev pppoe-wan
ip -6 neigh show proxy

VPS不支持IPv6时如何使用IPv6

VPS若不支持IPv6, 可以通过tunnelbroker来配置6in4隧道支持IPv6, 但前提是VPS要能支持配置允许proto-41流量通过 (iptables -A INPUT -p 41 -j ACCEPT), 目前google cloud VPS是无法配置这个的.
若您的VPS支持这个, 可以继续. 先在https://www.tunnelbroker.net/ 登录后在’User Functions -> Create Regular Tunnel’菜单创建 Create Regular Tunnel, 然后:

cat << EOF | sudo tee -a /etc/network/interfaces
auto he-ipv6
iface he-ipv6 inet6 v4tunnel
        address 2001:470:a:xx::2
        netmask 64
        endpoint 216.218.226.xx
        local 162.xx.xx.xx
        ttl 255
        gateway 2001:470:a:4c4::1
EOF
cat << EOF | sudo tee -a /etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0
EOF
sudo sysctl -p
sudo apt install -y ifupdown
sudo ifup he-ipv6
# can't do tunnelbroker as 6in4 is unsupported (NAT/gateways won't pass proto-41)
#sudo iptables -t nat -A PREROUTING -p 41 -d <VPS-IP> -j DNAT --to-destination <tunnelbroker-ip>
#sudo iptables -t nat -A POSTROUTING -p 41 -d <tunnelbroker-ip> -j SNAT --to-source <VPS-IP>
#sudo iptables -A INPUT -p 41 -j ACCEPT

使用tunnelbroker需要VPS有公网IPv4地址, 若没有, 可以使用miredo(sudo apt-get install miredo), 但前提也是要防火墙允许proto-41的流量

猜你喜欢

转载自blog.csdn.net/quqi99/article/details/81389399