Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
proxy.py — 💫 Ngrok FRPの代替 • ⚡ 高速 • 🪶 軽量 • 0️⃣ 依存関係なし • 🔌 プラグイン可能 • 😈 TLS傍受 • 🔒 DNS-over-HTTPS • 🔥 貧者のVPN • ⏪ リバース & ⏩ フォワード • 👮🏿 「プロキシサーバー」フレームワーク • 🌐 「ウェブサーバー」フレームワーク • ➵ ➶ ➷ ➠ 「PubSub」フレームワーク • 👷 「ワーク」アクセプター&エグゼキューターフレームワーク | Kitploit
ツール/GitHubGitHub/abhinavsingh/proxy.py
ウェブプロキシと傍受ペネトレーションテストユーティリティとフレームワークレッドチーミング
GitHubabhinavsingh/proxy.py

proxy.py

💫 Ngrok FRPの代替 • ⚡ 高速 • 🪶 軽量 • 0️⃣ 依存関係なし • 🔌 プラグイン可能 • 😈 TLS傍受 • 🔒 DNS-over-HTTPS • 🔥 貧者のVPN • ⏪ リバース & ⏩ フォワード • 👮🏿 「プロキシサーバー」フレームワーク • 🌐 「ウェブサーバー」フレームワーク • ➵ ➶ ➷ ➠ 「PubSub」フレームワーク • 👷 「ワーク」アクセプター&エグゼキューターフレームワーク

リポジトリを見る
3.5k6291年前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有
ウェブサイト

Proxy.Py

PyPi Monthly Docker Pulls No Dependencies Gitter License

Tested With MacOS, Ubuntu, Windows, Android, Android Emulator, iOS, iOS Simulator Android, Android Emulator iOS, iOS Simulator

pypi version Python 3.x Checked with mypy

doc codecov lib

Contributions Welcome Need Help Sponsored by Jaxl Innovations Private Limited

目次

  • 機能
  • インストール
    • PIPを使用
      • 安定版
      • 開発版
    • Dockerを使用
      • Docker Hubからの安定版
      • GHCRからの開発版
      • コンテナをローカルでビルド
    • HomeBrewを使用
      • 安定版
      • 開発版
  • proxy.pyを起動
    • PIPでインストールした場合のコマンドラインから
      • 実行
      • ログの理解
      • DEBUGログを有効化
    • リポジトリソースからのコマンドライン
    • Dockerイメージ
      • 起動フラグのカスタマイズ
  • プラグイン例
    • HTTPプロキシプラグイン
      • ShortLinkプラグイン
      • POSTデータ変更プラグイン
      • Mock Apiプラグイン
      • カスタムサーバーへのリダイレクトプラグイン
      • アップストリームホストによるフィルタープラグイン
      • レスポンスキャッシュプラグイン
      • レスポンスタイプによるキャッシュ
      • 中間者プラグイン
      • プロキシプールプラグイン
      • クライアントIPによるフィルタープラグイン
      • チャンクレスポンス変更プラグイン
      • リクエストヘッダー変更プラグイン
      • Cloudflare DNSリゾルバープラグイン
      • カスタムDNSリゾルバープラグイン
      • カスタムネットワークインターフェース
      • プログラム名プラグイン
    • HTTP Webサーバープラグイン

機能

  • ngrokのドロップイン代替

  • 高速かつスケーラブル

    • システム上の全てのコアを利用してスケールアップ

    • asyncioを使用したスレッドレス実行

    • 数万コネクション/秒を処理可能

      root@kitploit:~
      # On Macbook Pro M2 2022
      ❯ python --version
      Python 3.11.8
      ❯ oha --version
      oha 1.4.3
      ❯ ./benchmark/compare.sh
        CONCURRENCY: 100 workers, DURATION: 1m, TIMEOUT: 1sec
        =============================
        Benchmarking Proxy.Py
        Server (pid:75969) running
        Summary:
          Success rate: 100.00%
          Total:        60.0006 secs
          Slowest:      0.2525 secs
          Fastest:      0.0002 secs
          Average:      0.0019 secs
          Requests/sec: 51667.3774
      
          Total data:   56.17 MiB
          Size/request: 19 B
          Size/sec:     958.64 KiB
      
        Response time histogram:
          0.000 [1]       |
          0.025 [3073746] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
          0.051 [10559]   |
          0.076 [4980]    |
          0.101 [2029]    |
          0.126 [5896]    |
          0.152 [2466]    |
          0.177 [116]     |
          0.202 [40]      |
          0.227 [52]      |
          0.253 [87]      |
      
        Response time distribution:
          10.00% in 0.0005 secs
          25.00% in 0.0007 secs
          50.00% in 0.0009 secs
          75.00% in 0.0014 secs
          90.00% in 0.0021 secs
          95.00% in 0.0035 secs
          99.00% in 0.0198 secs
          99.90% in 0.1262 secs
          99.99% in 0.1479 secs
      
        Details (average, fastest, slowest):
          DNS+dialup:   0.0018 secs, 0.0004 secs, 0.0031 secs
          DNS-lookup:   0.0000 secs, 0.0000 secs, 0.0002 secs
      
        Status code distribution:
          [200] 3099972 responses
      
        Error distribution:
          [100] aborted due to deadline
        =============================
      

インストール

proxy.pyを使用した本番環境向けアプリケーションのデプロイについては、proxy.pyを本番環境にデプロイするを参照してください。

PIPを使用

Pipによる安定版のインストール

PyPiからインストール```console ❯ pip install --upgrade proxy.py

root@kitploit:~
または GitHub の `master` ブランチ```console
❯ pip install git+https://github.com/abhinavsingh/proxy.py.git@master

PIPを使用した開発版```console

❯ pip install git+https://github.com/abhinavsingh/proxy.py.git@develop

root@kitploit:~
## Dockerの使用

マルチプラットフォームコンテナは以下から入手可能です:

- Docker Hub
  - `latest` タグは最後の `stable` リリースを指します
  - `docker pull abhinavsingh/proxy.py:latest`
- GitHub Container Registry (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` の最新コンテナを実行:```console
❯ docker run -it -p 8899:8899 --rm abhinavsingh/proxy.py:latest

Dockerデーモンは自動的に該当するプラットフォームのイメージをプルします。 マルチプラットフォーム対応のサーバーで特定のターゲットプラットフォームのコンテナを実行するには:```console ❯ docker run -it -p 8899:8899 --rm --platform linux/arm64/v8 abhinavsingh/proxy.py:latest

root@kitploit:~
### GHCRからの開発バージョン

developブランチの最先端コードから `proxy.py` コンテナを実行します:```console
❯ docker run -it -p 8899:8899 --rm ghcr.io/abhinavsingh/proxy.py:latest

開発版をローカルでビルドする```console

❯ git clone https://github.com/abhinavsingh/proxy.py.git ❯ cd proxy.py && make container ❯ docker run -it -p 8899:8899 --rm abhinavsingh/proxy.py:latest

