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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
iron-proxy — 信頼できないワークロードのためのegressファイアウォール。 | Kitploit
ツール/GitHubGitHub/paradigmxyz/iron-proxy
コンテナセキュリティウェブプロキシと傍受データ流出ウェブセキュリティネットワークセキュリティクラウドセキュリティDevSecOpsデータベースセキュリティ
GitHubparadigmxyz/iron-proxy

iron-proxy

信頼できないワークロードのためのegressファイアウォール。

リポジトリを見る
61236135日前Kitploit レビュー済み

人気

すべて見る →

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

すべてのツールを探索

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

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

iron-proxy

Docs Latest Release Docker Pulls

問題

CI ジョブ、AI コーディングエージェント、サンドボックス化されたコンテナは、任意のアウトバウンド リクエストを行うことができます。侵害された依存関係、プロンプトインジェクション、悪意のあるビルド ステップによって、シークレットの外部への持ち出し、ホームへのコールバック、リバースシェルの起動が行われる可能性があります。多くの チームは、ワークロードから何が出て行っているのかをまったく把握できておらず、ましてやそれを止める手段も ありません。

iron-proxy の機能

iron-proxy は、内蔵 DNS サーバーを備えた MITM エグレスプロキシであり、信頼できない ワークロードとインターネットの間に位置します。ネットワーク境界でデフォルト拒否を 強制するため、ワークロードは明示的に許可したドメインにのみ到達できます。 実際のシークレットはサンドボックスに入りません。ワークロードはプロキシトークンを使用し、 iron-proxy はエグレス時に実際の認証情報に置き換えます。つまり、侵害されたワークロードは プロキシの外では無価値なトークンを外部に持ち出せるだけです。

単一バイナリ。単一の YAML 設定。

  • デフォルト拒否エグレス。 宛先が許可リストに一致しない限り、すべてのアウトバウンドリクエストは ブロックされます。ドメインと CIDR を列挙し、それ以外はすべて 403 を返します。
  • アップストリーム IP 拒否リスト。 ホストが許可されていても、解決されたアドレスが拒否された CIDR 内にある場合、プロキシは そのホストへの接続を拒否します。これにより、許可されたホスト名が IMDS または ループバックを指す SSRF/DNS リバインディングのギャップを埋めます。クラウドメタデータエンドポイント( 169.254.169.254、 fd00:ec2::254、fd20:ce::254)とループバックはデフォルトで拒否されます。 proxy.upstream_deny_cidrs または IRON_PROXY_UPSTREAM_DENY_CIDRS で上書きできます。
  • 境界レベルのシークレット注入。 ワークロードはプロキシトークンを送信します。iron-proxy はリクエストが外部に出る前にそれらを実際のシークレットに置き換えます。サンドボックスが 侵害された場合、攻撃者が得るのはプロキシの外では無価値なトークンだけです。
  • リクエストごとの監査証跡。 すべてのリクエストは構造化 JSON としてログに記録され、 完全な変換パイプラインの結果(どのシークレットが置き換えられたか、どのルールが 一致したか、何がブロックされ、その理由)が含まれます。
  • ストリーミング対応。 WebSocket アップグレードと Server-Sent Events はネイティブに プロキシされます。長期間の接続を保持するエージェントワークロードに特別な設定は 不要です。
  • 明示的プロキシサポート。 HTTP_PROXY、HTTPS_PROXY、SOCKS5 設定による プロキシ設定をネイティブにサポートするツール向けのオプションのトンネル リスナー。
  • PostgreSQL MITM プロキシ。 プロキシ管理の認証情報に対してクライアントを認証し、 アップストリームセッションに SET ROLE を注入し、 クライアントがロールを変更しようとする試み(SET ROLE、 set_config('role', ...)、DO ブロックなど)を SQL AST ウォークで拒否するオプションのリスナー。 PostgreSQL の行レベルセキュリティと組み合わせることで、 アプリケーションが共有サービスアカウントユーザーとして接続する際に、テナントごとのデータ分離を実現します。要件: PgBouncer(使用する場合)は pool_mode = session で実行する必要があります — トランザクションまたは ステートメントプールモードでは、クエリ間でバックエンドが暗黙的に再バインドされ、 ポリシーが無効になります。詳細は docs.iron.sh を参照してください。

CI パイプライン、GitHub Actions、AI エージェント(Claude Code、Cursor、 Codex)、および完全には信頼できないコードを実行するあらゆる環境向けに作られています。

ブロックされた外部持ち出し+シークレット書き換えの動作デモ:

インストール

Docker イメージは Docker Hub で入手でき、 Linux/macOS(amd64/arm64)向けのビルド済みバイナリは GitHub Releases にあります。

またはソースからビルド:```bash go build -o iron-proxy ./cmd/iron-proxy

root@kitploit:~
## クイックスタート```bash
cd examples/docker-compose
docker compose up

これにより iron-proxy と、プロキシを通じて5つのリクエストを送信するデモクライアントが起動し ます。ログを確認して、許可されたリクエスト、ブロックされたリクエスト、シークレットが書き換えられたリクエストを確認してください:```bash docker compose logs proxy

root@kitploit:~
すべてのリクエストは構造化されたJSON監査エントリを生成します:```json
{
  "host": "httpbin.org",
  "method": "GET",
  "path": "/headers",
  "action": "allow",
  "status_code": 200,
  "duration_ms": 142,
  "request_transforms": [
    { "name": "allowlist", "action": "continue" },
    {
      "name": "secrets",
      "action": "continue",
      "annotations": { "swapped": [{ "secret": "OPENAI_API_KEY", "locations": ["header:Authorization"] }] }
    }
  ]
}

拒否されたリクエストには rejected_by フィールドが含まれ、WARN レベルでログが記録されます。完全なスキーマについては 監査ログ形式 を参照してください。

本番環境での使用

1. CA の生成

