如何模拟非 SNI 浏览器(不支持 SNI)?
How to simulate non-SNI browsers (without SNI support)?
我正在为驻留在同一服务器上的不同域(因此共享相同的 IP 地址)设置几个不同的 SSL 证书的 Apache。
使用 Qualys SSL Test I discovered that there are clients (i.e. BingBot as of december 2013) 不支持 SNI 扩展。
所以我正在考虑制作一个特殊的默认 Web 应用程序来收集此类客户端的请求,但我该如何模拟这些客户端?
我在 Windows 8,无法访问 Linux 个盒子,如果这很重要的话。
您可以安装 Strawberry Perl 然后使用以下脚本模拟不支持 SNI 的客户端:
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(ssl_opts => {
# this disables SNI
SSL_hostname => '',
# These disable certificate verification, so that we get a connection even
# if the certificate does not match the requested host or is invalid.
# Do not use in production code !!!
SSL_verify_mode => 0,
verify_hostname => 0,
});
# request some data
my $res = $ua->get('https://example.com');
# show headers
# pseudo header Client-SSL-Cert-Subject gives information about the
# peers certificate
print $res->headers_as_string;
# show response including header
# print $res->as_string;
通过将 SSL_hostname 设置为空字符串,您可以禁用 SNI,禁用此行将再次启用 SNI。
您可以使用最常用的 SSL 库 OpenSSL。 Windows 二进制文件可供下载。
openssl s_client -connect domain.com:443
命令非常适合从客户端测试 SSL 连接。它默认不支持 SNI。您可以附加 -servername domain.com
参数以启用 SNI。
使用特殊默认 Web 应用程序的方法根本行不通。
你不能那样做,因为所说的受限客户端不仅会打开不同的页面,而且会完全失败。
假设您有一个 "default" 虚拟主机,non-SNI 客户端可以正常打开它。
您还有一个额外的虚拟主机,应该由 SNI-supporting 客户端打开。
显然,这两个必须具有不同的主机名(例如,default.example.com
和 www.example.com
),否则 Apache 或 nginx 将不知道向哪个连接客户端显示哪个站点.
现在,如果 non-SNI 客户端尝试打开 https://www.example.com
,他将收到来自 default.example.com
的证书,这会给他一个证书错误。这是一个重要的警告。
此错误的修复方法是创建一个包含 www.example.com
和 default.example.com
的 SAN (multi-domain) 证书。然后,如果 non-SNI 客户端尝试打开 https://www.example.com
,他将获得有效证书,但即便如此,他的 Host:
header 仍将指向 www.example.com
,他的请求将不会路由到 default.example.com
,而是路由到 www.example.com
。
如您所见,您要么完全阻止 non-SNI 客户端,要么将它们转发到预期的虚拟主机。 默认 Web 应用程序没有合理的选项。
类似于openssl s_client是gnutls-cli
gnutls-cli --disable-sni www.google.com
如果您使用的是 OpenSSL 1.1.0 或更早版本,请使用 openssl s_client -connect $ip:$port
,OpenSSL 不会启用 SNI 扩展
如果您使用的是 OpenSSL 1.1.1,则需要将 -noservername
标志添加到 openssl s_client
。
使用 Java HTTP 客户端,您可以通过设置系统 属性 jsse.enableSNIExtension=false
.
来禁用 SNI 扩展
更多信息:
我正在为驻留在同一服务器上的不同域(因此共享相同的 IP 地址)设置几个不同的 SSL 证书的 Apache。
使用 Qualys SSL Test I discovered that there are clients (i.e. BingBot as of december 2013) 不支持 SNI 扩展。
所以我正在考虑制作一个特殊的默认 Web 应用程序来收集此类客户端的请求,但我该如何模拟这些客户端?
我在 Windows 8,无法访问 Linux 个盒子,如果这很重要的话。
您可以安装 Strawberry Perl 然后使用以下脚本模拟不支持 SNI 的客户端:
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(ssl_opts => {
# this disables SNI
SSL_hostname => '',
# These disable certificate verification, so that we get a connection even
# if the certificate does not match the requested host or is invalid.
# Do not use in production code !!!
SSL_verify_mode => 0,
verify_hostname => 0,
});
# request some data
my $res = $ua->get('https://example.com');
# show headers
# pseudo header Client-SSL-Cert-Subject gives information about the
# peers certificate
print $res->headers_as_string;
# show response including header
# print $res->as_string;
通过将 SSL_hostname 设置为空字符串,您可以禁用 SNI,禁用此行将再次启用 SNI。
您可以使用最常用的 SSL 库 OpenSSL。 Windows 二进制文件可供下载。
openssl s_client -connect domain.com:443
命令非常适合从客户端测试 SSL 连接。它默认不支持 SNI。您可以附加 -servername domain.com
参数以启用 SNI。
使用特殊默认 Web 应用程序的方法根本行不通。
你不能那样做,因为所说的受限客户端不仅会打开不同的页面,而且会完全失败。
假设您有一个 "default" 虚拟主机,non-SNI 客户端可以正常打开它。
您还有一个额外的虚拟主机,应该由 SNI-supporting 客户端打开。
显然,这两个必须具有不同的主机名(例如,
default.example.com
和www.example.com
),否则 Apache 或 nginx 将不知道向哪个连接客户端显示哪个站点.
现在,如果 non-SNI 客户端尝试打开 https://www.example.com
,他将收到来自 default.example.com
的证书,这会给他一个证书错误。这是一个重要的警告。
此错误的修复方法是创建一个包含 www.example.com
和 default.example.com
的 SAN (multi-domain) 证书。然后,如果 non-SNI 客户端尝试打开 https://www.example.com
,他将获得有效证书,但即便如此,他的 Host:
header 仍将指向 www.example.com
,他的请求将不会路由到 default.example.com
,而是路由到 www.example.com
。
如您所见,您要么完全阻止 non-SNI 客户端,要么将它们转发到预期的虚拟主机。 默认 Web 应用程序没有合理的选项。
类似于openssl s_client是gnutls-cli
gnutls-cli --disable-sni www.google.com
如果您使用的是 OpenSSL 1.1.0 或更早版本,请使用 openssl s_client -connect $ip:$port
,OpenSSL 不会启用 SNI 扩展
如果您使用的是 OpenSSL 1.1.1,则需要将 -noservername
标志添加到 openssl s_client
。
使用 Java HTTP 客户端,您可以通过设置系统 属性 jsse.enableSNIExtension=false
.
更多信息: