目录

WSL 代理自由切换记

从被动继承,到把代理、直连、apt 和多套本地端口真正握回自己手里

真正让我决定把这件事写下来,不是因为 WSL 代理有多复杂,而是因为它表面上看起来“能用”,实际上一直处在一种很脆弱的偶然状态里。外网能不能连,apt 会不会失败,本地的 LM Studio 能不能被 OpenClaw 调到,似乎都取决于 Windows 那边某个代理软件今天是不是刚好开着。

这种状态最浪费时间。它不会让我们立刻报废,但会不停吞掉注意力:一次 curl 失败,一次 apt update 卡住,一次以为是模型服务没起,后来才发现其实是网络路径又变了。问题不在某一条命令上,而在于整个环境缺少“我自己知道现在到底走的是哪条路”这件事。

现象

最早暴露问题的,是 WSL 里一些行为看上去互相矛盾。

一方面,终端里明明没有在 ~/.bashrc 里写代理,curl -I https://bun.sh 却能返回 HTTP/1.1 200 Connection established 以及后续的 200 响应;另一方面,一旦 Windows 上那套指定的代理软件关掉,WSL 里的网络请求又会整体失效。本地环境里还叠加了另一个条件:装在 WSL 里的 OpenClaw,要调用 Windows 侧 LM Studio 暴露的 http://127.0.0.1:5868/,而这条链路在某些时候居然也依赖那套代理是否打开。

这说明问题已经不是单纯的“有没有代理”,而是 WSL 里的网络行为并不完全由我显式配置,而是混入了外部继承、程序自身读取环境变量、apt 独立配置,以及本地 localhost 访问路径这几件事。

第一轮误判

最开始很自然地会怀疑:是不是我以前在 ~/.bashrc/etc/environment/etc/profile 之类的位置写过代理,只是自己忘了。

于是先查了最直观的地方。echo $http_proxy 能看到 http://127.0.0.1:10808,但 grep -i proxy ~/.bashrc 却是空的,再往 /etc/environment/etc/profile/etc/profile.d/~/.profile 里搜,也没有明确的代理设置。到这里,线索开始变得清楚:变量存在,但不是从当前 Linux 用户手工写进去的。

证据

真正有价值的证据不是某一条花哨命令,而是几组朴素的对照。

第一组对照,是 proxy_onproxy_off 之后直接用 curl 测站点。开代理时访问 https://bun.sh,能够稳定返回 200;切成直连后访问清华镜像,也能够直接返回 200。这说明 WSL 内部通过环境变量切换网络出口这件事,本身是成立的。

第二组对照,是 apt 的行为。把 apt 单独设成直连时,sudo apt update 可以顺利命中 mirrors.tuna.tsinghua.edu.cn;切到 Hiddify 之后,再看 apt_proxy_status,能明确看到:

Acquire::http::Proxy "http://127.0.0.1:12334/";
Acquire::https::Proxy "http://127.0.0.1:12334/";

这说明 apt 不是“神秘地自动跟着 shell 走”,而是被明确写到了自己的配置文件里。它和普通命令行程序的行为层级,本来就不是一回事。

第三组对照,是新开终端和旧终端的差异。旧终端里执行 use_direct 之后,当前会话会进入直连模式;但新开一个 WSL 终端,又会因为 .bashrc 末尾默认执行了 proxy_v2rayn_on,回到默认代理状态。到这里,范围也清楚了:代理命令会影响当前 shell 会话,而 .bashrc 决定每个新会话的默认值。

根因

根因其实分成两层。

第一层,是 WSL 环境里原本存在从 Windows 侧继承下来的代理变量。这类变量不一定能在 ~/.bashrc 里找到,却会在 shell 启动时已经出现在环境里。于是表面上看,像是“WSL 自己天生就能上网”,实际上只是 Windows 那边某个本地代理端口刚好被继承进来了。

第二层,是 不同程序读取代理配置的方式根本不同。像 curl、很多 Python/Node 工具、OpenClaw 这类程序,通常会读取 http_proxyhttps_proxyall_proxy;而 apt 更偏向自己的配置文件,需要单独控制。再加上本地服务 127.0.0.1 这类地址本该永远直连,如果不靠 NO_PROXY 把它排出去,本地 API 也可能被误送进代理。

换句话说,之前最混乱的地方,不是“代理坏了”,而是 控制权不在自己手里。网络偶尔可用,只是因为几层配置碰巧叠在一起,而不是因为环境被真正整理过。

修复思路

这次修复没有追求某种“最炫的自动化”,而是追求三件事:可见、可切、可验证。

