curl 网络排障实战:从 DNS 解析到 HTTPS 握手

举报
GGBondHere 发表于 2026/11/02 22:42:47 2026/11/02
【摘要】 介绍使用 curl 排查 HTTPS 连接故障的方法,包括 DNS 解析、TCP 连接、TLS 证书验证、HTTP 状态码、各阶段耗时分析及代理对照测试,帮助快速定位网络问题。

前言

在 Linux 服务器上部署应用时,经常会遇到网站访问超时、接口请求失败或者 HTTPS 连接异常的问题。

这类问题不能简单地归结为“网络不通”。一次 HTTPS 请求通常需要经历域名解析、TCP 连接、TLS 握手和 HTTP 数据传输等阶段,不同阶段失败,对应的排查方向也不一样。

curl 不仅能发送 HTTP 请求,还可以显示连接详情、响应状态和各阶段耗时。下面介绍几个比较实用的排查方法。

一、先发起一次完整请求

首先设置目标域名,后续命令均使用这个变量:

DOMAIN="替换成需要测试的域名"

例如要检查一个 HTTPS 网站,可以执行:

curl -v --connect-timeout 5 --max-time 15 "https://$DOMAIN/"

其中:

  • -v:显示详细连接信息。
  • --connect-timeout 5:限制建立连接阶段的等待时间。
  • --max-time 15:限制整个请求允许的最长时间。

在输出中可以看到 curl 使用的 IP 地址、连接过程、TLS 相关信息以及 HTTP 响应头。

如果遇到错误,先观察失败发生在哪个阶段,不要直接判断为服务器故障。

二、排查 DNS 解析问题

如果出现:

Could not resolve host

通常表示 curl 没有成功解析目标主机名。

可以先用系统命令查看解析情况:

getent ahosts "$DOMAIN"

在支持该命令的 Linux 系统中,它可以通过系统名称解析机制查询主机地址。

如果解析失败,可以检查:

  1. 域名是否输入正确。
  2. 系统使用了哪个 DNS 解析服务。
  3. DNS 服务器是否能够访问。
  4. 是否存在本地解析配置问题。

还要注意,DNS 解析成功只能说明获得了地址,并不能证明目标服务器能够建立 TCP 连接。

三、检查 TCP 连接

如果已经解析到了 IP,但连接依然失败,可以关注 curl 的错误信息。

例如:

Failed to connect
Connection refused

Connection refused 通常表示目标地址没有接受此次 TCP 连接,可能是服务没有监听对应端口,也可能是防火墙主动拒绝。

如果一直超时,则可能涉及网络路由、防火墙丢弃、服务器不可达等问题。

可以指定 IPv4 或 IPv6 进行对比:

curl -4 -v --connect-timeout 5 "https://$DOMAIN/"
curl -6 -v --connect-timeout 5 "https://$DOMAIN/"

如果 IPv4 正常、IPv6 失败,就应该进一步检查 AAAA 记录、IPv6 路由及服务监听情况。

不过,不能仅凭一次连接失败就断定是哪台网络设备造成的,需要结合具体报错和网络环境判断。

四、排查 TLS 握手和证书问题

HTTPS 在建立 TCP 连接后,还需要进行 TLS 握手。

如果出现:

SSL certificate problem

就需要检查证书链、证书有效期、系统信任的 CA,以及访问域名是否与证书匹配。

另一个常见问题是使用 IP 地址直接访问 HTTPS 网站。

对于使用虚拟主机的网站,直接访问 IP 可能无法匹配正确的域名、SNI 或证书。

如果想指定连接的目标 IP,同时保留正常的域名访问方式,可以使用:

IP="替换成目标服务器IP"

curl -v --resolve "$DOMAIN:443:$IP" "https://$DOMAIN/"

--resolve 会为指定的主机名和端口提供临时地址映射。这对于排查 DNS 解析结果异常、测试不同服务器入口非常方便。

需要注意,它改变的是连接目标地址,并不会自动忽略 HTTPS 证书验证。