root@kitploit:~
[![WARNING](https://img.shields.io/static/v1?label=MacOS&message=warning&color=red)](https://github.com/moby/vpnkit/issues/469)
`docker` イメージは現在、[vpnkit](https://github.com/moby/vpnkit/issues/469) との互換性の問題により `macOS` で動作していません。

## HomeBrew の使用

`HomeBrew` 用の更新されたフォーミュラは、`helper/homebrew` ディレクトリ内の `develop` ブランチで管理されています。

- `stable` フォーミュラは `master` ブランチからパッケージをインストールします。
- `develop` フォーミュラは `develop` ブランチからパッケージをインストールします。

### HomeBrew での安定版```console
❯ brew install https://raw.githubusercontent.com/abhinavsingh/proxy.py/develop/helper/homebrew/stable/proxy.rb

HomeBrewを使用した開発版```console

❯ brew install https://raw.githubusercontent.com/abhinavsingh/proxy.py/develop/helper/homebrew/develop/proxy.rb

root@kitploit:~
# Start proxy.py

## PIPでインストールした場合のコマンドラインから

`proxy.py` が `pip` でインストールされると、
`proxy` という名前の実行ファイルが `$PATH` 配下に配置されます。

### 実行する

デフォルト設定で起動するには、コマンドラインに `proxy` と入力するだけです。```console
❯ 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.py はデフォルトで proxy.http.proxy.HttpProxyPlugin を読み込みます
    • 名前が示す通り、このコアプラグインは http(s) プロキシサーバー機能を proxy.py インスタンスに追加します
  • Started N threadless workers

    • デフォルトでは、proxy.py はマシンのCPUコア数と同じ数のワーカープロセスを起動します
    • ワーカープロセスの数をカスタマイズするには --num-workers フラグを使用します
    • 実行モードを制御する方法については スレッド vs スレッドレス を参照してください
  • Started N acceptors

    • デフォルトでは、proxy.py はマシンのCPUコア数と同じ数のアクセプタープロセスを起動します
    • アクセプタープロセスの数をカスタマイズするには --num-acceptors フラグを使用します
    • アクセプターとワーカーの関係を理解するには 高レベルアーキテクチャ を参照してください
  • Started server on ::1:8899

DEBUG ログの有効化

上記のログはすべて INFO レベルのログで、proxy.py のデフォルトの --log-level です。

proxy.py を DEBUG レベルのログで起動してみましょう:```console ❯ 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

root@kitploit:~
ログレベルをカスタマイズするために、1文字を使用できます。例:
- `d = DEBUG`
- `i = INFO`
- `w = WARNING`
- `e = ERROR`
- `c = CRITICAL`

上記のログからわかるように、起動前には:

- `proxy.py` はシステムのオープンファイル制限 `ulimit` の設定を試みました。
- 使用された `--open-file-limit` のデフォルト値は `1024` です。
- `--open-file-limit` フラグは `Windows` オペレーティングシステムでは無効です。

利用可能な全設定オプションの一覧は [flags](#flags) を参照してください。

## コマンドラインからリポジトリソースを使用する場合

ソースコードから `proxy.py` を実行しようとしている場合、
ソースコードには `proxy` という名前のバイナリファイルはありません。

ソースコードから `proxy.py` を起動するには、以下の手順に従ってください:

- リポジトリをクローンする  ```console
  ❯ git clone https://github.com/abhinavsingh/proxy.py.git
  ❯ cd proxy.py
  • Python 3の仮想環境を作成する ```console ❯ python3 -m venv venv ❯ source venv/bin/activate

    root@kitploit:~
  • 依存関係をインストール ```console ❯ make lib-dep

    root@kitploit:~
  • 生成する proxy/common/_scm_version.py

    注記: 次の手順は編集可能インストールには必要ありません。

    このファイルはSCM検出バージョンを proxy/common/_scm_version.py ファイルに書き込みます。 ```console ❯ ./write-scm-version.sh

    root@kitploit:~
  • オプションで、テストを実行する ```console ❯ make

    root@kitploit:~
  • proxy.py を実行 ```console ❯ python -m proxy

    root@kitploit:~

プラグイン開発者・コントリビューターガイド を参照してください。 proxy.py のソースコードを扱う予定がある場合。

Docker イメージ

スタートアップフラグのカスタマイズ

デフォルトでは、docker バイナリは IPv4 ネットワーキングフラグで起動されます:

root@kitploit:~
--hostname 0.0.0.0 --port 8899

Docker コンテナを起動する際に、コマンドラインからフラグを上書きできます。例えば、Docker コンテナ内で proxy.py のバージョンを確認するには、以下を実行します:

root@kitploit:~
❯ docker run -it \
    -p 8899:8899 \
    --rm abhinavsingh/proxy.py:latest \
    -v

プラグインの例

  • 完全なコードは plugin モジュールを参照してください。
  • バンドルされているすべてのプラグイン例は https トラフィックでも動作します
    • 追加のフラグと証明書の生成が必要です
    • TLS インターセプション を参照してください。
  • プラグインの例は Docker イメージにもバンドルされています。
    • Docker イメージでプラグインを試すには、スタートアップフラグのカスタマイズ を参照してください。

HTTP プロキシプラグイン

ShortLinkPlugin

お気に入りのブラウザやアプリケーションでショートリンクをサポートします。

ショートリンクプラグイン

proxy.py を次のように起動します:```console ❯ proxy
--plugins proxy.plugin.ShortLinkPlugin

root@kitploit:~
Now you can speed up your daily browsing experience by visiting your favorite website using single character domain names :). This works across all browsers.

Following short links are enabled by default:

| ショートリンク |  宛先URL   |
| :--------: |  :--------------:  |
|     a/     |    `amazon.com`    |
|     i/     |  `instagram.com`   |
|     l/     |   `linkedin.com`   |
|     f/     |   `facebook.com`   |
|     g/     |    `google.com`    |
|     t/     |   `twitter.com`    |
|     w/     | `web.whatsapp.com` |
|     y/     |   `youtube.com`    |
|   proxy/   |  `localhost:8899`  |

### ModifyPostDataPlugin

Modifies POST request body before sending request to upstream server.

Start `proxy.py` as:```console
❯ proxy \
    --plugins proxy.plugin.ModifyPostDataPlugin

デフォルトでは、プラグインはPOSTボディの内容をハードコードされた b'{"key": "modified"}' に置き換え、 Content-Type: application/json を強制します。

curl -x localhost:8899 -d '{"key": "value"}' http://httpbin.org/post を使用して同じことを確認してください。```console { "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" }

root@kitploit:~
上記のレスポンスに続く注意:

1. POSTデータが変更されました `"data": "{\"key\": \"modified\"}"`。
   元の `curl` コマンドのデータは `{"key": "value"}` でした。
2. 私たちの `curl` コマンドは `Content-Type` ヘッダーを追加しませんでしたが、
   プラグインは `"Content-Type": "application/json"` を追加しました。
   同じことは、上記の出力の `json` フィールドを見ても確認できます:   ```
   "json": {
    "key": "modified"
   },
  1. 当プラグインは、変更されたボディの長さに合わせて Content-Length ヘッダーも追加します。

MockRestApiPlugin

サーバーのREST APIに対するモックレスポンスです。実際のアップストリームREST APIサーバーを必要とせずに、クライアントサイドアプリケーションのテストと開発に使用します。

proxy.py を次のように起動します:```console ❯ proxy
--plugins proxy.plugin.ProposedRestApiPlugin

root@kitploit:~
モックAPIレスポンスを確認するには、次のコマンドを使用します: `curl -x localhost:8899 http://api.example.com/v1/users/````console
{"count": 2, "next": null, "previous": null, "results": [{"email": "[email protected]", "groups": [], "url": "api.example.com/v1/users/1/", "username": "admin"}, {"email": "[email protected]", "groups": [], "url": "api.example.com/v1/users/2/", "username": "admin"}]}

同じことをproxy.pyのログを確認して検証してください。```console ... [redacted] ... - access_log:1210 - ::1:64792 - GET None:None/v1/users/ - None None - 0 byte

root@kitploit:~
Access log には、サーバーの `ip:port` として `None:None` と表示されます。`None` は、レスポンスがプラグインによって返されたため、サーバー接続が行われなかったことを意味します。

次に、`ProposedRestApiPlugin` を変更して、クライアントが期待する REST API のモックレスポンスを返すようにします。

### RedirectToCustomServerPlugin

すべての受信 `http` リクエストをカスタム Web サーバーにリダイレクトします。デフォルトでは、クライアントリクエストを同じく `8899` ポートで動作している組み込み Web サーバーにリダイレクトします。

`proxy.py` を起動し、組み込み Web サーバーを有効にします:```console
❯ 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
root@kitploit:~
上記の `404` レスポンスは `proxy.py` Web サーバーから返されました。

`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 を以下のように起動します:```console ❯ proxy
--plugins proxy.plugin.FilterByUpstreamHostPlugin

root@kitploit:~
次を使用して確認: `curl -v -x localhost:8899 http://facebook.com````console
... [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 のログを確認して、同じことを検証してください:```console ... [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

root@kitploit:~
### CacheResponsesPlugin

上流サーバーのレスポンスをキャッシュします。

`proxy.py` を以下のように起動します:```console
❯ proxy \
    --plugins proxy.plugin.CacheResponsesPlugin

リクエストパケットキャッシュを有効にして検査するために、--cache-requests フラグを使用することもできます。

以下を使用して確認します: curl -v -x localhost:8899 http://httpbin.org/get:```console ... [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
root@kitploit:~
キャッシュファイルへのパスを `proxy.py` のログから取得する:```console
... [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````console 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" }

root@kitploit:~
### CacheByResponseType

`CacheResponsesPlugin` プラグインは、`content-type` に基づいてレスポンスを自動的にキャッシュすることもできます。
これを使用するには、[TLS Interception](#tls-interception) モードで実行し、
その後 `--cache-by-content-type` フラグを指定する必要があります。例:```console
❯ proxy \
    --plugins proxy.plugin.CacheResponsesPlugin \
    --cache-by-content-type \
    --ca-key-file ca-key.pem \
    --ca-cert-file ca-cert.pem \
    --ca-signing-key ca-signing-key.pem

プロキシサーバーにいくつかリクエストを行うと、~/.proxy/cache ディレクトリの下にデータが表示されます。

2つのフォルダが表示されます:

  • content: コンテンツタイプごとに解析された jpg、css、js、html、pdf などが含まれます
  • responses: 受信した生のレスポンスが含まれます(傍受により復号化されています)

ManInTheMiddlePlugin

上流サーバーのレスポンスを変更します。

proxy.py を次のように起動します:```console ❯ proxy
--plugins proxy.plugin.ManInTheMiddlePlugin

root@kitploit:~
次を使用して `curl -v -x localhost:8899 http://google.com`:```console
... [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 は当プラグインによって送信されます。

ProxyPoolPlugin

受信したプロキシリクエストを一連の上流プロキシサーバーに転送します。

まず、2つの上流プロキシを起動します。 上流プロキシをシミュレートするには、ポート 9000 と 9001 で proxy.py を起動してください。```console ❯ proxy --port 9000

root@kitploit:~
翻訳対象のMarkdownコンテンツが提供されていません。内容を入力してください。```console
❯ proxy --port 9001

次に、proxy.py を ProxyPoolPlugin とともに(デフォルトの 8899 ポートで)起動し、上流プロキシの 9000 ポートと 9001 ポートを指定します。```console ❯ proxy
--plugins proxy.plugin.ProxyPoolPlugin
--proxy-pool localhost:9000
--proxy-pool localhost:9001

root@kitploit:~
`8899`プロキシを介してcurlリクエストを送信します:

`curl -v -x localhost:8899 http://httpbin.org/get`

`8899`プロキシがリクエストを上流プロキシに転送していることを、それぞれのログを確認して検証します。

上流プロキシが認証情報を必要とする場合は、引数として渡します。例:

`--proxy-pool user:[email protected]:port`

### FilterByClientIpPlugin

特定のIPアドレスからのトラフィックを拒否します。デフォルトでは、このプラグインは`127.0.0.1`と`::1`からのトラフィックをブロックします。

`proxy.py`を次のように起動します:```console
❯ proxy \
    --plugins proxy.plugin.FilterByClientIpPlugin

リクエストを送信するには curl -v -x localhost:8899 http://google.com を使用します:```console ... [redacted] ...

Proxy-Connection: Keep-Alive

< HTTP/1.1 418 I'm a tea pot < Connection: close <

  • Closing connection 0
root@kitploit:~
プラグインを好みに合わせて変更してください。例:特定のIPアドレスのみを許可する。

### ModifyChunkResponsePlugin

このプラグインは、チャンクエンコードされたレスポンスを変更する方法を示します。それを可能にするために、このプラグインは`proxy.py`のコアを使用してチャンクエンコードされたレスポンスを解析します。その後、上流サーバーから受信した元のチャンクを無視し、カスタムのハードコードされたチャンクを使用してレスポンスを再構築します。

`proxy.py`を次のように起動します:```console
❯ proxy \
    --plugins proxy.plugin.ModifyChunkResponsePlugin

検証には次を使用します: curl -v -x localhost:8899 http://httpbin.org/stream/5:```console ... [redacted] ... modify chunk response plugin

  • Connection #0 to host localhost left intact
  • Closing connection 0
root@kitploit:~
`ModifyChunkResponsePlugin` をお好みに合わせて変更してください。例: ハードコードされたチャンクを送信する代わりに、上流サーバーから受信した元の `JSON` チャンクを解析して変更します。

### ModifyRequestHeaderPlugin

このプラグインは、TLS インターセプションモードで送信 HTTPS リクエストヘッダーを変更する方法を示します。

`proxy.py` を次のように起動します:```console
❯ proxy \
    --plugins proxy.plugin.ModifyRequestHeaderPlugin \
    ... [TLS interception flags] ...

次のコマンドで確認します:curl -x localhost:8899 --cacert ca-cert.pem https://httpbin.org/get:```console { "args": {}, "headers": { ... [redacted] ..., "X-Proxy-Py-Version": "2.4.4rc6.dev15+gf533c711" }, ... [redacted] ... }

root@kitploit:~
### CloudflareDnsResolverPlugin

このプラグインは、Cloudflareがホストする`DNS-over-HTTPS` [API](https://developers.cloudflare.com/1.1.1.1/encrypted-dns/dns-over-https/make-api-requests/dns-json)(json)を使用します。

`DoH` は HTTP2 準拠のクライアントを必須とします。残念ながら `proxy.py` はまだそれを提供していないため、依存関係を使用します。インストール:```console
❯ pip install "httpx[http2]"

ここで proxy.py を次のように起動します:```console ❯ proxy
--plugins proxy.plugin.CloudflareDnsResolverPlugin

root@kitploit:~
デフォルトでは、`CloudflareDnsResolverPlugin` は `security` モードで動作し、マルウェア対策を提供します。
`--cloudflare-dns-mode family` を使用すると、アダルトコンテンツ保護も有効になります。

### CustomDnsResolverPlugin

このプラグインは、`proxy.py` でカスタム DNS 解決実装を使用する方法を示しています。
このサンプルプラグインは現在、Python の組み込み解決メカニズムを使用しています。コードはお好みに合わせてカスタマイズしてください。例:カスタム DNS サーバーにクエリを実行したり、`DoH` やその他のメカニズムを実装したりします。

`proxy.py` を次のように起動します。```console
❯ proxy \
    --plugins proxy.plugin.CustomDnsResolverPlugin

CustomNetworkInterface

HttpProxyBasePlugin.resolve_dns コールバックを使用して、アップストリームサーバーへの接続の source_address として使用する必要がある network interface を設定することもできます。

詳細はこちらのスレッドを参照してください。

PS: 同名のプラグインはありませんが、CustomDnsResolverPlugin は必要に応じて簡単にカスタマイズできます。

ProgramNamePlugin

ローカルマシンからのプロキシリクエストのプログラム (application) 名を解決しようとします。 識別された場合、アクセスログのクライアント IP はプログラム名に置き換えられます。

proxy.py を次のように起動します:```console ❯ proxy
--plugins proxy.plugin.ProgramNamePlugin

root@kitploit:~
`curl`を使ってリクエストを行う:```console
❯ curl -v -x localhost:8899 https://httpbin.org/get

以下のようなログ行が表示されるはずです:```console ... [redacted] ... - [I] server.access_log:419 - curl:58096 - CONNECT httpbin.org:443 - 6010 bytes - 1824.62ms

root@kitploit:~
注意:クライアントIPとして`::1`または`127.0.0.1`の代わりに`curl`を使用してください。

[![WARNING](https://img.shields.io/static/v1?label=Compatibility&message=warning&color=red)](#programnameplugin) お使いのオペレーティングシステムで`ProgramNamePlugin`が安定して動作しない場合は、プルリクエストを送信したり、Issueを開いたりしてご協力をお願いします。ありがとうございます!!!

## HTTP Webサーバープラグイン

### Webサーバールート

プラグインを使用した組み込みWebサーバールーティングのデモンストレーション。

以下のように`proxy.py`を起動します:

proxy.py --plugins proxy.plugin.WebServerRoutePlugin

root@kitploit:~
❯ proxy --enable-web-server \
    --plugins proxy.plugin.WebServerPlugin
```
`curl -v localhost:8899/http-route-example` を使用して確認します、次のように返されるはずです:```console
HTTP route response
```
## リバースプロキシプラグイン

内蔵Webサーバを拡張してリバースプロキシ機能を追加します。

### リバースプロキシ

以下のように `proxy.py` を起動します:```console
❯ proxy --enable-reverse-proxy \
    --plugins proxy.plugin.ReverseProxyPlugin
```
デフォルト設定では、`ReverseProxyPlugin` プラグインは次の `Nginx` 設定と同等です。```console
location /get {
    proxy_pass http://httpbin.org/get;
}
```
`curl -v localhost:8899/get` を使用して確認してください:```console
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "localhost",
    "User-Agent": "curl/7.64.1"
  },
  "origin": "1.2.3.4, 5.6.7.8",
  "url": "https://localhost/get"
}
```
#### Host Header の書き換え

上記の例では、次のように表示されることがあります:```console
>
* Empty reply from server
* Closing connection
curl: (52) Empty reply from server
```
これは、デフォルトのリバースプロキシプラグイン `ReverseProxyPlugin` が `http` および `https` アップストリームサーバーで構成されているために発生します。そして、デフォルトでは `ReverseProxyPlugin` は元のホストヘッダーを保持します。これは `https` アップストリームでは機能しますが、`http` アップストリームでは確実に機能しません。この問題を回避するには、`--rewrite-host-header` フラグを使用します。

例:```console
❯ proxy --enable-reverse-proxy \
    --plugins proxy.plugin.ReverseProxyPlugin \
    --rewrite-host-header
```
これにより、`Host`ヘッダーフィールドが `httpbin.org` に設定され、`http` と `https` の両方の上流で動作します。

> 注: `--rewrite-host-header` を使用するかどうかは、ユースケースによって異なります。

## プラグインの順序

複数のプラグインを使用する場合、プラグインの機能に応じて、コマンドラインでプラグインを渡す順序を考慮する価値があるかもしれません。

プラグインは渡された順序と同じ順序で呼び出されます。例えば、`FilterByUpstreamHostPlugin` と `RedirectToCustomServerPlugin` の両方を使用しているとします。考え方としては、`facebook.com` と `www.facebook.com` へのすべての受信 `http` リクエストをドロップし、その他の `http` リクエストを組み込みの Web サーバーにリダイレクトすることです。

したがって、このシナリオでは、`FilterByUpstreamHostPlugin` を `RedirectToCustomServerPlugin` の前に使用することが重要です。`RedirectToCustomServerPlugin` を `FilterByUpstreamHostPlugin` の前に有効にすると、`facebook` リクエストもドロップされる代わりに組み込みの Web サーバーにリダイレクトされてしまいます。

# エンドツーエンド暗号化

デフォルトでは、`proxy.py` は `http` プロトコルを使用してクライアント(例:`curl`、`browser`)と通信します。`tls` / `https` を使用したエンドツーエンド暗号化を有効にするには、まず証明書を生成します。**リポジトリをチェックアウト** して、以下を実行します。```console
make https-certificates
```
次のように `proxy.py` を起動します:```console
❯ 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````console
{
  "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証明書を生成します。```console
make ca-certificates
```
次に、SSL証明書に署名します:```console
make sign-https-certificates
```
これで、`--cert-file https-signed-cert.pem` フラグを指定してサーバーを再起動します。生成された `ca-cert.pem` をシステムのキーチェーンで信頼する必要があることに注意してください。

# TLS インターセプト

デフォルトでは、`proxy.py` はクライアントとサーバー間の `https` トラフィックを復号化しません。
TLS インターセプトを有効にするには、まずルート CA 証明書を生成します:```console
❯ make ca-certificates
```
また、`CacheResponsePlugin` を有効にして、サーバーからの復号された応答を確認できるようにしましょう。`proxy.py` を次のように起動します:```console
❯ 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
```
[![NOTE](https://img.shields.io/static/v1?label=MacOS&message=note&color=yellow)](https://github.com/abhinavsingh/proxy.py#user-content-flags) また、ピア証明書の検証に必要な明示的なCAバンドルパスを指定します。`--ca-file`フラグを参照してください。

`curl`を使用してTLSインターセプションを検証します。```console
❯ curl -v -x localhost:8899 --cacert ca-cert.pem https://httpbin.org/get
```
(empty output)```console
*  issuer: C=US; ST=CA; L=SanFrancisco; O=proxy.py; OU=CA; CN=Proxy PY CA; [email protected]
*  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````console
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
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"
}
```
できた!!! CAフラグを削除すると、暗号化されたデータがキャッシュされたファイル内に平文の代わりに見つかります。

次に、CAフラグを他の
[プラグイン例](#plugin-examples)と一緒に使用して、それらが`https`トラフィックで動作するのを確認してください。

## 安全でないTLSインターセプション

自己署名証明書を使用しているサーバーからのTLSトラフィックをインターセプトするには、`--insecure-tls-interception`フラグを追加して、必須のTLS証明書検証を無効にします。

注: このフラグはすべてのサーバーの証明書チェックを無効にします。

## DockerによるTLSインターセプション

DockerコンテナでのTLSインターセプションに関する重要な注意点:

- `v2.2.0`以降、`proxy.py` Dockerコンテナには`openssl`も同梱されています。これにより、`proxy.py`はTLSインターセプションのためにその場で証明書を生成できます。

- セキュリティ上の理由から、`proxy.py` DockerコンテナにはCA証明書は同梱されていません。

`proxy.py` Dockerコンテナを
TLSインターセプション付きで起動する方法は次のとおりです:

1. ホストコンピュータでCA証明書を生成します。   ```console
   ❯ make ca-certificates
   ```
2. 生成されたすべての証明書を別のディレクトリにコピーします。後ほど、このディレクトリをDockerコンテナにマウントします。   ```console
   ❯ mkdir /tmp/ca-certificates
   ❯ cp ca-cert.pem ca-key.pem ca-signing-key.pem /tmp/ca-certificates
   ```
3. Dockerコンテナを起動する   ```console
   ❯ 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-certificates` フラグは、CA証明書ディレクトリをコンテナ環境にマウントします
   - `--plugins proxy.plugin.CacheResponsesPlugin` は`CacheResponsesPlugin`を有効にし、傍受したトラフィックを検査できるようにします
   - `--ca-*` フラグはTLSインターセプションを有効にします。

4. 別のターミナルから、`curl`を使用してTLSインターセプションを試してください。CA証明書がシステムにすでに信頼されている場合は、`--cacert`フラグを省略できます。   ```console
   ❯ curl -v \
       --cacert ca-cert.pem \
       -x 127.0.0.1:8899 \
       https://httpbin.org/get
   ```
5. レスポンスヘッダーの `issuer` フィールドを確認します。   ```console
   * 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ターミナルに戻り、応答ダンプパスログをコピーします。   ```console
   ...[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` を使って応答ダンプを表示:   ```console
   ❯ docker exec -it $(docker ps | grep proxy.py | awk '{ print $1 }') cat /tmp/httpbin.org-ae1a927d064e4ab386ea319eb38fe251.txt
   HTTP/1.1 200 OK
   ...[redacted]...
   {
     ...[redacted]...,
     "url": "http://httpbin.org/get"
   }
   ```
# GROUT(NGROKの代替)

1. `grout`は`ngrok`および`frp`のドロップイン代替品です
2. `grout`は`proxy.py`に同梱されています

## Groutの使い方```console
❯ grout
NAME:
  grout - securely tunnel local files, folders and services to public URLs

USAGE:
  grout route [name]

DESCRIPTION:
  grout exposes local networked services behinds NATs and firewalls to the
  public internet over a secure tunnel. Share local folders, directories and websites,
  build/test webhook consumers and self-host personal services to public URLs.

EXAMPLES:
  Share Files and Folders:
    grout C:\path\to\folder                          # Share a folder on your system
    grout /path/to/folder                            # Share a folder on your system
    grout /path/to/folder --basic-auth user:pass     # Add authentication for shared folder
    grout /path/to/photo.jpg                         # Share a specific file on your system

  Expose HTTP, HTTPS and Websockets:
    grout http://localhost:9090                      # Expose HTTP service running on port 9090
    grout https://localhost:8080                     # Expose HTTPS service running on port 8080
    grout https://localhost:8080 --path /worker/     # Expose only certain paths of HTTPS service on port 8080
    grout https://localhost:8080 --basic-auth u:p    # Add authentication for exposed HTTPS service on port 8080

  Expose TCP Services:
    grout tcp://:6379                                # Expose Redis service running locally on port 6379
    grout tcp://:22                                  # Expose SSH service running locally on port 22

  Custom URLs:
    grout https://localhost:8080 abhinavsingh        # Custom URL for HTTPS service running on port 8080
    grout tcp://:22 abhinavsingh                     # Custom URL for SSH service running locally on port 22

  Custom Domains:
    grout tcp://:5432 abhinavsingh.domain.tld        # Custom URL for Postgres service running locally on port 5432

  Self-hosted solutions:
    grout tcp://:5432 abhinavsingh.my.server         # Custom URL for Postgres service running locally on port 5432

  (*) Wildcard Domains:
    grout https://host:443 do.main --wildcard        # Receive traffic on provided domain and all it's subdomains

  (*) Host based routing for Wildcard Domains:
    grout ... --tunnel-route-url host=https://h:p    # When using wildcards, optionally route traffic by incoming host header

SUPPORT:
  Write to us at [email protected]

  Privacy policy and Terms & conditions
  https://jaxl.com/privacy/

  Created by Jaxl™
  https://jaxl.io
```
## Grout 認証

Grout は、ファイル、フォルダ、サービスを不正アクセスから保護するための認証をサポートしています。認証を強制するには、`--basic-auth` フラグを使用します。例:```console
grout /path/to/folder --basic-auth user:pass
grout https://localhost:8080 --basic-auth u:p
```
## Grout パス

デフォルトでは、Grout はサービス上のすべてのパスへのアクセスを許可します。`--path` フラグを使用して、Web サービス上の特定のパスのみにアクセスを制限します。例:```console
grout https://localhost:8080 --path /worker/
grout https://localhost:8080 --path /webhook/ --path /callback/
```
## Grout ワイルドカードドメイン

デフォルトでは、Groutクライアントは専用のサブドメインで受信トラフィックを処理します。
ただし、一部のサービス(例:Kubernetes)は、アドホックなサブドメインでトラフィックを処理したい場合があります。
アドホックなサブドメインごとに専用のGroutクライアントを起動するのは実用的ではないかもしれません。

このようなシナリオのために、Groutはワイルドカードドメインをサポートしています。以下は、Groutクライアントで使用する独自のワイルドカードドメインを設定する方法です。

1. ドメインを選択します(例:`custom.example.com`)
2. あなたのサービスで`custom.example.com`と`*.custom.example.com`のトラフィックを処理したい場合
3. `https://`を使用する予定がある場合は、ロードバランサーを設定する必要があります。
   - HTTPSロードバランサー(LB)を設定
   - `custom.example.com`と`*.custom.example.com`用に生成された証明書でLBを構成
   - トラフィックをGroutサービスのパブリックIPアドレスに向ける
4. Groutチーム([email protected])に連絡して、`custom.example.com`をホワイトリストに登録します。Groutチームは、あなたが実際にドメインを所有しており、上記のように有効なSSL証明書を設定していることを確認します。

`--wildcard`フラグを付けてGroutを起動します。例:```console
grout https://localhost:8080 custom.example.com --wildcard
2024-08-05 18:24:59,294 - grout - Logged in as [email protected]
2024-08-05 18:25:03,159 - setup - Grouting https://*.custom.domain.com
```
## 「Host」ヘッダーに基づくGroutワイルドカードドメインルーティング

  > `--wildcard`でのみ利用可能

デフォルトルートに加えて、ホストフィールドが一致した場合に優先される追加ルートを提供することもできます。  例:```console
grout https://localhost:8080 custom.example.com \
  --wildcard \
  --tunnel-route-url stream.example.com=http://localhost:7001
```
このフラグを繰り返すことで、複数のカスタムルートを指定できます。

## Grout Client Plugin

`GroutClientBasePlugin` を使用すると、トラフィックを異なる上流サーバーに動的にルーティングできます。以下は、その使用方法の説明を含む簡単な実装例です。```python
class GroutClientPlugin(GroutClientBasePlugin):

    def resolve_route(
        self,
        route: str,
        request: HttpParser,
        origin: HostPort,
        server: HostPort,
    ) -> Tuple[Optional[str], HttpParser]:
        print(request, origin, server, '->', route)
        print(request.header(b'host'), request.path)
        #
        # Here, we send traffic to localhost:7001 irrespective
        # of the original "route" value provided to the grout
        # client OR any custom host:upstream mapping provided
        # through the --tunnel-route-url flags (when using
        # --wildcard).
        #
        # Optionally, you can also strip path before
        # sending traffic to upstrem, like:
        # request.path = b"/"
        #
        # To drop the request, simply return None for route
        # return None, request
        #
        return 'http://localhost:7001', request
```
詳細については、[grout_client.py](https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/plugin/grout_client.py) を参照してください。これを試すには、groutクライアントを起動する際に `--plugin proxy.plugin.grout_client.GroutClientPlugin` を渡してください。

## Dockerを使用したGrout```console
❯ docker run --rm -it \
  --entrypoint grout \
  -v ~/.proxy:/root/.proxy \
  abhinavsingh/proxy.py:latest \
  http://host.docker.internal:29876
```
上記:

- `--entrypoint` を `grout` に変更しました
- `localhost` を `host.docker.internal` に置き換えました。これにより、`grout` がホストマシンで実行されているポート `29876` へのトラフィックをルーティングできるようになります
- *(オプション)* ホストマシンの `~/.proxy` フォルダをマウントします。これにより、`grout` の認証情報がコンテナ再起動後も保持されます

## Groutの仕組み

- `grout` インフラストラクチャには、クライアントとサーバーの2つのコンポーネントがあります
- `grout` クライアントには、シンクライアントとシッククライアントの2つのコンポーネントがあります
- `grout` シンクライアントはオープンソースの `proxy.py` (BSD 3-Clause License) の一部です
- `grout` シッククライアントとサーバーは [jaxl.io](https://jaxl.io) でホストされており、[Jaxl Innovations Private Limited](https://jaxl.com) の著作権です
- `grout` サーバーには、レジストリサーバー、リバースプロキシサーバー、トンネルサーバーの3つのコンポーネントがあります

## セルフホストの `grout`

- `grout` シッククライアントとサーバーは、お客様の GCP、AWS、クラウドインフラストラクチャ上でもホストできます
- セルフホスト版では、トラフィックはお客様が制御および信頼するネットワークを流れます
- `grout` の開発者 ([jaxl.io](https://jaxl.io)) は、セルフホストソリューション向けに GCP、AWS、Docker イメージを提供しています
- 開始するには、[[email protected]](mailto:[email protected]) までメールをお送りください。

# SSHトンネル経由のプロキシ

**これは作業中であり、ドキュメント通りに動作しない可能性があります**

動作には `paramiko` が必要です。依存関係をインストールするには、`pip install "proxy.py[tunnel]"` を実行してください。

## リモートリクエストをローカルでプロキシ

                            |
    +------------+          |            +----------+
    |   LOCAL    |          |            |  REMOTE  |
    |   HOST     | <== SSH ==== :8900 == |  PROXY   |
    +------------+          |            +----------+
    :8899 proxy.py          |
                            |
                         FIREWALL
                      (tcp/22を許可)

### 概要

`localhost` で実行されている `proxy.py` サーバーを介して、`remote` プロキシサーバーで行われた HTTP(s) リクエストをプロキシします。

### 仕組み

- 要求された `remote` ポートは SSH 接続経由で転送されます。
- `localhost` で実行されている `proxy.py` が `remote` プロキシリクエストを処理し、応答します。

### 必要条件

1. `localhost` は `remote` サーバーへの SSH アクセスが必須です
2. `remote` サーバーは、転送されたポート番号 (例: `:8900`) を介して HTTP(s) リクエストをプロキシするように構成されている必要があります。
   - `remote` と `localhost` のポートは同じでも構いません (例: `:8899`)。
   - `:8900` は区別のためにアスキーアートで選択されています。

### 試してみる

次のように `proxy.py` を起動します:```console
❯ # On localhost
❯ proxy --enable-ssh-tunnel \
    --tunnel-username username \
    --tunnel-hostname ip.address.or.domain.name \
    --tunnel-port 22 \
    --tunnel-remote-port 8899 \
    --tunnel-ssh-key /path/to/ssh/private.key \
    --tunnel-ssh-key-passphrase XXXXX
...[redacted]... [I] listener.setup:97 - Listening on 127.0.0.1:8899
...[redacted]... [I] pool.setup:106 - Started 16 acceptors in threadless (local) mode
...[redacted]... [I] transport._log:1873 - Connected (version 2.0, client OpenSSH_7.6p1)
...[redacted]... [I] transport._log:1873 - Authentication (publickey) successful!
...[redacted]... [I] listener.setup:116 - SSH connection established to ip.address.or.domain.name:22...
...[redacted]... [I] listener.start_port_forward:91 - :8899 forwarding successful...
```
`remote`サーバーに対してHTTPプロキシリクエストを行い、レスポンスに`localhost`のパブリックIPアドレスが送信元として含まれていることを確認します。```console
❯ # On remote
❯ curl -x 127.0.0.1:8899 http://httpbin.org/get
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.54.0"
  },
  "origin": "x.x.x.x, y.y.y.y",
  "url": "https://httpbin.org/get"
}
```
また、`proxy.py` の `localhost` 上のログに `remote` IP が `client IP` として含まれていることを確認してください。```console
access_log:328 - remote:52067 - GET httpbin.org:80
```
## ローカルリクエストをリモートでプロキシする

                            |
    +------------+          |     +----------+
    |   LOCAL    |          |     |  REMOTE  |
    |   HOST     | === SSH =====> |  SERVER  |
    +------------+          |     +----------+
                            |     :8899 proxy.py
                            |
                        FIREWALL
                     (allow tcp/22)

未計画。

有効なユースケースがある場合は、遠慮なく issue を開いてください。この機能を追加するためのプルリクエストによる貢献はいつでも歓迎します :)

> ローカルリクエストをリモートでプロキシするには、[Proxy Pool Plugin](#proxypoolplugin) を利用してください。

# proxy.py の埋め込み

## ブロッキングモード

デフォルト設定で `proxy.py` を埋め込みモードで開始するには、`proxy.main` メソッドを使用します。例:```python
import proxy

if __name__ == '__main__':
  proxy.main()
```
起動フラグをkwargsとして渡すことでカスタマイズします:```python
import ipaddress
import proxy

if __name__ == '__main__':
  proxy.main(
    hostname=ipaddress.IPv6Address('::1'),
    port=8899
  )
```
注意事項:

1. `main`はコマンドラインから`proxy.py`を起動するのと同等です。
2. `main`は`args`を受け付けません(`kwargs`のみを受け付けます)。
3. `main`は利用可能な`sys.argv`を自動的に`args`として消費します。
3. `main`は`proxy.py`がシャットダウンするまでブロックします。

## ノンブロッキングモード

デフォルト設定で`Proxy`コンテキストマネージャを使用して、ノンブロッキング埋め込みモードで`proxy.py`を起動します。例:```python
import proxy

if __name__ == '__main__':
  with proxy.Proxy() as p:
    # Uncomment the line below and
    # implement your app your logic here
    proxy.sleep_loop()
```
注意:

1. `Proxy` は `main` と似ていますが、`Proxy` はブロックしません。
2. 内部的には、`Proxy` はコンテキストマネージャであり、呼び出されると `proxy.py` を起動し、スコープが終了するとシャットダウンします。
3. `main` とは異なり、`Proxy` の起動フラグは `args` と `kwargs` を使用してカスタマイズすることもできます。例:`Proxy(['--port', '8899'])` または kwargs としてフラグを渡すことでカスタマイズできます。例:`Proxy(port=8899)`。
4. `main` とは異なり、`Proxy` は `sys.argv` を検査しません。

## 一時ポート

`--port=0` を使用すると、カーネルによって割り当てられたランダムなポートに `proxy.py` をバインドできます。

埋め込みモードでは、このポートにアクセスできます。例:```python
import proxy

if __name__ == '__main__':
  with proxy.Proxy(port=0) as p:
    print(p.flags.port)
    proxy.sleep_loop()
```
`flags.port` を使用すると、カーネルによって割り当てられたランダムなポートにアクセスできます。

## プラグインの読み込み

ユーザーは `--plugins` フラグを複数回使用して、複数のプラグインを読み込むことができます。
問題が発生している場合は、[プラグインを読み込めない](#unable-to-load-plugins) を参照してください。

埋め込みモードで使用する場合、さらにいくつかのオプションがあります。例:

1. プラグインクラスの完全修飾名を `bytes` として `proxy.main` メソッドまたは `proxy.Proxy` コンテキストマネージャに指定します。
2. プラグインクラスの `type` インスタンスを指定します。これは、特に実行時にプラグインを定義する場合に便利です。

例: `--plugins` フラグを使用して単一のプラグインを読み込む:```python
import proxy

if __name__ == '__main__':
  proxy.main(plugins=['proxy.plugin.CacheResponsesPlugin'])
```
簡略化のために、プラグインのリストをキーワード引数として `proxy.main` または `Proxy` コンストラクタに渡すこともできます。

例:```python
import proxy
from proxy.plugin import FilterByUpstreamHostPlugin

if __name__ == '__main__':
  proxy.main(plugins=[
    b'proxy.plugin.CacheResponsesPlugin',
    FilterByUpstreamHostPlugin,
  ])
```
# proxy.py を使った単体テスト

## `proxy.TestCase`

Python の `unittest` クラスに対して `proxy.py` のセットアップとティアダウンを行うには、`unittest.TestCase` の代わりに `proxy.TestCase` を使用するだけです。
例:```python
import proxy

class TestProxyPyEmbedded(proxy.TestCase):

    def test_my_application_with_proxy(self) -> None:
        self.assertTrue(True)
```
注意:

1. `proxy.TestCase` は `unittest.TestCase.run()` メソッドをオーバーライドして `proxy.py` のセットアップと後処理を行います。
2. `proxy.py` サーバーはシステム上のランダムな利用可能ポートで待機します。
   このランダムポートは、テストケース内で `self.PROXY.flags.port` として利用可能です。
3. デフォルトでは、より高速なセットアップと後処理のために、単一のアクセプターとワーカーのみが起動されます(`--num-workers 1 --num-acceptors 1`)。
4. 最も重要な点として、`proxy.TestCase` はテストの実行前に `proxy.py` サーバーが起動し実行中であることを保証します。デフォルトでは、`proxy.TestCase` は `proxy.py` サーバーが起動するまで `10 秒` 待機し、失敗した場合は `TimeoutError` 例外が発生します。

## 起動フラグのオーバーライド

デフォルトの起動フラグをオーバーライドするには、テストクラス内で `PROXY_PY_STARTUP_FLAGS` 変数を定義します。
例:```python
class TestProxyPyEmbedded(TestCase):

    PROXY_PY_STARTUP_FLAGS = [
        '--num-workers', '2',
        '--num-acceptors', '1',
        '--enable-web-server',
    ]

    def test_my_application_with_proxy(self) -> None:
        self.assertTrue(True)
```
See [test_embed.py] for full working example.

[test_embed.py]:
https://raw.githubusercontent.com/abhinavsingh/proxy.py/develop/tests/testing/test_embed.py

## With `unittest.TestCase`

Some reason you are unable to directly use `proxy.TestCase`,
then simply override `unittest.TestCase.run` yourself to setup and tear down `proxy.py`.
Example:```python
import unittest
import proxy


class TestProxyPyEmbedded(unittest.TestCase):

    def test_my_application_with_proxy(self) -> None:
        self.assertTrue(True)

    def run(self, result: Optional[unittest.TestResult] = None) -> Any:
        with proxy.start([
                '--num-workers', '1',
                '--num-acceptors', '1',
                '--port', '... random port ...']):
            super().run(result)
```
または、単に`proxy.py`のセットアップ/ティアダウンを`setUpClass`と`teardownClass`のクラスメソッド内で行うこともできます。

# ユーティリティ

## TCPソケット

### new_socket_connection

与えられたアドレスに対して、まずIPv4接続、次にIPv6、最後にデュアルスタック接続の作成を試みます。```python
>>> conn = new_socket_connection(('httpbin.org', 80))
>>> ...[ use connection ]...
>>> conn.close()
```
### socket_connection

`socket_connection` は、`new_socket_connection` をラップした便利なデコレーター兼コンテキストマネージャーであり、`conn.close` が暗黙的に呼び出されることを保証します。

コンテキストマネージャーとして:```python
>>> with socket_connection(('httpbin.org', 80)) as conn:
>>>   ... [ use connection ] ...
```
デコレータとして:```python
>>> @socket_connection(('httpbin.org', 80))
>>> def my_api_call(conn, *args, **kwargs):
>>>   ... [ use connection ] ...
```
## HTTP クライアント

### build_http_request

- HTTP GETリクエストを生成する  ```python
  >>> build_http_request(b'GET', b'/')
  b'GET / HTTP/1.1\r\n\r\n'
  ```
- HTTP GETリクエスト(ヘッダー付き)を生成する  ```python
  >>> build_http_request(b'GET', b'/', conn_close=True)
  b'GET / HTTP/1.1\r\nConnection: close\r\n\r\n'
  ```
- ヘッダーとボディを含むHTTP POSTリクエストを生成する  ```python
  >>> import json
  >>> build_http_request(b'POST', b'/form',
          headers={b'Content-type': b'application/json'},
          body=proxy.bytes_(json.dumps({'email': '[email protected]'})))
      b'POST /form HTTP/1.1\r\nContent-type: application/json\r\n\r\n{"email": "[email protected]"}'
  ```
### build_http_response```python
build_http_response(
    status_code: int,
    protocol_version: bytes = HTTP_1_1,
    reason: Optional[bytes] = None,
    headers: Optional[Dict[bytes, bytes]] = None,
    body: Optional[bytes] = None) -> bytes
```
## PKI

### API の使用

- `gen_private_key`  ```python
  gen_private_key(
      key_path: str,
      password: str,
      bits: int = 2048,
      timeout: int = 10) -> bool
  ```
- `gen_public_key`  ```python
  gen_public_key(
      public_key_path: str,
      private_key_path: str,
      private_key_password: str,
      subject: str,
      alt_subj_names: Optional[List[str]] = None,
      extended_key_usage: Optional[str] = None,
      validity_in_days: int = 365,
      timeout: int = 10) -> bool
  ```
- `remove_passphrase`  ```python
  remove_passphrase(
      key_in_path: str,
      password: str,
      key_out_path: str,
      timeout: int = 10) -> bool
  ```
- `gen_csr`  ```python
  gen_csr(
      csr_path: str,
      key_path: str,
      password: str,
      crt_path: str,
      timeout: int = 10) -> bool
  ```
- `sign_csr`  ```python
  sign_csr(
      csr_path: str,
      crt_path: str,
      ca_key_path: str,
      ca_key_password: str,
      ca_crt_path: str,
      serial: str,
      alt_subj_names: Optional[List[str]] = None,
      extended_key_usage: Optional[str] = None,
      validity_in_days: int = 365,
      timeout: int = 10) -> bool
  ```
`pki.py`](https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/common/pki.py) および
[test_pki.py](https://github.com/abhinavsingh/proxy.py/blob/develop/tests/common/test_pki.py) を参照してください。

### CLI の使用法

`proxy.common.pki` モジュールを次の目的で使用します:

1. 公開鍵と秘密鍵の生成
2. CSR リクエストの生成
3. カスタム CA を使用した CSR リクエストの署名```console
❯ python -m proxy.common.pki -h
usage: pki.py [-h] [--password PASSWORD] [--private-key-path PRIVATE_KEY_PATH] [--public-key-path PUBLIC_KEY_PATH]
              [--subject SUBJECT] [--csr-path CSR_PATH] [--crt-path CRT_PATH] [--hostname HOSTNAME] [--openssl OPENSSL]
              action

proxy.py v2.4.4rc2.dev12+gdc06ea4 : PKI Utility

positional arguments:
  action                Valid actions: remove_passphrase, gen_private_key, gen_public_key, gen_csr, sign_csr

options:
  -h, --help            show this help message and exit
  --password PASSWORD   Password to use for encryption. Default: proxy.py
  --private-key-path PRIVATE_KEY_PATH
                        Private key path
  --public-key-path PUBLIC_KEY_PATH
                        Public key path
  --subject SUBJECT     Subject to use for public key generation. Default: /CN=localhost
  --csr-path CSR_PATH   CSR file path. Use with gen_csr and sign_csr action.
  --crt-path CRT_PATH   Signed certificate path. Use with sign_csr action.
  --hostname HOSTNAME   Alternative subject names to use during CSR signing.
  --openssl OPENSSL     Path to openssl binary. By default, we assume openssl is in your PATH
```
## 内部ドキュメント

### ドキュメントを読む

- [proxypy.readthedocs.io](https://proxypy.readthedocs.io/) を参照してください。
- ローカルでビルドするには:

`make lib-doc`

### pydoc

コードは十分に文書化されています。ソースコードを取得して実行:

`pydoc3 proxy`

### pyreverse

クラスレベルの階層UMLダイアグラムを生成して詳細な分析を行います:

`make lib-pyreverse`

# ダッシュボードの実行

ダッシュボードは現在開発中であり、`pip` パッケージにはまだバンドルされていません。
ダッシュボードを実行するには、ソースをチェックアウトする必要があります。

ダッシュボードはTypescriptとSCSSで書かれているので、まず以下のコマンドでビルドしましょう:```console
❯ make dashboard
```
また、使用する予定がある場合は、組み込みの `Chrome DevTools` をビルドしてください:```console
❯ make devtools
```
ここで、ダッシュボードプラグインを使用し、静的サーバーのルートディレクトリを上書きして `proxy.py` を起動します:```console
❯ proxy --enable-dashboard --static-server-dir dashboard/public
...[redacted]... - Loaded plugin proxy.http.server.HttpWebServerPlugin
...[redacted]... - Loaded plugin proxy.dashboard.dashboard.ProxyDashboard
...[redacted]... - Loaded plugin proxy.dashboard.inspect_traffic.InspectTrafficPlugin
...[redacted]... - Loaded plugin proxy.http.inspector.DevtoolsProtocolPlugin
...[redacted]... - Loaded plugin proxy.http.proxy.HttpProxyPlugin
...[redacted]... - Listening on ::1:8899
...[redacted]... - Core Event enabled
```
現在、ダッシュボードを有効にすると、すべてのダッシュボードプラグインも有効になります。ダッシュボードにアクセス:```console
❯ open http://localhost:8899/dashboard/
```
## トラフィック検査

***これは WIP であり、ドキュメント通りに動作しない可能性があります***

埋め込まれた `Chrome Dev Console` が読み込まれるのを待ちます。  現在、`proxy.py` を流れるすべてのトラフィックの詳細は `Inspect Traffic` タブにプッシュされます。  ただし、受信したペイロードはまだ埋め込みの開発者コンソールと統合されていません。

現在の機能は、ダッシュボードの `Dev Console` を開き、ダッシュボードが `proxy.py` サーバーと確立した WebSocket 接続を検査することで確認できます。

[![Proxy.Py ダッシュボード トラフィック検査](https://assets.kitploit.com/production/public/readmes/157/1e6258665ca9259fc526ebb90892d4b322094bb1e8139d329ab2379fc76ab66d.png)](https://github.com/abhinavsingh/proxy.py)

# Chrome DevTools プロトコル

`Chrome DevTools` プロトコルの WebSocket エンドポイントに直接アクセスしたいシナリオの場合は、次のように `proxy.py` を起動します:```console
❯ proxy --enable-devtools --enable-events
```
Now point your CDT instance to `ws://localhost:8899/devtools`.

# Prometheus Metrics

1) `--enable-metrics` フラグを指定して `proxy.py` を起動し、Prometheus エンドポイント経由で内部メトリクスを公開します。
2) `prometheus.yaml` を設定して、`/metrics` エンドポイント(例:[http://localhost:8899/metrics](http://localhost:8899/metrics))からスクレイプするようにします。
3) `--metrics-path` フラグを使用してメトリクスパスをカスタマイズします。
4) 注意:`--enable-metrics` は内部的に `--enable-events` とウェブサーバープラグインも有効にします。

# Frequently Asked Questions

## 本番環境への proxy.py のデプロイ

以下に、プライベート/本番/企業プロジェクトで `proxy.py` を使用するためのいくつかの戦略を記載します。

### やってはいけないこと

> プラグインコードを `proxy/plugin` ディレクトリに配置するためだけに、リポジトリを「フォーク」することは **避けてください**。フォークはプロジェクトの貢献者には推奨されるワークフローですが、プロジェクト利用者には推奨されません。

- 代わりに、以下のいずれかのアプローチを使用してください。
- その後、`--plugin`、`--plugins` フラグまたは `plugin` キーワード引数を使用してプラグインをロードします。
- `proxy.py` を使用したスタンドアロンプロジェクトの例として、[skeleton](https://github.com/abhinavsingh/proxy.py/tree/develop/skeleton) アプリを参照してください。

### 要件ファイル(Requirements)経由

`proxy.py` は `requirements.txt` または同様の依存関係管理設定を使用することを **強く** お勧めします。これにより、`proxy.py` エコシステムで行われている定期的なパフォーマンス更新、バグ修正、セキュリティパッチ、その他の改善を活用できます。例:

1. `--pre` オプションを使用して最新の `pre-release` に依存する

    ```console
    ❯ pip install proxy.py --pre
    ```

    プレリリースは `develop` ブランチのコードに依存するのと似ていますが、プレリリースが `HEAD` を指しているとは限りません。これは、PR マージのたびにプレリリースが `PyPi` で利用可能になるわけではないために発生します。

2. `TestPyPi` を `--pre` オプションとともに使用して `develop` ブランチのコードに依存する

    ```console
    ❯ pip install -i https://test.pypi.org/simple/ proxy.py --pre
    ```

    PR マージのたびにプレリリースが `TestPyPi` で利用可能になります。

3. 最新の `stable` リリースコードを使用する

    通常通り、単に以下を使用します:

    ```console
    ❯ pip install proxy.py
    ```

### Docker コンテナ経由

コンテナをデプロイする場合は、ベースの `proxy.py` コンテナイメージからイメージをビルドするだけです。

1. `GHCR` を使用して `develop` ブランチコードからビルドする:

    ```console
    FROM ghcr.io/abhinavsingh/proxy.py:latest as base
    ```

    *PS: 私はいくつかの本番レベルのプロジェクトで GHCR の最新版を使用しています*

2. `DockerHub` を使用して最新の `stable` リリースコードからビルドする:

    ```console
    FROM abhinavsingh/proxy.py:latest as base
    ```

PS: 私見ですが、コンテナベースの戦略が **最善のアプローチ** であり、**私自身が使用している唯一の戦略** です。

### CI/CD を proxy.py と統合する

*でも、develop ブランチで互換性を破る変更を加え続けていますよね。*

ご意見は承知しています。そのため、本番グレードのアプリケーションでは、アプリケーションの CI/CD を `proxy.py` と統合する **必要があります**。`proxy.py` のアップストリームリポジトリへの PR マージごとに、アプリケーションがビルドされ、テストに合格することを確認しなければなりません。

アプリケーションのリポジトリが公開されている場合、特定のシナリオでは、PR 作成者が後方互換性とグリーンな CI/CD を維持するために、すべての依存関係に対してパッチ PR を送信することがあります。

CI/CD の統合により、アプリケーションが最新の `proxy.py` コードでビルドされ続けることが保証されます。コードのホスティング場所に応じて、以下の戦略を使用してください。

- GitHub

    TBD

- Google Cloud Build

    TBD

- AWS

    TBD

- Azure

    TBD

- Others

    TBD

> いずれかの段階で、`master` ブランチの区分を廃止し、単に `develop` ブランチを維持する予定です。依存関係側が CI/CD 統合によって安定性を維持できるためです。現時点では、本番グレードのプロジェクトが盲目的に `develop` ブランチに依存することは困難です。

## Stable と Develop の違い

- `master` ブランチには最新の `stable` コードが含まれており、`PyPi` リポジトリ、および `docker.io` と `ghcr.io` レジストリを介した `Docker` コンテナとして利用できます。

  `stable` リリースに対して報告された問題は最優先で対応されます。ただし、現在、修正を古いリリースにバックポートすることはしていません。例:`v2.3.1` で問題を報告したが、現在の `master` ブランチには `v2.4.0rc1` が含まれている場合、修正は `v2.4.0rc2` に含まれます。

- `develop` ブランチには最先端の変更が含まれています。

  開発ブランチは(ほとんどの場合)安定した状態に保たれています。**しかし**、*100% の信頼性* を求め、*本番環境* でユーザーにサービスを提供する場合は、常に安定版を使用してください。

### リリーススケジュール

`vX.Y.ZrcN` プルリクエストが月に一度作成され、`develop` を `master` にマージします。以下は、プルリクエストから次の安定版リリースまでのコードの流れです。

1. 開発リリースは、PR マージのたびに `develop` → `test.pypi.org` にデプロイされます。

2. アルファリリースは、`vX.Y.Z.rcN` プルリクエストを `develop` → `master` ブランチにマージする **前に**、`develop` → `pypi.org` にデプロイされます。`rc` プルリクエストをマージする前に、複数のアルファリリースが行われる可能性があります。

3. ベータリリースは `master` → `pypi.org` にデプロイされます。ベータリリースは `rc` リリースの準備として行われ、不要な場合はスキップできます。

4. リリース候補(Release candidate)は `master` → `pypi.org` にデプロイされます。リリース候補は常に最終安定版リリースの前に利用可能になります。

5. 安定版リリースは `master` → `pypi.org` にデプロイされます。

## スレッド処理 vs スレッドレス処理

### `v1.x`

`proxy.py` はクライアントリクエストの処理に新しいスレッドを生成していました。

### `v2.0+`

`proxy.py` は `asyncio` を使用したクライアントリクエストのスレッドレス実行のサポートを追加しました。

### `v2.4.0+`

`mac` および `linux` 環境の `Python 3.8+` では、スレッドレス実行がデフォルトで有効になりました。

`proxy.py` のスレッドレス実行は、これらの環境ではユーザーによって安全であると報告されています。問題が発生した場合は、`--threaded` フラグを使用してスレッドモードにフォールバックしてください。

`windows` および `Python < 3.8` では、`--threadless` フラグを指定して `proxy.py` を起動することで、スレッドレスモードを試すことができます。

スレッドレスが動作する場合は、`proxy/common/constants.py` ファイルの `_env_threadless_compliant` メソッドを編集して PR を送信することを検討してください。

## スレッドレス:リモート実行モード vs ローカル実行モード

元のスレッドレス実装は `remote` 実行モードを使用していました。これは [ハイレベルアーキテクチャ](#high-level-architecture) の ASCII アートでも示されています。

`remote` 実行モードでは、アクセプターが受信したクライアント接続の処理をリモートワーカープロセスに委譲します。デフォルトでは、アクセプターはラウンドロビン方式で接続を委譲します。リクエストを処理するワーカーは、アクセプターと同じ CPU コアで実行されている場合もあれば、そうでない場合もあります。このアーキテクチャは高スループットに適していますが、CPU コアあたり 2 つのプロセスが生成されることになります。

例:マシンに N 個の CPU がある場合、デフォルトで N 個のアクセプターと N 個のワーカープロセスが起動されます。`--num-acceptors` および `--num-workers` フラグを使用してプロセス数を調整できます。ユースケースによって、アクセプターよりもワーカーを多くしたい場合や、その逆もあるでしょう。

v2.4.x では、主にデフォルトで生成されるプロセス数を減らすために `local` 実行モードが追加されました。このモデルは、日常的なシングルユーザーのユースケースや開発者のテストシナリオに適しています。`local` 実行モードでは、アクセプターはリモートプロセスではなく、コンパニオンスレッドにクライアント接続を委譲します。`local` 実行モードは CPU アフィニティを保証します。一方、`remote` モードではアクセプターとワーカーが異なる CPU コアで実行される可能性があります。

v2.4.x シリーズでは `--local-executor 1` がデフォルトになりました。`local` 実行モードでは、リモートワーカーが起動されないため、`--num-workers` フラグは効果がありません。

`remote` 実行モードを使用するには、`--local-executor 0` フラグを使用します。その後、`--num-workers` を使用してワーカープロセスの数を調整します。

## SyntaxError: invalid syntax

`proxy.py` は厳密に型指定されており、Python の `typing` アノテーションを使用しています。例:```python
>>> my_strings : List[str] = []
>>> #############^^^^^^^^^#####
```
したがって、型注釈を理解するPythonバージョンが必要です。
`Python 3.6+` を使用していることを確認してください。

`proxy.py` を実行する前にバージョンを確認してください:

`❯ python --version`

すべての `typing` アノテーションは `comment-only` アノテーションに置き換えることができます。例:```python
>>> my_strings = [] # List[str]
>>> ################^^^^^^^^^^^
```
これにより、`proxy.py` は Python `pre-3.6` でも、さらには `2.7` でも動作するようになります。
しかし、将来のすべてのPythonバージョンは `typing` アノテーションをサポートするため、これは考慮されていません。

## プラグインを読み込めない場合

プラグインモジュールが検出可能であることを確認するには、`PYTHONPATH` に追加します。例:

`PYTHONPATH=/path/to/my/app proxy --plugins my_app.proxyPlugin````console
...[redacted]... - Loaded plugin proxy.HttpProxyPlugin
...[redacted]... - Loaded plugin my_app.proxyPlugin
```
または、完全修飾パスをパラメータとして直接渡します。例:

`proxy --plugins /path/to/my/app/my_app.proxyPlugin`

以下は簡単な動作例です:

- `/tmp/plug` フォルダの内容```console
╰─ ls -1 /tmp/plug                                                                                                                       ─╯
my_plugin.py
```
- カスタム `MyPlugin` クラス```console
╰─ cat /tmp/plug/my_plugin.py                                                                                                            ─╯
from proxy.http.proxy import HttpProxyBasePlugin


class MyPlugin(HttpProxyBasePlugin):
  pass
```
これは、外部プラグインの使用法を示すための空のプラグインです。実際のトラフィックでプラグインを動作させるには、必要なメソッドを実装する必要があります。

- `proxy.py` を `MyPlugin` で起動する```console
╰─ PYTHONPATH=/tmp/plug proxy --plugin my_plugin.MyPlugin                                                                      ─╯
...[redacted]... - Loaded plugin proxy.http.proxy.HttpProxyPlugin
...[redacted]... - Loaded plugin my_plugin.MyPlugin
...[redacted]... - Listening on ::1:8899
```
## Unable to connect with proxy.py from remote host

`proxy.py`が正しいネットワークインターフェースでリッスンしていることを確認してください。
次のフラグを試してください:

- IPv6の場合 `--hostname ::`
- IPv4の場合 `--hostname 0.0.0.0`

## Basic auth not working with a browser

おそらく、ブラウザとシステムキーチェーンの統合の問題です。

- まず、`curl`を使用してBasic認証が機能することを確認してください

  `curl -v -x username:password@localhost:8899 https://httpbin.org/get`

- 詳細は[このスレッド](https://github.com/abhinavsingh/proxy.py/issues/89)
  を参照してください。

## Docker image not working on macOS

これは`vpnkit`との互換性の問題です。

背景については、[moby/vpnkit exhausts docker resources](https://github.com/abhinavsingh/proxy.py/issues/43)
および[Connection refused: The proxy could not connect](https://github.com/moby/vpnkit/issues/469)
を参照してください。

## GCE log viewer integration for proxy.py

スターター[fluentd.conf](https://github.com/abhinavsingh/proxy.py/blob/develop/helper/fluentd.conf)
テンプレートが利用可能です。

1. この設定ファイルを`proxy.py.conf`として
   `/etc/google-fluentd/config.d/`にコピーします。

2. `path`フィールドを`--log-file`フラグで使用されるログファイルのパスに更新します。
   デフォルトでは`/tmp/proxy.log`パスが追跡されます。

3. `google-fluentd`をリロードします:

   `sudo service google-fluentd restart`

これで、`proxy.py`のログを
[GCEログビューア](https://console.cloud.google.com/logs/viewer)で閲覧できます。

## `ValueError: filedescriptor out of range in select`

`proxy.py`は、ソケットリークなしで毎秒数千の接続を処理できるように作られています。

1. `--open-file-limit`フラグを使用して`ulimit -n`をカスタマイズします。
2. 高い同時実行性のために`--backlog`フラグを調整してください。

問題が解決しない場合は、送信された`requests per second`と以下のデバッグスクリプトの出力を含めて[イシューを開く](https://github.com/abhinavsingh/proxy.py/issues/new)てください:```console
❯ ./helper/monitor_open_files.sh <proxy-py-pid>
```
## アクセスログにおける None:None

アクセスログに `None:None` が表示されることがあります。これは単に
アップストリームサーバーへの接続が確立されなかったことを意味します。
すなわち、`upstream_host=None`、`upstream_port=None` です。

アップストリーム接続が確立されない理由はいくつか考えられます。
明らかな例としては以下が挙げられます:

1. クライアントが接続を確立したが、リクエストを完了しなかった。
2. プラグインが早期にレスポンスを返し、アップストリームサーバーへの接続を回避した。

## TLSインターセプション時のクライアントラッピングにおけるOSError

`TLS Interception` を有効にすると、以下の例外が発生することがあります。```console
2021-11-06 23:33:34,540 - pid:91032 [E] server.intercept:678 - OSError when wrapping client
Traceback (most recent call last):
  ...[redacted]...
  ...[redacted]...
  ...[redacted]...
ssl.SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:997)
...[redacted]... - CONNECT oauth2.googleapis.com:443 - 0 bytes - 272.08 ms
```
一部のクライアントは、サーバーの証明書が不明な発行元CAによって署名されているため認証できない場合に、`TLSV1_ALERT_UNKNOWN_CA` をスローすることがあります。これはTLSインターセプションを行っている場合に該当します。この原因は、例えば証明書ピンニングなど様々です。

もう一つ発生する可能性がある例外は `CERTIFICATE_VERIFY_FAILED` です:```console
2021-11-06 23:36:02,002 - pid:91033 [E] handler.handle_readables:293 - Exception while receiving from client connection <socket.socket fd=28, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8899), raddr=('127.0.0.1', 51961)> with reason SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:997)')
Traceback (most recent call last):
  ...[redacted]...
  ...[redacted]...
  ...[redacted]...
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:997)
...[redacted]... - CONNECT init.push.apple.com:443 - 0 bytes - 892.99 ms
```
将来的には、そのようなクライアントに対して元のHTTPSコンテンツを提供しつつ、
バックグラウンドでTLSインターセプトを実行することをサポートするかもしれません。  これにより、クライアントを満足させつつ、
TLSインターセプトの能力に影響を与えません。残念ながら、この機能は現在利用できません。

別の例として、`SSLEOFError` 例外:```console
2021-11-06 23:46:40,446 - pid:91034 [E] server.intercept:678 - OSError when wrapping client
Traceback (most recent call last):
  ...[redacted]...
  ...[redacted]...
  ...[redacted]...
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:997)
...[redacted]... - CONNECT stock.adobe.io:443 - 0 bytes - 685.32 ms
```
# プラグイン開発者およびコントリビューターガイド

## 高レベルアーキテクチャ```console
                        +-------------+
                        |             |
                        |  Proxy([])  |
                        |             |
                        +------+------+
                               |
                               |
                   +-----------v--------------+
                   |                          |
                   |    AcceptorPool(...)     |
                   |                          |
                   +------------+-------------+
                                |
+-----------------+             |           +-----------------+
|                 |             |           |                 |
|   Acceptor(..)  <-------------+----------->  Acceptor(..)   |
|                 |                         |                 |
+---+-------------+                         +---------+-------+
    |                                                 |
    |                                                 |
    |    +------++------++------++------++------+     |
    |    |      ||      ||      ||      ||      |     |
    +---->      ||      ||      ||      ||      <-----+
         |      ||      ||      ||      ||      |
         +------++------++------++------++------+
                Threadless Worker Processes
```
`proxy.py` はパフォーマンスを重視して作られています。デフォルトでは、`proxy.py` は利用可能なすべての CPU コアを使用して新しいクライアント接続を受け入れようとします。これは、設定されたサーバーポートでリッスンする `AcceptorPool` を起動することで実現されます。次に、`AcceptorPool` は `Acceptor` プロセス(`--num-acceptors`)を起動して、受信クライアント接続を受け入れます。さらに、`--threadless` が有効になっている場合は、`ThreadlessPool` がセットアップされ、受信クライアント接続を処理する `Threadless` プロセス(`--num-workers`)を起動します。

各 `Acceptor` プロセスは、`Work` クラスを介して受け入れたクライアント接続をスレッドレスプロセスに委譲します。現在、デフォルトのワーククラスは `HttpProtocolHandler` です。

`HttpProtocolHandler` は、受信クライアントが HTTP 仕様に従うことを単純に想定しています。特定の HTTP プロキシと HTTP サーバーの実装は、`HttpProtocolHandler` のプラグインとして記述されます。

利用可能なライフサイクルフックについては、`HttpProtocolHandlerPlugin` のドキュメントを参照してください。`HttpProtocolHandlerPlugin` を使用して、http(s) クライアント向けの新機能を追加します。例については、`HttpWebServerPlugin` を参照してください。

## すべてはプラグイン

`proxy.py` 内では、すべてがプラグインです。

- `--plugins` フラグを使用して、`プロキシサーバー` プラグインを有効にします。
  プロキシサーバー `HttpProxyPlugin` は `HttpProtocolHandler` のプラグインです。
  さらに、プロキシサーバーは `HttpProxyBasePlugin` 仕様を通じてプラグインを許可します。

- すべてのプロキシサーバー [プラグイン例](#plugin-examples) は `HttpProxyBasePlugin` を実装していました。利用可能なライフサイクルフックについては、`HttpProxyBasePlugin` のドキュメントを参照してください。`HttpProxyBasePlugin` を使用して、クライアントとアップストリームサーバー間の http(s) プロキシプロトコルの動作を変更します。例: [FilterByUpstreamHostPlugin](#filterbyupstreamhostplugin)。

- また、`--enable-web-server` を使用して組み込みの `Web サーバー` を有効にします。
  Web サーバー `HttpWebServerPlugin` は `HttpProtocolHandler` のプラグインであり、`HttpProtocolHandlerPlugin` 仕様を実装します。

- さらに、`--disable-http-proxy` フラグもあります。これは組み込みのプロキシサーバーを無効にします。
  このフラグを `--enable-web-server` フラグと併用して、`proxy.py` をプログラム可能な http(s) サーバーとして実行します。

## ステートレスなプラグインの状態管理

プラグインクラスのインスタンスはリクエストごとに作成されます。最も重要なのは、プラグインインスタンスはリクエストが受信された CPU コアコンテキスト内で作成されることです。

上記の理由から、プラグイン内のグローバル変数は期待どおりに動作しない場合があります。設計上、プラグインコードは**ステートレス**である必要があります。

グローバルな状態を管理するには、いくつかのオプションがあります:
1) Python の [multiprocessing セーフなデータ構造](https://python.readthedocs.io/en/latest/library/multiprocessing.html#sharing-state-between-processes) を利用する
2) `proxy.py` 組み込みの [イベント機構](https://github.com/abhinavsingh/proxy.py/blob/develop/tutorial/eventing.ipynb) を利用する

## プラグイン間の処理コンテキストの受け渡し

場合によっては、プラグインが処理チェーン内の後続のプラグインに追加のコンテキストを渡す必要があることがあります。たとえば、この追加のコンテキストをアクセスログの一部として出力することもできます。

処理コンテキストを渡すには、プラグインの `on_access_log` メソッドを利用します。[Program Name](https://github.com/abhinavsingh/proxy.py/blob/develop/proxy/plugin/program_name.py) プラグインが、コンテキスト内のデフォルトの `client_ip` キーを検出されたプログラム名に変更する方法を参照してください。

その結果、[Program Name Plugin](#programnameplugin) を有効にすると、アクセスログに IP アドレスの代わりにローカルクライアントのプログラム名が表示されます。

## 開発ガイド

### ローカル環境のセットアップ

コントリビューターは、新機能/修正を検証および開発するために、ソースから `proxy.py` を起動する必要があります。

詳細は、[コマンドラインからリポジトリソースを使用して proxy.py を実行する](#from-command-line-using-repo-source) を参照してください。


[![警告](https://img.shields.io/static/v1?label=MacOS&message=warning&color=red)](https://github.com/abhinavsingh/proxy.py/issues/642) `macOS` では、`pyenv` を使用して `Python` をインストールする必要があります。`homebrew` でインストールされた `Python` は問題が発生しやすい傾向があります。詳細については、リンク先のスレッドを参照してください。

### Git フックのセットアップ

Pre-commit フックは、テストが合格していることを確認します。

1. `cd /path/to/proxy.py`
2. `ln -s $(PWD)/git-pre-commit .git/hooks/pre-commit`

Pre-push フックは、リンターとテストが合格していることを確認します。

1. `cd /path/to/proxy.py`
2. `ln -s $(PWD)/git-pre-push .git/hooks/pre-push`

### プルリクエストの送信

すべてのプルリクエストは GitHub Actions を使用してテストされます。

テストの一覧については、[GitHub ワークフロー](https://github.com/abhinavsingh/proxy.py/tree/develop/.github/workflows) を参照してください。

# Proxy.Py を使用しているプロジェクト

`proxy.py` を使用している人気のあるプロジェクト

- [pip](https://github.com/pypa/pip)
- [ray-project](https://github.com/ray-project/ray)
- [aio-libs](https://github.com/aio-libs/aiohttp)
- [Selenium Base](https://github.com/seleniumbase/SeleniumBase)
- [wifipumpkin3](https://github.com/P0cL4bs/wifipumpkin3)
- [MerossIot](https://github.com/albertogeniola/MerossIot)
- [pyshorteners](https://github.com/ellisonleao/pyshorteners)
- [Slack API](https://github.com/slackapi/python-slack-events-api)
- [ibeam](https://github.com/Voyz/ibeam)
- [PyPaperBot](https://github.com/ferru97/PyPaperBot)

完全なリストについては、[使用プロジェクト](https://github.com/abhinavsingh/proxy.py/network/dependents?package_id=UGFja2FnZS01MjQ0MDY5Ng%3D%3D) を参照してください。

# ベンチマーク

他の OSS Web サーバーとのベンチマーク比較を実行する方法については、[ベンチマーク](https://github.com/abhinavsingh/proxy.py/tree/develop/benchmark) ディレクトリを参照してください。

`proxy.py` の単体ベンチマークを実行するには、リポジトリルートから次のコマンドを使用します:```console
❯ ./benchmark/compare.sh
```
# フラグ```console
❯ proxy -h
usage: -m [-h] [--tunnel-hostname TUNNEL_HOSTNAME] [--tunnel-port TUNNEL_PORT]
          [--tunnel-username TUNNEL_USERNAME]
          [--tunnel-ssh-key TUNNEL_SSH_KEY]
          [--tunnel-ssh-key-passphrase TUNNEL_SSH_KEY_PASSPHRASE]
          [--tunnel-remote-port TUNNEL_REMOTE_PORT] [--threadless]
          [--threaded] [--num-workers NUM_WORKERS] [--enable-events]
          [--inactive-conn-cleanup-timeout INACTIVE_CONN_CLEANUP_TIMEOUT]
          [--enable-proxy-protocol] [--enable-conn-pool] [--key-file KEY_FILE]
          [--cert-file CERT_FILE] [--client-recvbuf-size CLIENT_RECVBUF_SIZE]
          [--server-recvbuf-size SERVER_RECVBUF_SIZE]
          [--max-sendbuf-size MAX_SENDBUF_SIZE] [--timeout TIMEOUT]
          [--local-executor LOCAL_EXECUTOR] [--backlog BACKLOG]
          [--hostname HOSTNAME] [--hostnames HOSTNAMES [HOSTNAMES ...]]
          [--port PORT] [--ports PORTS [PORTS ...]] [--port-file PORT_FILE]
          [--unix-socket-path UNIX_SOCKET_PATH]
          [--num-acceptors NUM_ACCEPTORS] [--version] [--log-level LOG_LEVEL]
          [--log-file LOG_FILE] [--log-format LOG_FORMAT]
          [--open-file-limit OPEN_FILE_LIMIT]
          [--plugins PLUGINS [PLUGINS ...]] [--enable-dashboard]
          [--basic-auth BASIC_AUTH] [--enable-ssh-tunnel]
          [--work-klass WORK_KLASS] [--pid-file PID_FILE] [--openssl OPENSSL]
          [--data-dir DATA_DIR] [--ssh-listener-klass SSH_LISTENER_KLASS]
          [--disable-http-proxy] [--disable-headers DISABLE_HEADERS]
          [--ca-key-file CA_KEY_FILE] [--insecure-tls-interception]
          [--ca-cert-dir CA_CERT_DIR] [--ca-cert-file CA_CERT_FILE]
          [--ca-file CA_FILE] [--ca-signing-key-file CA_SIGNING_KEY_FILE]
          [--auth-plugin AUTH_PLUGIN] [--cache-requests]
          [--cache-by-content-type] [--cache-dir CACHE_DIR]
          [--proxy-pool PROXY_POOL] [--enable-web-server]
          [--enable-static-server] [--static-server-dir STATIC_SERVER_DIR]
          [--min-compression-length MIN_COMPRESSION_LENGTH]
          [--enable-reverse-proxy] [--rewrite-host-header] [--enable-metrics]
          [--metrics-path METRICS_PATH] [--pac-file PAC_FILE]
          [--pac-file-url-path PAC_FILE_URL_PATH]
          [--cloudflare-dns-mode CLOUDFLARE_DNS_MODE]
          [--filtered-upstream-hosts FILTERED_UPSTREAM_HOSTS]
          [--filtered-client-ips-mode FILTERED_CLIENT_IPS_MODE]
          [--filtered-client-ips FILTERED_CLIENT_IPS]
          [--filtered-url-regex-config FILTERED_URL_REGEX_CONFIG]

proxy.py v2.4.8.dev8+gc703edac.d20241013

options:
  -h, --help            show this help message and exit
  --tunnel-hostname TUNNEL_HOSTNAME
                        Default: None. Remote hostname or IP address to which
                        SSH tunnel will be established.
  --tunnel-port TUNNEL_PORT
                        Default: 22. SSH port of the remote host.
  --tunnel-username TUNNEL_USERNAME
                        Default: None. Username to use for establishing SSH
                        tunnel.
  --tunnel-ssh-key TUNNEL_SSH_KEY
                        Default: None. Private key path in pem format
  --tunnel-ssh-key-passphrase TUNNEL_SSH_KEY_PASSPHRASE
                        Default: None. Private key passphrase
  --tunnel-remote-port TUNNEL_REMOTE_PORT
                        Default: 8899. Remote port which will be forwarded
                        locally for proxy.
  --threadless          Default: True. Enabled by default on Python 3.8+ (mac,
                        linux). When disabled a new thread is spawned to
                        handle each client connection.
  --threaded            Default: False. Disabled by default on Python < 3.8
                        and windows. When enabled a new thread is spawned to
                        handle each client connection.
  --num-workers NUM_WORKERS
                        Defaults to number of CPU cores.
  --enable-events       Default: False. Enables core to dispatch lifecycle
                        events. Plugins can be used to subscribe for core
                        events.
  --inactive-conn-cleanup-timeout INACTIVE_CONN_CLEANUP_TIMEOUT
                        Time after which inactive works must be cleaned up.
                        Increase this value if your backend services are slow
                        to response or when proxy.py is handling a high
                        volume. When running proxy.py on Google Cloud (GCP)
                        you may see 'backend_connection_closed_before_data_sen
                        t_to_client', with curl clients you may see 'Empty
                        reply from server' error when '--inactive-conn-
                        cleanup-timeout' value is low for your use-case.
                        Default 1 seconds
  --enable-proxy-protocol
                        Default: False. If used, will enable proxy protocol.
                        Only version 1 is currently supported.
  --enable-conn-pool    Default: False. (WIP) Enable upstream connection
                        pooling.
  --key-file KEY_FILE   Default: None. Server key file to enable end-to-end
                        TLS encryption with clients. If used, must also pass
                        --cert-file.
  --cert-file CERT_FILE
                        Default: None. Server certificate to enable end-to-end
                        TLS encryption with clients. If used, must also pass
                        --key-file.
  --client-recvbuf-size CLIENT_RECVBUF_SIZE
                        Default: 128 KB. Maximum amount of data received from
                        the client in a single recv() operation.
  --server-recvbuf-size SERVER_RECVBUF_SIZE
                        Default: 128 KB. Maximum amount of data received from
                        the server in a single recv() operation.
  --max-sendbuf-size MAX_SENDBUF_SIZE
                        Default: 64 KB. Maximum amount of data to flush in a
                        single send() operation.
  --timeout TIMEOUT     Default: 10.0. Number of seconds after which an
                        inactive connection must be dropped. Inactivity is
                        defined by no data sent or received by the client.
  --local-executor LOCAL_EXECUTOR
                        Default: 1. Enabled by default. Use 0 to disable. When
                        enabled acceptors will make use of local (same
                        process) executor instead of distributing load across
                        remote (other process) executors. Enable this option
                        to achieve CPU affinity between acceptors and
                        executors, instead of using underlying OS kernel
                        scheduling algorithm.
  --backlog BACKLOG     Default: 100. Maximum number of pending connections to
                        proxy server.
  --hostname HOSTNAME   Default: 127.0.0.1. Server IP address.
  --hostnames HOSTNAMES [HOSTNAMES ...]
                        Default: None. Additional IP addresses to listen on.
  --port PORT           Default: 8899. Server port. To listen on more ports,
                        pass them using --ports flag.
  --ports PORTS [PORTS ...]
                        Default: None. Additional ports to listen on.
  --port-file PORT_FILE
                        Default: None. Save server port numbers. Useful when
                        using --port=0 ephemeral mode.
  --unix-socket-path UNIX_SOCKET_PATH
                        Default: None. Unix socket path to use. When provided
                        --host and --port flags are ignored
  --num-acceptors NUM_ACCEPTORS
                        Defaults to number of CPU cores.
  --version, -v         Prints proxy.py version.
  --log-level LOG_LEVEL
                        Valid options: DEBUG, INFO (default), WARNING, ERROR,
                        CRITICAL. Both upper and lowercase values are allowed.
                        You may also simply use the leading character e.g.
                        --log-level d
  --log-file LOG_FILE   Default: sys.stdout. Log file destination.
  --log-format LOG_FORMAT
                        Log format for Python logger.
  --open-file-limit OPEN_FILE_LIMIT
                        Default: 1024. Maximum number of files (TCP
                        connections) that proxy.py can open concurrently.
  --plugins PLUGINS [PLUGINS ...]
                        Comma separated plugins. You may use --plugins flag
                        multiple times.
  --enable-dashboard    Default: False. Enables proxy.py dashboard.
  --basic-auth BASIC_AUTH
                        Default: No authentication. Specify colon separated
                        user:password to enable basic authentication.
  --enable-ssh-tunnel   Default: False. Enable SSH tunnel.
  --work-klass WORK_KLASS
                        Default: proxy.http.HttpProtocolHandler. Work klass to
                        use for work execution.
  --pid-file PID_FILE   Default: None. Save "parent" process ID to a file.
  --openssl OPENSSL     Default: openssl. Path to openssl binary. By default,
                        assumption is that openssl is in your PATH.
  --data-dir DATA_DIR   Default: ~/.proxypy. Path to proxypy data directory.
  --ssh-listener-klass SSH_LISTENER_KLASS
                        Default: proxy.core.ssh.listener.SshTunnelListener. An
                        implementation of BaseSshTunnelListener
  --disable-http-proxy  Default: False. Whether to disable
                        proxy.HttpProxyPlugin.
  --disable-headers DISABLE_HEADERS
                        Default: None. Comma separated list of headers to
                        remove before dispatching client request to upstream
                        server.
  --ca-key-file CA_KEY_FILE
                        Default: None. CA key to use for signing dynamically
                        generated HTTPS certificates. If used, must also pass
                        --ca-cert-file and --ca-signing-key-file
  --insecure-tls-interception
                        Default: False. Disables certificate verification
  --ca-cert-dir CA_CERT_DIR
                        Default: ~/.proxy/certificates. Directory to store
                        dynamically generated certificates. Also see --ca-key-
                        file, --ca-cert-file and --ca-signing-key-file
  --ca-cert-file CA_CERT_FILE
                        Default: None. Signing certificate to use for signing
                        dynamically generated HTTPS certificates. If used,
                        must also pass --ca-key-file and --ca-signing-key-file
  --ca-file CA_FILE     Default: /Users/abhinavsingh/Dev/proxy.py/.venv3122/li
                        b/python3.12/site-packages/certifi/cacert.pem. Provide
                        path to custom CA bundle for peer certificate
                        verification
  --ca-signing-key-file CA_SIGNING_KEY_FILE
                        Default: None. CA signing key to use for dynamic
                        generation of HTTPS certificates. If used, must also
                        pass --ca-key-file and --ca-cert-file
  --auth-plugin AUTH_PLUGIN
                        Default: proxy.http.proxy.auth.AuthPlugin. Auth plugin
                        to use instead of default basic auth plugin.
  --cache-requests      Default: False. Whether to also write request packets
                        in the cache file.
  --cache-by-content-type
                        Default: False. Whether to extract content by type
                        from responses. Extracted content type is written to
                        the cache directory e.g. video.mp4.
  --cache-dir CACHE_DIR
                        Default: /Users/abhinavsingh/.proxy/cache. Flag only
                        applicable when cache plugin is used with on-disk
                        storage.
  --proxy-pool PROXY_POOL
                        List of upstream proxies to use in the pool
  --enable-web-server   Default: False. Whether to enable
                        proxy.HttpWebServerPlugin.
  --enable-static-server
                        Default: False. Enable inbuilt static file server.
                        Optionally, also use --static-server-dir to serve
                        static content from custom directory. By default,
                        static file server serves out of installed proxy.py
                        python module folder.
  --static-server-dir STATIC_SERVER_DIR
                        Default: "public" folder in directory where proxy.py
                        is placed. This option is only applicable when static
                        server is also enabled. See --enable-static-server.
  --min-compression-length MIN_COMPRESSION_LENGTH
                        Default: 20 bytes. Sets the minimum length of a
                        response that will be compressed (gzipped).
  --enable-reverse-proxy
                        Default: False. Whether to enable reverse proxy core.
  --rewrite-host-header
                        Default: False. If used, reverse proxy server will
                        rewrite Host header field before sending to upstream.
  --enable-metrics      Default: False. Enables metrics.
  --metrics-path METRICS_PATH
                        Default: /metrics. Web server path to serve proxy.py
                        metrics.
  --pac-file PAC_FILE   A file (Proxy Auto Configuration) or string to serve
                        when the server receives a direct file request. Using
                        this option enables proxy.HttpWebServerPlugin.
  --pac-file-url-path PAC_FILE_URL_PATH
                        Default: /. Web server path to serve the PAC file.
  --cloudflare-dns-mode CLOUDFLARE_DNS_MODE
                        Default: security. Either "security" (for malware
                        protection) or "family" (for malware and adult content
                        protection)
  --filtered-upstream-hosts FILTERED_UPSTREAM_HOSTS
                        Default: Blocks Facebook. Comma separated list of IPv4
                        and IPv6 addresses.
  --filtered-client-ips-mode FILTERED_CLIENT_IPS_MODE
                        Default: blacklist. Can be either "whitelist"
                        (restrict access to specific IPs)or "blacklist" (allow
                        everything except specific IPs).
  --filtered-client-ips FILTERED_CLIENT_IPS
                        Default: 127.0.0.1,::1. Comma separated list of IPv4
                        and IPv6 addresses.
  --filtered-url-regex-config FILTERED_URL_REGEX_CONFIG
                        Default: No config. Comma separated list of IPv4 and
                        IPv6 addresses.

Proxy.py not working? Report at:
https://github.com/abhinavsingh/proxy.py/issues/new
```
ツールをダウンロード
  • Webサーバールート
  • リバースプロキシプラグイン
    • リバースプロキシ
  • プラグインの順序
  • エンドツーエンド暗号化
  • TLS傍受
    • 安全でないTLS傍受
    • DockerでのTLS傍受
  • GROUT (NGROK代替)
    • Groutの使用方法
    • Grout認証
    • Groutパス
    • Groutワイルドカードドメイン
    • "Host"ヘッダーベースのワイルドカードルーティング
    • "動的"ルーティング
    • DockerでのGrout
    • Groutの仕組み
    • セルフホストGrout
  • SSHトンネル経由のプロキシ
    • リモートリクエストをローカルでプロキシ
    • ローカルリクエストをリモートでプロキシ
  • proxy.pyの組み込み
    • ブロッキングモード
    • 非ブロッキングモード
    • エフェメラルポート
    • プラグインの読み込み
  • proxy.pyによる単体テスト
    • proxy.TestCase
    • 起動フラグのオーバーライド
    • unittest.TestCaseを使用
  • ユーティリティ
    • TCP
      • new_socket_connection
      • socket_connection
    • Http
      • build_http_request
      • build_http_response
    • 公開鍵基盤
      • APIの使用方法
      • CLIの使用方法
  • ダッシュボードの実行
    • トラフィックの検査
  • Chrome DevTools Protocol
  • Prometheusメトリクス
  • よくある質問
    • proxy.pyの本番環境へのデプロイ
      • やってはいけないこと
      • Requirements経由
      • Dockerコンテナ経由
      • proxy.pyとCI/CDの統合
    • 安定版と開発版
      • リリーススケジュール
    • スレッド vs スレッドレス
    • スレッドレスのリモート vs ローカル実行モード
    • SyntaxError: invalid syntax
    • プラグインが読み込めない
    • リモートホストからproxy.pyに接続できない
    • ブラウザで基本認証が動作しない
    • DockerイメージがMacOSで動作しない
    • ValueError: filedescriptor out of range in select
    • アクセスログのNone:None
    • TLS傍受時のクライアントラップでのOSError
  • プラグイン開発者およびコントリビューターガイド
    • 高レベルのアーキテクチャ
    • すべてはプラグイン
    • ステートレスプラグインの状態管理
    • プラグイン間での処理コンテキストの受け渡し
    • 内部ドキュメント
      • Read The Doc
      • pydoc
      • pyreverse
    • 開発ガイド
      • ローカル環境のセットアップ
      • Gitフックのセットアップ
      • プルリクエストの送信
  • Proxy.Pyを使用しているプロジェクト
  • ベンチマーク
  • フラグ
  • 変更履歴
    • v2.x
    • v1.x
    • v0.x
  • スレッド vs スレッドレスおよびスレッドレスのリモート vs ローカル実行モードを参照して、使用するCPUコア数を制御してください。

    詳細とローカルでのベンチマーク実行方法についてはベンチマークを参照してください。

  • 軽量

    • わずか~5-20 MBのRAMのみ使用
      • メモリリークなし
      • 一度起動すればそのまま、再起動不要
    • 圧縮コンテナサイズはわずか~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を本番環境にデプロイするを参照してください。
  • 複数のアドレスとポートで待ち受け可能

    • 追加アドレスを指定するには--hostnamesフラグを使用
    • 追加ポートを指定するには--portsフラグを使用
    • オプションで、--portフラグを使用してデフォルトポート8899を上書き
    • 同一ポートで複数のプロトコルを処理可能
  • リアルタイムダッシュボード

    • オプションでproxy.pyダッシュボードを有効化。
      • --enable-dashboardを使用
      • その後、http://localhost:8899/dashboardにアクセス
    • 実行時にproxy.pyを検査、監視、制御、設定
    • Chrome DevTools Protocol対応
    • typescriptベースのプラグインを使用してダッシュボードフロントエンドを拡張
    • ダッシュボードは現在開発段階です。破壊的変更が予想されます。
  • 安全

    • クライアントと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フラグを参照
  • IPv4およびIPv6対応

    • --hostnameフラグを参照
  • Unixドメインソケット対応

    • --unix-socket-pathフラグを参照
  • 基本認証対応

    • --basic-authフラグを参照
  • PAC(プロキシ自動設定)対応

    • --pac-fileおよび--pac-file-url-pathフラグを参照
    • デフォルトでは、proxy.py はIPv6の ::1 で待機します。これはIPv4の 127.0.0.1 と同等です
    • 外部ホストから proxy.py にアクセスしたい場合は、--hostname :: または --hostname 0.0.0.0 を使用するか、マシンで利用可能な他のインターフェースにバインドしてください。
    • proxy.py の アップストリームサーバーから見える公開IP をカスタマイズする方法については カスタムネットワークインターフェース を参照してください。
  • Port 8899

    • デフォルトのTCPポートをカスタマイズするには --port フラグを使用します。