第一步,是在 ~/.bashrc 里把 Windows 可能继承下来的代理变量先清掉,再定义一组明确的函数:proxy_v2rayn_onproxy_clashparty_onproxy_clashverge_onproxy_hiddify_onproxy_alt_onproxy_offproxy_status。这样,WSL 里普通程序到底走哪条代理,不再由宿主机偷偷决定,而是由当前 shell 会话里的明确命令决定。

第二步,是把 apt 从“含混地跟随 shell”里剥离出来。新增 apt_proxy_onapt_proxy_offapt_proxy_status,让 apt 始终通过 /etc/apt/apt.conf.d/01proxy 这一个出口被管理。这样一来,中国镜像源就能长期直连,而国外源或偶发下载问题又可以随时切回代理。

第三步,是把常用组合封装成 use_v2raynuse_clashpartyuse_clashvergeuse_hiddifyuse_altuse_direct。这样每天真正需要记住的,不再是很多底层变量,而只是几个工作流级别的动作:今天我是在“国内直连模式”下干活,还是在“某一套代理模式”下拉外网资源。

现在这套的详细使用说明

现在这套配置已经跑起来了,这份 面向“日常使用”的说明书,可以当小手册用。


一、我们现在拥有什么

在 WSL 里,我们有三类“开关”:

  1. 通用代理(影响 curl/pip/git/OpenClaw 等程序)
    • proxy_v2rayn_on
    • proxy_clashparty_on
    • proxy_clashverge_on
    • proxy_hiddify_on
    • proxy_alt_on
    • proxy_off
    • proxy_status

这些控制的是环境变量 http_proxy / https_proxy / all_proxy,大多数命令行程序都会跟着走。

  1. apt 专用
    • apt_proxy_on
    • apt_proxy_off
    • apt_proxy_status

控制 /etc/apt/apt.conf.d/01proxy,只影响 apt update / apt install

  1. 组合快捷键(通用代理 + apt 一起切)
    • use_v2rayn
    • use_clashparty
    • use_clashverge
    • use_hiddify
    • use_alt
    • use_direct

一条命令同时切换“WSL 里的所有程序”和 apt,最省心。


二、最常用的 3 个场景

场景 1:只用中国镜像 / 本地服务(推荐日常默认)

目标:

  • WSL 直连国内源和 LM Studio、各种本地端口
  • apt 只走中国镜像,不走梯子

做法:

use_direct

这会自动做两件事:

  • proxy_off → 所有程序直连(但 localhost/127.0.0.1 永远直连,本来就不走代理)。
  • apt_proxy_off → apt 配置改成“完全直连”。[^27_5][^27_6]

可选检查:

proxy_status        # 显示 当前:直连模式
apt_proxy_status    # 显示 当前:直连模式

适合做什么:

  • 用清华/中科大镜像 sudo apt update && sudo apt upgrade
  • 访问 http://127.0.0.1:5868(LM Studio)
  • 拉国内源、国内 Git 仓库

场景 2:所有东西都走 v2rayN(需要外网)

目标:

  • curl / pip / git / OpenClaw 等全部走 v2rayN 的 10808
  • apt 拉包也走 v2rayN

做法:

use_v2rayn

相当于:

  • proxy_v2rayn_on → 设置 http_proxy=http://127.0.0.1:10808 等。
  • apt_proxy_on → apt 也用当前代理(这时就是 10808)。[^27_3][^27_1]

检查:

proxy_status        # [WSL] 当前代理: v2rayN -> http://127.0.0.1:10808
apt_proxy_status    # Acquire::http::Proxy "http://127.0.0.1:10808/";

适合:

  • 拉 GitHub / PyPI / npm / 外网 deb 仓库
  • OpenClaw 调用外网 API(前提是它读环境变量)

场景 3:v2rayN 不稳,切到 Hiddify/Clash 之类的备线

假设我们发现 10808 很容易重置,想换 Hiddify 的 12334:

use_hiddify

相当于:

  • proxy_hiddify_on → 通用代理改为 127.0.0.1:12334
  • apt_proxy_on → apt 也用这个端口。[^27_7][^27_3]

检查:

proxy_status
# [WSL] 当前代理: Hiddify -> http://127.0.0.1:12334

apt_proxy_status
# Acquire::http::Proxy "http://127.0.0.1:12334/";
# Acquire::https::Proxy "http://127.0.0.1:12334/";

同理,如果我们想让一切都走 Clash Party 或 Clash Verge:

