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

时间:2015-11-12 21:01:17

标签: ruby ssl httpclient

我有一个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地址,同时利用更新,更安全的通信协议吗?"

2 个答案:

答案 0 :(得分:0)

  

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

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

  

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

如果您必须处理需要SNI的服务器,那么您必须使用SNI,并且必须使用具有正确主机名的SNI,该主机名不一定与您从反向查找中获得的名称相同。

答案 1 :(得分:0)

解决此问题的最简单方法是添加@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地址。