信頼済みプロキシ
OxPHP をリバースプロキシ(Kubernetes Ingress、Cloudflare、AWS ALB、nginx)の背後で動作させると、すべてのリクエストはプロキシの IP アドレスから届きます。信頼済みプロキシの設定がないと、レート制限、アクセスログ、そして $_SERVER['REMOTE_ADDR'] のいずれもが、実際のクライアントではなくプロキシの IP を参照してしまいます。
設定
# 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"未設定の場合、OxPHP はすべての転送ヘッダーを無視します。これが安全なデフォルトです。
仕組み
信頼済みの IP からリクエストが届くと、OxPHP は次の優先順位で転送ヘッダーを検査します。
Forwarded(RFC 7239) — 標準化されたヘッダー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 が採用しているのと同じ方式です。
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 からのリクエストは、その転送ヘッダーが完全に無視されます