有些教程会使用 -k 跳过证书检查,但这样会降低连接安全性。生产环境不应把关闭证书验证当作正常解决方案。

五、查看 HTTP 状态码

如果 DNS、TCP 和 TLS 阶段都成功了,还需要检查应用层返回了什么。

可以执行:

curl -sS -o /dev/null -w 'HTTP状态码: %{http_code}\n' "https://$DOMAIN/"

其中:

  • -sS:减少普通进度信息,同时保留错误提示。
  • -o /dev/null:不在终端输出响应正文。
  • -w:自定义请求完成后的统计信息。

常见 HTTP 状态码包括:

状态码 常见含义
200 请求成功
301 / 302 请求被重定向
403 服务器拒绝访问
404 请求的资源不存在
500 服务器发生内部错误
502 网关收到了无效的上游响应
504 网关等待上游响应超时

需要注意,返回 403 或 404 并不代表网络没有连接成功。它们说明已经获得了 HTTP 响应,只是请求没有得到预期结果。

另外,如果 curl 在收到 HTTP 响应前就失败,状态码可能显示为 000,这不是正式的 HTTP 状态码。

六、查看请求各阶段耗时

curl 的 -w 功能还可以用于分析请求慢在哪个阶段。

例如:

curl -sS -o /dev/null \
  -w 'DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\n首字节: %{time_starttransfer}s\n总耗时: %{time_total}s\n' \
  "https://$DOMAIN/"

这些字段的含义分别为:

  • time_namelookup:从请求开始到名称解析完成的耗时。
  • time_connect:从开始到 TCP 连接建立完成的累计耗时。
  • time_appconnect:从开始到 TLS 等应用层握手完成的累计耗时。
  • time_starttransfer:从开始到收到第一个响应字节的累计耗时。
  • time_total:整个请求的总耗时。

这里有一个容易理解错的地方:这些时间大多是从请求开始计算的累计值,并不是各阶段独立耗时。

例如,想计算 TCP 连接阶段的近似耗时,可以用 time_connect 减去 time_namelookup。

想估算 TLS 握手耗时,可以用 time_appconnect 减去 time_connect。

如果通过 HTTP 代理访问,这些计时值还可能包含代理连接相关操作,不能直接当作客户端到最终目标服务器的独立网络延迟。

七、检查是不是代理影响了请求

服务器或终端中如果设置了代理环境变量,curl 可能会自动使用这些代理。

可以先查看:

env | grep -i proxy

如果希望临时绕过代理进行对照测试,可以使用:

curl --noproxy '*' -v "https://$DOMAIN/"

这样可以帮助区分代理连接问题和直连问题。

不过,--noproxy 只影响 curl 自身的代理选择,无法绕过系统网络层已经存在的透明代理或其他转发规则。

如果直连正常、使用代理失败,就应进一步检查代理服务器、认证和转发配置。

八、一个简单的排查顺序

遇到 HTTPS 请求失败时,可以按下面的顺序排查:

第一步,使用 curl -v 查看具体报错,判断是否已经解析到目标 IP。

第二步,如果解析失败,检查 DNS 配置;如果解析成功但连接失败,检查 TCP 连接及防火墙。

第三步,如果 TCP 已连接但 HTTPS 失败,重点检查 TLS 握手、SNI 和证书。

第四步,如果已经收到 HTTP 响应,就根据状态码和服务器日志排查应用层问题。

最后,如果只是访问慢而不是完全失败,可以使用 -w 查看各阶段累计耗时,进一步缩小排查范围。

总结

curl 不只是一个下载工具,也非常适合排查 Linux 服务器上的网络连接问题。

最常用的几个参数包括:

  • -v:显示详细连接信息。
  • -4、-6:分别测试 IPv4 和 IPv6。
  • --resolve:指定域名对应的连接地址。
  • --connect-timeout:限制建立连接的等待时间。
  • -w:输出状态码和请求耗时。
  • --noproxy:临时排除代理干扰。

实际排障时,最重要的不是一次执行多少命令,而是先判断失败发生在 DNS、TCP、TLS 还是 HTTP 阶段,再针对对应环节检查。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。