我有一个装有 2 个网卡的 Linux 机器,用于检查通过端口 80 的流量。一个网卡用于连接到互联网,另一个网卡连接到网络交换机。这样做的目的是为了能够检查连接到该交换机的设备上的所有 HTTP 和 HTTPS 流量,以便进行调试。
我为 iptables 编写了以下规则:
nat
-A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.2.1:1337
-A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 1337
-A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
在 192.168.2.1:1337 上,我使用 Charles 建立了一个透明的 http 代理(http://www.charlesproxy.com/) 进行录制。
端口 80 一切正常,但是当我为指向端口 1337 的端口 443(SSL)添加类似规则时,我收到有关通过 Charles 发送的无效消息的错误。
我之前曾在同一台计算机上使用过 Charles 的 SSL 代理(http://www.charlesproxy.com/documentation/proxying/ssl-proxying/),但由于某种原因,一直无法透明地做到这一点。我在谷歌上搜索的一些资源说这是不可能的——如果有人能解释原因,我愿意接受这个答案。
需要注意的是,我拥有所述设置(包括连接到子网的所有客户端)的完全访问权限 - 因此我可以接受 Charles 的自签名证书。解决方案不必是特定于 Charles 的,因为理论上任何透明代理都可以。
谢谢!
编辑:经过一番尝试,我能够让它在特定主机上运行。当我将 iptables 修改为以下内容(并在 charles 中打开 1338 以进行反向代理)时:
nat
-A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.2.1:1337
-A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 1337
-A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j DNAT --to-destination 192.168.2.1:1338
-A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 1338
-A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
我能够得到响应,但没有目标主机。在反向代理中,如果我仅指定从 1338 开始的所有内容都发送到我想要访问的特定主机,它就会正确执行握手,我可以打开 SSL 代理来检查通信。
该设置不太理想,因为我不想假设来自 1338 的所有内容都转到该主机 - 知道为什么目标主机被剥离吗?
再次感谢
答案1
您看到的问题是相同的防止在单个 IP 地址/端口上使用多个证书(不使用服务器名称指示)。
在纯 HTTP 中,您的透明代理可以通过查看标头来判断客户端想要连接哪个主机Host
。
当 HTTPS MITM 透明代理收到请求时,它无法知道客户端首先请求的是哪个主机名。(我甚至不确定它是否可以使用这些规则获取 IP 地址,这至少可能允许它使用反向 DNS 查找进行猜测,尽管在一般情况下不太可能起作用。)
- 为了获取预期的主机名,MITM 代理必须读取
Host
HTTP 消息中的标头,这只有在成功握手后才会发生。 - 为了成功握手,MITM 代理需要生成与预期主机名匹配的欺骗证书。
因此,MITM 代理在握手之前无法知道要生成哪个证书。
这可以与非透明的 MITM 代理一起工作,因为您至少可以通过 HTTPCONNECT
方法获取预期的主机名。
答案2
仅有关该主题的一些基本信息。
据我所知,只有少数设备可以成功完成此操作。然而,它们实际上并不向公众开放。我自己使用的是带 SSL 卸载功能的 Fortinet Fortigate。
它的基本作用是:拦截与主机的 SSL 连接并在硬件中解密连接,然后检查您要去的地方并根据该信息做出防火墙决策。
之后,它会建立与该主机的连接来检索数据,并使用用户提供的 CA 重新签署对客户端的原始请求。为了使此操作顺利进行,需要将 CA 置于客户端上受信任的根 CA 中。
此类设置用于组织强制执行有关互联网使用的公司政策。由于使用 Active Directory,因此可以轻松地在客户端安装公司 CA,这对于大型组织来说不成问题。
这是唯一一种无需创建手动代理即可实现的方法,因为 SSL 流量是加密的。它基本上是一种 MITM,因此务必要涵盖所有法律问题。
答案3
您可能已经看到了关于这个问题的另外一些建议:透明 SSL 代理的谬论与事实。还有这个链接解释了如何将 Squid 配置为透明 SSL 代理。这不是您要找的内容,但至少可以让您了解可能出现的问题。
iptables 规则似乎没问题,但我不知道您使用的代理软件是否能够完成您要做的事情。文档中确实声称情况确实如此。
答案4
为了补充 Bruno 的解决方案,我进行了一些调查,并想分享我如何得到另一个不太理想的快速解决方案。
设置这些 iptables 后,我可以在端口 1338 上放置一个反向代理,并将其转发到端口 1337 上的本地主机。由于端口 1337 是一个透明的 http 代理并且数据已被解密,它将获取主机头并使其成为目标主机。
主要的缺点是我基本上将 https 连接转换为 http - 但它并不总是适用于每个服务器(更不用说我从中暴露的安全漏洞了)。
我的工作范围在我的软件限制之内。我认为 Bruno 认为更简洁的解决方案是假设所有来自 1338 的流量都应解密。解密后,检查目标主机,然后使用 SSL 代理请求。