我有一个x.example
,为a.example
和b.example
提供流量。
x.example
拥有a.example
和b.example
的证书。 a.example
和b.example
的DNS尚未设置。
如果我为/etc/hosts
添加a.example
条目,指向x.example
的IP并运行curl -XGET https://a.example
,则会获得200.
但是如果我运行curl --header 'Host: a.example' https://x.example
,我会得到:
卷曲:(51)SSL:没有替代证书主题名称与目标匹配 主机名x.example
我认为它会使用a.example作为主机。也许我不理解SNI / TLS是如何工作的。
因为a.example
是一个HTTP标头,TLS握手还没有访问权限吗?但它本身可以访问URL吗?
答案 0 :(得分:6)
事实上,TLS中的SNI并不像那样。 SNI,因为与TLS相关的所有内容都发生在任何类型的HTTP流量之前,因此在该步骤中不会考虑Host
标头(但稍后将对网络服务器有用,以便知道您正在连接哪个主机) )。
因此,要启用SNI,您需要HTTP客户端中的特定交换机,以告知它在握手期间使用您需要的主机名值发送相应的TLS扩展。
如果是curl
,您至少需要版本7.18.1(基于https://curl.haxx.se/changes.html),然后它似乎会自动使用Host
标头中提供的值。它还取决于它链接到哪个OpenSSL(或您平台上的等效库)。
参见https://curl.haxx.se/docs/knownbugs.html的第1.10点,其中提到了一个错误,但解释了会发生什么:
当给出一个带有主机名部分尾随点的URL:“https://example.com./”时,libcurl将剥离该点,并在内部使用不带点的名称,并在HTTP Host:header中将其发送为无点并在TLS SNI字段中。
--connect-to
选项对您的情况也很有用。或--resolve
代替/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
您可以在所有情况下添加--verbose
,以查看更多详细信息。请参阅此示例:https://www.claudiokuenzler.com/blog/693/curious-case-of-curl-ssl-tls-sni-http-host-header;您还将看到如何使用openssl
直接测试。
如果a.example
中有/etc/hosts
,则应该使用https://a.example/
运行curl,它应该处理Host
标头,因此SNI(或使用{{ 1}}代替)
答案 1 :(得分:0)
选择的答案可以帮助我找到答案,即使它没有包含。 Patrick Mevzek提供的邮件/归档链接中的答案具有错误端口号。因此,即使遵循该答案也将导致其继续失败。
我使用this container运行调试服务器来检查请求。我强烈建议调试此类问题的任何人都这样做。
这是如何解决OP的问题。
# Instead of this:
# curl --header 'Host: a.example' https://x.example
# Do:
ip=$(dig +short x.example | head -n1)
curl -sv --resolve a.example:443:$ip https://a.example
注意:由于您使用的是https,因此必须在443
参数中使用--resolve
,而不要像{{3} }