Ruby 的网络/http 中的 SNI 支持,如果没有到主机名的路由



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

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

或通过openssl utility

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.1rn"
  ssl_client.print "Host: example.comrnrn"
  header, body = ssl_client.read.split("rnrn")
else
  header, body = ['', '']
end
ssl_client.sysclose
tcp_client.close

我最初想用纯net/http实现这一点,但是,除非我为example.com正确设置DNS(我无法访问DNS设置,所以我通过编辑我的主机文件作弊),无论我如何尝试,它都不会起作用。考虑到我对ruby比较陌生,我想知道是否有一种方法可以只使用net/http?

我讨厌这么说,但是看着这个,看起来好像必须对TCPSocket::open进行猴子补丁,这样它就可以将给定的地址解析成其他东西。在将TCPSocket对象传递给SSL之前,没有办法拦截和更改它。参见HTTP#connect法的来源。我认为猴子给TCPSocket打补丁是一个非常糟糕的主意,只能用于非生产测试。

相关内容

最新更新