use_clashparty    # 走 127.0.0.1:7890
use_clashverge    # 走 127.0.0.1:7897
use_alt           # 走 127.0.0.1:10809(我们备用端口)

(前提是 Windows 里对应软件/端口已经启动并监听。)


三、细一点的使用说明

1)通用代理函数(不动 apt)

如果我们只想让某些程序走代理、apt 保持原样,可以单独用这些:

proxy_v2rayn_on      # 改成 v2rayN
proxy_clashparty_on  # 改成 Clash Party
proxy_clashverge_on  # 改成 Clash Verge
proxy_hiddify_on     # 改成 Hiddify
proxy_alt_on         # 改成备用端口
proxy_off            # 完全直连
proxy_status         # 当前代理情况
  • 改完后,在 这个终端里新启动的程序 都会用新的代理设置。
  • 已经在跑的进程一般不会“自动跟着变”,除非它重新读取环境变量。

2)apt 专用函数

如果我们只想改变 apt 的行为,不动其他程序:

apt_proxy_on     # 让 apt 用“当前通用代理”的 http 地址
apt_proxy_off    # 让 apt 完全直连
apt_proxy_status # 看 apt 现在用不用代理

注意:apt_proxy_on 会读 CURRENT_PROXY_HTTP,也就是我们之前用 proxy_xxx_onuse_xxx 选的那个端口;如果当前没选就默认 10808。[^27_4][^27_3]


四、推荐“心智模型”

我们可以这样在脑子里简化成两层开关:

  1. 上层:我现在的终端要走哪条线?
    • 直连:proxy_offuse_direct
    • v2rayN:proxy_v2rayn_onuse_v2rayn
    • Clash Party:proxy_clashparty_onuse_clashparty
    • Clash Verge:proxy_clashverge_onuse_clashverge
    • Hiddify:proxy_hiddify_onuse_hiddify
  2. 下层:apt 要不要跟着走?
    • 跟着当前代理:apt_proxy_on 或直接用 use_xxx
    • 只用中国镜像:apt_proxy_offuse_direct

只要我们记住这两层,基本不会再被“到底走没走代理”“为什么 apt 又拉不动包”这类问题绕住。


五、出问题时怎么看

如果我们拉东西失败,排查顺序可以用这几条:

  1. 看 WSL 代理状态:
proxy_status
  1. 看 apt 状态:
apt_proxy_status
  1. 用 curl 测一下:
curl -I https://bun.sh        # 测外网
curl -I https://mirrors.tuna.tsinghua.edu.cn/ubuntu  # 测国内镜像
  1. 检查我们要用的代理软件在 Windows 里有没有真的开着、端口对不对。

最终落地

最终保留下来的配置,并不复杂,但很够用。

普通程序层面,用的是环境变量切换:

proxy_v2rayn_on
proxy_hiddify_on
proxy_off
proxy_status

apt 层面,用的是独立状态切换:

apt_proxy_on
apt_proxy_off
apt_proxy_status

日常真正高频使用的,是组合命令:

use_direct
use_v2rayn
use_clashparty
use_clashverge
use_hiddify

这里面,use_direct 会同时让 shell 和 apt 进入直连,适合中国镜像、本地 LM Studio 以及各种不需要外网代理的场景;而 use_hiddifyuse_v2rayn 这些命令,则同时切换普通程序和 apt 的出口,适合拉外网资源、安装海外仓库、或者在某条线路不稳时迅速换路。

经验

这次最大的经验,不是某个命令怎么写,而是:不要把“碰巧能用”误当成“已经配置清楚”

WSL 这种环境特别容易出现一种错觉:今天能上网、今天能拉包、今天本地 API 也能通,于是就先用着。但只要控制权不在自己手里,后面一定会用更高的时间成本把这笔账补回来。

真正稳妥的做法,是给每一层都留出清楚的开关和状态检查。能直连的,明确直连;必须代理的,明确代理;apt 单独管;本地 localhost 永远排除;新终端默认值写清楚。这样以后再遇到问题,不需要猜,只需要看状态。


“技术终归是工具,而我们一次次认真把问题理顺,守住的其实不只是页面样式和代码输出等等,还有那一点不愿被混乱打败的心气,是每一个深夜仍愿点灯前行的人。”
若我们有故事想讲、有困惑想聊、或是想找个人说说心里话,甚至只是吐槽发泄一下情绪,都欢迎来找我聊聊:   《内容已折叠,点击展开》

希望我写的每一个字,成为我自己和某个人活下去、拼下去的力量。                     《内容已折叠,点击展开》

转载请注明来自https://oklife.me。

文尾配图水墨画图片