⚡ 快 •
项目描述
目录
- 特征
- 安装
- 启动代理.py
- 插件示例
- 端到端加密
- TLS 拦截
- SSH 隧道上的代理
- 嵌入代理.py
- 使用 proxy.py 进行单元测试
- 实用程序
- 运行仪表板
- Chrome 开发者工具协议
- 经常问的问题
- 插件开发者和贡献者指南
- 使用 Proxy.Py 的项目
- 基准
- 标志
- 变更日志
特征
-
快速且可扩展
-
通过使用系统上的所有可用内核进行扩展
-
使用 asyncio 的无线程执行
-
处理
tens-of-thousands连接数/秒# On Macbook Pro 2019 / 2.4 GHz 8-Core Intel Core i9 / 32 GB RAM ❯ ./helper/benchmark.sh CONCURRENCY: 100 workers, TOTAL REQUESTS: 100000 req Summary: Success rate: 1.0000 Total: 2.5489 secs Slowest: 0.0443 secs Fastest: 0.0006 secs Average: 0.0025 secs Requests/sec: 39232.6572 Total data: 1.81 MiB Size/request: 19 B Size/sec: 727.95 KiB Response time histogram: 0.001 [5006] |■■■■■ 0.001 [19740] |■■■■■■■■■■■■■■■■■■■■■ 0.002 [29701] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 0.002 [21278] |■■■■■■■■■■■■■■■■■■■■■■ 0.003 [15376] |■■■■■■■■■■■■■■■■ 0.004 [6644] |■■■■■■■ 0.004 [1609] |■ 0.005 [434] | 0.006 [83] | 0.006 [29] | 0.007 [100] | Latency distribution: 10% in 0.0014 secs 25% in 0.0018 secs 50% in 0.0023 secs 75% in 0.0030 secs 90% in 0.0036 secs 95% in 0.0040 secs 99% in 0.0047 secs Details (average, fastest, slowest): DNS+dialup: 0.0025 secs, 0.0015 secs, 0.0030 secs DNS-lookup: 0.0000 secs, 0.0000 secs, 0.0001 secs Status code distribution: [200] 100000 responses
请参阅线程与无线程和无线程远程与本地执行模式以控制使用的 CPU 内核数量。
有关更多详细信息以及如何在本地运行基准测试,请参阅基准测试。
-
-
轻的
- 仅使用
~5-20 MBRAM- 没有内存泄漏
- 启动一次即可忘记,无需重新启动
- 压缩容器尺寸仅为
~25 MB - 除标准 Python 库外,没有外部依赖项
- 仅使用
-
可编程的
- 使用代理服务器插件自定义代理行为。例子:
--plugins proxy.plugin.ProxyPoolPlugin
- 启用内置Web 服务器。例子:
--enable-web-server --plugins proxy.plugin.WebServerPlugin
- 启用内置反向代理服务器。例子:
--enable-reverse-proxy --plugins proxy.plugin.ReverseProxyPlugin
- 插件 API 目前处于开发阶段。期待重大变化。有关如何确保跨代码更改的可靠性,请参阅在生产中部署 proxy.py 。
- 使用代理服务器插件自定义代理行为。例子:
-
可以监听多个端口
- 使用
--ports标志提供额外的端口 - (可选)使用
--port标志覆盖默认端口8899 - 能够在同一个端口上服务多个协议
- 使用
-
实时仪表板
- (可选)启用proxy.py 仪表板。
- 利用
--enable-dashboard - 然后,访问
http://localhost:8899/dashboard
- 利用
-
proxy.py在运行时检查、监控、控制和配置 - Chrome DevTools 协议支持
typescript使用基于插件扩展仪表板前端- 仪表板目前处于开发阶段 预计会发生重大变化。
- (可选)启用proxy.py 仪表板。
-
安全的
- 在客户端和客户端之间启用端到端加密
proxy.py - 请参阅端到端加密
- 在客户端和客户端之间启用端到端加密
-
私人的
- 防御基于 DNS 的流量拦截器
- 浏览启用恶意软件和成人内容保护
- 请参阅DNS-over-HTTPS
-
中间人
- 可以解密客户端和上游服务器之间的 TLS 流量
- 请参阅TLS 拦截
-
代理请求支持的 http 协议
http(s)http1http1.1带管道
http2websockets
-
支持
HAProxy Protocol- 见
--enable-proxy-protocol标志
- 见
-
静态文件服务器支持
- 查看
--enable-static-server和--static-server-dir标记
- 查看
-
针对大文件上传和下载进行了优化
- 见
--client-recvbuf-size,--server-recvbuf-size,--max-sendbuf-size标志
- 见
-
IPv4和IPv6支持- 见
--hostname标志
- 见
-
Unix 域套接字支持
- 见
--unix-socket-path标志
- 见
-
基本身份验证支持
- 见
--basic-auth标志
- 见
-
PAC(代理自动配置)支持
- 查看
--pac-file和--pac-file-url-path标记
- 查看
安装
在使用proxy.py. _
使用画中画
带 PIP 的稳定版本
从安装PyPi
❯ pip install --upgrade proxy.py
或来自 GitHubmaster分支
❯ pip install git+https://github.com/abhinavsingh/proxy.py.git@master
带 PIP 的开发版本
❯ pip install git+https://github.com/abhinavsingh/proxy.py.git@develop
使用 Docker
多平台容器可通过以下方式获得:
- 码头工人中心
latest标签指向最后一个stable版本docker pull abhinavsingh/proxy.py:latest
- GitHub 容器注册表 (GHCR)
latest标签指向最后一个develop版本docker pull ghcr.io/abhinavsingh/proxy.py:latest
稳定版容器版本可用于以下平台:
linux/386linux/amd64linux/arm/v6linux/arm/v7linux/arm64/v8linux/ppc64lelinux/s390x
来自 Docker Hub 的稳定版本
运行proxy.py最新的容器:
❯ docker run -it -p 8899:8899 --rm abhinavsingh/proxy.py:latest
Docker daemon 会自动拉取匹配的平台镜像。在支持多平台的服务器上运行特定的目标平台容器:
❯ docker run -it -p 8899:8899 --rm --platform linux/arm64/v8 abhinavsingh/proxy.py:latest
GHCR 的开发版本
proxy.py从开发分支中的尖端代码运行容器:
❯ docker run -it -p 8899:8899 --rm ghcr.io/abhinavsingh/proxy.py:latest
在本地构建开发版本
❯ git clone https://github.com/abhinavsingh/proxy.py.git
❯ cd proxy.py && 制作容器
❯ docker run -it -p 8899:8899 --rm abhinavsingh/proxy.py:latest
dockermacOS由于与vpnkit不兼容,图像目前已中断。
使用自制
更新的公式在目录下的分支HomeBrew中维护。develophelper/homebrew
stable公式从master分支安装包。develop公式从develop分支安装包。
HomeBrew 稳定版
❯ brew install https://raw.githubusercontent.com/abhinavsingh/proxy.py/develop/helper/homebrew/stable/proxy.rb
使用 HomeBrew 的开发版本
❯ brew install https://raw.githubusercontent.com/abhinavsingh/proxy.py/develop/helper/homebrew/develop/proxy.rb
启动代理.py
使用 PIP 安装时从命令行
当proxy.py使用 安装时pip,一个名为的可执行文件将proxy放在您的$PATH.
运行
只需proxy在命令行上键入即可从默认配置开始。
❯ proxy
...[redacted]... - Loaded plugin proxy.http.proxy.HttpProxyPlugin
...[redacted]... - Started 8 threadless workers
...[redacted]... - Started 8 acceptors
...[redacted]... - Listening on 127.0.0.1:8899
了解日志
从以上日志中需要注意的事项:
-
Loaded pluginproxy.py将proxy.http.proxy.HttpProxyPlugin默认加载- 顾名思义,这个核心插件为实例添加了
http(s)代理服务器功能proxy.py
-
Started N threadless workers- 默认情况下,
proxy.py将启动与机器上的 CPU 内核一样多的工作进程 - 使用
--num-workersflag 自定义工作进程数 - 请参阅Threads vs Threadless以了解如何控制执行模式
- 默认情况下,
-
Started N acceptors- 默认情况下,
proxy.py将启动与机器上的 CPU 内核一样多的接受器进程 - 使用
--num-acceptorsflag 自定义接受器进程的数量 - 请参阅高级架构以了解接受者和工作人员之间的关系
- 默认情况下,
-
Started server on ::1:8899- 默认情况下,
proxy.py侦听 IPv6::1,相当于 IPv4127.0.0.1 - 如果您想
proxy.py从外部主机访问,请使用--hostname ::或--hostname 0.0.0.0绑定到您机器上可用的任何其他接口。 - 有关如何自定义上游服务器看到的公共 IP,请参阅CustomNetworkInterface。
proxy.py
- 默认情况下,
-
Port 8899- 使用
--portflag 自定义默认 TCP 端口。
- 使用
启用调试日志记录
以上所有日志均为INFO级别日志,默认--log-level为proxy.py
让我们从proxy.py级别DEBUG日志开始:
❯ proxy --log-level d
...[redacted]... - Open file descriptor soft limit set to 1024
...[redacted]... - Loaded plugin proxy.http_proxy.HttpProxyPlugin
...[redacted]... - Started 8 workers
...[redacted]... - Started server on ::1:8899
您可以使用单个字母来自定义日志级别。例子:
d = DEBUGi = INFOw = WARNINGe = ERRORc = CRITICAL
从上面的日志中我们可以看到,在启动之前:
proxy.py试图ulimit在系统上设置打开文件限制--open-file-limit使用的默认值为1024--open-file-limitWindowsflag 在操作系统上是无操作的
有关可用配置选项的完整列表,请参阅标志。
从命令行使用 repo 源
如果您尝试proxy.py从源代码运行,则源代码中没有指定二进制文件proxy。
proxy.py要从源代码开始,请遵循以下说明:
-
克隆回购
❯ git clone https://github.com/abhinavsingh/proxy.py.git ❯ cd proxy.py
-
创建一个 Python 3 虚拟环境
❯ python3 -m venv venv ❯ source venv/bin/activate
-
安装部门
❯ make lib-dep -
产生
proxy/common/_scm_version.py注意:可编辑安装不需要执行以下步骤。
此文件将 SCM 检测到的版本写入
proxy/common/_scm_version.py文件。❯ ./write-scm-version.sh -
(可选)运行测试
❯ make -
跑
proxy.py❯ python -m proxy
如果您打算使用源代码,请参阅插件开发人员和贡献者指南。proxy.py
Docker 镜像
自定义启动标志
默认情况下docker,二进制文件以 IPv4 网络标志启动:
--hostname 0.0.0.0 --port 8899
您可以在启动 docker 容器时从命令行覆盖标志。例如,要检查proxy.pydocker 容器中的版本,请运行:
❯ docker run -it \
-p 8899:8899 \
--rm abhinavsingh/proxy.py:latest \
-v
插件示例
- 完整代码见插件模块。
- 所有捆绑的插件示例也适用于
https流量- 需要额外的标志和证书生成
- 请参阅TLS 拦截。
- 插件示例也与 Docker 映像捆绑在一起。
- 请参阅自定义启动标志以尝试使用 Docker 映像的插件。
HTTP 代理插件
短链接插件
在您喜欢的浏览器/应用程序中添加对短链接的支持。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.ShortLinkPlugin
现在,您可以通过使用单字符域名访问您最喜爱的网站来加快您的日常浏览体验 :)。这适用于所有浏览器。
默认情况下启用以下短链接:
| 短链接 | 目标网址 |
|---|---|
| 一个/ | amazon.com |
| 一世/ | instagram.com |
| 升/ | linkedin.com |
| F/ | facebook.com |
| G/ | google.com |
| 吨/ | twitter.com |
| 带/ | web.whatsapp.com |
| 是/ | youtube.com |
| 代理人/ | localhost:8899 |
修改后数据插件
在向上游服务器发送请求之前修改 POST 请求正文。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.ModifyPostDataPlugin
默认情况下,插件将 POST 正文内容替换为硬编码b'{"key": "modified"}'
和强制的Content-Type: application/json.
使用相同的验证curl -x localhost:8899 -d '{"key": "value"}' http://httpbin.org/post
{
"args": {},
"data": "{\"key\": \"modified\"}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Content-Length": "19",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
},
"json": {
"key": "modified"
},
"origin": "1.2.3.4, 5.6.7.8",
"url": "https://httpbin.org/post"
}
请注意以下回复:
- POST 数据已修改
"data": "{\"key\": \"modified\"}"。原始curl命令数据是{"key": "value"}. - 我们的
curl命令没有添加任何Content-Type标题,但我们的插件确实添加了一个"Content-Type": "application/json". 同样也可以通过查看json上面输出中的字段来验证:"json": { "key": "modified" }, - 我们的插件还添加了一个
Content-Length标题来匹配修改后的正文长度。
MockRestApiPlugin
模拟服务器 REST API 的响应。用于测试和开发客户端应用程序,而无需实际的上游 REST API 服务器。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.ProposedRestApiPlugin
使用验证模拟 API 响应curl -x localhost:8899 http://api.example.com/v1/users/
{"count": 2, "next": null, "previous": null, "results": [{"email": "you@example.com", "groups": [], "url": "api.example.com/v1/users/1/", "username": "admin"}, {"email": "someone@example.com", "groups": [], "url": "api.example.com/v1/users/2/", "username": "admin"}]}
通过检查proxy.py日志进行验证:
... [redacted] ... - access_log:1210 - ::1:64792 - GET None:None/v1/users/ - None None - 0 byte
访问日志显示None:None为 server ip:port。None只是意味着从未建立服务器连接,因为我们的插件返回了响应。
现在修改ProposedRestApiPlugin以返回您的客户所期望的 REST API 模拟响应。
重定向到自定义服务器插件
http将所有传入请求重定向到自定义 Web 服务器。默认情况下,它将客户端请求重定向到内置 Web 服务器,也运行在8899端口上。
启动proxy.py并启用内置 Web 服务器:
❯ proxy \
--enable-web-server \
--plugins proxy.plugin.RedirectToCustomServerPlugin
验证使用curl -v -x localhost:8899 http://google.com
... [redacted] ...
< HTTP/1.1 404 NOT FOUND
< Server: proxy.py v1.0.0
< Connection: Close
<
* Closing connection 0
以上404响应是从proxy.pyWeb 服务器返回的。
通过检查日志来验证是否相同proxy.py。除了代理请求日志,您还必须查看 http Web 服务器请求日志。
... [redacted] ... - access_log:1241 - ::1:49525 - GET /
... [redacted] ... - access_log:1157 - ::1:49524 - GET localhost:8899/ - 404 NOT FOUND - 70 bytes
FilterByUpstreamHostPlugin
通过检查上游主机丢弃流量。默认情况下,插件会丢弃facebook.com和的流量www.facebok.com。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.FilterByUpstreamHostPlugin
验证使用curl -v -x localhost:8899 http://facebook.com:
... [redacted] ...
< HTTP/1.1 418 I'm a tea pot
< Proxy-agent: proxy.py v1.0.0
* no chunk, no close, no size. Assume close to signal end
<
* Closing connection 0
以上418 I'm a tea pot是我们的插件发送的。
通过检查日志来验证proxy.py:
... [redacted] ... - handle_readables:1347 - HttpProtocolException type raised
Traceback (most recent call last):
... [redacted] ...
... [redacted] ... - access_log:1157 - ::1:49911 - GET None:None/ - None None - 0 bytes
缓存响应插件
缓存上游服务器响应。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.CacheResponsesPlugin
您还可以使用该--cache-requests标志来启用请求数据包缓存以进行检查。
验证使用curl -v -x localhost:8899 http://httpbin.org/get:
... [redacted] ...
< HTTP/1.1 200 OK
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: *
< Content-Type: application/json
< Date: Wed, 25 Sep 2019 02:24:25 GMT
< Referrer-Policy: no-referrer-when-downgrade
< Server: nginx
< X-Content-Type-Options: nosniff
< X-Frame-Options: DENY
< X-XSS-Protection: 1; mode=block
< Content-Length: 202
< Connection: keep-alive
<
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
},
"origin": "1.2.3.4, 5.6.7.8",
"url": "https://httpbin.org/get"
}
* Connection #0 to host localhost left intact
proxy.py从日志中获取缓存文件的路径:
... [redacted] ... - GET httpbin.org:80/get - 200 OK - 556 bytes
... [redacted] ... - Cached response at /var/folders/k9/x93q0_xn1ls9zy76m2mf2k_00000gn/T/httpbin.org-1569378301.407512.txt
验证缓存文件的内容cat /path/to/your/cache/httpbin.org.txt
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Wed, 25 Sep 2019 02:24:25 GMT
Referrer-Policy: no-referrer-when-downgrade
Server: nginx
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Content-Length: 202
Connection: keep-alive
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
},
"origin": "1.2.3.4, 5.6.7.8",
"url": "https://httpbin.org/get"
}
中间人插件
修改上游服务器响应。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.ManInTheMiddlePlugin
验证使用curl -v -x localhost:8899 http://google.com:
... [redacted] ...
< HTTP/1.1 200 OK
< Content-Length: 28
<
* Connection #0 to host localhost left intact
Hello from man in the middle
响应正文Hello from man in the middle由我们的插件发送。
代理池插件
将传入的代理请求转发到一组上游代理服务器。
让我们先启动 2 个上游代理。要模拟上游代理,请proxy.py在端口9000和9001
❯ proxy --port 9000
❯ proxy --port 9001
现在,从proxy.py(ProxyPoolPlugin在默认8899端口上)开始,指向我们的上游代理9000和9001端口。
❯ proxy \
--plugins proxy.plugin.ProxyPoolPlugin \
--proxy-pool localhost:9000 \
--proxy-pool localhost:9001
通过8899代理发出 curl 请求:
curl -v -x localhost:8899 http://httpbin.org/get
通过检查相应的日志来验证8899代理是否将请求转发到上游代理。
如果上游代理需要凭据,请将它们作为参数传递。例子:
--proxy-pool user:pass@upstream.proxy:port
FilterByClientIpPlugin
拒绝来自特定 IP 地址的流量。默认情况下,此插件会阻止来自127.0.0.1和的流量::1。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.FilterByClientIpPlugin
使用发送请求curl -v -x localhost:8899 http://google.com:
... [redacted] ...
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 418 I'm a tea pot
< Connection: close
<
* Closing connection 0
根据您的喜好修改插件,例如只允许特定的 IP 地址。
修改ChunkResponsePlugin
这个插件演示了如何修改分块编码的响应。为了做到这一点,这个插件使用proxy.py核心来解析分块编码的响应。然后我们使用自定义硬编码块重建响应,忽略从上游服务器接收到的原始块。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.ModifyChunkResponsePlugin
验证使用curl -v -x localhost:8899 http://httpbin.org/stream/5:
... [redacted] ...
modify
chunk
response
plugin
* Connection #0 to host localhost left intact
* Closing connection 0
ModifyChunkResponsePlugin根据你的口味修改。例如,不是发送硬编码的块,而是解析和修改JSON从上游服务器接收到的原始块。
CloudflareDnsResolverPlugin
该插件使用Cloudflare托管DNS-over-HTTPS API (json)。
DoH要求使用符合 HTTP2 的客户端。不幸的是proxy.py
还没有提供,所以我们使用依赖项。安装它:
❯ pip install "httpx[http2]"
现在开始proxy.py:
❯ proxy \
--plugins proxy.plugin.CloudflareDnsResolverPlugin
默认情况下,CloudflareDnsResolverPlugin以security模式运行并提供恶意软件防护。也可用于--cloudflare-dns-mode family启用成人内容保护。
CustomDnsResolverPlugin
这个插件演示了如何使用自定义 DNS 解析实现proxy.py。这个示例插件当前使用 Python 的内置解析机制。根据您的喜好自定义代码。例如,查询您的自定义 DNS 服务器、实施DoH或其他机制。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.CustomDnsResolverPlugin
自定义网络接口
HttpProxyBasePlugin.resolve_dnscallback 也可用于配置network interface必须使用哪个作为source_address连接上游服务器的连接。
有关更多详细信息,请参阅此线程 。
PS:没有插件命名,但是CustomDnsResolverPlugin 可以根据你的需要轻松定制。
程序名插件
尝试解析(application)来自本地机器的代理请求的程序名称。如果识别,访问日志中的客户端 IP 将替换为程序名称。
开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.ProgramNamePlugin
使用以下命令发出请求curl:
❯ curl -v -x localhost:8899 https://httpbin.org/get
您必须看到这样的日志行:
... [redacted] ... - [I] server.access_log:419 - curl:58096 - CONNECT httpbin.org:443 - 6010 bytes - 1824.62ms
通知curl就地::1或127.0.0.1作为客户端 IP。
如果
ProgramNamePlugin在您的操作系统上无法可靠运行,请通过发送拉取请求和/或打开问题来贡献。谢谢!!!
HTTP Web 服务器插件
Web 服务器路由
演示使用插件的内置 Web 服务器路由。
开始proxy.py为:
❯ proxy --enable-web-server \
--plugins proxy.plugin.WebServerPlugin
验证 using curl -v localhost:8899/http-route-example,应该返回:
HTTP route response
反向代理插件
扩展内置 Web 服务器以添加反向代理功能。
反向代理
开始proxy.py为:
❯ proxy --enable-reverse-proxy \
--plugins proxy.plugin.ReverseProxyPlugin
使用默认配置,ReverseProxyPlugin插件相当于以下Nginx配置:
location /get {
proxy_pass http://httpbin.org/get
}
验证使用curl -v localhost:8899/get:
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "localhost",
"User-Agent": "curl/7.64.1"
},
"origin": "1.2.3.4, 5.6.7.8",
"url": "https://localhost/get"
}
插件订购
当使用多个插件时,根据插件的功能,可能值得考虑插件在命令行中传递的顺序。
插件的调用顺序与传递它们的顺序相同。例如,假设我们同时使用FilterByUpstreamHostPlugin和
RedirectToCustomServerPlugin。想法是丢弃所有传入http
的请求,facebook.com并将www.facebook.com其他请求重定向
http到我们的内置 Web 服务器。
FilterByUpstreamHostPlugin因此,在这种情况下,使用before很重要
RedirectToCustomServerPlugin。如果我们启用RedirectToCustomServerPluginbefore FilterByUpstreamHostPlugin,
facebook请求也会被重定向到内置的 Web 服务器,而不是被丢弃。
端到端加密
默认情况下,proxy.py使用http协议与客户端进行通信,curl例如browser. tls使用/https首先生成证书启用端到端加密。签出存储库并运行:
make https-certificates
开始proxy.py为:
❯ proxy \
--cert-file https-cert.pem \
--key-file https-key.pem
验证使用curl -x https://localhost:8899 --proxy-cacert https-cert.pem https://httpbin.org/get:
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
},
"origin": "1.2.3.4, 5.6.7.8",
"url": "https://httpbin.org/get"
}
如果您想避免传递--proxy-cacert标志,还可以考虑签署生成的 SSL 证书。例子:
首先,生成CA证书:
make ca-certificates
然后,签署 SSL 证书:
make sign-https-certificates
--cert-file https-signed-cert.pem现在用标志重新启动服务器。请注意,您还必须信任ca-cert.pem在您的系统钥匙串中生成的。
TLS 拦截
默认情况下,proxy.py不会解密https客户端和服务器之间的流量。要启用 TLS 拦截,首先生成根 CA 证书:
❯ make ca-certificates
让我们也启用CacheResponsePlugin,以便我们可以验证来自服务器的解密响应。开始proxy.py为:
❯ proxy \
--plugins proxy.plugin.CacheResponsesPlugin \
--ca-key-file ca-key.pem \
--ca-cert-file ca-cert.pem \
--ca-signing-key-file ca-signing-key.pem
还提供验证对等证书所需的显式 CA 捆绑路径。见
--ca-file旗。
验证 TLS 拦截使用curl
❯ curl -v -x localhost:8899 --cacert ca-cert.pem https://httpbin.org/get
* issuer: C=US; ST=CA; L=SanFrancisco; O=proxy.py; OU=CA; CN=Proxy PY CA; emailAddress=proxyca@mailserver.com
* SSL certificate verify ok.
> GET /get HTTP/1.1
... [redacted] ...
< Connection: keep-alive
<
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
},
"origin": "1.2.3.4, 5.6.7.8",
"url": "https://httpbin.org/get"
}
该issuer行确认响应已被拦截。
还要验证缓存响应文件的内容。proxy.py从日志中获取缓存文件的路径。
❯ cat /path/to/your/tmp/directory/httpbin.org-1569452863.924174.txt
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Content-Type: application/json
Date: Wed, 25 Sep 2019 23:07:05 GMT
Referrer-Policy: no-referrer -when-downgrade
服务器:nginx
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1;模式=块
内容长度:202
连接:保持活动
{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.54.0"
},
"origin": "1.2.3.4, 5.6.7.8",
"url": "https://httpbin.org/get"
}
中提琴!!!如果您删除 CA 标志,将在缓存文件中找到加密数据,而不是纯文本。
现在将 CA 标志与其他
插件示例一起使用,以查看它们如何处理https流量。
使用 Docker 进行 TLS 拦截
使用 Docker 容器进行 TLS 拦截的重要说明:
-
由于
v2.2.0dockerproxy.py容器还附带openssl. 这允许proxy.py为 TLS 拦截动态生成证书。 -
出于安全原因,
proxy.pydocker 容器不附带 CA 证书。
以下是如何proxy.py使用 TLS 拦截启动 docker 容器:
-
在主机上生成 CA 证书
❯ make ca-certificates -
将所有生成的证书复制到一个单独的目录中。稍后我们将把这个目录挂载到我们的 docker 容器中
❯ mkdir /tmp/ca-certificates ❯ cp ca-cert.pem ca-key.pem ca-signing-key.pem /tmp/ca-certificates
-
启动 docker 容器
❯ docker run -it --rm \ -v /tmp/ca-certificates:/tmp/ca-certificates \ -p 8899:8899 \ abhinavsingh/proxy.py:latest \ --hostname 0.0.0.0 \ --plugins proxy.plugin.CacheResponsesPlugin \ --ca-key-file /tmp/ca-certificates/ca-key.pem \ --ca-cert-file /tmp/ca-certificates/ca-cert.pem \ --ca-signing-key /tmp/ca-certificates/ca-signing-key.pem
-v /tmp/ca-certificates:/tmp/ca-certificatesflag 在容器环境中挂载我们的 CA 证书目录--plugins proxy.plugin.CacheResponsesPlugin启用CacheResponsesPlugin,以便我们可以检查拦截的流量--ca-*标志启用 TLS 拦截。
-
从另一个终端,尝试使用 TLS 拦截
curl。--cacert如果 CA 证书已被系统信任,您可以省略flag。❯ curl -v \ --cacert ca-cert.pem \ -x 127.0.0.1:8899 \ https://httpbin.org/get
-
验证
issuer响应标头中的字段。* Server certificate: * subject: CN=httpbin.org; C=NA; ST=Unavailable; L=Unavailable; O=Unavailable; OU=Unavailable * start date: Jun 17 09:26:57 2020 GMT * expire date: Jun 17 09:26:57 2022 GMT * subjectAltName: host "httpbin.org" matched cert's "httpbin.org" * issuer: CN=example.com * SSL certificate verify ok.
-
回到 docker 终端,复制响应转储路径日志。
...[redacted]... [I] access_log:338 - 172.17.0.1:56498 - CONNECT httpbin.org:443 - 1031 bytes - 1216.70 ms ...[redacted]... [I] close:49 - Cached response at /tmp/httpbin.org-ae1a927d064e4ab386ea319eb38fe251.txt
-
在另一个终端中,
cat响应转储:❯ docker exec -it $(docker ps | grep proxy.py | awk '{ print $1 }') cat /tmp/httpbin.org-ae1a927d064e4ab386ea319eb38fe251.txt HTTP/1.1 200 OK ...[已编辑]..