Cursor 3.9+ 在 macOS 上绕过 http.proxy 的精简分流方案

· macOS + V2rayU + tun2socks

参考: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 正常运行,本地入站:

安装 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.shapi.cursor.com 是 NetworkService 经 HTTP 代理可覆盖的域名,但 Extension Host / AlwaysLocal 可能直连其 AWS IP,实测需纳入分流列表。

macOS 与 Linux 原版的关键差异: -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'

完整流程:

  1. 确认 V2rayU 已启动:nc -z 127.0.0.1 1080
  2. 启动分流:cursor-tun-start
  3. Cmd+Q 完全退出 Cursor 后重开(不要只 Reload Window)
  4. 不用时: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.x206.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.jsonhttp.proxy,也不理会 V2rayU 的系统代理全局模式。要在不降级、不开全局 TUN 的前提下解决,需要在操作系统路由层对 Cursor 域名对应的 IP 做精确劫持,经 tun2socks 转入本地 SOCKS 代理出境。

本方案按需启停、仅影响 Cursor 相关 IP,其余流量直连。若你的网络环境能直达 Cursor 服务器,http.proxy: 1087 alone 可能已够用;但在必须代理出境的场景下,这套 OS 层分流才是可靠解。


脚本:~/.V2rayU/cursor-tun-mac.py · tun2socks:~/.V2rayU/tun2socks · 状态目录:/tmp/cursor-tun/