iron-proxy は、提供された CA によって署名されたリーフ証明書をその場で生成して TLS を終端します。 クライアントコンテナはこの CA を信頼する必要があります。```bash mkdir -p certs openssl genrsa -out certs/ca.key 4096 openssl req -x509 -new -nodes
-key certs/ca.key
-sha256 -days 3650
-subj "/CN=iron-proxy CA"
-addext "basicConstraints=critical,CA:TRUE"
-addext "keyUsage=critical,keyCertSign"
-out certs/ca.crt

root@kitploit:~
### 2. Dockerネットワークを作成する

iron-proxyは固定IPを必要とするため、コンテナがDNSをそのIPに向けられるようにします:```bash
docker network create --subnet=172.20.0.0/24 iron-proxy

3. iron-proxy を起動

シークレットを含む env ファイルを作成します(バージョン管理の対象外にしてください):```bash echo "OPENAI_API_KEY=sk-real-key" > .env

root@kitploit:~
[No input provided]```bash
docker run -d --name iron-proxy \
  --network iron-proxy --ip 172.20.0.2 \
  -v $(pwd)/proxy.yaml:/etc/iron-proxy/proxy.yaml:ro \
  -v $(pwd)/certs/ca.crt:/etc/iron-proxy/ca.crt:ro \
  -v $(pwd)/certs/ca.key:/etc/iron-proxy/ca.key:ro \
  --env-file .env \
  ironsh/iron-proxy:latest -config /etc/iron-proxy/proxy.yaml

4. コンテナをプロキシ経由でルーティングする

最も簡単な方法はDNSベースのルーティングです。コンテナのDNSをiron-proxyに向けると、すべてのホスト名ルックアップがプロキシIPに解決され、トラフィックが自動的にプロキシ経由でルーティングされます:```bash docker run --rm
--network iron-proxy
--dns 172.20.0.2
-v $(pwd)/certs/ca.crt:/certs/ca.crt:ro
curlimages/curl --cacert /certs/ca.crt https://httpbin.org/get

root@kitploit:~
より強力な適用を行うには、nftables ルールを重ねてプロキシを経由しない外部送信をブロックするか、または
カーネルレベルでの傍受には TPROXY を使用します。各アプローチの詳細は [プロキシへのトラフィックの
ルーティング](#routing-traffic-to-the-proxy) を参照してください。

## なぜ iron-proxy なのか?

|                          | iron-proxy                     | Squid                       | mitmproxy                 | Envoy                              |
| ------------------------ | ------------------------------ | --------------------------- | ------------------------- | ---------------------------------- |
| デフォルト拒否の外部送信 | 組み込み                       | 複雑なACL設定が必要         | カスタムスクリプトが必要   | RBAC/フィルター設定が必要           |
| シークレット注入         | 組み込み                       | なし                        | なし                      | なし                               |
| 構造化監査ログ           | 組み込み、変換ごとのトレース   | 基本的なアクセスログ        | プラグインベース          | 設定可能なアクセスログ             |
| セットアップの複雑さ     | 単一バイナリ + YAML            | 広範な設定言語              | Pythonスクリプト          | 複雑なYAMLまたはコントロールプレーン |

iron-proxy は、信頼できないワークロードからの外部送信を制御・監査するという単一の目的のために設計されています。Squid はデフォルト拒否を実行できますが、かなりの ACL 設定が必要であり、シークレット注入の概念はありません。mitmproxy は優れたデバッグツールですが、本番環境での強制適用を目的としていません。Envoy は汎用プロキシであり、この機能の一部を実行するように設定できますが、問題が必要とするよりもはるかに複雑です。

## 仕組み

iron-proxy は DNS サーバーと HTTP/HTTPS プロキシを実行します。コンテナの DNS を iron-proxy に向けると、すべてのホスト名のルックアップがプロキシ IP に解決され、トラフィックが自動的にプロキシを経由します。プロキシは TLS を終端し(提供する CA からリーフ証明書をその場で生成)、リクエストを順序付けられた変換パイプラインに通し、アップストリームに転送し、レスポンスを再度パイプラインに通します。```
Container → DNS lookup → iron-proxy IP → TLS termination → transforms → upstream

変換は順に実行されます。組み込み変換:

変換説明
allowlist一致するドメイン/CIDRへのリクエストを許可し、それ以外はすべて拒否します (403)。
secretsプロキシトークンがないかヘッダー(必要に応じてクエリ、パス、本文)をスキャンし、環境変数から実際のシークレットと置き換えます。
body_capture一致するホストのデコードされたリクエスト本文を request_body 監査フィールドとして記録します。観察専用であり、拒否はしません。

Configuration

