你是否也拥有过一台“身兼数职”的 VPS?它可能有一个香港的 IPv4,同时又绑定了来自新加坡、美国、甚至其他地区的多个 IPv6 地址。你希望精细地控制流量:访问 AI 网站走美国线路,看流媒体用新加坡线路...

通过 X-UIV2Ray 等代理工具,我们可以轻松设定分流规则。但一个棘手的问题很快就浮现了:那些没有被规则匹配到的默认流量,究竟会从哪个 IP 出去呢?

很多时候,我们会发现服务器的默认出口 IP “不听话”,并没有如我们所愿地选择我们希望的线路。本篇文章将带你走过一次完整的排错之旅,从发现问题到彻底解决,让你也能成为自己 VPS 的网络指挥官。

序章:我的困境

在开始之前,让我们先明确一下我们的“剧本”:

  • 服务器配置:一台 VPS,拥有以下 IP 地址:

    • 香港 (HK) IPv4

    • 美国 (US) IPv6

    • 新加坡 (SG) IPv6

    • 中国 (CN) IPv6

  • 我的目标

    1. 3X-UI 中的分流规则保持不变(例如 AI 走 US,流媒体走 SG)。

    2. 将所有未匹配规则的默认 IPv6 流量,全部通过新加坡 (SG) 的 IPv6 出站。

  • 遇到的问题:尽管我心里想让 SG IP 当老大,但服务器自作主张,让 CN IP 或者 US IP 成了默认出口。

第一章:知己知彼,看清现状

在动手之前,我们得先搞清楚服务器当前的“想法”。

1. 查看当前默认出口 IP

想知道服务器默认用哪个“马甲”出门?一个简单的命令就够了。

Bash

curl -6 ip.sb
# 或者
curl -6 ifconfig.me

这个命令会访问一个专门显示你 IP 的网站,-6 参数强制它只通过 IPv6 连接。执行后,它返回的 IP 就是你当前默认的 IPv6 出口。在我的案例中,它返回了那个“不听话”的中国 IP。

2. 解读服务器的“交通图”——路由表

服务器如何决定数据包该走哪条路?答案就藏在路由表 (Routing Table) 中。

Bash

ip -6 route show

你会看到类似这样的输出:

default via 2001:550:1601::1 dev eth0 proto static metric 1024 pref medium
...

这是什么意思呢?我们可以用一个比喻来理解:

  • default: 代表所有“未知地址”的包裹。

  • via 2001:550:1601::1: 这些包裹需要发往 2001:550:1601::1 这个网关 (Gateway)。网关就像是你家小区的快递中转站,所有外出的包裹都得先送到那。

  • dev eth0: 包裹从 eth0 这个网卡 (Interface) 发出去。

  • metric 1024: 这是跃点数,你可以理解为“优先级”。这个数字越小,优先级越高! 如果有多条 default 规则,系统会优先选择 metric 值最小的那一条。

通过这个命令,我们确认了,当前优先级最高的是通往美国 IP 的网关,这就是问题的根源之一。

第二章:初次尝试与意外的“滑铁卢”

既然找到了问题,那解决方案看起来很简单:删除旧的默认路由,添加一条指向新加坡网关、并且 metric 值更低的新路由不就行了?

说干就干!

1. 寻找新加坡网关

首先,我们得知道新加坡线路的“快递中转站”地址。我们通过服务商后台、ping 测试等方法,最终确定了新加坡网关是 2a0f:7802:e2f8:3af::1

2. 修改路由表

Bash

# 1. 删除旧的美国默认路由
sudo ip -6 route del default via 2001:550:1601::1 dev eth0

# 2. 添加指向新加坡的新路由,给它一个很高的优先级 (metric 100)
sudo ip -6 route add default via 2a0f:7802:e2f8:3af::1 dev eth0 metric 100

看起来天衣无缝!让我们来验证一下胜利的果实。

3. 意想不到的结果

Bash

curl -6 ip.sb

终端返回的结果,让我们大跌眼镜:

2401:1da0:2::199

出来的竟然是中国 (CN) 的 IP!明明我们已经把默认的“快递中转站”改成了新加坡,为什么包裹出门时,盖上的“发件人地址”邮戳却是中国的呢?

第三章:刨根问底,揪出真正的“幕后黑手”

这次失败让我们明白,事情没有那么简单。问题出在一个常常被忽略的概念上:源地址选择 (Source Address Selection)

一个绝妙的比喻:

刚才的操作,相当于你告诉一位要出远门的司机:“请你务必从‘新加坡高速口’离开城市。”(指定了网关)。

但你这台服务器有好几本“护照”(US/SG/CN 的 IP)。你没有告诉司机出门时具体要用哪一本“护照”。于是司机为了省事,随手从抽屉里拿了一本,恰好就是那本中国的“护照”(系统自己选择了源 IP)。

所以,我们的指令缺少了最关键的一环:不仅要告诉系统走哪条路 (Gateway),还要明确告诉它用哪个身份出门 (Source IP)

第四章:终极必杀技,釜底抽薪

有了新的思路,我们就能写出精准无误的指令了。我们需要用到 ip 命令中的 src 参数。

1. 临时但有效的解决方案

这条指令,就是我们寻找的终极答案。

Bash

# 首先,清空所有默认路由,确保一个干净的环境
sudo ip -6 route flush default

# 重新添加路由,这次不仅指定 gateway,更指定了 src (Source IP)
sudo ip -6 route add default via 2a0f:7802:e2f8:3af::1 dev eth0 src 2a0f:7802:e2f8:3af::63
  • src 2a0f:7802:e2f8:3af::63: 这部分就是指令的灵魂!它强制规定,所有走这条路由的流量,都必须使用新加坡 IP 作为源地址。

再次验证:

Bash

curl -6 ip.sb

这一次,终端终于返回了我们梦寐以求的新加坡 IP!🎉

2. 让服务器“记住”这个选择——永久化配置

上面的命令只在当前有效,服务器一旦重启就会“失忆”。为了让它永久记住,我们需要将命令写入开机启动脚本。这里我们使用最经典、兼容性最强的 rc.local 方法。

第一步:创建并编辑 rc.local 文件

Bash

sudo nano /etc/rc.local

第二步:写入配置

将以下内容完整地复制粘贴到文件中。

Bash

#!/bin/bash
#
# rc.local

# 为确保每次开机都能正确设定,先清除旧的IPv6默认路由
/sbin/ip -6 route flush default

# 添加我们那条带有指定源IP的完美路由规则
/sbin/ip -6 route add default via 2a0f:7802:e2f8:3af::1 dev eth0 src 2a0f:7802:e2f8:3af::63

exit 0

提示:在 rc.local 这类启动脚本中,使用命令的绝对路径(如 /sbin/ip)是一个好习惯。

第三步:赋予权限并启用服务

Bash

sudo chmod +x /etc/rc.local
sudo systemctl enable rc-local
sudo systemctl start rc-local

至此,大功告成!无论你如何重启,服务器的默认 IPv6 出口都会坚定不移地使用你的新加坡 IP。

总结

这次排错之旅告诉我们:

  1. 眼见为实curlip route show 是我们诊断网络问题的左膀右臂。

  2. 简单不一定对:只修改网关,在多 IP 环境下可能会因为“源地址选择”问题而失效。

  3. 精确制导:同时指定网关 (via)源地址 (src),才是操控多 IP 出站流量的王道。

希望这篇文章能帮助到遇到同样困扰的你,让你在通往“网络大师”的道路上少走一些弯路。