VPN 已连上,内部维基在浏览器里正常打开,而 apt update 仍然卡在它访问不到的镜像上。这幅画面里隧道本身没有任何问题。浏览器和包管理器做出了 两个彼此独立的代理决定,而只有其中一个被配置过。

先确定是哪一步决定失败了,这才是唯一值得查的事。

改设置之前先读错误信息

每个环节留下的信息各不相同。名字始终解析不出来是 DNS,连接始终建立不起来是路由或防火墙,立刻返回 407 是代理认证,报证书问题是 TLS 验证,而签名警告则是仓库元数据。这五种故障要五种不同的修法,把一行代理配置盖在 DNS 问题上只会把卡顿挪个位置。

动手之前先复制那行原文和它点名的仓库。「当时超时了」这种模糊印象,正是把十分钟的诊断拖成一整天的原因。

APT 有自己的代理设置

APT 读取 /etc/apt/apt.conf.d/、主 apt.conf,以及 APT_CONFIG 指定的任何文件。它不读桌面代理配置、GNOME 网络设置或浏览器扩展。传输层确实会遵守代理环境变量,所以你在 shell 里能用的 export https_proxy=... 并不能说明那个在别的环境里运行的定时任务。

导出失败进程实际看到的内容:apt-config dump | grep -i proxy。

要用失败操作所运行的那个用户来执行。如果 root 读到的是另一组文件,或者 systemd 定时任务以另一套环境启动,导出结果就会不同,而这个差异就是答案。两个互相矛盾的代理值,比一个缺失的值更糟,因为传输层会采用它能找到的最具体的那条匹配。

把代理设在配置主人期望的位置

对于管理员批准的显式代理,在新文件里写一小段就够:

Acquire::http::Proxy "http://proxy.corp.example:3128/";
Acquire::https::Proxy "http://proxy.corp.example:3128/";
Acquire::http::Proxy::archive.example.internal "DIRECT";

第三行是大多数示例都略去的部分。按主机设置的键会覆盖通用值,因此可经隧道访问的内部镜像可以绕过代理,而其他流量依旧走它。DIRECT 是这件事的官方取值,而不是空字符串。

把这段作为新的编号文件加入,例如 /etc/apt/apt.conf.d/95proxy。覆盖发行版自带的文件意味着下一次包更新会悄悄把你的改动还原。

凭据不要写进 URI

APT 传输层参考文档在认证上指向 apt_auth.conf,用户名和密码就该放在那里。把它们塞进代理 URI,就会出现在进程列表、shell 历史,以及每一份贴进工单的配置导出里。认证文件需要严格权限,因为它是凭据存储。

也要检查 scheme。HTTPS 仓库依然可以经由 HTTP 代理访问;传输层与镜像的 URI scheme 是两回事。

图形软件中心是另一个前端。如果它用的是 PackageKit 或 snap 后端,APT 那段配置对它毫无作用,所以要确认失败请求是哪个进程发出的。

确认走的是哪条路径,而不只是退出码

配好之后要观察请求本身,别只信一个绿色的结果。apt-get -o Debug::Acquire::http=true update 会打印连接尝试、它选中的代理以及响应码,正好把「代理错了」和「代理拒绝了你」分开。

然后测那个本不该成功的场景。断开 VPN,确认内部镜像不再应答;如果它还在下载,那就是有东西绕过隧道,或者旧缓存在给你供数。确认允许的路径仍然验证 TLS、仍然校验仓库签名,因为代理检查流量并不是关掉这两件事的理由。也要确认未认证的客户端拿到的是明确的拒绝,而不是一声不响地超时。

把能用的那段配置和失败时的输出一起留在变更记录里。下一个撞上同样卡顿的人,会比看任何解释都更快认出那两行的差别。

相关文章