iron-proxy は単一のフラグ -config path/to/config.yaml を受け取ります。以下が 全体の構造です(iron-proxy.example.yaml はコピーして 使える出発点として参照してください):```yaml dns: listen: ":53" proxy_ip: "10.16.0.1" # IP where iron-proxy is running (required) passthrough: # Domains forwarded to OS resolver - "*.internal.corp" - "metadata.google.internal" records: # Static DNS records (highest precedence) - name: "internal.example.com" type: A value: "10.0.0.5"

proxy: http_listen: ":80" https_listen: ":443" tunnel_listen: ":8080" # Optional CONNECT/SOCKS5 listener max_request_body_bytes: 1048576 # 1 MiB (default) max_response_body_bytes: 0 # uncapped (default)

tls: ca_cert: "/etc/iron-proxy/ca.crt" # Required ca_key: "/etc/iron-proxy/ca.key" # Required cert_cache_size: 1000 # LRU cache for generated leaf certs leaf_cert_expiry_hours: 72

transforms:

  • name: allowlist config: domains: - "api.openai.com" - "*.anthropic.com" cidrs: - "10.0.0.0/8"

  • name: secrets config: secrets: - source: type: env var: OPENAI_API_KEY # Env var holding the real secret proxy_value: "proxy-token-123" # Token the sandbox sends match_headers: ["Authorization"] match_body: false require: true # Reject requests without the proxy token rules: - host: "api.openai.com"

log: level: "info" # debug, info, warn, error

root@kitploit:~
### DNS

デフォルトではすべてが `proxy_ip` に解決されます。これによりトラフィックがプロキシ経由でルーティングされます。例外は以下のとおりです。

- **`passthrough`:** OSリゾルバに転送されるグロブパターン(例: `*.internal.corp`)。これらのホストへのトラフィックはプロキシを完全にバイパスします。
- **`records`:** 静的AレコードまたはCNAMEレコード。最も優先度が高くなります。

### レスポンス再試行ハンドラ

`IRON_RESPONSE_RETRY_HANDLER_URL`、`IRON_RESPONSE_RETRY_COMPLETE_URL`、`IRON_RESPONSE_RETRY_HANDLER_TOKEN`、`IRON_RESPONSE_RETRY_HANDLER_SANDBOX_ID`、およびカンマ区切りの `IRON_RESPONSE_RETRY_STATUSES` リストを設定すると、外部認証によるレスポンス再試行を有効にできます。認証ハンドラは、正確なアップストリームのスキーム、オーソリティ、メソッド、パス/クエリ、再試行可能性、レスポンスステータスとヘッダー、トレースコンテキスト、サンドボックスIDを受け取ります。ハンドラは、1回の正確な再試行のためのリクエストヘッダーと試行IDを返すことができます。完了ハンドラは、`IRON_RESPONSE_RETRY_COMPLETION_HEADERS` によって選択された再試行ステータスとレスポンスヘッダーを受け取ります。これはデフォルトで `Payment-Receipt` になります。

レスポンスボディはどちらのハンドラにも送信されず、宛先を変更することはできず、接続/フレーミングヘッダーは拒否されます。`proxy.max_request_body_bytes` を超えるリクエストは通常どおり処理されますが、再試行不可としてマークされます。チャレンジされた場合、元のレスポンスが返されます。ハンドラの障害でも元のレスポンスは保持されます。ハンドラURLは、ループバックまたは信頼された内部ネットワーク向けに `IRON_RESPONSE_RETRY_HANDLER_ALLOW_HTTP=true` が明示的に設定されている場合を除き、HTTPSを使用する必要があります。リダイレクトは拒否され、レスポンス再試行トークンはコントロールプレーントークンとは独立して設定する必要があります。WebSocket、gRPC、および長さ不明のストリーミングリクエストは、レスポンス再試行処理をバイパスします。

信頼されたハンドラが `proxy.upstream_deny_cidrs` 内で解決される場合、`IRON_RESPONSE_RETRY_HANDLER_ALLOW_CIDRS` に、ハンドラが使用できる狭いプライベートCIDRのカンマ区切りリストを設定します。この例外は、設定された正確な認証エンドポイントと完了エンドポイントにのみ適用されます。通常のプロキシトラフィックは、引き続き完全なアップストリーム拒否リストの対象となります。パブリック、ループバック、リンクローカル、およびクラウドメタデータのレンジは、この設定では追加できません。

### 許可リスト

デフォルトは拒否です。リクエストは、少なくとも1つのドメイングロブまたはCIDRに一致する必要があります。一致しないリクエストには `403 Forbidden` が返されます。

ドメインパターンはグロブマッチングを使用します。`*.example.com` は任意のサブドメインと `example.com` 自体に一致します。

**警告モード:** `warn: true` を設定すると、許可リストが実際に適用せずに何をブロックするかを確認できます。拒否されるはずのリクエストは通過できますが、変換トレースに `"action": "warn"` という注釈が付けられます。これは、新しい許可リストルールを段階的に導入したり、適用に切り替える前に既存のトラフィックを監査したりするのに役立ちます。

### 注釈 (Annotate)

ホスト/メソッド/パスルールに基づいて、HTTPリクエストヘッダーを監査ログの注釈に取り込みます。これは、プロキシコアを変更せずに、リクエストIDなどのリクエスト固有のコンテキストで監査ログを強化するのに役立ちます。

各注釈グループは、照合するルールと取得するヘッダーを指定します。リクエストがグループ内のいずれかのルールに一致すると、指定されたヘッダー値が変換トレースの注釈に `header:<Name>` エントリとして書き込まれます。一致しないリクエストは変更されずに通過します。この変換がリクエストを拒否することはありません。

> **警告:** ヘッダー値は監査ログに平文で出力されます。リクエストIDやプロキシのシークレットトークンを含むヘッダーなど、公開しても安全なヘッダーのみをログに記録してください。生のシークレットを含むヘッダーはログに記録しないでください。```yaml
transforms:
  - name: annotate
    config:
      annotations:
        - rules:
            - host: "api.openai.com"
              methods: ["POST"]
              paths: ["/v1/*"]
          headers: ["x-request-id"]
        - rules:
            - host: "*.anthropic.com"
          headers: ["x-request-id"]

ヘッダー許可リスト

デフォルト拒否方式のリクエストヘッダーフィルターです。正規名が設定済みの headers リストに含まれないリクエストヘッダーは、リクエストが上流へ送信される前に除去されます。サンドボックスが付与する可能性のあるトラッキング、フィンガープリンティング、または偶発的な漏洩ヘッダー(クッキー、内部相関ID、X-Forwarded-* など)をブロックするのに役立ちます。

エントリは正規ヘッダー名に対して大文字小文字を区別せず照合されます。/.../ で区切られたパターン(例: /^X-Trace-.*$/)は大文字小文字を区別しない正規表現であり、secrets トランスフォームの match_headers 構文と同様です。

オプションの rules は、許可リストを特定のホスト/メソッド/パスに制限します。省略した場合、許可リストはこのトランスフォームに到達するすべてのリクエストに適用されます。

少なくとも1つのヘッダーが除去されると、トレースには除去された名前を列挙した stripped_headers が注釈として付与されます。

