1. 问题现象与初步判断
上周五晚上10点,我正在家里通过SSH连接公司服务器部署新版本,突然发现连接中断。尝试重新连接时,终端不断返回"Network is unreachable"错误。作为运维人员,我立即意识到这可能是网络层面的问题。
通过手机热点测试发现可以正常连接,这排除了服务器本身的问题。进一步检查家庭网络时,注意到一个关键现象:所有IPv4服务都工作正常,但任何需要IPv6连接的资源都无法访问。我的Nextcloud同步、IPv6-only的测试服务器、甚至Google的IPv6测试页面(ipv6.google.com)全都无法连通。
经验提示:当出现网络故障时,首先要确定问题范围。通过对比不同网络环境(如蜂窝数据/WiFi)和不同协议(IPv4/IPv6)的表现,可以快速缩小排查范围。
2. 基础网络环境检查
2.1 本地IPv6配置验证
首先在终端执行ifconfig查看网卡配置,发现ens33接口确实获得了IPv6地址:
code复制ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.100 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 2408:8207:7890:abcd::1234 prefixlen 64 scopeid 0x0<global>
inet6 fe80::250:56ff:fea5:6789 prefixlen 64 scopeid 0x20<link>
ether 00:50:56:a5:67:89 txqueuelen 1000 (Ethernet)
这说明本地主机的IPv6协议栈工作正常,且通过DHCPv6获取到了公网IPv6地址。接下来测试基础连通性:
bash复制ping6 -c 4 ipv6.google.com
PING ipv6.google.com(ord38s01-in-x0e.1e100.net) 56 data bytes
From 2408:8207:7890:abcd::1234 icmp_seq=1 Destination unreachable: Address unreachable
2.2 路由器配置检查
登录OpenWRT路由器管理界面,检查IPv6相关设置:
- LAN口配置:确认已启用"DHCPv6服务"和"RA服务"
- WAN口状态:显示已获取到/64的IPv6前缀(2408:8207:7890:abcd::/64)
- 防火墙规则:发现"入站"、"出站"和"转发"都设置为"接受"IPv6流量
奇怪的是,路由器本身可以ping通外部IPv6地址:
bash复制root@OpenWRT:~# ping6 -c 4 2001:4860:4860::8888
PING 2001:4860:4860::8888 (2001:4860:4860::8888): 56 data bytes
64 bytes from 2001:4860:4860::8888: seq=0 ttl=118 time=12.345 ms
这个现象表明问题可能出在路由器的转发规则或主机的路由配置上。
3. 深入排查网络路径
3.1 路由追踪分析
在主机上执行traceroute6测试:
bash复制traceroute6 ipv6.google.com
traceroute to ipv6.google.com (2a00:1450:4001:811::200e), 30 hops max, 80 byte packets
1 2408:8207:7890:abcd::1 (2408:8207:7890:abcd::1) 2.345 ms 1.234 ms 1.567 ms
2 * * *
3 * * *
数据包在跳出第一跳(路由器)后就丢失了。为了确认是路由器问题还是ISP问题,我在路由器上同样执行traceroute6:
bash复制root@OpenWRT:~# traceroute6 ipv6.google.com
1 2408:8207:7890::1 (2408:8207:7890::1) 5.678 ms 5.123 ms 5.456 ms
2 2408:8000:1::2 (2408:8000:1::2) 7.890 ms 7.123 ms 7.456 ms
3 2408:8000:0:1::3 (2408:8000:0:1::3) 9.012 ms 8.765 ms 9.098 ms
路由器可以正常完成路径追踪,这说明问题确实局限在局域网内部。
3.2 防火墙规则检查
虽然之前看到防火墙设置为"接受",但实际规则可能更复杂。查看OpenWRT的详细IPv6防火墙规则:
bash复制root@OpenWRT:~# ip6tables -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
10 1024 ACCEPT all * * ::/0 ::/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all * * ::/0 ::/0
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
15 1536 ACCEPT all * * ::/0 ::/0
发现一个异常现象:FORWARD链的计数器始终为0,这意味着IPv6数据包根本没有进入转发流程。
3.3 内核参数检查
检查系统IPv6转发是否启用:
bash复制root@OpenWRT:~# cat /proc/sys/net/ipv6/conf/all/forwarding
0
这个关键参数应该为1才能允许IPv6转发。手动启用后测试:
bash复制root@OpenWRT:~# echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
root@OpenWRT:~# ping6 -c 4 2001:4860:4860::8888
PING 2001:4860:4860::8888(2001:4860:4860::8888) 56 data bytes
64 bytes from 2001:4860:4860::8888: icmp_seq=1 ttl=118 time=12.345 ms
关键发现:OpenWRT默认安装后,IPv6转发功能是关闭的,这与IPv4的默认行为不同。这是很多用户忽略的重要配置差异。
4. 问题修复与持久化配置
4.1 临时解决方案
通过前面的排查,我们已经确认只需启用IPv6转发即可解决问题:
bash复制echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
但这种方法在路由器重启后会失效。
4.2 永久配置方案
在OpenWRT中,有两种方法可以持久化这个配置:
方法一:通过UCI系统配置
bash复制uci set network.globals.ipv6_forwarding=1
uci commit network
/etc/init.d/network restart
方法二:修改sysctl.conf
bash复制echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf
sysctl -p
个人建议:在OpenWRT环境下优先使用UCI方法,因为这是OpenWRT的标准配置系统,能更好地与其他服务集成。
4.3 完整配置检查清单
为确保IPv6网络正常工作,建议检查以下配置项:
-
路由器基础配置:
- WAN口已成功获取IPv6地址和前缀
- LAN口启用了DHCPv6和RA服务
- IPv6转发已启用(ipv6_forwarding=1)
-
防火墙配置:
- 确保IPv6的INPUT/FORWARD/OUTPUT链默认策略为ACCEPT
- 检查是否有自定义规则阻止了特定流量
-
客户端配置:
- 确认客户端获得了正确的IPv6地址(非fe80开头的链路本地地址)
- 检查客户端默认路由是否指向路由器
5. 进阶排查技巧
5.1 使用tcpdump进行流量分析
当基础排查无法定位问题时,可以在路由器上抓包分析:
bash复制tcpdump -i br-lan ip6 -vv
关键观察点:
- 是否能看到内网主机的IPv6请求发出
- 路由器是否转发了这些请求
- 是否有来自ISP的响应返回
5.2 MTU问题排查
IPv6不支持分片,MTU问题更常见。测试方法:
bash复制ping6 -s 1472 -M do ipv6.google.com
如果大包不通但小包通,可能是MTU问题。解决方案:
bash复制uci set network.wan.mtu=1480
uci commit network
5.3 RA公告检查
使用radvdump检查路由器公告:
bash复制radvdump
确保包含以下关键信息:
- 前缀(Prefix)与WAN口获取的一致
- 标志位(Flags)正确:ManagedFlag=1表示使用DHCPv6
6. 常见问题与解决方案
6.1 获取不到IPv6前缀
现象:WAN口只有IPv6链路本地地址(fe80::)
可能原因:
- ISP未分配IPv6前缀
- 路由器请求前缀失败
解决方案:
bash复制uci set network.wan6.reqprefix=64
uci commit network
/etc/init.d/network restart
6.2 DHCPv6地址分配异常
现象:客户端获得的是临时地址(临时地址随机生成),而非基于EUI-64的稳定地址
解决方法:
bash复制uci set dhcp.lan.ra_default=2
uci set dhcp.lan.dhcpv6=server
uci set dhcp.lan.ra_management=1
uci commit dhcp
/etc/init.d/odhcpd restart
6.3 IPv6 DNS解析失败
现象:可以ping通IPv6地址,但无法解析域名
解决方法:
- 确保路由器通告了DNS服务器
bash复制uci add_list dhcp.lan.dns='2408:8888::8' uci commit dhcp - 检查客户端是否使用了正确的DNS服务器
bash复制cat /etc/resolv.conf
7. 性能优化建议
7.1 禁用不必要的IPv6扩展头
某些ISP对IPv6扩展头支持不佳,可能导致性能下降:
bash复制uci set firewall.@defaults[0].disable_ipv6_extensions=1
uci commit firewall
7.2 调整NDP缓存设置
优化邻居发现协议缓存:
bash复制echo 1024 > /proc/sys/net/ipv6/neigh/default/gc_thresh3
7.3 启用硬件加速
如果路由器支持硬件NAT:
bash复制uci set firewall.@defaults[0].flow_offloading=1
uci set firewall.@defaults[0].flow_offloading_hw=1
uci commit firewall
/etc/init.d/firewall restart
经过上述排查和配置,我的IPv6连接终于恢复正常。整个过程中最大的教训是:不要假设IPv6和IPv4的默认行为一致,特别是在转发和防火墙规则方面。现在我的家庭网络不仅修复了IPv6访问问题,还通过优化配置获得了更好的性能表现。
