帮助 Ruby 中的 HTTP 拦截代理?

Posted

技术标签:

【中文标题】帮助 Ruby 中的 HTTP 拦截代理?【英文标题】:Help with HTTP Intercepting Proxy in Ruby? 【发布时间】:2011-02-10 08:50:38 【问题描述】:

我开始使用 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 连接时遇到了问题。

我该如何解决这些问题?

【问题讨论】:

【参考方案1】:

首先,在现有的 Ruby HTTP 代理实现上构建可能会更好。 Ruby 标准库中已经提供了这样的一种,即WEBrick::HTTPProxyServer。例如,有关基于同一类的实现的相关问题:Webrick transparent proxy。

关于代理 HTTPS,您只能传递原始字节。由于 HTTPS 受到加密保护,您无法在 HTTP 协议级别检查内容。它只是一个不透明的字节流。

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

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

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

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

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

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

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

【讨论】:

以上是关于帮助 Ruby 中的 HTTP 拦截代理?的主要内容,如果未能解决你的问题,请参考以下文章

burpsuite拦截https数据包(Firefox)

[转]使用 mitmproxy + python 做拦截代理

配置charles代理拦截Android N设备上的流量

如何在 ruby​​ 中获取 IP 地址、引用者和用户代理?

IOS Charles(代理服务器软件,可以用来拦截网络请求)

第二章 Burp Suite代理和浏览器设置