---
url: /article/vcyvsp35/index.md
---
## 前言

之前打折超低价购入一台 NAT 🐔，虽然它配置很低，但好歹是一个有公网的机器，流量也是可以“吃到饱”。可到手开玩之后发现个问题，IPv4是厂商固定没什么好说的，IPv6是给你一个地址池自行分配，在分配好后确发现虽然小鸡有了IPv6地址，可无法通过IPv6访问，亦无法访问其他IPv6地址。

## 1. 故障表现

由于小鸡内存仅 384MB，故安装的是 Alpine 系统。执行`apk update`时，终端显示访问`https://dl-cdn.alpinelinux.org/alpine/v3.19/main`，然后就卡住不动了。测试网络连通性`curl -6 ifconfig.co`一样卡住不动。

## 2. 故障排查

`ip -6 addr show`查看IPv6地址：

```bash
1: lo: mtu 65536 state UNKNOWN qlen 1000
inet6 ::1/128 scope host proto kernel_lo
valid_lft forever preferred_lft forever
2: eth0: mtu 1420 state UP qlen 1000
inet6 2026:fef8:6:6:888:e8ff:98at:at98/64 scope global dynamic mngtmpaddr proto kernel_ra
valid_lft forever preferred_lft forever
inet6 fe80::888:e8ff:98at:at98/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
```

这里可以看出，系统通过 SLAAC（路由广播）自动分配到了`2026:fef8:6:6:.../64`网段的地址，但厂商实际划分的专属网段是`2026:fef8:6:68::/64`，网关是`2026:fef8:6::2`。子网和网关不在一个网关段，自然无法把流量发出去。

## 3. 故障处理

既然发现了问题所在，那么就做些修改：

```bash
# 删除系统自动获取的错误 IPv6 地址
ip -6 addr del 2026:fef8:6:6:888:e8ff:98at:at98/64 dev eth0

# 配置正确的静态 IPv6 地址(这个地址是在控制台自行分配的)
ip -6 addr add 2026:fef8:6:68::a/64 dev eth0

# 强制告诉系统：网关 2026:fef8:6::2 就在 eth0 这个物理接口上
ip -6 route add 2026:fef8:6::2 dev eth0

# 设置默认 IPv6 流量全部走这个网关
ip -6 route add default via 2026:fef8:6::2
```

之后再次执行`apk update`成功了，执行`curl -6 ifconfig.co`也能立即返回本机的IPv6地址`2026:fef8:6:68::a`，问题解决了。可以当断开 SSH 后重新连接问题依旧，这说明修改并没有永久生效。

## 4. 永久生效

为了永久生效，我们需要修改`/etc/network/interfaces`文件，原文件内容如下：

```bash
# 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}

auto lo
iface lo inet loopback
    dns-nameservers 8.8.8.8 1.0.0.1 2001:4860:4860::8888 2001:4860:4860::8844

auto eth0
iface eth0 inet static
    address 192.168.0.118/24
    dns-nameservers 8.8.8.8 1.0.0.1 2001:4860:4860::8888 2001:4860:4860::8844
    gateway 192.168.202.1
    dns {'nameservers': ['8.8.8.8', '1.0.0.1', '2001:4860:4860::8888', '2001:4860:4860::8844'], 'search':

# control-alias eth0
iface eth0 inet6 static
    address 2026:fef8:6:68::a/64
    gateway 2026:fef8:6::2
```

从文件头可以看出来，文件内容是从数据源自动生成的，这是厂商控制的。修改这个文件内容并不会持久化生效，系统重启后就会丢失修改。为了禁用这个功能，需要创建一个文件`/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg`，并写入内容`network: {config: disabled}`。\
不仅如此，这个文件内容其实是有问题的，尤其是`dns {'nameservers': ['8.8.8.8', '1.0.0.1', '2001:4860:4860::8888', '2001:4860:4860::8844'], 'search':`这一行，可能从厂商的脚本有 BUG。

为了修改上面的问题，我们先创建`99-disable-network-config.cfg`文件：

```bash
echo "network: {config: disabled}" > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
```

修改`/etc/network/interfaces`文件内容，完全覆盖如下：

```bash
auto lo
iface lo inet loopback
    dns-nameservers 8.8.8.8 1.0.0.1 2001:4860:4860::8888 2001:4860:4860::8844

auto eth0
iface eth0 inet static
    address 192.168.202.136/24
    gateway 192.168.202.1
    dns-nameservers 8.8.8.8 1.0.0.1 2001:4860:4860::8888 2001:4860:4860::8844

iface eth0 inet6 static
    address 2026:fef8:6:68::a
    netmask 64
    # 禁用系统自动接收路由器广播，防止获取到错误的 IPv6
    pre-up sysctl -w net.ipv6.conf.eth0.accept_ra=0
    
    # 强制指定跨网段网关路由
    up ip -6 route add 2026:fef8:6::2 dev eth0
    up ip -6 route add default via 2026:fef8:6::2
    
    # 关机/重启网卡时自动清理路由表
    down ip -6 route del default via 2026:fef8:6::2
    down ip -6 route del 2026:fef8:6::2 dev eth0
```

保存退出后重启系统，然后执行`ip -6 route`查看：

```bash
2026:fef8:6::2 dev eth0 metric 1024 pref medium
2026:fef8:6:68::/64 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via 2026:fef8:6::2 dev eth0 metric 1024 pref medium
```

重启后依然有效，问题解决。