配置: header_allowlist は secrets の後(許可リストにない注入済み認証情報が除去されないよう、それらを列挙できます)および annotate の後(注釈が元のヘッダーを読み取れるように)に配置してください。```yaml transforms:

  • name: header_allowlist config: headers: - "Authorization" - "Content-Type" - "User-Agent" - "Accept" - "/^X-Trace-.*$/" rules: - host: "api.openai.com"
root@kitploit:~
### ボディキャプチャ

一致するリクエストのデコード済みリクエストボディを記録し、監査ログレコードの `body_capture` グループに `request_body` と `request_body_truncated` として表示します。プロキシを通過するペイロード(サンドボックスがLLMプロバイダーに送信するプロンプトなど)を、上流のトラフィックを変更せずに監査するのに役立ちます。

ホスト、メソッド、パスは、`allowlist` や `secrets` と同じ `rules` 構文で照合されます。`max_request_body_bytes` は、各ボディのうちどれだけをキャプチャするかを制限します。上限を超えるボディはプレフィックスに切り詰められ、`request_body_truncated` が `true` に設定されます。上限のデフォルトは16 KiBで、グローバルな `proxy.max_request_body_bytes` 制限とは独立しています。このトランスフォームは観察専用であり、リクエストを拒否することはありません。また、ボディの読み取りエラーはリクエストを失敗させるのではなく、トレースに注釈として記録されます。

キャプチャが成功すると、`request_transforms` 内のこのトランスフォームのエントリに `captured_bytes` と `truncated` が注釈として付与され、ボディ自体を複製することなく、ボディがキャプチャされたことがトレースに記録されます。

レスポンスボディはキャプチャされません。ストリーミングレスポンス(SSE)は、転送前にエンドツーエンドでバッファリングする必要があり、クライアントを停滞させることになります。

> **警告:** キャプチャされたボディは監査ログに平文で書き込まれます。`secrets` を `match_body: true` で実行する場合は、`body_capture` を `secrets` の *前* に配置して、監査ログが `secrets` がボディに置き換える実際の認証情報ではなく、サンドボックスのプロキシトークンを記録するようにしてください。```yaml
transforms:
  - name: body_capture
    config:
      max_request_body_bytes: 16384
      rules:
        - host: "api.anthropic.com"
          methods: ["POST"]
          paths: ["/v1/messages"]
        - host: "api.openai.com"
          methods: ["POST"]
          paths: ["/v1/chat/completions"]

シークレット

サンドボックスは実際の認証情報を保持しません。その代わりに:

  1. 実際のシークレットソースを使用して iron-proxy を構成します:環境変数、 ディスク上のファイル、AWS Secrets Manager、AWS Systems Manager Parameter Store、 1Password(サービスアカウント)、または 1Password Connect。
  2. サンドボックスにプロキシトークンを渡します(例:proxy-openai-abc123)。
  3. secrets 変換を構成して、プロキシトークンをそれらのソースにマッピングします。

iron-proxy は送信リクエストをスキャンし、上流へ転送する前にプロキシトークンを実際の値に置き換えます。検索場所は次のように制御できます:

  • match_headers: スキャンするヘッダー名のリスト。空リスト = すべてのヘッダー。 リテラル名は大文字小文字を区別せずに一致しますが、記述した大文字小文字の表記は ヘッダーが上流へ転送されるときに保持されます。/.../ で区切られたエントリは、 正規化されたヘッダー名に対して照合される大文字小文字を区別しない正規表現として コンパイルされます(例:/^x-.*-key$/)。
  • match_body: リクエストボディをスキャンします(max_request_body_bytes までバッファリング)。
  • match_query: URL クエリ文字列をスキャンします。デフォルトは false。クエリパラメータで シークレットを期待する上流のためにオプトインします。クエリ文字列はプロキシの両側の アクセスログに頻繁に現れるため、デフォルトではオフになっています。
  • match_path: URL パスをスキャンします。デフォルトは false。Telegram のように シークレットをパスに埋め込む上流(例:/bot<TOKEN>/sendMessage)のためにオプトインします。 URL パスはプロキシの両側のアクセスログに頻繁に現れるため、デフォルトではオフになっています。
  • require: true の場合、一致するホストへのリクエストで、プロキシトークンを リクエストは 403 で拒否されます。これにより、侵害されたワークロードが代替認証情報で シークレット交換メカニズムをバイパスするのを防ぎます。デフォルト: 。

クエリパラメータは常にスキャンされます。

シークレットソース:

  • env: プロキシプロセスの環境から var を読み取ります。プロセス開始時に固定 — 実行中のプロキシで値をローテーションする必要がある場合は、代わりに file を使用します。
  • file: ディスク上の path からシークレットを読み取ります。ファイルは構成の再読み込み ごと(起動時および各 POST /v1/reload 時)、および ttl が設定されている場合は キャッシュの有効期限ごとに再読み取りされます。そのため、実行中のプロキシのシークレットは、 ファイルを書き換え(原子的に: temp への書き込み + リネーム)して再読み込みすることで、 再起動なしにローテーションできます。値はファイルの正確な内容(トリミングなし)なので、 末尾の空白は書き込み側が制御します。オプションの ttl と failure_ttl がサポートされています。
  • aws_sm: AWS Secrets Manager から secret_id を読み取ります。オプションの region、 ttl、failure_ttl がサポートされています。

すべてのソースはオプションの json_key も受け入れます。設定されている場合、解決された値は JSON オブジェクトとして解析され、そのキーにある単一のトップレベル文字列フィールドが 抽出されます。JSON シークレットから 1 つのフィールドを取り出すために使用します。

ttl は、正常に取得された値が更新前にキャッシュされる期間を制御します (空の場合は無期限にキャッシュ)。failure_ttl は、取得エラーが再試行前にキャッシュされる 期間を制御します。デフォルトは 1m で、ttl とは独立しているため、成功時の TTL が長くても 一時的なバックエンド障害からの回復が遅れることはありません。

注: onepassword-sdk-go のバグにより CGO_ENABLED=0 でのビルドが失敗するため、 iron-proxy は修正が上流に取り込まれるまで、go.mod の replace ディレクティブを介して フォーク を固定しています。

Judge

