Skip to main content

⚡ 快 •

项目描述

代理.Py

皮皮月刊 码头工人拉 无依赖 吉特 执照

使用 MacOS、Ubuntu、Windows、Android、Android 模拟器、iOS、iOS 模拟器测试 安卓,安卓模拟器 iOS, iOS 模拟器

pypi版本 Python 3.x 用 mypy 检查

文档 编解码器 库

欢迎投稿 需要帮忙 由 Jaxl Innovations Private Limited 赞助

目录

特征

  • 快速且可扩展

    • 通过使用系统上的所有可用内核进行扩展

    • 使用 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 库外,没有外部依赖项
  • 可编程的

  • 可以监听多个端口

    • 使用--ports标志提供额外的端口
    • (可选)使用--port标志覆盖默认端口8899
    • 能够在同一个端口上服务多个协议
  • 实时仪表板

  • 安全的

    • 在客户端和客户端之间启用端到端加密proxy.py
    • 请参阅端到端加密
  • 私人的

    • 防御基于 DNS 的流量拦截器
    • 浏览启用恶意软件和成人内容保护
    • 请参阅DNS-over-HTTPS
  • 中间人

    • 可以解密客户端和上游服务器之间的 TLS 流量
    • 请参阅TLS 拦截
  • 代理请求支持的 http 协议

    • http(s)
      • http1
      • http1.1带管道
    • http2
    • websockets
  • 支持HAProxy Protocol

    • --enable-proxy-protocol标志
  • 静态文件服务器支持

    • 查看--enable-static-server--static-server-dir标记
  • 针对大文件上传和下载进行了优化

    • --client-recvbuf-size, --server-recvbuf-size,--max-sendbuf-size标志
  • IPv4IPv6支持

    • --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/386
  • linux/amd64
  • linux/arm/v6
  • linux/arm/v7
  • linux/arm64/v8
  • linux/ppc64le
  • linux/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 plugin

    • proxy.pyproxy.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,请参阅CustomNetworkInterfaceproxy.py
  • Port 8899

    • 使用--portflag 自定义默认 TCP 端口。

启用调试日志记录

以上所有日志均为INFO级别日志,默认--log-levelproxy.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 = DEBUG
  • i = INFO
  • w = WARNING
  • e = ERROR
  • c = 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 映像捆绑在一起。

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"
}

请注意以下回复:

  1. POST 数据已修改"data": "{\"key\": \"modified\"}"。原始curl命令数据是{"key": "value"}.
  2. 我们的curl命令没有添加任何Content-Type标题,但我们的插件确实添加了一个"Content-Type": "application/json". 同样也可以通过查看json上面输出中的字段来验证:
    "json": {
     "key": "modified"
    },
    
  3. 我们的插件还添加了一个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:portNone只是意味着从未建立服务器连接,因为我们的插件返回了响应。

现在修改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在端口90009001

❯ proxy --port 9000
❯ proxy --port 9001

现在,从proxy.pyProxyPoolPlugin在默认8899端口上)开始,指向我们的上游代理90009001端口。

❯ 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

默认情况下,CloudflareDnsResolverPluginsecurity模式运行并提供恶意软件防护。也可用于--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就地::1127.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"
}

插件订购

当使用多个插件时,根据插件的功能,可能值得考虑插件在命令行中传递的顺序。

插件的调用顺序与传递它们的顺序相同。例如,假设我们同时使用FilterByUpstreamHostPluginRedirectToCustomServerPlugin。想法是丢弃所有传入http 的请求,facebook.com并将www.facebook.com其他请求重定向 http到我们的内置 Web 服务器。

FilterByUpstreamHostPlugin因此,在这种情况下,使用before很重要 RedirectToCustomServerPlugin。如果我们启用RedirectToCustomServerPluginbefore FilterByUpstreamHostPluginfacebook请求也会被重定向到内置的 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 容器:

  1. 在主机上生成 CA 证书

    ❯ make ca-certificates
    
  2. 将所有生成的证书复制到一个单独的目录中。稍后我们将把这个目录挂载到我们的 docker 容器中

    ❯ mkdir /tmp/ca-certificates
    ❯ cp ca-cert.pem ca-key.pem ca-signing-key.pem /tmp/ca-certificates
    
  3. 启动 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 拦截。
  4. 从另一个终端,尝试使用 TLS 拦截curl--cacert如果 CA 证书已被系统信任,您可以省略flag。

    ❯ curl -v \
        --cacert ca-cert.pem \
        -x 127.0.0.1:8899 \
        https://httpbin.org/get
    
  5. 验证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.
    
  6. 回到 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
    
  7. 在另一个终端中,cat响应转储:

    ❯ docker exec -it $(docker ps | grep proxy.py | awk '{ print $1 }') cat /tmp/httpbin.org-ae1a927d064e4ab386ea319eb38fe251.txt 
    HTTP/1.1 200 OK 
    ...[已编辑]..