用GitHub 的人,几乎都撞到过这样一幕:git push正推得起劲,屏幕上突然砸下来一行红色报错,大意是fatal: unable to access 'https://github.com/xxx/xxx.git/': Failed to connect to github.com port 443: Connection refused。第一次遇到的人多少有点慌,以为是自己的代码仓库没了,或者是电脑坏了。其实都不用慌,443 这个报错在 GitHub 的使用过程中实在太常见了,它往往不是你仓库的问题,而是你的网络到 GitHub 服务器之间某个环节出了问题。
443 是 HTTPS 默认的服务端口,GitHub 的网页、API、HTTPS 方式克隆和推送全都走这个端口。换句话说,只要这个端口上的 TCP 连接建不起来,或者建起来之后 TLS 握手失败,你看到的就是各种各样的 443 报错。这篇文章我会把手头积累的排查经验拆开讲:报错到底卡在哪一层、先用哪几条命令定位、常见的几个坑在哪里、最后再给你一套可以照着做的处理顺序。不管你是刚碰 GitHub 的新手,还是已经被 443 折磨过几次的老手,按着这篇文章走,至少能让你在下一次遇到报错的时候,不至于对着屏幕干瞪眼。
1. 先别急着改配置,443 报错到底卡在哪一层
1.1 443 不是玄学,它是 HTTPS 的默认大门
很多同学一看到 443 就头大,下意识觉得是"网络被墙了"或者"服务器挂了"。其实 443 这个数字本身只是一个端口号,就像一台服务器开了一扇门,HTTPS 请求都得从这扇门进去。你的电脑要和 GitHub 通信,需要完成这样几步:先通过 DNS 查到 GitHub 服务器的 IP 地址,然后从你的电脑到这个 IP 的 443 端口建立一条 TCP 连接,连接建立之后再做 TLS 加密握手,最后才传输 HTTP 数据。
这四步里任何一步出问题,你看到的报错文案都会不一样。有的是Connection refused,说明连接被直接拒绝了;有的是Connection timed out,说明数据包发出去了但一直没回应;还有的是SSL connect error,说明 TCP 连上了,但加密握手没谈拢。理解了这一层,你就知道为什么网上那么多"解决办法"有些对你有效、有些完全没用——因为你们卡住的层可能根本不一样。
1.2 三种常见报错形态,对应三种不同的故障层
我整理了实际工作中最常碰到的三类 443 报错,以及它们背后的含义:
| 报错特征 | 问题大概率出在 |
|---|---|
Failed to connect to github.com port 443: Connection refused | 本地出口到 GitHub 443 端口的链路不通,或者本地网络设备把请求拦了 |
Failed to connect to github.com port 443: Connection timed out | 网络寻址或路由质量差,DNS 解析异常、网络延迟过高都有可能导致 |
SSL connect error或OpenSSL SSL_read: Connection reset by peer, errno 104 | TCP 能连上,但 TLS 握手阶段失败,常见于证书链、系统时间、HTTP/2 协议等问题 |
你可以把这三类理解成寄快递的三个环节:第一类是快递柜的柜门坏了,根本投不进去;第二类是快递员找不到地址,在楼下绕圈;第三类是快递柜门能开,但你填的收件人信息和柜子里的标签对不上。这三种情况对应的处理方式完全不同,所以拿到报错先看一眼它属于哪一种,比直接搜"终极解决办法"要高效得多。
1.3 排查心法:本地优先、简单优先、验证优先
我踩过无数次坑之后总结出来的排查顺序很简单:先换网络,再查本地,最后才动配置。很多人一上来就改 Git 的全局配置,或者折腾 hosts 文件,结果问题不但没解决,反而把原本好用的环境改乱了。
正确的打开方式是:先用自己的手机热点试一次,如果热点能通,说明你当前所在网络的出口有问题;如果热点也不通,再看是不是本地 DNS、Git 配置、SSL 证书这些环节。每做一步修改,就重新跑一次最简单的访问命令来验证,比如curl -I https://github.com。一次只改一个变量,改了立刻验证,这是排查网络问题最不容易把自己绕晕的方法。
2. 3 分钟自查清单:先跑这几条命令再动手
2.1 用 curl 验证最原始的 HTTPS 链路是否通畅
不管报错文案多花哨,第一步我都建议先做一次最干净的 HTTPS 请求测试。打开终端,执行:
curl -I https://github.com你可能会看到两种结果。一种是HTTP/2 200或者HTTP/1.1 200 OK之类的响应,说明你的网络到 GitHub 443 端口是通的,问题大概率出在 Git 客户端的配置或者具体仓库的 URL 上。另一种是直接超时、拒绝连接,或者证书报错,那就说明问题在更基础的网络层。
这一步看起来简单,但意义很大。因为它绕开了 Git 的所有配置,直接用系统自带的网络工具去访问 GitHub。如果 curl 都通不了,那改 Git 配置是没用的;如果 curl 是通的,你再回头看 Git 的报错,方向就完全不一样了。
2.2 用 git 命令定位到具体仓库的访问链路
curl 通过之后,再用 Git 自己测一次远程仓库的连通性。比如你有一个仓库地址是https://github.com/某用户/某项目.git,执行:
git ls-remote https://github.com/某用户/某项目.git这个命令的作用是列出远程仓库的分支引用,整个过程会走一次真实的 HTTPS 访问,但不修改你本地任何文件。如果它能列出refs/heads/main之类的内容,说明 Git 走 HTTPS 访问仓库的能力是正常的,后面 push 或 clone 报错的原因就要往具体仓库目录、本地 .git 状态、大文件传输这些方向去想。如果这个命令也报 443,那就继续往下排查。
2.3 端口探测与网络切换对比
做完上面两步,再做一个端口级的探测,确认 443 端口连通性:
nc -vz github.com 443如果系统没有nc,可以用telnet github.com 443,连上之后屏幕上会提示连接成功,直接输入quit退出。这一步能验证 TCP 层是否通,和 curl 的区别在于它不发送 HTTPS 请求,只看端口能不能连。
拿到结果之后,再做一次"换网络"的对比测试。用手机开热点,让电脑连上热点后再跑一遍curl -I https://github.com。如果热点能通,那就是你所在网络环境的出口问题;如果热点也不通,可以把嫌疑范围锁定在本地设备本身。这一步几乎不花时间,但能帮你砍掉一半的排查方向。
3. DNS 解析异常:九成 443 报错的隐形元凶
3.1 为什么 DNS 问题会被误认为"网络断了"
我处理过的 443 报错里,十次有七八次最后都指向 DNS 解析异常。DNS 的作用是把github.com这样的域名翻译成服务器实际的 IP 地址。如果解析出来的 IP 是不存在的、过期很久的,或者解析本身就超时,那你的请求根本找不到 GitHub 的门在哪,表现就是连接超时。
这里有个特别坑的地方:网上很多东西会告诉你"GitHub 某个 IP 永远能用",然后让你直接写进 hosts 文件里。但 GitHub 的 IP 不是一成不变的,不同地区、不同时间的解析结果可能都不一样。你照抄了一个别人几个月前的 IP,当时可能有效,现在可能已经失效了,反而会让问题更加扑朔迷离。所以遇到 443,第一件事不是看网上的教程,而是先看你本地到底把 GitHub 解析到了哪个 IP。
执行:
nslookup github.com或者:
ping github.com要注意,ping走的是 ICMP 协议,和 HTTPS 的 443 端口不是一回事。有些环境下ping能通但 443 端口不通,也有反过来ping不通但 curl 正常的情况。所以ping只能作为参考,别把它当成唯一标准。真正要看的是nslookup返回的 IP 地址列表,以及解析耗时。
3.2 三步紧急修复:取 IP、写 hosts、清缓存
如果确认 DNS 解析出来的结果有问题,可以按下面三步做紧急处理:
第一步,通过多个公开的解析渠道查询 GitHub 当前可用的 IP。直接用你本地默认的 DNS 查一次,再用公共 DNS 的地址解析一次,对比一下结果是不是一样。公共解析服务可以用223.5.5.5或者119.29.29.29,这些在国内访问都比较快。如果不同渠道查出来的 IP 差异很大,说明本地 DNS 缓存或者运营商 DNS 可能存在问题。
第二步,把你确认能用的 IP 写进系统 hosts 文件,绕过 DNS 解析的过程。hosts 文件的路径在 Windows 是C:\Windows\System32\drivers\etc\hosts,在 macOS 和 Linux 是/etc/hosts。写入的格式是 IP 地址在前、域名在后,中间用空格隔开,一行一个域名。建议把github.com和www.github.com都写上,示例:
140.82.112.3 github.com 140.82.112.3 www.github.com注意,上面 IP 只是格式示例,千万不要照抄,一定要用你自己查询确认过的结果。不同网络环境下能用的 IP 可能完全不同,照抄旧 IP 是我见过最多人踩的坑。
第三步,刷新本地 DNS 缓存,让 hosts 文件的修改立即生效。Windows 执行ipconfig /flushdns,macOS 执行sudo dscacheutil -flushcache,Linux 上不同发行版命令不一样,常见的是sudo systemd-resolve --flush-caches,如果提示命令不存在,可以尝试sudo resolvectl flush-caches。
3.3 hosts 文件怎么维护才不会越修越乱
hosts 文件是个好东西,但它也是一把双刃剑。我见过很多人的 hosts 文件里堆了十几个"网上找到的 GitHub IP",五花八门,有的早就不通了,还夹杂着各种注释,看都看不懂。这种文件不但解决不了问题,反而会干扰后续排查。
维护 hosts 文件就记住三个原则。第一,写清楚注释,每一行后面用#注明是什么时候、因为什么原因加进去的,比如140.82.112.3 github.com # 2024-06-01 备用。第二,保持精简,只写真正需要的域名,不要一口气加几十个。第三,定时复查,过一段时间就删掉 hosts 里的 GitHub 相关行,重新走一遍正常 DNS 解析,如果已经恢复正常,就不要再保留这些人为指定了。
3.4 更省心的长期方案:切换公共 DNS
如果频繁出现 DNS 解析异常,我的建议是从根上换掉本地默认的 DNS 设置。很多人用的是运营商自动分配的上网 DNS,解析速度和质量不一定好。可以在系统网络设置里手动指定一组公共 DNS 地址,比如223.5.5.5和119.29.29.29。
切换之后记得再跑一遍curl -I https://github.com验证效果。如果解析恢复正常,说明问题确实出在默认 DNS 上。这种方式比维护 hosts 文件更省心,因为 DNS 服务器会自动更新解析记录,你不用手动追踪 IP 的变化。我自己的电脑长期就是用手动指定的公共 DNS,遇到 GitHub 443 的概率明显下降。
4. Git 自身配置与 TLS 层问题:连上了却握不上手
4.1 检查 Git 历史遗留的全局配置
很多时候你的网络是通的,curl 也正常,但 Git 一跑就报 443 错。这时候就要怀疑 Git 自己的配置是不是有问题。执行:
git config --global --list把输出内容看一遍,重点看有没有http.开头的配置项。如果你从来没有手动配过这些项,这里应该是空的。一旦看到很多http.开头的自定义项,就要想想是不是之前为了某个特定场景手动设置过,比如调整过 SSL 校验方式,或者设置过转发的网关参数。这些配置在当前网络环境下可能已经失效,反而成了阻碍。
处理的方法是先备份,再逐项删除可疑项。备份可以直接把~/.gitconfig文件复制一份到别的地方,然后针对可疑项执行:
git config --global --unset 配置项名称每删一项就跑一次git ls-remote验证,直到恢复通畅。这里我特别想提醒一句:不要为了图省事,把整个.gitconfig删掉重来,因为你里面可能还留着用户名、邮箱、别名等有用的设置,删了之后一堆东西要重新配。
4.2 SSL 证书验证失败:三查时间、证书链、Git 版本
如果报错信息里带SSL certificate problem或者SSL connect error,那问题就从"连不上"变成了"握不上手"。SSL/TLS 握手的时候,你的电脑会验证 GitHub 服务器的证书是不是合法、是不是过期、签发链是不是完整。这一关挂掉,常见原因有三个。
第一个是系统时间不对。证书的有效期是限定的,如果你的电脑时间比真实时间偏了好几天,证书验证就会直接失败。这种问题在电脑长期休眠、主板电池没电的机器上特别常见。打开系统设置看一眼时间,校对一下再试。
第二个是证书链不完整。有些企业内网或者特殊环境下,系统里缺少必要的根证书,导致 GitHub 的证书链验证不通过。这种情况可以检查一下系统是否更新了最新的根证书包,macOS 用户看看"钥匙串访问"里有没有对应的证书,Windows 用户检查一下系统更新。
第三个是 Git 版本太旧,旧版本的 Git 内置的证书库可能不识别新的证书签发方。执行git --version看看版本号,如果版本比较老,建议直接升级到新版本。
这里有一条红线要划清楚:网上很多人遇到 SSL 证书报错就直接建议git config --global http.sslVerify false关掉验证,我强烈不建议这么干。关掉验证意味着你不再确认对方服务器的身份,中间有任何设备伪造证书你都不知情,这在安全性上是把自己完全暴露了。关验证只能作为临时测试手段,测完一定要恢复。
4.3 HTTP/2 协议惹的祸:一条配置切换回 HTTP/1.1
Git 在较新版本里默认使用 HTTP/2 协议和服务器通信。HTTP/2 本身效率更高,但它在某些网络设备、防火墙或者旧版 Git 的组合下,会出现一个很经典的问题:连接能建立,请求也发出去了,但服务器返回数据的一瞬间,连接被重置,报错东西类似OpenSSL SSL_read: Connection reset by peer, errno 104。
遇到这种报错,可以先怀疑是 HTTP/2 协商出了问题。把 Git 的 HTTP 协议版本强制切回 HTTP/1.1:
git config --global http.version HTTP/1.1这是个很安全的配置改动,它只是让 Git 用老版本的 HTTP 协议,不涉及任何安全风险。改完之后重新跑一次git ls-remote,大概率能看到报错消失。等确认没问题之后,可以留着这个配置,它对你的日常操作几乎没影响,只是少了一点点性能优势。
4.4 大仓库推送失败:postBuffer 与超时参数的调优
443 报错还有一种典型场景,不是连不上,而是传着传着就断了。尤其是推大仓库、传大文件的时候,报错信息里经常带RPC failed; curl 18 transfer closed with outstanding read data remaining。这往往是因为 Git 默认的 HTTP 缓冲区不够大,或者网络稍有延迟就超时。
针对这类问题,有两个参数很管用。一个是调大 HTTP 缓冲:
git config --global http.postBuffer 524288000这个值的单位是字节,524288000 就是 500MB。原理是让 Git 在上传大对象时分块更从容,避免一次发送太多数据被网络设备掐断。另一个是放宽低速限制:
git config --global http.lowSpeedLimit 0 git config --global http.lowSpeedTime 999999Git 默认在传输速度低于某个阈值并持续一段时间后,会主动断开连接。上面这两条配置相当于告诉 Git"别因为慢就掐断我",在弱网环境下尤其有效。不过要注意,这些只是权衡方案,如果你要推的仓库有好几个 GB,更好的做法是考虑用 SSH 通道,或者把大文件交给专门的大文件存储方案,而不是让 Git 硬扛。
5. 走备线:SSH 443 端口与仓库自救方案
5.1 用官方支持的 SSH 443 通道作为备选接入
如果 HTTPS 的 443 端口在当前网络环境下怎么都不通,还有一条官方支持的备选接入方式:用 SSH 协议走 443 端口。默认情况下 SSH 走 22 端口,但 GitHub 官方提供了一个特殊的 SSH 服务地址ssh.github.com,专门监听 443 端口。
先测试一下这条通道通不通:
ssh -T -p 443 git@ssh.github.com如果返回Hi 用户名! You've successfully authenticated,说明这条通道可用。接下来把它写进 SSH 配置文件,让以后访问 GitHub 都走这条线路。编辑~/.ssh/config,加入这样一段:
Host github.com HostName ssh.github.com Port 443 User git保存之后,测试一下正常的 SSH 连接:
ssh -T git@github.com同样能收到成功的提示,就说明配置生效了。之后你把远程仓库地址改成 SSH 格式,比如git@github.com:某用户/某项目.git,就能在这个网络环境下顺畅推拉。这里要提醒一句:使用 SSH 需要你提前在 GitHub 账号里配置过公钥,如果没配过,得先去生成密钥对、把公钥添加到账号里,这部分内容 GitHub 官方文档写得很清楚。
5.2 浅克隆与大仓库断续拉取技巧
还有一种经常被忽略的自救方案,是针对"仓库太大、历史太深导致 443 拉取失败"的场景。当你 clone 一个超大仓库时,Git 要下载全部历史对象,一旦中间断网或超时,整个克隆就失败了。这时候可以改用"浅克隆",先只拉最近一次提交:
git clone --depth 1 https://github.com/某用户/某项目.git浅克隆之后,仓库体积会小很多,网络压力也小很多。如果你后续需要完整历史,可以再手动加深历史:
git fetch --unshallow如果仓库实在太大,--unshallow也会很吃力,那就按需加深,比如把历史加深到最近 20 次提交:
git fetch --depth 20这个思路的核心是"先让自己能干活,再去补齐历史",而不是一次拉到位。我遇到超大仓库的 443 超时,几乎都是用这套方法救回来的。
5.3 .git 目录异常自救:锁文件与对象损坏
有时候 443 报错只是表象,真正的根因在本地.git目录已经处于一个不健康的状态。最常见的两种情况是存在锁文件和对象损坏。
如果你执行 Git 命令时提示Unable to create '.git/index.lock': File exists,说明上一次 Git 操作异常中断,留下了一个锁文件。处理方式是在确定没有其他 Git 进程运行的前提下,手动删除这个文件:
rm .git/index.lock注意,一定要确认没有正在跑的 Git 进程才删,否则可能损坏仓库状态。另一种情况是提示对象损坏或者.git/objects里的文件不完整,可以先运行完整性检查:
git fsck --full如果报告有损坏对象,而且你本地有未推送的提交,先想办法把提交备份出来。如果没有未推送的重要提交,最省事的办法是从远端重新拉一份干净的副本,把本地有问题的目录删掉重来。不要试图手动去改.git/objects里面的文件,那是拿着手术刀给心脏做手术,风险远大于收益。
6. 常见问题速查表与我的踩坑记录
6.1 一张表搞定常见 443 报错场景
为了让你以后遇到问题能对号入座,我把常见场景整理成一张速查表:
| 报错特征 | 最可能原因 | 第一步动作 |
|---|---|---|
Failed to connect to github.com port 443: Connection refused | 本地到 443 端口链路不通 | 换手机热点测试,再查 hosts 与 Git 配置 |
Failed to connect to github.com port 443: Connection timed out | DNS 解析异常或网络质量差 | 刷新 DNS 缓存,切换公共 DNS,对比多个解析结果 |
SSL connect error或certificate verify failed | TLS 握手阶段失败 | 检查系统时间、证书链、Git 版本 |
OpenSSL SSL_read: Connection reset by peer, errno 104 | HTTP/2 协商被网络设备重置 | 设置http.version HTTP/1.1后重试 |
RPC failed; curl 18 transfer closed | 大仓库传输超时或被中断 | 调大http.postBuffer,放宽低速限制 |
unable to access ... 403 | 仓库不存在或权限不足 | 检查仓库 URL、账号权限、凭据是否正确 |
这张表覆盖了我日常排障中九成以上的情况。真正需要花时间深挖的,往往是那些做了三四项测试还找不到问题所在的个例,那时候就需要结合系统日志和抓包工具再分析了。
6.2 我踩过的三个坑:DNS 缓存、配置残留、IP 过期
第一个坑是刚改完 hosts 文件就以为万事大吉,结果忘了刷新 DNS 缓存,导致实测还是旧 IP。后来我养成了习惯,每次改完 hosts 立即执行刷新命令,然后重新跑 curl 验证,再往下推进。
第二个坑是 Git 全局配置里的残留项。有一阵子我的 Git 访问特别诡异,同一个仓库有时候能连有时候不能连,折腾了半天才发现是早期为了某次测试手动加过几个http.开头的参数,一直没清理。那次之后我给自己立了条规矩:每过几个月看一眼git config --global --list,但凡看到不认识的参数,问一句"这个参数是怎么来的、现在还需要吗",不然就删。
第三个坑是照着网上的"万能 IP"写 hosts。有一回我复制了一组网上流传的 GitHub IP,当时确实通了,但过了一段时间又不行了,排查之后发现那组 IP 早就变了。现在我宁可让正常 DNS 去解析,也尽量少碰 hosts 文件,除非真的走投无路,而且每次用之前都必须自己多渠道验证。我的一点小建议是:在使用别人的方案前,先想清楚它解决的是 DNS 层、TLS 层还是 Git 配置层的问题,对症下药,才是最快的路径。
6.3 给团队的一键自查方案
如果是团队协作时有人频繁遇到 443 报错,我的建议是把上面这些排查步骤整理成一段简单脚本,放到团队的共享文档里。脚本的核心内容是跑几条命令、给出判断建议,让新手也能照着做。
echo "== 1. 测试 HTTPS 基础链路 ==" curl -I https://github.com echo "== 2. 查看 GitHub 当前解析 IP ==" nslookup github.com echo "== 3. 查看 Git 全局配置中的 http 相关项 ==" git config --global --get-regexp '^http\.' echo "== 4. 测试 SSH 443 备线 ==" ssh -T -p 443 git@ssh.github.com让遇到问题的人先跑一遍这段脚本,把输出贴回来,有经验的人一看就能判断问题在哪一层,不用再隔着屏幕反复问"你报错信息是什么"。
写到现在,我想把整个排查思路浓缩成一句我自己的操作准则:遇到 443 报错,先做链路验证,再查 DNS 解析,最后动 Git 配置。这三步不会让你踩太多弯路。一次解决不了就换网络再验一次,很多时候"重启一下手机热点""换一个 DNS"就能解决,根本不用上升到"改什么高级配置"的程度。这些方法看似基础,但恰恰是它们帮我处理了绝大多数 GitHub 访问问题,希望你也能用上。