你是否也拥有过一台“身兼数职”的 VPS?它可能有一个香港的 IPv4,同时又绑定了来自新加坡、美国、甚至其他地区的多个 IPv6 地址。你希望精细地控制流量:访问 AI 网站走美国线路,看流媒体用新加坡线路...
通过 X-UI 或 V2Ray 等代理工具,我们可以轻松设定分流规则。但一个棘手的问题很快就浮现了:那些没有被规则匹配到的默认流量,究竟会从哪个 IP 出去呢?
很多时候,我们会发现服务器的默认出口 IP “不听话”,并没有如我们所愿地选择我们希望的线路。本篇文章将带你走过一次完整的排错之旅,从发现问题到彻底解决,让你也能成为自己 VPS 的网络指挥官。
序章:我的困境
在开始之前,让我们先明确一下我们的“剧本”:
服务器配置:一台 VPS,拥有以下 IP 地址:
香港 (HK) IPv4
美国 (US) IPv6
新加坡 (SG) IPv6
中国 (CN) IPv6
我的目标:
3X-UI中的分流规则保持不变(例如 AI 走 US,流媒体走 SG)。将所有未匹配规则的默认 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。
总结
这次排错之旅告诉我们:
眼见为实:
curl和ip route show是我们诊断网络问题的左膀右臂。简单不一定对:只修改网关,在多 IP 环境下可能会因为“源地址选择”问题而失效。
精确制导:同时指定网关 (via) 和源地址 (src),才是操控多 IP 出站流量的王道。
希望这篇文章能帮助到遇到同样困扰的你,让你在通往“网络大师”的道路上少走一些弯路。
评论