judge 変換は LLM を呼び出して、その URL ルールに一致するリクエストに対する許可/拒否の判断を 生成します。transforms: の各エントリは、独自の自然言語ポリシー、LLM バックエンド、 タイムアウト、セマフォ、およびサーキットブレーカーを持つ独立した judge インスタンスです。 オペレーターは、異なるルールにスコープされた異なるプロンプトを持つ judge を 0 個、1 個、 または複数デプロイできます。```yaml

  • name: judge config: name: "github-write-guard" # required; identifies the instance in audit logs fallback: "deny" # deny (default) | skip. No "allow" fallback ships in v1. timeout: "8s" # per-call LLM timeout max_concurrent: 100 # semaphore capacity; additional calls wait circuit_breaker: consecutive_failures: 5 cooldown: "10s" rules: # uses the same matcher as allowlist/secrets - host: "api.github.com" methods: ["POST", "PATCH", "DELETE", "PUT"] provider: type: "anthropic" # "anthropic" or "openai" model: "claude-haiku-4-5-20251001" api_key_env: "ANTHROPIC_API_KEY" max_tokens: 256 prompt: | Natural-language policy describing what is allowed for requests that match the rules above. Kept short and specific.
root@kitploit:~
不変条件:

- 判定は拒否のみを行います。静的許可リストが拒否するリクエストを承認することはありません。
  静的拒否が常に優先されます。
- 一致しないリクエストは無視されます。LLM呼び出しも監査注釈も行われません。
- LLMエラー、タイムアウト、サーキットブレーカー解放、または不正なモデル出力の場合、
  設定された`fallback`が適用されます。`deny`はリクエストをブロックします
  (本番環境での推奨デフォルト)。`skip`はパイプラインの残りに委ねます。iron-proxyは
  デフォルト拒否のため、一致しないリクエストも引き続きブロックされます。

シークレット変換とのパイプライン順序:

- **推奨:** 判定をシークレット変換の**前**に配置します。LLMプロバイダーには
  プロキシトークンのみが表示され、ワークロードがアクセスできる実際の認証情報が
  表示されることはありません。
- あるいは、判定をシークレット変換の後に配置すると、実際に外部へ送信されるワイヤー形式
  そのものを評価できますが、実際の認証情報をLLMプロバイダーに送信するという
  コストがかかります。このトレードオフを脅威モデルが許容できる場合にのみ選択してください。

対応プロバイダー:

- **`anthropic`** (Messages API)。`api_key_env`、`model`、オプションの
  `base_url`と`max_tokens`を使用します。
- **`openai`** (Chat Completions API)。上記と同じフィールドです。
  `type: openai`を設定し、`api_key_env`をOpenAIキーを保持する環境変数
  に向け、`gpt-5.4-nano`のようなモデルを選択してください。

監査出力: 一致したすべてのリクエストは、変換トレースの下に構造化フィールドを追加します。
これには`judge.instance`、`judge.decision`、`judge.reason`、
`judge.duration_ms`、`judge.input_tokens`、`judge.output_tokens`、
`judge.fallback_applied`(フォールバックが発動した場合)、および
`judge.circuit_breaker_tripped`(ブレーカーが開いている場合)が含まれます。

クレジット: この設計に影響を与えたBrexのCrabTrapプロジェクト(MITライセンス)に
感謝します。

## MCPポリシー

iron-proxyは[MCPのStreamable HTTPトランスポート](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports)に対応しています。リクエストが設定済みのMCPサーバーに一致すると、プロキシはJSON-RPCボディを解析し、デフォルト拒否のツール許可リストを適用し、`tools/list`レスポンスをフィルタリングして、拒否されたツールがエージェントに届かないようにします。SSEレスポンスはイベントごとにフィルタリングされるため、長期間存続するMCPストリームもライブのまま維持されます。

これはトランスフォームではなく、第一級のプロキシ機能です。MCPレスポンスは、サーバーが任意に開始するメッセージを運ぶオープンエンドのSSEストリームになり得るため、リクエスト/レスポンスのトランスフォーム契約には適合しません。```yaml
mcp:
  # JSON-RPC error envelope returned to the agent on policy denial.
  # Defaults: code -32001, message "blocked by iron-proxy policy".
  error:
    code: -32001
    message: "blocked by iron-proxy policy"
  servers:
    - name: github                         # appears in audit as mcp.server
      rules:                               # standard host/method/path rules
        - host: "mcp.github.com"
          paths: ["/mcp", "/mcp/*"]
      tools:
        - name: "search_repositories"      # always allowed
        - name: "create_issue"
          when:                            # all clauses must hold; otherwise deny
            - path: "owner"                # dotted path against arguments
              equals: "ironsh"
            - path: "repo"
              in: ["iron-proxy", "tunis-v2"]
        # Anything not listed is denied (default-deny).

動作:

  • tools/call の強制。 サーバーの tools リストにないツールへの呼び出し、またはその arguments が 1 つでも when 節を満たさない呼び出しは、アップストリームに到達せずに拒否されます。プロキシは、設定されたコードとメッセージ、およびリクエストの元の id を含む JSON-RPC エラーレスポンスを返すため、MCP クライアントは HTTP エラーではなく通常のプロトコルエラーを受け取ります。
  • tools/list のフィルタリング。 tools/list へのレスポンスでは、許可リストにないツールはすべて、エージェントに到達する前に削除されます。これは application/json と text/event-stream の両方のレスポンスで機能します。SSE フィルタリングはイベント単位で動作するため、ストリーム上のハートビートやその他のメッセージはそのまま通過します。
  • 引数のマッチング。 各 when 節は、ドット区切りの path(例: arguments.repo、labels.0)と、equals(任意の JSON スカラー)、(スカラーのリスト)、または (文字列値に対する正規表現)のいずれかを持ちます。節は AND で結合されます。 を省略すると、そのツールは無条件に許可されます。

パイプラインの順序: MCP インターセプターは変換パイプラインの後に実行されるため、allowlist は依然として到達可能なホストを制限し、インターセプターがボディを評価する時点では secrets がすでにプロキシトークンを置き換えています。

MCP Gateway

