项目地址: github.com/qtopie/vproxy
首先需要明确:
vproxy是一个网络拦截和转发工具,它本身不提供任何网络穿透能力。也就是说,你依然需要自备一个可用的代理服务(本文假定你已经有一个 SOCKS5 代理)。vproxy做的事情是利用 TUN 模式和 eBPF 等高级网络技术,把那些不支持网络代理设置的软件(例如 Antigravity、Codex)的网络流量强制路由到你的代理上。它本质上是一个网络路由工具,设计思路启发自开源软件proxychains4。本文以 macOS 平台为例。
为什么需要强制代理
绝大多数命令行工具都支持通过环境变量(HTTP_PROXY / HTTPS_PROXY / ALL_PROXY)走代理,例如 curl、git、wget。但像 Codex、Antigravity 这类 AI Agent 工具,往往并不读取这些环境变量,也没有内置的代理配置项。
它们的网络请求是直接用系统 socket 发出去的,传统的 export https_proxy=... 对它们毫无效果。vproxy 的思路与 proxychains4 一脉相承:不指望目标程序自己支持代理,而是在系统网络层把它发出的连接劫持下来,转交给上游代理。
提示:Codex 桌面端是内嵌在 ChatGPT.app 里运行的,ChatGPT 主进程会拉起 codex 及其渲染器子进程。所以除了
PROCESS,codex,PROXY,还需要给 ChatGPT 主进程加上代理规则(见下文配置),否则只匹配 codex 子进程会漏掉一部分流量。
工作原理
macOS 上 vproxy 通过创建虚拟 TUN 网卡(utun),把系统路由表里 0.0.0.0/1 和 128.0.0.0/1 两个网段的路由指向 TUN,再借助 gVisor 用户态协议栈把拦下来的流量还原成 Go 的 net.Conn,交给规则引擎处理。整个过程的核心模式是:
- 把目标进程产生的 TCP/UDP 连接流量拦下来;
- 还原出它真正要访问的目标域名/IP;
- 交给规则引擎按域名、进程、IP 段分流;
- 命中
PROXY规则的流量,通过你自己的 SOCKS5 / HTTP 代理转发出去; - 给
vproxy自己发出的出站 socket 绑定物理网卡(IP_BOUND_IF),避免被 TUN 再次捕获形成环路。
前置条件
- 一台 macOS 主机(macOS 10.15+)
- 一个你自己已有的 SOCKS5 代理(例如
socks5://127.0.0.1:1080,假设跑在本地) - Go 1.21+(如果从源码构建)
- 初始化需要
sudo权限(创建 TUN 接口、修改路由表)
安装
从 Releases 下载对应平台的二进制,或从源码构建:
git clone https://github.com/qtopie/vproxy.git
cd vproxy
go build -o bin/vproxy ./cmd/vproxy
配置
vproxy 按以下顺序查找配置文件:
-c参数显式指定;- 全局配置
~/.vproxy/config.json(macOS); - 当前目录下的
vproxy.json。
在 ~/.vproxy/config.json(或项目目录 vproxy.json)中写入:
{
"upstreams": [
"socks5://127.0.0.1:1080"
],
"rules": [
"DOMAIN-SUFFIX,openai.com,PROXY",
"DOMAIN-SUFFIX,oaiusercontent.com,PROXY",
"DOMAIN-SUFFIX,chatgpt.com,PROXY",
"IP-CIDR,192.168.0.0/16,DIRECT",
"PROCESS,codex,PROXY",
"PROCESS,Codex,PROXY",
"PROCESS,ChatGPT,PROXY",
"PROCESS,/Applications/ChatGPT.app/Contents/MacOS/ChatGPT,PROXY",
"PROCESS,/Applications/ChatGPT.app/Contents/Resources/codex,PROXY",
"PROCESS,agy,PROXY",
"PROCESS,Antigravity,PROXY",
"PROCESS,/Users/calvin.y/.local/bin/agy,PROXY",
"PROCESS,/Applications/Antigravity.app/Contents/MacOS/Antigravity,PROXY",
"PROCESS,Google Drive,PROXY",
"PROCESS,DFSFileProviderExtension,PROXY",
"FINAL,PROXY"
],
"test_interval": 30,
"direct_dns": true,
"dial_timeout_ms": 5000,
"dial_retry_count": 3
}
字段说明:
upstreams:你的上游代理列表,支持socks5://与http://两种协议,可配置多个,vproxy会做健康探测和故障切换;rules:自上而下匹配的分流规则,支持DOMAIN-SUFFIX(域名后缀)、DOMAIN(精确域名)、IP-CIDR(网段)、PROCESS(进程名或完整可执行路径)、FINAL(兜底动作),动作为PROXY或DIRECT;direct_dns:DIRECT直连时是否使用上游 DNS 解析(防止本地 DNS 污染);dial_timeout_ms:连接上游超时时间,默认 5000ms,快速失败避免应用长时间卡住;dial_retry_count:失败重试次数,配合故障切换使用。
运行
初始化后台服务
先初始化全局路由环境(需要 sudo,会创建 TUN 接口、修改路由表并启动后台守护进程):
sudo vproxy init
然后直接用 vproxy 包裹目标命令即可:
vproxy codex
vproxy agy
也可以加上参数:
vproxy codex exec "写一个 python 脚本"
或者直接打开ChatGPT软件就可以了。
不使用代理的时候清理规则
sudo vproxy clean
常见问题
为什么 codex 还是直连?
检查配置是否被正确加载:vproxy status 可以查看后台守护进程状态。另外确认 PROCESS,codex,PROXY 这条规则存在——如果不带配置包裹运行,vproxy 也会自动把目标进程名追加到规则里,但最好在配置里显式声明。
会不会形成环路?
不会。macOS 上 vproxy 用 IP_BOUND_IF 把自己发出的出站 socket 绑定到真实物理网卡,绕过 TUN 虚拟网卡,这些连接不会被自己的拦截规则二次捕获。
和 proxychains4 有什么区别?
两者思路一致,但 vproxy 的实现层面更底层:proxychains4 靠 LD_PRELOAD 劫持 connect() 系统调用,对静态链接或绕过 libc 的程序无效;vproxy 则在 TUN 虚拟网卡层面直接接管流量,适用范围更广,还内置了上游健康探测与故障切换。