Codex 不开 TUN 也能用:Windows 桌面端排查实录,以及 VS Code 插件的代理配置
使用 Codex 时,我遇到了一个很典型的问题:浏览器能访问 ChatGPT,代理软件的服务检测也是绿色,但只要关掉 TUN,Codex 就会停在“正在思考”,随后出现“正在重新连接 2/5、3/5”。
使用 Codex 时,我遇到了一个很典型的问题:浏览器能访问 ChatGPT,代理软件的服务检测也是绿色,但只要关掉 TUN,Codex 就会停在“正在思考”,随后出现“正在重新连接 2/5、3/5”。
为了不用一直开着虚拟网卡,我试了系统代理、代理环境变量和启动脚本。最后真正发现的问题是:启动命令里有代理参数,不代表客户端的后台进程也拿到了代理环境变量。
这篇文章把排查过程和最终脚本整理出来,也附上 VS Code 中 Codex 插件的启动配置。
先分清:系统代理、全局模式、TUN 是三回事
这里使用的代理软件是 FlClash,本机代理端口为 7890。
- 系统代理:把代理地址登记到系统设置,供支持它的程序使用。
- 规则/全局模式:决定进入代理软件的请求如何分流。
- TUN/虚拟网卡:通过虚拟网络接口接管匹配的流量,能覆盖更多不主动使用代理的程序。
所以,切换“全局模式”不等于开启 TUN,也不意味着所有程序都自动进入代理。
本文使用的代理地址是:
http://127.0.0.1:7890
请先确认自己的 HTTP 或混合端口。7890 是本次环境的值,不是所有人的固定值。即使目标网站使用 HTTPS,本地 HTTP 代理地址也仍可能以 http:// 开头。
为什么只开启系统代理,Codex 还会重连?
桌面客户端不只有显示页面的窗口,还会启动后台执行器。界面请求和后台连接可能使用不同的网络实现。
这次排查中,我看到过这样的情况:
- 客户端界面的部分连接已经走
127.0.0.1:7890。 - 后台执行器却不断出现
websocket_error和timed_out。 - 进一步读取进程中的代理变量,发现主程序和执行器都没有
HTTP_PROXY、HTTPS_PROXY等变量。
因此,“页面能打开”“代理服务检测正常”,都不能单独证明聊天执行链路已经连通。
桌面端:保留两个启动文件即可
新建一个固定目录,例如 E:\Tools\CodexProxy,把下面两个文件放在一起。
1. start-codex-proxy.cmd
双击入口如下:
@echo off
setlocal
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0start-codex-proxy.ps1"
if errorlevel 1 pause
endlocal
-ExecutionPolicy Bypass 只用于这次 PowerShell 启动,不会永久修改系统执行策略。
2. start-codex-proxy.ps1
以下是本次实际使用的脚本。端口不同的话,把代码中所有 7890 一并替换。
param([switch]$CheckOnly)
$ErrorActionPreference = 'Stop'
try {
$pkg = Get-AppxPackage -Name OpenAI.Codex | Select-Object -First 1
if (-not $pkg) { throw 'OpenAI.Codex package not found.' }
$manifest = Get-AppxPackageManifest -Package $pkg.PackageFullName
$app = $manifest.Package.Applications.Application | Where-Object { $_.Executable -match '(^|[/\\])ChatGPT\.exe$' } | Select-Object -First 1
if (-not $app) { throw 'Desktop app entry not found in package manifest.' }
$exe = Join-Path $pkg.InstallLocation $app.Executable
$quotedExe = $exe.Replace("'", "''")
$inner = @"
`$ErrorActionPreference = 'Stop'
`$env:HTTP_PROXY = 'http://127.0.0.1:7890'
`$env:HTTPS_PROXY = 'http://127.0.0.1:7890'
`$env:ALL_PROXY = 'http://127.0.0.1:7890'
`$env:NO_PROXY = 'localhost,127.0.0.1,::1'
`$startInfo = New-Object System.Diagnostics.ProcessStartInfo
`$startInfo.FileName = '$quotedExe'
`$startInfo.Arguments = '--proxy-server=http://127.0.0.1:7890'
`$startInfo.UseShellExecute = `$false
`$startInfo.WorkingDirectory = [IO.Path]::GetDirectoryName('$quotedExe')
`$startInfo.EnvironmentVariables['HTTP_PROXY'] = 'http://127.0.0.1:7890'
`$startInfo.EnvironmentVariables['HTTPS_PROXY'] = 'http://127.0.0.1:7890'
`$startInfo.EnvironmentVariables['ALL_PROXY'] = 'http://127.0.0.1:7890'
`$startInfo.EnvironmentVariables['NO_PROXY'] = 'localhost,127.0.0.1,::1'
`$startedProcess = [System.Diagnostics.Process]::Start(`$startInfo)
Write-Host ('Started Codex PID ' + `$startedProcess.Id + ' with explicit proxy environment.')
"@
if ($CheckOnly) {
Write-Output "Package: $($pkg.PackageFamilyName)"
Write-Output "App ID: $($app.Id)"
Write-Output "Executable: $exe"
Get-Command Invoke-CommandInDesktopPackage -ErrorAction Stop | Out-Null
Write-Output 'Package and launcher command verified; application not started.'
exit 0
}
$running = Get-CimInstance Win32_Process -Filter "name = 'ChatGPT.exe'" | Where-Object { $_.ExecutablePath -eq $exe }
if ($running) {
throw 'Codex is still running. Exit Codex completely, then run this launcher again. Existing processes cannot inherit new proxy variables.'
}
$wrapped = "try {`n" + $inner + "`n} catch { Write-Host `$_; Read-Host 'Press Enter to close'; exit 1 }"
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($wrapped))
Invoke-CommandInDesktopPackage -PackageFamilyName $pkg.PackageFamilyName -AppId $app.Id -Command "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -Args "-NoProfile -EncodedCommand $encoded" -PreventBreakaway
} catch {
Write-Error $_ -ErrorAction Continue
exit 1
}
脚本中的提示使用英文,保存成普通 UTF-8 文件即可,避免 Windows PowerShell 5.1 对无 BOM 中文脚本的编码兼容问题。
使用顺序
- 启动 FlClash,确认节点可用、代理端口正确。
- 关闭 TUN,系统代理可以保持开启。
- 从托盘菜单完全退出 Codex。
- 双击
start-codex-proxy.cmd。 - 发送消息,确认可以收到完整回复。
如果脚本提示 Codex 仍在运行,说明它检测到了已有客户端进程。关窗口可能只是隐藏到托盘,需要真正退出后再启动。
这一步很关键:已经运行的程序,不会因为你在另一个终端设置代理变量,就自动获得新配置。
VS Code:用同一个思路给 Codex 插件传代理
VS Code 不需要套用上面的 MSIX 启动逻辑。对于运行在本机的 Codex 插件,可以先给 VS Code 设置代理环境,让后续启动的插件后台进程继承。
新建 vscode-with-proxy.cmd:
@echo off
setlocal
set "HTTP_PROXY=http://127.0.0.1:7890"
set "HTTPS_PROXY=http://127.0.0.1:7890"
set "ALL_PROXY=http://127.0.0.1:7890"
set "NO_PROXY=localhost,127.0.0.1,::1"
rem Replace this path with your actual VS Code executable.
start "" "C:\Program Files\Microsoft VS Code\Code.exe" %*
endlocal
把 Code.exe 路径改成自己的安装位置。通过快捷方式使用时,目标可以写成:
C:\Windows\System32\cmd.exe /c "E:\Tools\CodexProxy\vscode-with-proxy.cmd"
使用前先保存工作,完全退出所有 VS Code 窗口,确认没有残留的 Code.exe,再从这个快捷方式启动。
否则,新启动命令可能把窗口交给已有的 VS Code 实例,插件继续使用旧进程的环境,表现为“脚本明明写了代理,插件还是不通”。
这部分是本地插件进程的配置方法,不是本次已经验证通过的插件连接结果。 如果使用 WSL、Remote SSH 或 Dev Container,插件后台也可能运行在远端,需要检查代理实际配置在哪一侧;远端的 127.0.0.1 并不指向 Windows 上的 FlClash。
怎样确认真的生效?
不要只看窗口是否成功打开,可以分三层验证。
第一层,看使用结果。 关闭 TUN 后发送消息,能否完整收到回复;连续几轮是否仍然出现重连。
第二层,看进程环境。 检查实际主进程、执行器是否拥有代理变量,而不是只在终端执行 echo。终端有变量,不能证明应用进程也有。
第三层,看连接和日志。 本次修复后,后台执行器的连接指向 127.0.0.1:7890,日志出现 connected to rendezvous;此前它会连续记录 WebSocket 超时。
在有权限的 PowerShell 中,可以先查执行器 PID:
Get-CimInstance Win32_Process |
Where-Object {
$_.Name -eq 'codex.exe' -and
$_.CommandLine -match 'exec-server --remote'
} |
Select-Object ProcessId, ParentProcessId
再把下面的 12345 替换成查到的实际 PID:
Get-NetTCPConnection -OwningProcess 12345 -State Established |
Select-Object RemoteAddress, RemotePort
看到本机代理连接是有用证据,但它不能独自证明所有请求和所有功能正常。FlClash 的“实时连接”页面也可以辅助核对目标域名、连接和分流结果。
参考资料
- 微软:Invoke-CommandInDesktopPackage:应用包上下文启动命令的行为与限制。
- OpenAI:Codex 配置参考:配置项查询入口。本文的 Windows 启动绕行脚本来自本次排查,不应理解为该文档承诺的官方代理方案。
*测试环境:Windows、FlClash、OpenAI.Codex MSIX 包;记录时间:2026 年 10 月。客户端版本与安装方式变化后,请重新验证。*
本文链接:https://www.choudalao.com/article/361
转载请注明来源,感谢尊重原创内容。
留言评论
支持表情、回复和点赞。评论需要先登录。