【问题标题】:SNI support in ruby's net/http if there is no route to hostname如果没有到主机名的路由,则在 ruby​​ 的 net/http 中支持 SNI
【发布时间】:2014-08-08 09:53:05
【问题描述】:

我正在为一个项目编写集成测试代码,它在服务器上设置了一个新的安全虚拟主机。服务器支持 SNI。但是,由于测试代码是在开发环境中运行的,因此主机名的 DNS 记录没有正确设置。因此,为了检查是否返回了正确的证书,使用 curl 我必须这样做

curl -i --cacert sample_ca.crt --resolve example.com:443:1.2.3.4 https://example.com/

或通过 openssl 实用程序

openssl s_client -connect 1.2.3.4:443 -servername example.com

我设法找到了在 ruby​​ 中重现用例的参考,如下所示

context = OpenSSL::SSL::SSLContext.new
context.ca_file = 'sample_ca.crt'
context.verify_mode = OpenSSL::SSL::VERIFY_PEER

tcp_client = TCPSocket.new('1.2.3.4', 443)
ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_client, context)
ssl_client.hostname = 'example.com'
ssl_client.connect

cert = OpenSSL::X509::Certificate.new(ssl_client.peer_cert)
pkey = OpenSSL::PKey.read(File.read(''sample_pkey.key))

if cert.check_private_key(pkey) then
  ssl_client.print "GET #{uri} HTTP/1.1\r\n"
  ssl_client.print "Host: example.com\r\n\r\n"
  header, body = ssl_client.read.split("\r\n\r\n")
else
  header, body = ['', '']
end

ssl_client.sysclose
tcp_client.close

我最初想用纯 net/http 来实现它,但是除非我为 example.com 正确设置了 DNS(我无权访问 DNS 设置,所以我通过编辑我的主机文件来作弊),它不管我怎么尝试都行不通。考虑到我对 ruby​​ 比较陌生,我想知道是否有办法只使用 net/http?

【问题讨论】:

  • 您可以使用 localhost 针对自签名证书运行它吗?您甚至可以设置一个私有 PKI 来测试和认证本地主机的证书。
  • 不确定,必须尝试,但这并不能模拟我希望复制的环境(:

标签: ruby ssl sni


【解决方案1】:

我不想这么说,但是看着这个,看起来必须给TCPSocket::open 打补丁,这样它才能将给定的地址解析成其他东西。在将TCPSocket 对象传递给 SSL 之前,无法对其进行拦截和更改。请参阅HTTP#connect 方法的来源。 我认为猴子补丁TCPSocket 是一个非常糟糕的主意,并且只能用于非生产测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-12
    • 2019-03-08
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    相关资源
    最近更新 更多