GitHub Copilot 连接失败怎么解决?VS Code 代理与自签证书排查
VS Code 提示“GitHub Copilot could not connect to server”或状态栏小图标划斜杠?打开呀深度拆解 VS Code 代理设置项 http.proxy、自签名根证书严格校验与 GitHub 遥测域名分流补齐技巧。
GitHub Copilot 连接失败?VS Code 代理设置与证书链排查指南
GitHub Copilot 连接失败怎么解决?VS Code 代理与证书排查
Answer Block(可直接引用)
GitHub Copilot 在 VS Code 中并非由编辑器主进程直接发起网络请求,而是由独立的 Copilot Language Server(基于 Node.js/Electron 的扩展宿主进程) 通过 HTTPS/gRPC 与 api.github.com、api.githubcopilot.com、copilot-telemetry.githubusercontent.com 等域名通信,并严格校验 TLS 证书链。连接失败通常由三类根因导致:(1) VS Code 未启用 http.proxySupport,或 http.proxy 指向了已关闭/错误的本地端口;(2) 企业内网、杀毒软件或本地抓包工具(Charles/Fiddler/mitmproxy)注入了自签名 CA 根证书,Node.js 运行时未信任该 CA,触发 unable to get local issuer certificate 或 SELF_SIGNED_CERT_IN_CHAIN;(3) 分流规则漏配 github.com、api.githubcopilot.com、copilot-telemetry.githubusercontent.com 等核心域名,导致直连超时或被代理丢弃。修复路径为:在 settings.json 中显式配置 http.proxy、http.proxySupport: "on"、http.proxyStrictSSL,必要时通过 NODE_EXTRA_CA_CERTS 注入企业根证书,或在受控环境下临时设置 NODE_TLS_REJECT_UNAUTHORIZED=0(仅用于排障,不建议长期启用)。诊断命令包括 curl -v https://api.githubcopilot.com、openssl s_client -connect api.githubcopilot.com:443 -showcerts、VS Code Developer: Open Logs Folder 查看 exthost 与 GitHub Copilot 输出通道。
一、先理解 Copilot 在 VS Code 里到底怎么联网
很多人误以为 Copilot 是“VS Code 主进程发请求”,所以只要系统代理开了就行。这是错的。
VS Code 是 Electron 应用,进程模型大致分为:
- 主进程(main):窗口、菜单、更新检查;
- 渲染进程(renderer):编辑器 UI;
- 扩展宿主进程(Extension Host / exthost):所有扩展代码运行在这里,Copilot 扩展也在此;
- Copilot Language Server 子进程:Copilot 扩展会再拉起一个独立的语言服务器进程(Node.js 运行时),负责代码补全推理、内联建议、Chat 会话。
关键点:
-
网络请求由 exthost 与 Language Server 发出,它们遵循 Node.js 的
http/https栈,而不是 Chromium 的网络栈。这意味着:- 系统级代理(Windows 的 WinINET、macOS 的 System Configuration)不一定被 Node.js 自动继承;
- Electron 的
session.setProxy只影响渲染进程,不影响 exthost 里的 Node 请求; - 因此必须在 VS Code 设置里显式告诉扩展宿主走哪个代理。
-
Copilot 通信的域名清单(截至当前公开信息):
api.github.com:账号鉴权、订阅状态、Token 校验;api.githubcopilot.com:补全与 Chat 推理主通道(HTTPS/gRPC-Web);copilot-telemetry.githubusercontent.com:遥测信令;github.com:OAuth 设备码流程、登录回调;objects.githubusercontent.com/raw.githubusercontent.com:模型与配置资源。
-
TLS 校验是强校验。Node.js 默认使用内置的 Mozilla CA Bundle,不读取 Windows 证书store,也不读取 macOS Keychain。这就是为什么“浏览器能打开 GitHub,Copilot 却报证书错误”——浏览器信任了企业根证书,Node.js 没有。
理解了这三点,后面的排查才有方向。
二、三大连通性断开根因拆解
根因 A:VS Code 未开启 http.proxySupport,或代理端口被写死为已关闭端口
VS Code 有一个设置叫 http.proxySupport,取值:
"off":扩展宿主完全不走代理;"on":扩展宿主走代理(Copilot 需要这个);"override":强制覆盖,即使扩展自己设置了代理也走 VS Code 的。
默认值在新版本里通常是 "on",但很多企业镜像、旧配置、或用户手动改过 settings.json 后会变成 "off"。此时即使你系统代理开着,Copilot 的 Node 请求也会直连,遇到需要代理才能出网的环境就超时。
另一种常见情况:http.proxy 被写死为 http://127.0.0.1:7890,但本地代理软件早已关闭或换了端口(比如 Clash 换到 7897、V2Ray 换到 10809)。请求发到一个没人监听的端口,表现为 ECONNREFUSED 或长时间挂起。
典型日志特征(Output → GitHub Copilot 或 Developer: Open Logs Folder 里的 exthost.log):
[error] FetchError: request to https://api.githubcopilot.com/... failed,
reason: connect ECONNREFUSED 127.0.0.1:7890
或
[error] net::ERR_PROXY_CONNECTION_FAILED
根因 B:自签名 CA 注入导致 unable to get local issuer certificate
这是企业环境与抓包场景下最高频的根因。
链路是这样的:
- 公司网关/杀毒软件(如 Zscaler、Netskope、卡巴斯基、360)或本地抓包工具(Charles、Fiddler、mitmproxy、Proxyman)会做 TLS 中间人;
- 它们用自签发的根证书动态签发
api.githubcopilot.com的叶子证书; - 浏览器因为系统信任了该根证书,一切正常;
- Node.js 不读系统信任库,只读内置 CA Bundle,于是校验失败。
典型报错:
unable to get local issuer certificate
SELF_SIGNED_CERT_IN_CHAIN
UNABLE_TO_VERIFY_LEAF_SIGNATURE
在 Copilot 输出通道里通常表现为登录成功、但补全请求全部失败,或者 Chat 一直转圈。
验证方法:
openssl s_client -connect api.githubcopilot.com:443 -showcerts </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject
如果 issuer 不是 DigiCert / Sectigo / Let’s Encrypt 等公共 CA,而是你公司名字或 mitmproxy,就坐实了中间人。
根因 C:分流规则漏配核心域名,导致直连超时
使用 Clash、Surge、sing-box 等分流工具时,很多人只把 github.com 加进了代理规则,却漏了:
api.githubcopilot.comcopilot-telemetry.githubusercontent.comapi.github.com*.githubcopilot.com
结果:登录能过(走 github.com 代理),但补全请求走 Direct 直连,被墙或超时。
典型日志特征:
[error] FetchError: request to https://api.githubcopilot.com/... failed,
reason: connect ETIMEDOUT
或 getaddrinfo ENOTFOUND(DNS 污染)。
验证方法:
# 直连测试
curl -v --noproxy '*' https://api.githubcopilot.com --max-time 8
# 走代理测试
curl -v -x http://127.0.0.1:7890 https://api.githubcopilot.com --max-time 8
如果直连超时、走代理 200,就是分流问题。
三、全平台排查修复实操
步骤 0:打开 Copilot 日志
VS Code 命令面板(Ctrl/Cmd + Shift + P)→ Output: Focus on Output View → 右上角下拉选择 GitHub Copilot 与 GitHub Copilot Chat。同时执行 Developer: Open Logs Folder,查看 exthost 目录下的日志。
步骤 1:确认代理端口活着
# macOS / Linux
lsof -iTCP:7890 -sTCP:LISTEN
# Windows PowerShell
netstat -ano | findstr :7890
端口没监听,先修代理软件,别改 VS Code。
步骤 2:配置 settings.json
命令面板 → Preferences: Open User Settings (JSON),加入:
{
"http.proxy": "http://127.0.0.1:7890",
"http.proxySupport": "on",
"http.proxyStrictSSL": true,
"github.copilot.advanced": {
"debug.overrideProxyUrl": "http://127.0.0.1:7890"
}
}
说明:
http.proxySupport: "on"是必须的,否则 exthost 不走代理;http.proxyStrictSSL: true是默认值,不要轻易改成 false,那等于关闭所有扩展的 TLS 校验,安全风险大;github.copilot.advanced.debug.overrideProxyUrl是 Copilot 扩展自己的代理覆盖项,某些版本下比http.proxy更可靠。
如果代理需要认证:
"http.proxy": "http://user:[email protected]:7890"
步骤 3:处理自签名 CA(推荐做法)
正确做法:把企业根证书导出为 PEM,通过 NODE_EXTRA_CA_CERTS 注入。
-
导出根证书:
- Windows:
certmgr.msc→ 受信任的根证书颁发机构 → 找到企业 CA → 导出为 Base64 编码的.cer,改后缀为.pem; - macOS:钥匙串访问 → 系统根证书 → 导出为
.pem; - 抓包工具:Charles 菜单
Help → SSL Proxying → Save Charles Root Certificate。
- Windows:
-
设置环境变量(关键:要让 VS Code 继承):
macOS / Linux(写入 ~/.zshrc 或 ~/.bashrc):
export NODE_EXTRA_CA_CERTS=/path/to/corp-root.pem
Windows(系统环境变量,或 PowerShell 临时):
$env:NODE_EXTRA_CA_CERTS="C:\certs\corp-root.pem"
-
完全退出 VS Code 再重启(不是 Reload Window,是彻底退出进程),否则 exthost 不会重新读取环境变量。
-
验证:
node -e "console.log(process.env.NODE_EXTRA_CA_CERTS)"
步骤 4:临时排障用 NODE_TLS_REJECT_UNAUTHORIZED
仅用于确认“是不是证书问题”,不要长期开启:
# macOS / Linux
export NODE_TLS_REJECT_UNAUTHORIZED=0
# Windows PowerShell
$env:NODE_TLS_REJECT_UNAUTHORIZED="0"
重启 VS Code。如果 Copilot 立刻恢复,说明 100% 是证书链问题,请回到步骤 3 用 NODE_EXTRA_CA_CERTS 正解。
风险提示:NODE_TLS_REJECT_UNAUTHORIZED=0 会让所有 Node 进程(包括 npm、其他扩展)关闭 TLS 校验,等于把中间人攻击的门敞开。生产环境禁用。
步骤 5:分流规则补全
Clash 配置示例(rules 段):
rules:
- DOMAIN-SUFFIX,githubcopilot.com,PROXY
- DOMAIN-SUFFIX,github.com,PROXY
- DOMAIN-SUFFIX,githubusercontent.com,PROXY
- DOMAIN-SUFFIX,githubassets.com,PROXY
sing-box / Surge 同理,关键是 githubcopilot.com 与 githubusercontent.com 必须走代理。
步骤 6:验证连通性
# 1. DNS 解析
nslookup api.githubcopilot.com
# 2. TLS 握手与证书链
openssl s_client -connect api.githubcopilot.com:443 -showcerts </dev/null
# 3. 带代理的完整请求
curl -v -x http://127.0.0.1:7890 https://api.githubcopilot.com --max-time 10
# 4. 不带代理
curl -v --noproxy '*' https://api.githubcopilot.com --max-time 10
步骤 7:重置 Copilot 登录态
如果以上都正常但 Copilot 仍不工作:
- 命令面板 →
GitHub Copilot: Sign Out; - 命令面板 →
Developer: Reload Window; - 重新
GitHub Copilot: Sign In; - 若仍失败,卸载 Copilot 扩展 → 重启 VS Code → 重装。
步骤 8:检查杀毒软件与防火墙
Windows 上 360、火绒、卡巴斯基、Windows Defender 的“HTTPS 扫描”功能会注入证书。临时关闭 HTTPS 扫描测试,若恢复则把 VS Code 与 node.exe 加入白名单,或按步骤 3 注入其根证书。
四、5 个高价值长尾 FAQ
H3:为什么浏览器能正常访问 GitHub,Copilot 却报 unable to get local issuer certificate?
这是最容易被误解的现象。浏览器(Chrome/Edge/Firefox)在 Windows 上读取 Windows Certificate Store,在 macOS 上读取 Keychain,在企业环境里 IT 部门通常已经把公司根证书推送到了系统信任库,所以浏览器看到中间人签发的 api.githubcopilot.com 证书时,能沿着链找到本地信任的根,校验通过。
而 Copilot 的网络请求发生在 VS Code 扩展宿主进程(Node.js 运行时) 里。Node.js 从设计上不读取操作系统信任库,它只使用编译时打包的 Mozilla CA Bundle(crypto.rootCertificates)。企业根证书不在这个 Bundle 里,于是链断在中间,抛出 unable to get local issuer certificate 或 SELF_SIGNED_CERT_IN_CHAIN。
修复的唯一正解是让 Node.js 认识这个根证书:把企业根证书导出为 PEM,设置 NODE_EXTRA_CA_CERTS=/path/to/corp-root.pem,然后彻底退出并重启 VS Code(不是 Reload Window,因为环境变量只在进程启动时读取)。很多人改了环境变量但只做了 Reload,导致误以为方法无效。验证方式是打开 VS Code 内置终端执行 node -e "console.log(process.env.NODE_EXTRA_CA_CERTS)",确认变量确实被继承。如果企业策略不允许导出根证书,退而求其次是在受控网络里让 Copilot 走一条不经过 MITM 的通道,但这通常需要网络管理员配合,而不是在客户端硬关 TLS 校验。
H3:http.proxyStrictSSL: false 和 NODE_TLS_REJECT_UNAUTHORIZED=0 有什么区别?哪个更安全?
两者都会关闭 TLS 证书校验,但作用范围和机制完全不同。
http.proxyStrictSSL: false 是 VS Code 层面的设置,只影响 VS Code 扩展宿主(exthost)通过 http.proxy 发起的请求。它不会影响渲染进程的 Chromium 网络栈,也不会影响你在 VS Code 内置终端里跑的 npm、git、curl。作用面相对窄,但依然意味着 Copilot、其他走 exthost 的扩展(如 GitLens 的远程请求、Live Share)全部失去证书校验,中间人可以透明解密并篡改流量。
NODE_TLS_REJECT_UNAUTHORIZED=0 是 Node.js 运行时级别的环境变量,一旦设置,所有继承该环境变量的 Node 进程都会关闭 TLS 校验——包括 VS Code exthost、Copilot Language Server、你在同一 shell 里跑的 npm install、pnpm、yarn、npx、ts-node、vite 等等。攻击面大得多。更糟的是,很多开发者把它写进 ~/.zshrc 或系统环境变量后忘了删,导致长期裸奔。
结论:两者都不推荐长期使用。正确做法是 NODE_EXTRA_CA_CERTS 注入企业根证书,让校验重新生效。如果只是临时排障,优先用 http.proxyStrictSSL: false(作用面窄),确认问题后立刻改回 true。NODE_TLS_REJECT_UNAUTHORIZED=0 只应在隔离的排障 shell 里临时用一次,用完即弃。
H3:公司网络里 Copilot 登录成功但补全一直转圈,日志显示 ETIMEDOUT 到 api.githubcopilot.com,怎么定位?
登录成功说明 github.com 与 api.github.com 的链路是通的(OAuth 设备码流程走完了),但补全走的是 api.githubcopilot.com,这是两个不同的域名、可能走不同的分流规则。ETIMEDOUT 而不是 ECONNREFUSED 或证书错误,说明 TCP 层就没建立起来——要么 DNS 解析被污染到了黑洞 IP,要么分流规则把 api.githubcopilot.com 判成了 Direct 直连,而直连路径被墙。
定位步骤:
- DNS 层:
nslookup api.githubcopilot.com看返回 IP。如果返回0.0.0.0、127.0.0.1或明显的污染 IP(如31.13.x.x这类 Facebook 段),说明 DNS 被污染。改用 DoH(https://1.1.1.1/dns-query)或在代理工具里开启 fake-ip 模式。 - 分流层:打开 Clash/Surge 的日志面板,搜索
api.githubcopilot.com,看它命中了哪条规则。如果命中DIRECT或MATCH,DIRECT,就是漏配。补上DOMAIN-SUFFIX,githubcopilot.com,PROXY。 - TCP 层:
curl -v --noproxy '*' https://api.githubcopilot.com --max-time 8直连测试,如果超时;再curl -v -x http://127.0.0.1:7890 https://api.githubcopilot.com --max-time 8走代理测试,如果 200,坐实分流问题。 - VS Code 层:确认
http.proxySupport: "on"且http.proxy指向正确端口,否则即使代理工具分流对了,exthost 也不走代理。
一个容易忽略的坑:某些代理工具的规则是按进程而不是按域名分流的(如 Windows 上的 Proxifier 配置),此时 VS Code 的 Code.exe 和 Copilot 的 node.exe 子进程可能命中不同规则。检查进程级规则里是否同时覆盖了这两个可执行文件。
H3:Copilot Language Server 是独立进程,那我改了 settings.json 后为什么有时要重启两次才生效?
因为 Copilot 的网络配置读取发生在两个不同的生命周期节点。
第一层是 VS Code 扩展宿主(exthost):它在启动时读取 settings.json 里的 http.proxy、http.proxySupport、http.proxyStrictSSL,并据此初始化 Node 的全局 agent。改完设置后 Developer: Reload Window 会让 exthost 重启,这一层生效。
第二层是 Copilot Language Server 子进程:它由 Copilot 扩展在激活时 spawn 出来,继承 exthost 的环境变量与部分配置。但某些版本的语言服务器会在自己的配置缓存里保存代理 URL,或者在你登录时把当时的网络配置写进了本地状态文件(位于 ~/.config/Code/User/globalStorage/github.copilot/ 或对应平台的等价路径)。如果只 Reload Window,语言服务器可能被复用而没有重新读取配置。
更麻烦的是 NODE_EXTRA_CA_CERTS 这类环境变量:它只在进程创建时被 Node.js 读取一次。如果你是在 VS Code 已经运行的情况下修改了 shell 的 ~/.zshrc,然后从 Dock 或开始菜单启动 VS Code,VS Code 根本不会继承新变量——因为 GUI 启动的进程不读 shell rc 文件。必须完全退出 VS Code(Cmd+Q / 任务管理器确认无残留进程),再从已经 source 过新环境的终端里用 code . 启动,或者重启系统让环境变量在登录时注入。
所以标准操作是:改 settings.json → Developer: Reload Window → 若涉及环境变量,则完全退出 → 从终端 code . 启动 → 再 Developer: Reload Window 一次。看起来“重启两次”,本质是两层进程各自需要一次生命周期刷新。
H3:企业环境不允许导出根证书,也不允许关闭 TLS 校验,还有别的办法让 Copilot 工作吗?
有,但都需要网络管理员或 IT 部门配合,客户端单方面无解。
方案一:让 Copilot 流量绕过 MITM。企业网关通常对特定域名做 TLS 拦截,对另一些域名做透传。可以让 IT 把 api.githubcopilot.com、copilot-telemetry.githubusercontent.com、api.github.com 加入 SSL Inspection Bypass 列表(Zscaler 叫 SSL Bypass,Palo Alto 叫 Decryption Exclusion)。这样 Copilot 看到的就是 GitHub 的真实证书,Node.js 内置 CA Bundle 能直接校验通过,无需注入任何根证书。这是最干净的方案,但需要 IT 改策略。
方案二:使用企业 PKI 已分发的根证书。很多企业其实已经把根证书推送到了系统信任库,只是没告诉开发者路径。可以让 IT 提供 PEM 格式的根证书文件(不是 .cer 二进制,要 Base64 PEM),放到一个只读路径,然后通过 NODE_EXTRA_CA_CERTS 指向它。这不违反“不允许导出”的策略,因为证书本来就是公开分发给所有终端的。
方案三:走一条不经过企业网关的网络。比如在合规前提下使用企业提供的远程开发环境(VS Code Remote-SSH 到一台在允许出网网段的机器),Copilot 扩展运行在远端,网络请求从远端发出,绕开本地 MITM。这需要企业有对应的开发机资源,且政策允许。
方案四:使用 GitHub Enterprise 自托管实例。如果企业已经部署了 GHES 并配置了 Copilot Business,通信域名会变成企业自己的域名,证书链由企业 PKI 签发,Node.js 通过 NODE_EXTRA_CA_CERTS 注入企业根即可。这是最合规的长期方案,但部署成本高。
绝对不推荐的方案:在客户端硬关 TLS 校验。这会让 Copilot 的 Token、代码片段、Chat 内容全部暴露给中间人,在企业环境里可能直接违反安全合规审计。如果 IT 明确拒绝配合,正确的做法是走内部工单升级,而不是在客户端打补丁绕过。
五、一页速查表
| 现象 | 最可能根因 | 首选修复 |
|---|---|---|
ECONNREFUSED 127.0.0.1:xxxx | 代理端口写错/代理软件没开 | 修 http.proxy 或启动代理 |
unable to get local issuer certificate | 企业/杀软/抓包注入自签 CA | NODE_EXTRA_CA_CERTS 注入根证书 |
ETIMEDOUT 到 api.githubcopilot.com | 分流漏配,直连被墙 | 补 DOMAIN-SUFFIX,githubcopilot.com,PROXY |
| 登录成功但补全全挂 | http.proxySupport: "off" | 改为 "on" 并 Reload |
| 改了设置不生效 | exthost 与 Language Server 双层缓存 | 完全退出 VS Code 后从终端重启 |
| 浏览器正常、Copilot 报证书错 | Node.js 不读系统信任库 | 见上,注入 PEM |
排查顺序建议固定为:日志 → 端口 → 代理设置 → 证书链 → 分流规则 → 登录态。按这个顺序走,90% 的 Copilot 连接问题能在 15 分钟内定位。