禁用Ruby net / http的SNI扩展 – 使用带SSL / TLS的IP地址

我有一个Ruby轮询脚本,它运行在IP范围内的一组服务器上。 我非常强烈希望通过IP地址而不是主机名进行轮询,因为:

1)我已经定义了要轮询的IP地址范围,主机名是任意的/改变很多

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版本,因为我认为这可能是个问题。 我的下一个想法(谷歌只有Java的证据)是,“在我的客户端禁用SNI扩展有多容易?” 更一般的问题是,“我可以继续使用Ruby net / http的IP地址,同时利用更新,更安全的通信协议吗?”

… tlsv1无法识别的名称(OpenSSL :: SSL :: SSLError)

在大多数情况下,这可以通过在客户端禁用SNI来解决。 当您在同一IP地址上拥有多个证书时,如果您只是通过IP地址连接并且不发送请求的主机名(即禁用SNI),服务器将不知道它应该提供哪个证书,则需要SNI – 这会导致以上错误。

我非常强烈希望通过IP地址进行轮询,而不是通过主机名,…

如果您必须处理需要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地址。