mcp_gateway は、MCP ポリシーがリクエストを受理した後、クライアント向けの MCP ホストを具体的なアップストリームサーバーにルーティングします。これにより、エージェントは安定した内部ホストを呼び出し、iron-proxy が実際のアップストリームに転送して、サンドボックスに入ることのない認証情報を注入できます。

ゲートウェイルートは、MCP サーバーに一致したリクエストにのみ適用されます。MCP ポリシーは引き続き、ツールの許可リストを最初に適用します。ポリシーが tools/call を拒否した場合、ゲートウェイルートは適用されず、アップストリームには到達しません。```yaml mcp: servers: - name: github rules: - host: "github.mcp.local" paths: ["/mcp", "/mcp/*"] tools: - name: "search_repositories"

mcp_gateway: routes: - name: github rules: - host: "github.mcp.local" paths: ["/mcp", "/mcp/*"] upstream: "https://mcp.github.com/v1" credentials: - source: type: env var: GITHUB_MCP_TOKEN inject: header: Authorization formatter: "Bearer {{ .Value }}"

root@kitploit:~
資格情報は、`secrets` 変換と同じシークレットソースを使用します。これらはデフォルトで必須です。資格情報に `require: false` を設定すると、利用できない場合にスキップできます。監査ログには、ルート、アップストリームURL、資格情報の挿入場所が記録されますが、挿入された資格情報の値は決して記録されません。

v1での制限事項:

- Streamable HTTP トランスポートのみがサポートされます。レガシーの HTTP+SSE トランスポート(個別の `/messages` エンドポイントと `/sse` エンドポイント)はサポートされません。
- 拒否されたエントリを含む JSON-RPC バッチは、バッチ全体として拒否されます。部分的なバッチ転送はサポートされません。
- リソースとプロンプトは適用されません。エージェントは、ポリシーフィルタリングなしで `resources/list`、`resources/read` などを引き続き呼び出すことができます。

### ボディ制限

リクエスト/レスポンスボディを検査または転送する変換(シークレットのボディマッチング、gRPC 変換)は、バッファリングされたボディに対して動作します。最大バッファサイズを制御する2つのグローバル設定があります:

- **`max_request_body_bytes`** (デフォルト: `1048576` / 1 MiB): 変換用にバッファリングされるリクエストボディの量を制限します。この制限を超えるデータは、変換の観点からは切り捨てられますが、それでもアップストリームに転送されます。
- **`max_response_body_bytes`** (デフォルト: `0` / 無制限): バッファリングされるレスポンスボディの量を制限します。`0` に設定するとレスポンス全体がバッファリングされます。これはほとんどのワークロード(例: npm パッケージ、モデルウェイト)の適切なデフォルトです。

ボディは、変換が読み取る際に増分的にバッファリングされ、パイプラインステージ間で自動的に巻き戻されます。変換がボディを読み取らない場合、バッファリングは発生せず、ボディは変更されずにストリーミングされます。

### トンネルリスナー (HTTP/CONNECT/SOCKS5)

トンネルリスナーは、専用ポートで絶対形式の HTTP プロキシリクエスト、HTTP CONNECT、SOCKS5 接続を受け入れます。これは、DNS ベースのルーティングに依存するのではなく、`HTTP_PROXY`/`HTTPS_PROXY`/`ALL_PROXY` 環境変数または SOCKS5 設定を介したプロキシ設定をネイティブにサポートするツールに役立ちます。

これを有効にするには、`proxy` の下に `tunnel_listen` を設定します:```yaml
proxy:
  tunnel_listen: ":8080"

省略すると、トンネルリスナーは無効になります。

すべてのプロトコルは、通常のHTTP/HTTPSリクエストと同じ変換パイプラインを通過します。absolute-form HTTPリクエストは通常のHTTPプロキシパスで処理されます。CONNECTおよびSOCKS5の場合、プロキシは合成CONNECTリクエストを許可リストとシークレット変換に対して評価するため、トンネル接続も同じデフォルト拒否ポリシーの対象となります。

CONNECTまたはSOCKS5ハンドシェイクの後、プロキシは最初のバイトを覗き見て内部プロトコルを検出します:

  • TLS(0x16): HTTPSリスナーと同じ方法でMITMを実行し、変換処理がリクエストを検査・書き換えできるように、リーフ証明書をその場で生成します。
  • プレーンHTTP: リクエストを変換パイプラインを通じて直接処理します。

HTTP CONNECTの例:```bash curl -x http://172.20.0.2:8080
--cacert /certs/ca.crt
https://httpbin.org/get

root@kitploit:~
**プレーンHTTPプロキシの例:**```bash
curl -x http://172.20.0.2:8080 \
  http://httpbin.org/get

SOCKS5 の例:```bash curl --socks5-hostname 172.20.0.2:8080
--cacert /certs/ca.crt
https://httpbin.org/get

root@kitploit:~
また、標準環境変数を設定すると、すべてのツールが自動的にトンネル
経由でルーティングされます:```bash
export HTTP_PROXY=http://172.20.0.2:8080
export HTTPS_PROXY=http://172.20.0.2:8080
export ALL_PROXY=socks5h://172.20.0.2:8080

SOCKS5 実装は no-auth のみをサポートし、IPv4、IPv6、およびドメイン名アドレスタイプを受け入れます。

TLS

iron-proxy は、提供された CA によって署名されたリーフ証明書をその場で生成します。クライアントコンテナはこの CA を信頼する必要があります(システムのトラストストアに追加するか、--cacert で渡します)。証明書は、SNI ホスト名をキーとする LRU キャッシュにキャッシュされます。

プロキシへのトラフィックのルーティング

強制力が高まる3つのアプローチがあります。

DNSベース(シンプル)

