禁用 Ruby net/http 的 SNI 扩展 - 使用 SSL/TLS 的 IP 地址
Disable SNI Extension for Ruby net/http - Using IP address with SSL/TLS
我有一个 Ruby 轮询脚本 运行 在 IP 范围内的一组服务器上。我非常强烈更喜欢通过 IP 地址而不是主机名进行轮询,因为:
1) 我已经定义了要轮询的 IP 地址范围,并且主机名 arbitrary/change 很多
2) 因为它们变化很大,所以大多数主机名没有反向 DNS 查找,所以我无法根据 IP 设计主机名列表
在我们的 Web 服务器对此轮询没有问题之前,但是在不接受 SSLv3 通信的新服务器上,这是我 运行 我的轮询时遇到的错误:
/home/dashboard/.rvm/rubies/ruby-2.1.6/lib/ruby/2.1.0/net/http.rb:923:in `connect': SSL_connect returned=1 errno=0 state=unknown state: tlsv1 unrecognized name (OpenSSL::SSL::SSLError)
在服务器端,这是错误:
nss_engine_init.c(1802): start function ownSSLSNISocketConfig for SNI
nss_engine_init.c(1827): Search [val = 172.16.99.18] failed, unrecognized name
当我 运行 使用主机名进行投票时,一切正常。
这是 Ruby 中 HTTP 客户端代码的关键:
def init_http(url)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.read_timeout = 10
http.use_ssl = true
#http.ssl_version = 'TLSv1'
return [http, uri]
end
如您所知,我一直在研究 TLS 和 SSL 版本,因为我认为这可能是问题所在。我的下一个想法(Google 只有 Java 的证据)是,"How easy is it to just disable the SNI extension on my client?" 更一般的问题是,"Can I keep using IP addresses with Ruby net/http while taking advantage of newer, more secure communication protocols?"
... tlsv1 unrecognized name (OpenSSL::SSL::SSLError)
在大多数情况下,这不是您可以通过在客户端禁用 SNI 来解决的问题。当您在同一个 IP 地址上拥有多个证书并且如果您只是通过 IP 地址连接并且不发送请求的主机名(即禁用 SNI)时,SNI 是必需的,服务器将不知道它应该提供哪个证书 - 然后导致以上错误。
I very strongly prefer to do this polling by IP address, not by hostname, ...
如果您必须处理需要 SNI 的服务器,那么您必须使用 SNI,并且必须使用具有正确主机名的 SNI,该主机名不一定与您从反向查找中获得的名称相同。
解决此问题的最简单方法是添加@steffenullrich 为 bug 10613 提到的补丁。
我所做的只是查看差异,然后自己编辑文件,但是如果您熟悉 Linux 补丁工具,您可以使用它。
对于那些不确定 /net/http.rb 所在位置的人,它与您的其他 Ruby 来源位于同一位置。例如,我在这里:
/home/myuser/.rvm/rubies/ruby-2.1.6/lib/net/http.rb
修补文件后,将 HTTP 对象的 .disable_sni 属性 设置为 true,并且不需要 SNI,允许在混合 TLS 通信中使用 IP 地址。
我有一个 Ruby 轮询脚本 运行 在 IP 范围内的一组服务器上。我非常强烈更喜欢通过 IP 地址而不是主机名进行轮询,因为:
1) 我已经定义了要轮询的 IP 地址范围,并且主机名 arbitrary/change 很多
2) 因为它们变化很大,所以大多数主机名没有反向 DNS 查找,所以我无法根据 IP 设计主机名列表
在我们的 Web 服务器对此轮询没有问题之前,但是在不接受 SSLv3 通信的新服务器上,这是我 运行 我的轮询时遇到的错误:
/home/dashboard/.rvm/rubies/ruby-2.1.6/lib/ruby/2.1.0/net/http.rb:923:in `connect': SSL_connect returned=1 errno=0 state=unknown state: tlsv1 unrecognized name (OpenSSL::SSL::SSLError)
在服务器端,这是错误:
nss_engine_init.c(1802): start function ownSSLSNISocketConfig for SNI
nss_engine_init.c(1827): Search [val = 172.16.99.18] failed, unrecognized name
当我 运行 使用主机名进行投票时,一切正常。
这是 Ruby 中 HTTP 客户端代码的关键:
def init_http(url)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.read_timeout = 10
http.use_ssl = true
#http.ssl_version = 'TLSv1'
return [http, uri]
end
如您所知,我一直在研究 TLS 和 SSL 版本,因为我认为这可能是问题所在。我的下一个想法(Google 只有 Java 的证据)是,"How easy is it to just disable the SNI extension on my client?" 更一般的问题是,"Can I keep using IP addresses with Ruby net/http while taking advantage of newer, more secure communication protocols?"
... tlsv1 unrecognized name (OpenSSL::SSL::SSLError)
在大多数情况下,这不是您可以通过在客户端禁用 SNI 来解决的问题。当您在同一个 IP 地址上拥有多个证书并且如果您只是通过 IP 地址连接并且不发送请求的主机名(即禁用 SNI)时,SNI 是必需的,服务器将不知道它应该提供哪个证书 - 然后导致以上错误。
I very strongly prefer to do this polling by IP address, not by hostname, ...
如果您必须处理需要 SNI 的服务器,那么您必须使用 SNI,并且必须使用具有正确主机名的 SNI,该主机名不一定与您从反向查找中获得的名称相同。
解决此问题的最简单方法是添加@steffenullrich 为 bug 10613 提到的补丁。
我所做的只是查看差异,然后自己编辑文件,但是如果您熟悉 Linux 补丁工具,您可以使用它。
对于那些不确定 /net/http.rb 所在位置的人,它与您的其他 Ruby 来源位于同一位置。例如,我在这里:
/home/myuser/.rvm/rubies/ruby-2.1.6/lib/net/http.rb
修补文件后,将 HTTP 对象的 .disable_sni 属性 设置为 true,并且不需要 SNI,允许在混合 TLS 通信中使用 IP 地址。