信頼済みプロキシ

OxPHP をリバースプロキシ(Kubernetes Ingress、Cloudflare、AWS ALB、nginx)の背後で動作させると、すべてのリクエストはプロキシの IP アドレスから届きます。信頼済みプロキシの設定がないと、レート制限、アクセスログ、そして $_SERVER['REMOTE_ADDR'] のいずれもが、実際のクライアントではなくプロキシの IP を参照してしまいます。

設定

bash
# Comma-separated CIDR list TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" # Shorthand: all RFC-1918 + loopback + link-local (IPv4 and IPv6) TRUSTED_PROXIES="private"
Note

未設定の場合、OxPHP はすべての転送ヘッダーを無視します。これが安全なデフォルトです。

仕組み

信頼済みの IP からリクエストが届くと、OxPHP は次の優先順位で転送ヘッダーを検査します。

  1. Forwarded (RFC 7239) — 標準化されたヘッダー
  2. X-Forwarded-For / X-Forwarded-Proto / X-Forwarded-Host / X-Forwarded-Port — 事実上のフォールバック

Forwarded ヘッダーが存在する場合、X-Forwarded-* ヘッダーは無視されます。

クライアント IP の抽出

OxPHP は**最右端の非信頼(rightmost-non-trusted)**アルゴリズムを使用します。これは nginx(real_ip_recursive on)、Caddy、Traefik、Apache が採用しているのと同じ方式です。

text
X-Forwarded-For: 203.0.113.50, 172.16.1.1, 10.0.0.5 TCP peer: 10.0.0.1 (trusted) Walk right-to-left: 10.0.0.5 → trusted → skip 172.16.1.1 → trusted → skip 203.0.113.50 → NOT trusted → client IP

これにより、先頭に値を付け加えることによるなりすましを防止できます。攻撃者は左側に偽の IP を追加できますが、最右端の非信頼 IP はチェーン内の最後の信頼済みプロキシによって設定されたものです。

変わる内容

TRUSTED_PROXIES が設定されていて、接続元の IP が信頼済みの場合は次のようになります。

コンポーネント 信頼済みプロキシなし 信頼済みプロキシあり
$_SERVER['REMOTE_ADDR'] プロキシ IP 実際のクライアント IP
$_SERVER['REMOTE_PORT'] プロキシの送信元ポート Forwarded: for=ip:port のクライアントポート、なければ 0
$_SERVER['HTTPS'] OxPHP の TLS 設定に基づく Forwarded: proto= または X-Forwarded-Proto から
$_SERVER['REQUEST_SCHEME'] TLS に基づく http または https 転送されたプロトコルから
$_SERVER['SERVER_NAME'] Host ヘッダーから Forwarded: host= または X-Forwarded-Host から
$_SERVER['SERVER_PORT'] Host ヘッダーから X-Forwarded-Port から、なければ X-Forwarded-Host / Forwarded: host= のポート、それもなければ 443/80
レート制限 プロキシ IP 単位 クライアント IP 単位
アクセスログ プロキシ IP 実際のクライアント IP

REMOTE_PORT は、RFC 7239 の Forwarded: for=ip:port ノードがクライアントの送信元ポートを保持していない限り、プロキシの背後では 0 になります。X-Forwarded-For にはポートフィールドがないため、書き換え後の値を復元できず、推測する代わりにゼロが設定されます。

private ネットワーク

private の短縮指定には次のものが含まれます。

ネットワーク 説明
10.0.0.0/8 クラス A プライベート
172.16.0.0/12 クラス B プライベート
192.168.0.0/16 クラス C プライベート
127.0.0.0/8 ループバック
169.254.0.0/16 リンクローカル
::1/128 IPv6 ループバック
fc00::/7 IPv6 ユニークローカル
fe80::/10 IPv6 リンクローカル

セキュリティ

  • 安全なデフォルトTRUSTED_PROXIES がなければ、転送ヘッダーは一切処理されません
  • CIDR 検証TRUSTED_PROXIES に無効な値があると起動時エラーになります
  • なりすまし耐性 — 最右端の非信頼アルゴリズムは、攻撃者が先頭に付け加えた値を無視します
  • 信頼できない IP からのリクエストは、その転送ヘッダーが完全に無視されます

関連項目