コンテナの DNS を iron-proxy に向けます。すべてのルックアップがプロキシ IP に解決されるため、HTTP/HTTPS トラフィックは自然にプロキシを通過します。これは、Docker Compose の例で使用されている方法です。```yaml services: client: dns: - 172.20.0.2 # iron-proxy IP

root@kitploit:~
セットアップは簡単ですが、迂回も簡単です。ワークロードはIPをハードコードするか、独自のDNSリゾルバを使用してプロキシを完全に迂回できます。

### DNS + nftables エグレスファイアウォール (強制)

DNSルーティングの上にnftablesファイアウォールを重ねます。DNSは依然としてトラフィックをプロキシへ誘導しますが、nftablesは、IPをハードコードしていても、ワークロードが他の何とも通信_できない_ことを保証します。

[`examples/nftables`](https://github.com/paradigmxyz/iron-proxy/blob/HEAD/examples/nftables/) ディレクトリには、動作するセットアップがあります。クライアントコンテナは、アプリケーショントラフィックを実行する前に、起動時にファイアウォールルールをロードします。

**nftables.conf** はプロキシへのトラフィックを許可し、その他すべてをドロップします:```
table ip iron {
  chain output {
    type filter hook output priority 0; policy drop;

    # allow loopback
    oif lo accept

    # allow traffic to the proxy itself (DNS + HTTP/HTTPS)
    ip daddr 172.20.0.2 tcp dport { 80, 443 } accept
    ip daddr 172.20.0.2 udp dport 53 accept

    # allow established/related (return traffic)
    ct state established,related accept

    # log and drop everything else
    log prefix "iron-proxy-drop: " drop
  }
}

docker-compose.yml: クライアントイメージは nftables があらかじめインストールされた状態でビルドされます。エントリポイントはルールを読み込んでから、デモを実行します。CAP_NET_ADMIN はルールを読み込むために必要です:```yaml services: proxy: # ... same as DNS example ... networks: demo: ipv4_address: 172.20.0.2

client: build: context: . dockerfile: Dockerfile.client # alpine + curl + nftables dns: - 172.20.0.2 cap_add: - NET_ADMIN volumes: - ./nftables.conf:/etc/nftables.conf:ro - certs:/certs:ro networks: demo: ipv4_address: 172.20.0.4

root@kitploit:~
本番環境では、エントリーポイントのラッパーでルールをロードし、その後
`CAP_NET_ADMIN` を持たない非 root ユーザーとして実際のプロセスを `exec` します。

### TPROXY (透過プロキシ)

ワークロードのDNSをまったく制御できない環境では、nftables
TPROXY がカーネルレベルでトラフィックをリダイレクトでき、ワークロード側の協力を
一切必要としません。これは PREROUTING チェーンでパケットを傍受し、それらを
直接 iron-proxy に渡します:```
table ip iron {
  chain prerouting {
    type filter hook prerouting priority mangle; policy accept;

    # redirect HTTP/HTTPS to iron-proxy via TPROXY
    tcp dport 80 tproxy to 172.20.0.2:80 meta mark set 1 accept
    tcp dport 443 tproxy to 172.20.0.2:443 meta mark set 1 accept
  }

  chain output {
    type route hook output priority mangle; policy accept;

    # mark locally-originated packets for policy routing
    tcp dport { 80, 443 } meta mark set 1
  }
}

マークされたパケットをローカルソケットにルーティングするには、ip rule と ip route のセットアップが必要です。さらに iron-proxy は IP_TRANSPARENT でバインドしなければなりません。セットアップはより複雑ですが、トラフィックがプロキシをバイパスできないという最も強力な保証を提供します。TPROXY は DNS の下位層で動作するため、ハードコードされた IP、カスタムリゾルバ、そしてワークロードが試みる可能性のあるその他のあらゆるものを捕捉します。

Docker Compose の例

examples/docker-compose ディレクトリには、動作するセットアップが含まれています。主要な構成要素は次のとおりです:

docker-compose.yml: proxy と client は共有ブリッジネットワーク上に配置されます。実際のシークレットは、プロキシコンテナのみに環境変数として設定されます:```yaml services: proxy: build: context: ../.. dockerfile: examples/docker-compose/Dockerfile environment: - OPENAI_API_KEY=sk-real-openai-key-do-not-share - INTERNAL_TOKEN=real-internal-secret-value volumes: - certs:/certs networks: demo: ipv4_address: 172.20.0.2

client: image: alpine:latest dns: - 172.20.0.2 # Point DNS at the proxy volumes: - certs:/certs:ro networks: demo: ipv4_address: 172.20.0.4

root@kitploit:~
**proxy.yaml** は `httpbin.org` と `icanhazip.com` を許可リストに登録し、2つの
シークレットを交換します:```yaml
transforms:
  - name: allowlist
    config:
      domains:
        - "httpbin.org"
        - "icanhazip.com"
      cidrs:
        - "172.20.0.0/24"

  - name: secrets
    config:
      secrets:
        - source:
            type: env
            var: OPENAI_API_KEY
          replace:
            proxy_value: "proxy-openai-abc123"
            match_headers: ["Authorization"]
            match_query: true # scan the query string
          rules:
            - host: "httpbin.org"

        - source:
            type: env
            var: INTERNAL_TOKEN
          proxy_value: "proxy-internal-tok"
          match_headers: [] # scan all headers
          rules:
            - host: "httpbin.org"

クライアントスクリプトは、各動作を示すために5つのリクエストを送信します:```bash

1. Allowed request

curl https://httpbin.org/get

2. Blocked request (not in allowlist)

curl https://example.com/

3. Secret swap: proxy token replaced with real key in Authorization header

curl -H "Authorization: Bearer proxy-openai-abc123" https://httpbin.org/headers

4. Secret swap: proxy token in custom header

curl -H "X-Internal: proxy-internal-tok" https://httpbin.org/headers

5. Secret swap: proxy token in query parameter

curl "https://httpbin.org/get?token=proxy-openai-abc123&q=hello"

root@kitploit:~
## 監査ログ形式

プロキシされたすべてのリクエストは、構造化されたJSONログエントリを生成します:```json
{
  "host": "httpbin.org",
  "method": "GET",
  "path": "/headers",
  "action": "allow",
  "status_code": 200,
  "duration_ms": 142,
  "request_transforms": [
    {
      "name": "allowlist",
      "action": "continue"
    },
    {
      "name": "secrets",
      "action": "continue",
      "annotations": {
        "swapped": [{ "secret": "OPENAI_API_KEY", "locations": ["header:Authorization"] }]
      }
    }
  ],
  "response_transforms": []
}

