用 curl --resolve 验证 HTTPS,同时保留 Host、SNI 与证书校验

09-30 7阅读

迁移网站时,经常需要先验证新服务器,再决定是否切换 DNS。直接请求 HTTPS IP 并添加 Host 请求头,容易碰到证书或虚拟主机不匹配。对于自己管理的域名,可以使用 --resolve 给当前 curl 请求指定解析结果,同时保留 URL 中的域名。本文使用 POSIX shell 写法,示例域名和 192.0.2.10 文档地址都必须替换。

为什么只改 Host 还不够

用 curl --resolve 验证 HTTPS,同时保留 Host、SNI 与证书校验

图:--resolve 为本次请求指定连接目标,URL 中的域名仍用于 Host、SNI 与证书名称校验;示例地址仅用于说明。

HTTP Host 用于选择站点,TLS 握手中的 SNI 则帮助服务器选择证书。curl 从 URL 获取 SNI 名称,证书也要与 URL 中的服务器名称匹配。因此,测试域名服务时,URL 应保留真实域名,连接 IP 通过 --resolve 指定。相关行为见 curl 官方名称解析说明。

先保留一份正常解析的结果

选一个已知只读、不会产生业务副作用的接口。在 Linux 或 macOS 中先执行:

curl --connect-timeout 5 --max-time 15 -sS \
  -D - -o /dev/null \
  -w '\nremote_ip=%{remote_ip} http_code=%{http_code} total=%{time_total}s\n' \
  https://api.example.com/health

命令发送 GET,打印响应头和概要,丢弃正文;它没有使用 HEAD,避免服务对两种方法处理不同。连接最多等待 5 秒,整次操作最多 15 秒。先记录状态码、响应中的应用标识和连接地址;单次耗时只适合对照排查,不能当成性能基准。

再固定目标 IP 做对照

curl --resolve 'api.example.com:443:192.0.2.10' \
  --connect-timeout 5 --max-time 15 -sS \
  -D - -o /dev/null \
  -w '\nremote_ip=%{remote_ip} http_code=%{http_code} total=%{time_total}s\n' \
  https://api.example.com/health

映射按“域名与端口”精确匹配,仅写 80 无法覆盖 HTTPS 的 443。这条命令不会修改系统 hosts 或权威 DNS。若环境使用 HTTP、HTTPS 或 SOCKS 代理,解析和连接路径可能由代理决定,remote_ip 也可能是代理地址;先确认网络路径,在组织允许直连的环境中测试,不要把代理地址误判成源站。

建议提前写下验收条件,例如预期状态码、响应正文中的版本号,以及应该出现的安全响应头。示例丢弃了正文,需要核验内容时可去掉 -o /dev/null。不要用登录、支付或发信接口反复试探,也不要把生产令牌写进公开命令示例。

让失败保留诊断价值

证书校验失败时,应检查域名覆盖范围、有效期、服务端证书链和本机信任配置。使用内部 CA 时,可在可信渠道核验 CA 后为该次请求添加 --cacert /path/to/internal-ca.pem。不要用 -k 把失败掩盖成验收通过。

默认情况下,curl 成功接收 HTTP 404 或 500 也可能以退出码 0 结束,所以要同时检查 HTTP 状态和响应内容。遇到 301、302 等跳转,先看 Location;示例没有自动跟随跳转,新增目标域名也需要单独检查。必要时临时加 -v 观察握手,但分享输出前要移除 Cookie、Authorization 和其他敏感信息。

定向请求成功,只能证明这条客户端到目标服务器的路径可用。正式切换后,还要按正常 DNS 解析复测,并检查应用依赖、缓存及不同网络的访问结果。

官方参考

文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。