Cursor 3.9+ 在 macOS 上绕过 http.proxy 的精简分流方案
参考:Anveena — 解决 Cursor 3.9+ 无法使用 http 代理的 Linux 脚本 · Cursor 官方网络配置文档 · xjasonlyu/tun2socks
升级到 Cursor 3.9 之后,我在 macOS 上配置了 http.proxy 指向 V2rayU 的 HTTP 端口(1087),却发现 AI 对话、索引同步仍然间歇性失败。排查日志后发现:并非代理本身坏了,而是 Cursor 的部分子进程根本不走应用层代理。V2rayU 的「全局模式」同样无效——它只是修改系统代理,管不住这些直连进程。
本文记录一套按需启停、仅劫持 Cursor 相关 IP 的 OS 层分流方案。不替换 V2rayU,不开全局 TUN,不降级 Cursor 版本。
问题现象
典型报错(Cursor 日志):
getaddrinfo ENOTFOUND api2.cursor.sh
missing proxy host context during addCertificatesV2; using safe no-proxy defaults
根因:Cursor 是多进程架构
| 进程 | 是否遵守 http.proxy / 系统代理 | 实际行为 |
|---|---|---|
| NetworkService(Chromium 网络层) | 遵守 | 连接 127.0.0.1:1087,走 HTTP 代理 |
| AlwaysLocal(AI 核心子进程) | 不遵守 | 直连 api2direct.cursor.sh 的 AWS / Cloudflare IP |
| Extension Host | 部分直连 | 部分连接绕过代理 |
用 lsof 可以直观看到差异:
# NetworkService — 走代理
Cursor 85101 TCP 127.0.0.1:54555 -> 127.0.0.1:1087
# AlwaysLocal — 直连公网(分流前)
Cursor 85679 TCP 10.158.x.x:56700 -> 32.194.x.x:443
为什么 V2rayU「全局模式」也没用
V2rayU 的全局模式在 macOS 上做的是修改系统代理设置(HTTP/HTTPS → 1087,SOCKS → 1080),告诉「愿意听话的应用」去连本地端口。它不是在网卡层截获所有 TCP 包。
┌─────────────────────────────────────────────────────┐
│ V2rayU 全局模式 = 系统代理 │
│ │
│ 应用 ──(主动查系统代理)──→ 127.0.0.1:1087 ──→ v2ray │
│ ↑ │
│ 不配合的应用 ──────────────────────→ 直连 Internet │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ 真正的 TUN 全局(Clash TUN / tun2socks 全量路由) │
│ │
│ 应用 ──→ 任意 TCP │
│ ↓ │
│ OS 路由表:流量 → utun → 代理出境(应用无感知) │
└─────────────────────────────────────────────────────┘
此外,config.json 里的 routing 规则只对已进入 v2ray 入站端口的流量生效。AlwaysLocal 若根本不连 1080/1087,规则永远不会被触发。
方案思路:手术刀式 OS 层分流
思路来自 Anveena 的 Linux 脚本,我在 macOS 上做了适配。核心不是全局 TUN,而是只对 Cursor 相关 IP 加主机路由:
┌──────────────────────────────────────────────────────────┐
│ 1. 经 SOCKS5 做 DoH 解析 Cursor 域名 → 拿到 IP 列表 │
│ 2. 写入 /etc/hosts(固定域名 → IP) │
│ 3. 启动 tun2socks(utun200 → socks5://127.0.0.1:1080) │
│ 4. 对每个 IP 加主机路由:route add -host IP -interface utun200 │
│ │
│ 结果:任意进程(含 AlwaysLocal)访问该 IP 均被 OS 导入代理 │
└──────────────────────────────────────────────────────────┘
与 http.proxy 的本质区别:
http.proxy | 本方案 | |
|---|---|---|
| 作用层 | 应用层(Chromium 主动配代理) | 操作系统路由层 |
| 覆盖范围 | NetworkService 等 Chromium 进程 | 所有进程(含 AlwaysLocal) |
| 粒度 | 应用内按 URL | 按 IP /32(/128)精确分流 |
| 是否全局 TUN | 否 | 否(仅 Cursor IP) |
环境准备
V2rayU 端口
确认 V2rayU 正常运行,本地入站:
- 1080 — SOCKS5(本方案使用)
- 1087 — HTTP(保留给 Cursor
http.proxy作为双保险)
安装 tun2socks
Homebrew 暂无此包,从 GitHub Release 下载 arm64 二进制到 ~/.V2rayU/tun2socks:
cd ~/.V2rayU
curl -sL -o tun2socks.zip \
"https://github.com/xjasonlyu/tun2socks/releases/download/v2.6.0/tun2socks-darwin-arm64.zip"
unzip -o tun2socks.zip && mv tun2socks-darwin-arm64 tun2socks
chmod +x tun2socks
./tun2socks -version
分流脚本
脚本路径:~/.V2rayU/cursor-tun-mac.py(约 250 行,仅 Python 标准库 + curl)。
覆盖的域名(来源 Cursor 官方文档 + 实测补充,共 12 个):
api.cursor.com
api2.cursor.sh, api3.cursor.sh, api5.cursor.sh
agent.global.api5.cursor.sh, agentn.global.api5.cursor.sh
repo42.cursor.sh
marketplace.cursorapi.com, downloads.cursor.com
authenticate.cursor.sh, authenticator.cursor.sh
metrics.cursor.sh
api5.cursor.sh 根域名经 DoH 常返回 NXDOMAIN,脚本已改为解析其子域名 agent.global.api5.cursor.sh / agentn.global.api5.cursor.sh。api.cursor.com 是 NetworkService 经 HTTP 代理可覆盖的域名,但 Extension Host / AlwaysLocal 可能直连其 AWS IP,实测需纳入分流列表。
-device utun200(不是 utun://);
必须加 -interface en0 避免连本地 SOCKS 时路由回环;
路由用 route -n add -host IP -interface utun200。
日常使用
在 ~/.zshrc 中可配置别名:
alias cursor-tun-start='sudo python3 ~/.V2rayU/cursor-tun-mac.py start'
alias cursor-tun-stop='sudo python3 ~/.V2rayU/cursor-tun-mac.py stop --clean-hosts'
alias cursor-tun-status='sudo python3 ~/.V2rayU/cursor-tun-mac.py status'
完整流程:
- 确认 V2rayU 已启动:
nc -z 127.0.0.1 1080 - 启动分流:
cursor-tun-start - Cmd+Q 完全退出 Cursor 后重开(不要只 Reload Window)
- 不用时:
cursor-tun-stop
cursor-tun-start,再打开(或重启)Cursor。若在分流启动前已打开 Cursor,部分 Extension Host 会保留分流前的老 TCP 连接(源地址仍是 10.x 而非 198.18.0.1),路由表改了也不会自动迁移,必须 Cmd+Q 重开。
验证是否生效
A. AlwaysLocal 连接方式变化
分流前(直连公网):
Cursor 85679 TCP 10.158.x.x:56700 -> 32.194.x.x:443
分流后(经 utun):
Cursor 85679 TCP 198.18.0.1:58051 -> 3.213.55.201:443
本地地址变为 198.18.0.1(tun 接口),说明流量已被 OS 导入 tun2socks。
B. tun2socks 日志
tail -f /tmp/cursor-tun/tun2socks.log
# [TCP] 198.18.0.1:58051 <-> 3.213.55.201:443
C. v2ray 日志
rg "api2.cursor.sh|repo42" ~/.V2rayU/v2ray-core.log | tail -10
# accepted //api2.cursor.sh:443 [proxy]
D. Cursor 日志无 DNS 失败
~/Library/Application Support/Cursor/logs/<latest>/alwaysLocalSingleton.log
# 不应再出现 ENOTFOUND api2.cursor.sh
E. 排查漏网连接
以下命令应无输出(或仅有本地回环)。若有 10.x → 公网 IP 的行,说明该进程仍走直连:
lsof -i -n -P | rg "Cursor" | rg -v "198\.18\.0\.1:|127\.0\.0\.1:"
常见漏网原因:分流启动前已建立的旧连接(Cmd+Q 重开即可);域名未纳入列表(补域名后重新 cursor-tun-start)。
实测:哪些操作真正起作用
| 操作 | 效果 | 说明 |
|---|---|---|
http.proxy: 1087 + proxySupport: override |
✅ 有效 | 覆盖 NetworkService(Chromium),v2ray 日志可见 accepted //api2.cursor.sh [proxy] |
cursor.general.disableHttp2: true |
✅ 建议保留 | 降低 HTTP/2 与代理组合的兼容问题 |
| V2rayU「全局模式」 | ❌ 无效 | 只改系统代理,AlwaysLocal 仍直连 |
| 精简分流(本方案) | ✅ 有效 | AlwaysLocal 连接变为 198.18.0.1 → AWS/CF IP,tun2socks 无报错 |
全局 TUN(0.0.0.0/1 走 utun) |
❌ 不可用 | 整机流量涌入 SOCKS,V2rayU 连接被 reset/timeout,网络瘫痪(见下节) |
| Reload Window | ❌ 不够 | 子进程与旧 TCP 连接不会完全重建,必须 Cmd+Q |
不要尝试:全局 TUN + V2rayU SOCKS
曾尝试将方案改为全局 TUN(route add -net 0.0.0.0/1 -interface utun200),结果完全不可用。日志对比:
| 模式 | tun2socks 目标 IP | 结果 |
|---|---|---|
| 精简分流 | 仅 Cursor IP(如 34.193.62.81) | 正常,零 warn |
| 全局 TUN | 国内 CDN 59.83.x、206.237.x 等上万次 | SOCKS connection reset 2000+ 次,断网 |
原因:V2rayU 无内置 TUN,全局 TUN 经 tun2socks 把所有应用(浏览器、微信、系统更新)的流量打进 1080 端口,远超 SOCKS 承载能力;国内流量虽在 v2ray routing 里配了 geoip:cn → direct,但已进入 SOCKS 入站后才分流,救不了连接数爆炸。在 V2rayU 环境下,仅 Cursor IP 的精简分流才是正解;若需全局 TUN,应换 Clash Verge / sing-box 等带内核 TUN 的客户端。
与 Cursor settings.json 的配合
建议保留以下配置(NetworkService 层双保险):
{
"http.proxy": "http://127.0.0.1:1087",
"http.proxySupport": "override",
"http.proxyStrictSSL": false,
"cursor.general.disableHttp2": true
}
V2rayU 可切回 PAC / 规则模式,不必开「全局模式」;分流脚本独立工作。
踩坑记录
| 现象 | 原因 | 处理 |
|---|---|---|
| 改完 proxy 不生效 | Cursor 未完整重启,配置未热更新 | Cmd+Q 退出后重开 |
unsupported driver: utun |
tun2socks v2.6 不接受 utun:// 写法 |
改用 -device utun200 -interface en0 |
| 长时间后偶发失败 | Cursor CDN IP 漂移 | 重新执行 cursor-tun-start |
分流后仍有 10.x → 公网 连接 |
分流启动前已建立的老 TCP 连接 | Cmd+Q 重开 Cursor;或先 stop 再 start 分流后重开 |
api.cursor.com 未走代理 |
域名未在分流列表,AlwaysLocal 直连 AWS IP | 已补入 DOMAINS,重新 cursor-tun-start |
| 全局 TUN 后整机断网 | 所有流量涌入 V2rayU SOCKS,代理过载 | 勿用全局 TUN;保持按 IP 精简分流 |
| v2ray-core.log 膨胀至 GB 级 | 日志级别 info + 长期积累 | 定期 : > ~/.V2rayU/v2ray-core.log |
总结
Cursor 3.9+ 的 AI 核心流量由 AlwaysLocal 子进程发起,它在应用层直连目标 IP,既不理会 settings.json 的 http.proxy,也不理会 V2rayU 的系统代理全局模式。要在不降级、不开全局 TUN 的前提下解决,需要在操作系统路由层对 Cursor 域名对应的 IP 做精确劫持,经 tun2socks 转入本地 SOCKS 代理出境。
本方案按需启停、仅影响 Cursor 相关 IP,其余流量直连。若你的网络环境能直达 Cursor 服务器,http.proxy: 1087 alone 可能已够用;但在必须代理出境的场景下,这套 OS 层分流才是可靠解。