HTTP2请求通过PROXY,ruby

时间:2016-11-18 11:06:08

标签: ruby-on-rails ruby ssl proxy

我有一些通过HTTP2运行的远程REST API。它使用证书运行SSL。目标是通过HTTP2通过代理发送和接收带有SSL证书的数据。

http-2& net-http2 gems,允许使用HTTP2发送请求。但是代理呢?在标准的Net :: HTTP库中,有一个子类Net :: HTTP :: Proxy,它复制了父的Net :: HTTP类的行为,除了它通过代理服务器发送请求的事实。但HTTP2宝石不支持它。

我提出的结论是制作类似于http1.1的代理实现的东西 - 将“Host:”和“Proxy-Authorization:”字段写入套接字,Net-Http2 gem使用:< / p>

  @socket.writeline sprintf('CONNECT %s:%s HTTP/%s',
                            @address, @port, HTTPVersion)
  @socket.writeline "Host: #{@address}:#{@port}"
  if proxy_user
    credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
    credential.delete!("\r\n")
    @socket.writeline "Proxy-Authorization: Basic #{credential}"
  end
  @socket.writeline ''

但最终结果是:

SSL_connect SYSCALL returned=5 errno=0 state=SSLv2/v3 read server hello A

我可能会错过一些技术知识来实现​​这一点,所以我们非常感谢任何与研究方向相关的帮助。

1 个答案:

答案 0 :(得分:0)

毕竟,我用net / http标准库中的示例完成了我的想法,并为Net-http2 gem创建了一个拉取请求:https://github.com/ostinelli/net-http2/pull/11

这个想法是正确的,我们所要做的就是使用任何tcp套接字发送代理“CONNECT”消息,其中包含我们想要连接的地址,因此它会创建一个绕过所有数据的TCP隧道,无论是HTTP1.1还是HTTP2,或其他任何内容都无关紧要。

以下是代码的一部分:

def self.proxy_tcp_socket(uri, options)
  proxy_addr = options[:proxy_addr]
  proxy_port = options[:proxy_port]
  proxy_user = options[:proxy_user]
  proxy_pass = options[:proxy_pass]

  proxy_uri = URI.parse("#{proxy_addr}:#{proxy_port}")
  # create a regular TCP socket (with or w/o SSL, if needed)
  proxy_socket = tcp_socket(proxy_uri, options)

  # The majority of proxies do not explicitly support HTTP/2 protocol,
  # while they successfully create a TCP tunnel
  # which can pass through binary data of HTTP/2 connection.
  # So we’ll keep HTTP/1.1
  http_version = '1.1'

  buf = "CONNECT #{uri.host}:#{uri.port} HTTP/#{http_version}\r\n"
  buf << "Host: #{uri.host}:#{uri.port}\r\n"
  if proxy_user
    credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
    credential.delete!("\r\n")
    buf << "Proxy-Authorization: Basic #{credential}\r\n"
  end
  buf << "\r\n"
  proxy_socket.write(buf)
  validate_proxy_response!(proxy_socket)

  proxy_socket
end