Ruby in the middle(RITM)是一个 HTTP/HTTPS 拦截代理,支持即时生成并签名证书,让用户能够利用 Ruby 语言的完整能力,随心所欲地拦截甚至修改请求和响应。
gem install ritm
require 'ritm'
# 对谷歌搜索的所有请求给出统一回答
Ritm.on_request do |req|
if req.request_uri.host.start_with? 'www.google.'
new_query_string = req.request_uri.query.gsub(/(?<=^q=|&q=)(((?!&|$).)*)(?=&|$)/, 'RubyInTheMiddle')
req.request_uri.query = new_query_string
end
end
my_picture = File.read('i_am_famous.jpg')
# 将网络上所有图片替换为我的靓照
Ritm.on_response do |_req, res|
if res.header['content-type'] && res.header['content-type'].start_with?('image/')
res.header['content-type'] = 'image/jpeg'
res.body = my_picture
end
end
Ritm.start
puts '按回车键结束'
gets
Ritm.shutdown
或者你想要拦截流量的其他 HTTP 客户端,使其连接到 localhost:8080 上的代理。
针对上面的示例,可以在谷歌中搜索任何内容,也可以访问你最喜欢的新闻网站。
在上一个示例中,你的客户端在访问 HTTPS 资源时可能会遇到问题。某些情况下,你可以为浏览器添加例外(或指示 HTTP 客户端不验证证书),但在另一些情况下你将无法添加例外。原因在于,为了解密并能够修改 SSL 流量,RITM 必须与客户端进行 SSL 协商(使用自己的证书集),然后与服务器建立独立的 SSL 会话。即:
客户端 <--- SSL 会话 ---> RITM <--- SSL 会话 ---> 服务器
对于你的客户端尝试通信的每个不同服务器主机名,RITM 都会即时生成一个证书,并使用预配置的证书颁发机构(CA)进行签名。因此,要建立安全连接,你需要配置客户端(例如浏览器)信任 RITM 的 CA。
出于安全原因,每次使用默认设置启动 RITM 代理时,它都会生成一个新的内部证书颁发机构。要改用你自己的 CA(以便浏览器加载并信任它),请执行以下步骤:
你可以使用 OpenSSL 或 RITM 来生成这两个文件。使用 OpenSSL:
openssl req -new -nodes -x509 -days 365 -extensions v3_ca -keyout insecure_ca.key -out insecure_ca.crt
或者使用 RITM:
require 'ritm/certs/ca'
ca = Ritm::CA.create common_name: 'InsecureCA'
File.write('insecure_ca.crt', ca.pem)
File.write('insecure_ca.key', ca.private_key.to_s)
Ritm.configure do
ssl_reverse_proxy.ca[:pem] = 'path/to/insecure_ca.crt'
ssl_reverse_proxy.ca[:key] = 'path/to/insecure_ca.key'
end
Ritm.start
puts '按回车键结束'
gets
Ritm.shutdown
具体如何操作,请自行查阅浏览器或客户端的相关文档。 4. 开始上网冲浪!
或者妥善保管 CA 私钥,因为任何拥有该密钥的人都能解密你所有的流量!另请注意,使用代理时,即使目标服务器证书无效,所有服务器也会自动被信任。
在上述示例中,我们一直使用默认的全局会话。如果你不喜欢使用静态配置的全局会话,或者希望同时运行多个会话(例如,多个代理监听不同端口并使用不同的拦截处理程序),可以按如下方式创建不同的会话实例:
session = Ritm::Session.new
# 现在可以在会话实例上使用相同的方法
session.configure { proxy[:bind_port] = 7777 }
session.on_request { |req| ...在此处执行某些操作 ... }
another_session = Ritm::Session.new
another_session.configure { proxy[:bind_port] = 8888 }
another_session.on_request { |req| ...在此处执行其他操作 ... }
session.start
another_session.start
puts '按回车键结束'
gets
session.shutdown
another_session.shutdown
根据 Apache 许可证 2.0 版(“许可证”)获得许可;除非遵守许可证,否则你不得使用此文件。你可以在以下位置获取许可证副本:
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则根据许可证分发的软件按“原样”分发,不附带任何明示或暗示的担保或条件。有关许可证下的权限和限制,请参阅许可证。