curl:如何为https请求指定目标主机名 [英] curl: how to specify target hostname for https request
问题描述
我有一个 x.example
,它同时为 a.example
和提供流量b.example
。
x.example
同时具有 a.example
和 b.example的证书
。 a.example
和 b.example
的DNS尚未设置。
I have a x.example
which serves traffic for both a.example
and b.example
.
x.example
has certificates for both a.example
and b.example
. The DNS for a.example
and b.example
is not yet set up.
如果我为 a.example
添加 / etc / hosts
条目,则指向 x.example
的ip并运行 curl -XGET https://a.example
,我得到200。
If I add an /etc/hosts
entry for a.example
pointing to x.example
's ip and run curl -XGET https://a.example
, I get a 200.
但是如果我运行 curl --header'Host:a.example'https://x.example
,我get:
However if I run curl --header 'Host: a.example' https://x.example
, I get:
卷曲:(51)SSL:没有其他证书主题名称与目标
主机名x.example匹配
curl: (51) SSL: no alternative certificate subject name matches target host name x.example
我认为它将使用a.example作为主机。也许我不太了解SNI / TLS的工作原理。
I would think it would use a.example as the host. Maybe I'm not understanding how SNI/TLS works.
因为 a.example
是TLS的HTTP标头握手还没有访问权限?
Because a.example
is an HTTP header the TLS handshake doesn't have access to it yet? But the URL itself it does have access to?
推荐答案
TLS中的独立SNI不能那样工作。由于SNI与TLS相关,因此发生在任何HTTP流量之前,因此在该步骤中不考虑 Host
标头(但稍后将对网络服务器也知道您正在连接哪个主机。)
Indeed SNI in TLS does not work like that. SNI, as everything related to TLS, happens before any kind of HTTP traffic, hence the Host
header is not taken into account at that step (but will be useful later on for the webserver to know which host you are connecting too).
因此,要启用SNI,您需要HTTP客户端中有一个特定的开关,以告诉它在
So to enable SNI you need a specific switch in your HTTP client to tell it to send the appropriate TLS extension during the handshake with the hostname value you need.
如果 curl
,则至少需要版本7.18.1(基于 https://curl.haxx.se/changes.html ),然后似乎自动使用 Host
标头中提供的值。它也取决于链接到的OpenSSL版本(或平台上的等效库)。
In case of curl
, you need at least version 7.18.1 (based on https://curl.haxx.se/changes.html) and then it seems to automatically use the value provided in the Host
header. It alo depends on which OpenSSL (or equivalent library on your platform) version it is linked to.
请参见 https://curl.haxx.se/docs/knownbugs.html 讲述了一个错误,但说明了会发生什么:
See point 1.10 of https://curl.haxx.se/docs/knownbugs.html that speaks about a bug but explains what happens:
给定主机名部分带有结尾点的URL时: https://example.com./ ,libcurl会删除该点并在内部使用不带点的名称,然后在HTTP Host:标头和TLS SNI字段中将其发送为无点。
When given a URL with a trailing dot for the host name part: "https://example.com./", libcurl will strip off the dot and use the name without a dot internally and send it dot-less in HTTP Host: headers and in the TLS SNI field.
-connect-to
选项在您的情况下也可能有用。或-解决
代替 / etc / hosts
,请参见 https://curl.haxx.se/mail/archive-2015-01/0042.html 例如,或 https: //makandracards.com/makandra/1613-make-an-http-request-to-a-machine-but-fake-the-hostname
您可以添加-在所有情况下都非常详细
,以了解发生了什么。参见以下示例: https ://www.claudiokuenzler.com/blog/693/curious-case-of-curl-ssl-tls-sni-http-host-header ;您还将看到那里如何直接使用 openssl
进行测试。
The --connect-to
option could also be useful in your case. Or --resolve
as a substitute to /etc/hosts
, see https://curl.haxx.se/mail/archive-2015-01/0042.html for am example, or https://makandracards.com/makandra/1613-make-an-http-request-to-a-machine-but-fake-the-hostname
You can add --verbose
in all cases to see in more details what is happening. See this example: https://www.claudiokuenzler.com/blog/693/curious-case-of-curl-ssl-tls-sni-http-host-header ; you will also see there how to test directly with openssl
.
如果您拥有 a .example
在您的 / etc / hosts
中,应该使用 https://a.example/
,它应该处理 Host
标头,并因此处理SNI(或使用-resolve
)
If you have a.example
in your /etc/hosts
you should just run curl with https://a.example/
and it should take care of the Host
header and hence SNI (or use --resolve
instead)
这篇关于curl:如何为https请求指定目标主机名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!