帮助Ruby中的HTTP拦截代理?

时间:2010-04-20 22:19:44

标签: html ruby http proxy https

我有一个用Ruby编写的HTTP拦截代理的开头:

require 'socket'                # Get sockets from stdlib

server = TCPServer.open(8080)   # Socket to listen on port 8080
loop {                          # Servers run forever
  Thread.start(server.accept) do |client|
    puts "** Got connection!"
    @output = ""
    @host = ""
    @port = 80
    while line = client.gets
        line.chomp!
        if (line =~ /^(GET|CONNECT) .*(\.com|\.net):(.*) (HTTP\/1.1|HTTP\/1.0)$/)
            @port = $3
        elsif (line =~ /^Host: (.*)$/ && @host == "")
            @host = $1
        end
        print line + "\n"
        @output += line + "\n"
        # This *may* cause problems with not getting full requests, 
        # but without this, the loop never returns.
        break if line == ""
    end
    if (@host != "")
        puts "** Got host! (#{@host}:#{@port})"
        out = TCPSocket.open(@host, @port)
        puts "** Got destination!"
        out.print(@output)
        while line = out.gets
            line.chomp!
            if (line =~ /^<proxyinfo>.*<\/proxyinfo>$/)
                # Logic is done here.
            end
            print line + "\n"
            client.print(line + "\n")
        end
        out.close
    end
    client.close
  end
}

我使用这个简单的代理解析HTTP请求中的目标,然后读取HTTP响应并根据特殊的HTML标记执行逻辑。代理在很大程度上起作用,但似乎在处理二进制数据和HTTPS连接时遇到了麻烦。

如何解决这些问题?

3 个答案:

答案 0 :(得分:3)

首先,您可能最好在现有的Ruby HTTP代理实现的基础上构建。其中一个已经在Ruby标准库中可用,即WEBrick::HTTPProxyServer。例如,请参阅基于同一类的实现的相关问题:Webrick transparent proxy

关于代理HTTPS,除了传递原始字节之外,您不能做更多的事情。由于HTTPS受加密保护,因此无法在HTTP协议级别检查内容。它只是一个不透明的字节流。

答案 1 :(得分:1)

WEBrick正在阻止I / O ......这意味着它无法传输响应。例如,如果您在YouTube页面上查看视频,则在代理下载了所有视频后,流将不会转发到您的浏览器。 如果您希望在下载过程中在浏览器中播放视频,则必须寻找像EventMachine这样的非阻塞I / O解决方案。 对于HTTPS,解决方案有点复杂,因为你必须在中间代理中开发一个人。

答案 2 :(得分:0)

这是一个老问题,但为了完整起见,这里有另一个答案。

我在Ruby中实现了一个HTTP / HTTPS拦截代理,该项目是hosted in github

HTTP情况很明显,HTTPS拦截是通过充当反向代理的HTTPS服务器完成的(并处理TLS握手)。即。

Client(e.g. Browser) <--> Proxy1 <--> HTTPS Reverse Proxy <--> Target Server

正如Valko所提到的,当客户端通过代理连接到HTTPS服务器时,您将看到加密字节流(因为SSL提供端到端加密)。但并非所有内容都经过加密,代理需要知道应该向谁转发字节流,因此客户端会发出CONNECT host:port请求(作为SSL流请求的主体)。

这里的诀窍是第一个代理会将此请求转发给HTTPS Reverse Proxy而不是真正的目标服务器。此反向代理将处理与客户端的SSL协商,可以访问已解密的请求,并通过充当普通客户端将这些请求的副本(可选地更改的版本)发送到真实目标服务器。它将从目标服务器获得响应,(可选)更改响应,并将它们发送回客户端。