DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

curl --resolve 指定 8443 后仍连接 443 端口

--resolve 中的端口用于匹配 URL,不会重定向连接端口。区分替换 IP、访问非默认 HTTPS 端口和使用 --connect-to 映射后端端口,并核对 TLS 与实际连接目标。

想把 HTTPS 请求发到某台服务器的 8443 端口,命令却仍然连接 443,甚至连 IP 都没有换成指定值:

curl --resolve example.com:8443:192.0.2.10 https://example.com/

这里的 8443 是解析规则的匹配条件。URL 没写端口,HTTPS 默认使用 443,因此请求查找的是 example.com:443,用不上这条 example.com:8443 规则。继续解析域名并连接 443,符合这组参数的含义。

同样的规则也适用于 libcurl 的 CURLOPT_RESOLVE。本文讨论直接连接服务器时的地址和端口选择;代理、其他连接选项及跳转可能改变实际连接路径,需要先排除它们的影响。

先区分 URL 端口与解析规则

--resolve 的基本格式是:

HOST:PORT:ADDRESS

它给指定的“主机名 + 端口”提供地址。决定请求端口的是 URL:https://example.com/ 使用 443,https://example.com:8443/ 使用 8443,http://example.com/ 使用 80。把解析规则中的数字换成 80、666 或 8443,都不会替 URL 改端口。

先对照当前命令的 URL、解析规则和实际连接端口,不要只看日志中规则已加入 DNS 缓存的提示。规则成功加入缓存,只说明 curl 接收了这条配置,不能证明当前请求匹配到了它。

下面命令采用 POSIX shell 写法。example.com 和文档示例地址 192.0.2.10 都需要替换为你有权访问的测试域名、服务器 IP;目标端口必须已经提供对应服务。

示例把 -q 放在 curl 后的第一个参数位置,跳过默认 curl 配置文件;--noproxy '*' 仅对本次调用禁用代理,便于看清直连目标。只在允许直连且服务器可达的网络里这样检查。如果必须经过代理,需要另外区分代理连接与目标连接,不能照搬直连结果。

只换服务器 IP,继续使用 443

如果目标是绕过 DNS,把同一个 HTTPS 地址临时指向另一台服务器,解析规则的端口应与 URL 的 443 匹配:

curl -q --noproxy '*' -v --max-time 20 \
  --resolve example.com:443:192.0.2.10 \
  https://example.com/

这时网络目标应为 192.0.2.10:443。URL 仍是域名,TLS 的 SNI、证书名称校验和 HTTP 请求中的主机名仍按 example.com 处理,适合检查尚未切换 DNS 的 HTTPS 站点。

服务地址本来就包含 8443

如果用户实际访问的地址就是带端口的 HTTPS URL,把端口写进 URL,并保留匹配的解析规则:

curl -q --noproxy '*' -v --max-time 20 \
  --resolve example.com:8443:192.0.2.10 \
  https://example.com:8443/

此时请求匹配 example.com:8443,网络目标应为 192.0.2.10:8443。URL 中的非默认端口也会体现在 HTTP 主机信息中,例如 HTTP/1.1 的 Host: example.com:8443。如果应用根据主机和端口生成跳转地址,这与不带端口的 URL 可能有不同表现。

URL 保持 443,实际连接后端 8443

另一种需求是模拟正常的 https://example.com/ 请求,但把连接临时送到后端的 8443。此时用 --connect-to 表达端口映射:

curl -q --noproxy '*' -v --max-time 20 \
  --connect-to example.com:443:192.0.2.10:8443 \
  https://example.com/

它的四段分别是原请求主机、原请求端口、连接目标主机、连接目标端口:

HOST1:PORT1:HOST2:PORT2

前两段匹配 URL 的 example.com:443,后两段把网络连接送到 192.0.2.10:8443。这个选项改变的是连接目标,TLS SNI、证书名称校验和应用协议里的主机、端口仍依据原 URL。因此它与“直接把 URL 改成 8443”适用于不同的测试需求。

目标 8443 必须提供 TLS。端口映射不会把 HTTPS 请求转换为明文 HTTP;如果后端实际上只提供 HTTP,连接端口即使正确,TLS 握手仍可能失败。

基本的 --resolve 从 curl 7.21.3 起提供,--connect-to 从 7.49.0 起提供。使用第三种方式前可查看版本:

curl --version

如果在程序里使用 libcurl,对应检查链接到的库版本和 CURLOPT_CONNECT_TO 支持情况,终端里的 curl 版本不一定等于程序使用的版本。

用连接目标和 HTTPS 响应分别验收

先不加 -L,只观察第一次请求。-v 输出中的连接目标应符合所选方案;也可以在上述命令中追加:

--write-out '\nremote=%{remote_ip}:%{remote_port}\nhttp=%{http_code}\n'

这一行是追加参数,不能单独执行。直连且只请求一个 URL 时,remote_ip、remote_port 可用于核对实际建立的连接。没有建立连接时,不要把空地址或零端口当作已匹配。检查网络目标后,还要确认 TLS 校验通过、HTTP 状态及响应正文来自预期应用;仅看到 TCP 连接成功不能证明站点已正常。

如果响应返回重定向,先看 Location 指向哪个主机和端口。随后跟随跳转时,新请求可能不再匹配原来的解析或连接规则。应按跳转后的 URL 单独判断,避免把第二次请求连接 443 误当成第一次映射失败。

证书错误要另行处理:目标服务器应提供匹配 URL 域名、且客户端信任的证书。测试环境使用私有 CA 时,可在确认 CA 文件来源后,为这次请求指定信任文件:

--cacert /path/to/test-ca.pem

这同样是追加参数,路径需替换为真实 CA 文件。不要靠 -k 关闭校验来判定 HTTPS 修复成功,也不要把 URL 换成 IP 后只加 Host 请求头;HTTPS 的 SNI 和证书名称校验取自 URL,单改 HTTP 头不能代替它们。分享详细日志前应检查其中是否包含认证信息或 Cookie。

这些示例只改变当前 curl 调用,不需要改系统 hosts、DNS 或服务器监听配置。检查结束后,移除命令中的 --resolve 或 --connect-to 即可恢复原来的目标选择;若同时改过 URL 端口,也要把 URL 恢复。写进脚本或客户端配置的规则需在对应位置撤回。