拒否されたリクエストには rejected_by フィールドが含まれ、WARN レベルでログに記録されます。

OpenTelemetry エクスポート

監査イベントは OpenTelemetry 構造化ログレコードとしてエクスポートでき、Axiom、ClickHouse、Logfire などのバックエンドでオフライン分析に使用できます。有効にするには OTEL_EXPORTER_OTLP_ENDPOINT を設定します:```bash docker run -d --name iron-proxy
-e OTEL_EXPORTER_OTLP_ENDPOINT=https://logfire-us.pydantic.dev
-e OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
-e OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer "
-e OTEL_SERVICE_NAME=iron-proxy
-e OTEL_RESOURCE_ATTRIBUTES="deployment.environment=staging" \

... other flags ...

ironsh/iron-proxy:latest -config /etc/iron-proxy/proxy.yaml

root@kitploit:~
すべての設定は、標準のOTEL環境変数を使用します:

| 変数                           | 説明                                                       | デフォルト          |
| ------------------------------ | ---------------------------------------------------------- | ------------------ |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLPコレクタのURL。未設定の場合はOTELエクスポートが無効になります。 | (無効)             |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf` または `grpc`。                             | `http/protobuf`    |
| `OTEL_EXPORTER_OTLP_HEADERS`  | 認証ヘッダー用のカンマ区切り `key=value` ペア。             | (なし)             |
| `OTEL_SERVICE_NAME`            | すべてのログレコードに付加されるサービス名。                 | `iron-proxy`       |
| `OTEL_RESOURCE_ATTRIBUTES`    | カンマ区切りの `key=value` リソース属性。                   | (なし)             |

有効にすると、既存のJSON stderrログに加えて、すべての監査イベントがOTELログレコードとして出力されます。ログレコードはJSON監査エントリと同じスキーマを保持します: `host`、`method`、`path`、`action`、`status_code`、`duration_ms`、および注釈付きの完全な `request_transforms`/`response_transforms` 配列です。

## 管理API

iron-proxyは、運用タスク用の認証付きHTTP APIをオプションで公開できます。現在は単一のエンドポイント `POST /v1/reload` を提供しており、ディスクからYAML設定を再読み込みし、新しく構築された変換パイプラインを原子的に交換します。新しい設定が無効な場合、実行中のパイプラインは維持されます。

管理サーバーはデフォルトでは無効です。有効にするには、設定に `management` ブロックを追加します:```yaml
management:
  # Bind on loopback unless you front this with a private network or auth proxy:
  # /v1/reload can rebuild the entire transform pipeline.
  listen: "127.0.0.1:9092"
  # Env var that holds the bearer token. Defaults to IRON_MANAGEMENT_API_KEY.
  api_key_env: "IRON_MANAGEMENT_API_KEY"

スタンドアロンモードのみ — コントロールプレーン管理モードとは互換性がありません。

実行中のプロキシをリロードします:```bash curl -X POST http://127.0.0.1:9092/v1/reload
-H "Authorization: Bearer $IRON_MANAGEMENT_API_KEY"

root@kitploit:~
## iron.sh

Need Vault/KMS シークレットバックエンド、Kubernetes オペレーター、または集中化されたポリシー管理が必要ですか? [iron.sh](https://iron.sh) は iron-proxy をベースに、これを大規模に運用するチーム向けのエンタープライズ機能を提供します。

## リリース署名の検証

リリースアーティファクトには、署名付きチェックサムマニフェストが含まれています:

- `checksums.txt`
- `checksums.txt.asc`(ASCIIアーマー形式の分離署名)

同梱の公開鍵 [`public-key.asc`](https://github.com/paradigmxyz/iron-proxy/blob/HEAD/public-key.asc) を使用して検証してください:```bash
# 1) Download release artifacts for a tag
TAG=vX.Y.Z
gh release download "$TAG" --pattern "checksums.txt" --pattern "checksums.txt.asc"

# 2) Import the project signing key
gpg --import public-key.asc

# 3) Verify the signature over checksums.txt
gpg --verify checksums.txt.asc checksums.txt

検証が成功すると、GPG は Matthew Slipper <[email protected]> からの良好な署名を報告します。

必要に応じて、インポートした鍵のフィンガープリントを検査し、検証前に信頼する情報源と一致することを確認できます。

署名付きチェックサムリストに対して特定のバイナリを検証するには(例: iron-proxy-linux-amd64):```bash shasum -a 256 iron-proxy-linux-amd64 | grep -F "$(grep -F 'iron-proxy-linux-amd64' checksums.txt | awk '{print $1}')"

root@kitploit:~
ツールをダウンロード
含まない
false
  • hosts: 交換を特定のドメインまたは CIDR に制限します。
  • aws_ssm: AWS Systems Manager Parameter Store から name を読み取ります。オプションの region、with_decryption、ttl、failure_ttl がサポートされています。 with_decryption はデフォルトで true になり、これは SecureString パラメータに期待される設定です。
  • 1password: 1Password サービスアカウントトークンを使用して secret_ref (op://vault/item/[section/]field 参照)を解決します。トークンは OP_SERVICE_ACCOUNT_TOKEN から読み取られます。オプションの ttl と failure_ttl がサポートされています。
  • 1password_connect: セルフホスト型 1Password Connect サーバーに対して同じ op://vault/item/[section/]field の secret_ref を解決します。サーバー URL は OP_CONNECT_HOST から、API トークンは OP_CONNECT_TOKEN から読み取られます。 オプションの ttl と failure_ttl がサポートされています。
  • in
    matches
    when
  • 監査。 観測されたすべての JSON-RPC メッセージは、監査ログエントリの新しい mcp セクションに記録されます。記録内容は、サーバー名、方向(request または response)、メソッド、ツール、判定(allow、deny、または filtered)、拒否時の理由、およびフィルターイベントで削除されたツールの数です。