TrustedProxyResolver
in package
信頼プロキシ経由のリクエスト情報の解釈をグローバル状態から切り離した純粋クラス。
Application::setTrustedProxyConstants() から呼ばれる想定だが、DI コンテナや $_SERVER に 直接触れないため、起動処理の外(Unit テスト含む)から単独で呼び出せる。
転送ヘッダを読むのは「接続元自身が信頼プロキシである」場合に限る(Symfony の Request::isFromTrustedProxy() と同じ考え方)。ロードバランサーを迂回してオリジンへ 直接届いたリクエストのヘッダは信じない。
信頼プロキシの IP が動的に変わる構成(マネージドなロードバランサー等)向けに、
TRUSTED_PROXY_LIST へ TRUST_DIRECT_PEER('')を書くと接続元を無条件に信頼できる。
Laravel の TrustProxies の $proxies = '*' と同義で、全 IP を信頼するのではなく
「接続してきた相手だけ」を信頼する。CIDR と併記でき(例 ',10.0.0.0/8')、
「全 IP を信頼」に相当する /0 は inCidr() が引き続き拒否する。
Why not: '' は「オリジンへプロキシ経由以外で到達できない」構成でのみ使う。直接到達 できる場合、接続元=攻撃者が無条件に信頼プロキシ扱いになり、転送ヘッダで任意の IP を 名乗れる。published range のある CDN(Cloudflare 等)は '' ではなく CIDR で列挙する。 また '*' は直近 1 段しか剥がせないため、多段(CDN→LB→オリジン)では中間プロキシの IP が 返る。その場合は間に入るプロキシを CIDR で併記する。
転送ヘッダは X-Forwarded-For 系(カンマ区切り)と RFC 7239 の Forwarded
(for=1.2.3.4;proto=https 形式)の両方を読める。どちらで解釈するかは
PROXY_IP_HEADER に HTTP_FORWARDED を指定したかどうかだけで決まる。
PROXY_IP_HEADER に HTTP_FORWARDED を指定した環境では、クライアント IP(for)
だけでなく proto / host も同じ Forwarded ヘッダから読む。ただし読む要素は
「クライアント IP の特定に採用したのと同じ要素」に限る(pickClientAddr() の信頼剥がし
走査で決まる位置)。多段構成で後続のプロキシが要素を追記しても、採用されるのは
TLS を終端した最前段プロキシが書いた要素であり、クライアントが偽装要素を前置しても
その偽装 proto が読まれることはない。採用要素に proto が無ければ X-Forwarded-Proto
(host が無ければ X-Forwarded-Server)へフォールバックし、互換性を保つ。
Table of Contents
Constants
- TRUST_DIRECT_PEER = '*'
- 「接続してきた相手をプロキシとして信頼する」を表す TRUSTED_PROXY_LIST の特別値。 ロードバランサーの IP が動的に変わり事前に列挙できない構成向け。
- INTERNAL_RANGES = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.0/8', '169.254.0.0/16', '::1/128', 'fc00::/7', 'fe80::/10']
- canTrustForwardedHeaders() が「内部からの接続」とみなす明示的なアドレス範囲。
Methods
- canTrustForwardedHeaders() : bool
- X-Forwarded-Proto(および同じ信頼境界を共有する X-Forwarded-Server 等)の値を 信頼してよいかを、接続元 IP だけで判定する。ヘッダの値自体はここでは見ない。
- extractHops() : array<int, string>
- 転送ヘッダの値からホップ列(左→右 = クライアント→直近プロキシ)を取り出す。
- hasUntrustedHttpsClaim() : bool
- 信頼していない転送ヘッダが https を主張しているかどうかを判定する (SSL 強制リダイレクトのループガード専用。HTTPS 定数の値には影響しない)。
- inCidr() : bool
- CIDR 判定(IPv4 / IPv6 両対応。inet_pton のバイト列を前置ビット単位で比較)。
- isForwardedHeaderName() : bool
- ヘッダ名が RFC 7239 の `Forwarded` を指しているか。
- isHttpsProto() : bool
- X-Forwarded-Proto ヘッダの値が「https」を示すかを判定する。
- isTrusted() : bool
- IP が信頼プロキシ(IP または CIDR)に含まれるか。
- isTrustedPeer() : bool
- 接続元(オリジンへ実際に接続してきたホスト)をプロキシとして信頼できるか。
- normalizeAddr() : string
- IPv4-mapped IPv6(::ffff:0:0/96、`::ffff:a.b.c.d` と `::ffff:xxxx:xxxx` の いずれの表記も含む)をドット十進の IPv4 表記へ展開する。解釈できない値は そのまま返す(呼び出し側の filter_var 等の検証に委ねる)。
- parseForwardedElements() : array<int, array{for: string, proto: string|null, host: string|null}>
- RFC 7239 の `Forwarded` ヘッダを要素単位で解釈し、`for` / `proto` / `host` を まとめて取り出す。
- parseForwardedHeader() : array<int, string>
- RFC 7239 の `Forwarded` ヘッダから `for` パラメータの値を左から順に取り出す。
- parseTrustedProxyList() : array<int, string>
- 信頼プロキシ設定文字列を配列に正規化する。
- pickClientAddr() : string|null
- X-Forwarded-For のホップ列からクライアント IP を決める。 右端(直近プロキシ)から信頼プロキシを剥がし、最初の非信頼ホップを返す。
- resolve() : TrustedProxyResult
- 信頼プロキシの設定とリクエスト情報から、プロキシ関連の値をまとめて解決する。
- resolveHttpsFlag() : bool
- Application::setConstant() が定義する HTTPS 定数の最終値を決定する。
- resolveRemoteAddr() : string
- $_SERVER と信頼プロキシ設定からクライアント IP 文字列を決める。 グローバル状態(PHP 定数・$_SERVER の直接参照)に一切触れず、引数だけで完結する。
- resolveServerName() : string
- Application::setConstant() が定義する SERVER_NAME 定数の最終値を決定する。
- stripPort() : string
- ホップに付随するポート表記を剥がす。
- pickClientIndex() : int|null
- pickClientAddr() の走査そのもの(採用したホップのインデックス)を返す。
- resolveAdoptedForwardedField() : string|null
- PROXY_IP_HEADER が Forwarded を指す環境で、クライアント IP の決定に採用した のと同じ要素(pickClientIndex() が返すインデックス)の `proto` / `host` を返す。
- splitOutsideQuotes() : array<int, string>
- quoted-string の外側にある区切り文字だけで分割する。
- unquote() : string
- quoted-string を素の値に戻し、`for`(node)向けに stripPort() まで適用する。 引用されていない値はそのまま返す。
- unquoteRaw() : string
- quoted-string を素の値に戻す(stripPort() は適用しない)。引用されていない値は そのまま返す。`proto` / `host` のように IP アドレスでもポート付きでもない値に使う。
Constants
TRUST_DIRECT_PEER
「接続してきた相手をプロキシとして信頼する」を表す TRUSTED_PROXY_LIST の特別値。 ロードバランサーの IP が動的に変わり事前に列挙できない構成向け。
public
mixed
TRUST_DIRECT_PEER
= '*'
INTERNAL_RANGES
canTrustForwardedHeaders() が「内部からの接続」とみなす明示的なアドレス範囲。
private
array<int, string>
INTERNAL_RANGES
= ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.0/8', '169.254.0.0/16', '::1/128', 'fc00::/7', 'fe80::/10']
Why not: filter_var(..., FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) に
判定を委ねていた旧実装は、IPv6 リテラルの表記だけで誤判定する(実測)。
dead:beef::1.2.3.4 のように、末尾がドット十進表記であるという理由だけで
「予約アドレス」と判定され、dead:beef::102:304(同一アドレスの 16 進表記)は
通常の公開アドレスと判定される。この判定は「予約 ⇒ 内部 ⇒ 信頼」という fail-open
方向に効くため、filter_var のフラグには頼らず、このクラスが既に持つ inCidr() で
明示的なレンジ一覧と比較する(fail-closed: 一覧に無ければ内部とはみなさない)。
Methods
canTrustForwardedHeaders()
X-Forwarded-Proto(および同じ信頼境界を共有する X-Forwarded-Server 等)の値を 信頼してよいかを、接続元 IP だけで判定する。ヘッダの値自体はここでは見ない。
public
canTrustForwardedHeaders(array<string, mixed> $server, mixed $trustedProxySetting) : bool
信頼プロキシ一覧(TRUSTED_PROXY_LIST)に一致する接続元、または INTERNAL_RANGES (プライベート/ループバック/リンクローカル)からの接続だけを信頼する(案 1)。
Why not: この判定に渡す $server は、ソケットの接続元をそのまま伝える $_SERVER でなければならない。setTrustedProxyConstants() が XFF 由来の値を REMOTE_ADDR 定数へ反映した後の値を使うと、信頼境界の判定基準そのものが攻撃者の送信値に 依存することになり、 「信頼されていないクライアントが、自分自身を信頼済みプロキシや内部アドレスだと 名乗るだけで転送ヘッダの信頼を得る」という循環が成立してしまう。これは呼び出し 順序(setTrustedProxyConstants() が先か後か)に依存しない不変条件であり、将来 REMOTE_ADDR 定数が先に定義されるよう変更されても、この理由がある限り置き換えてはならない。
Why not: 単純な fail closed(TRUSTED_PROXY_LIST 未設定なら常に信頼しない)は 採用しない。配布既定は空文字で、設定 UI も無いため、TLS 終端 LB/CDN 配下で これを設定していない既存サイトの HTTPS 判定が恒久 false になり、常時 SSL リダイレクトのループや Secure Cookie の喪失という運用事故に直結する。 実運用の LB・リバースプロキシはほぼ内部アドレスから接続するため、 接続元が INTERNAL_RANGES に含まれるかどうかで代替の安全網を張る。
Why not: CGNAT(100.64.0.0/10)は INTERNAL_RANGES に含まれないためこの判定では 救えない(TRUSTED_PROXY_LIST の設定が必要)。案 1 に残る既知の穴として受け入れる。
Parameters
- $server : array<string, mixed>
-
$_SERVER 相当(接続元をそのまま伝えるもの)
- $trustedProxySetting : mixed
-
TRUSTED_PROXY_LIST の値(未定義なら null)
Return values
boolextractHops()
転送ヘッダの値からホップ列(左→右 = クライアント→直近プロキシ)を取り出す。
public
extractHops(string $headerValue, string $proxyIpHeader) : array<int, string>
ヘッダ名が RFC 7239 の Forwarded($_SERVER のキーで HTTP_FORWARDED)のときだけ
RFC 7239 の文法で解釈し、それ以外は X-Forwarded-For 系としてカンマ区切りで分割する。
Why not: 値の中身で形式を判定(for= を含むかで振り分ける等)しない。X-Forwarded-For
に for= を含む文字列を送るだけで解釈方法を切り替えられてしまい、攻撃者が
パーサを選べる状態になる。どちらで読むかは運用者の設定(PROXY_IP_HEADER)だけで決める。
Parameters
- $headerValue : string
-
転送ヘッダの生の値
- $proxyIpHeader : string
-
PROXY_IP_HEADER の値($_SERVER のキー名)
Return values
array<int, string> —ホップ列
hasUntrustedHttpsClaim()
信頼していない転送ヘッダが https を主張しているかどうかを判定する (SSL 強制リダイレクトのループガード専用。HTTPS 定数の値には影響しない)。
public
hasUntrustedHttpsClaim(array<string, mixed> $server, mixed $trustedProxySetting[, string $proxyIpHeader = 'HTTP_X_FORWARDED_FOR' ]) : bool
Why not: HTTPS 定数は「信頼できる情報だけを見て false のまま」という結果が
正しいことがある(このメソッドが true を返すケースはまさにそれ)。しかし
main.php の常時 SSL リダイレクトは !HTTPS だけを見て https へ 301 する。
接続元が実際には https で届いているのに、信頼していないという理由だけで
!HTTPS を通してリダイレクトすると、クライアントは既に https で来ているため
何も変わらず再度リダイレクトを踏み、301 の無限ループになる。この判定は
ヘッダを信頼する(信頼済みとして扱う)わけではなく、あくまで「リダイレクトを
止めるべきかどうか」だけを見るための別の軸で、HTTPS 定数・Secure Cookie の
判定には一切影響しない。
Why not: Forwarded 側は「採用要素」まで絞らず、値に proto=https を含む要素が どこにあっても検知対象にする。この判定はそもそも信頼できない前提(呼び出し ガードで既に未信頼と分かっている)のループガードであり、「どの要素が正しい クライアントか」を厳密に決める必要が無い。むしろ偽装要素であっても https を 主張していればループを止めるべきなので、resolveHttpsFlag() 側の「採用要素だけ」 という絞り込みとは意図的に非対称にしている。
Parameters
- $server : array<string, mixed>
-
$_SERVER 相当
- $trustedProxySetting : mixed
-
TRUSTED_PROXY_LIST の値(未定義なら null)
- $proxyIpHeader : string = 'HTTP_X_FORWARDED_FOR'
-
PROXY_IP_HEADER の値
Return values
boolinCidr()
CIDR 判定(IPv4 / IPv6 両対応。inet_pton のバイト列を前置ビット単位で比較)。
public
inCidr(string $addr, string $cidr) : bool
Why not: $addr は normalizeAddr で正規化してから比較するため、IPv4-mapped IPv6
(::ffff:10.0.0.1 等)は 4 バイトの IPv4 として扱われる。そのため CIDR 側
($cidr)も正規化後のファミリに合わせて書く必要がある。::ffff:0:0/96 のように
IPv6 のまま書いた CIDR は、正規化後の $addr(4 バイト)と長さが噛み合わず
常に false になる(fail closed だが無警告なので、設定例には注意が必要)。
Parameters
- $addr : string
- $cidr : string
Return values
boolisForwardedHeaderName()
ヘッダ名が RFC 7239 の `Forwarded` を指しているか。
public
isForwardedHeaderName(string $proxyIpHeader) : bool
$_SERVER のキー(HTTP_FORWARDED)とヘッダ名そのまま(FORWARDED)の両方を受ける。
PROXY_IP_HEADER は運用者が手で書く設定値なので、大文字小文字は問わない。
Parameters
- $proxyIpHeader : string
Return values
boolisHttpsProto()
X-Forwarded-Proto ヘッダの値が「https」を示すかを判定する。
public
isHttpsProto(string $headerValue) : bool
Why not: 旧実装($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')は非数値文字列
同士の比較のため実質 === と同じで、'https, http'・'http,https'・前後空白
付き・末尾セミコロン付きの値は実測でもすべて false だった。ここで変えたのは
大文字小文字を無視するようにした点だけで、複数値やカンマ区切りを拒否する挙動
自体は旧実装からそのまま継続している。新たに何かを弾くようになったわけではなく、
HTTPS/Https のような表記ゆれを受け入れる方向への互換性拡大である。
Parameters
- $headerValue : string
Return values
boolisTrusted()
IP が信頼プロキシ(IP または CIDR)に含まれるか。
public
isTrusted(string $addr, array<int, string> $trustedProxyList) : bool
Parameters
- $addr : string
- $trustedProxyList : array<int, string>
Return values
boolisTrustedPeer()
接続元(オリジンへ実際に接続してきたホスト)をプロキシとして信頼できるか。
public
isTrustedPeer(string $peerAddr, array<int, string> $trustedProxyList) : bool
Why not: isTrusted() と同一視しない。TRUST_DIRECT_PEER('*')は「接続してきた 相手をプロキシとして信頼する」意味なので、接続元の判定でだけ真になり、XFF の 各ホップの判定(isTrusted)では偽のままでなければならない。両方で真にすると 全ホップが信頼扱いになり、pickClientAddr が null を返して接続元へ縮退する (クライアント IP が常に直近プロキシの IP に潰れる)。
Parameters
- $peerAddr : string
- $trustedProxyList : array<int, string>
Return values
boolnormalizeAddr()
IPv4-mapped IPv6(::ffff:0:0/96、`::ffff:a.b.c.d` と `::ffff:xxxx:xxxx` の いずれの表記も含む)をドット十進の IPv4 表記へ展開する。解釈できない値は そのまま返す(呼び出し側の filter_var 等の検証に委ねる)。
public
normalizeAddr(string $addr) : string
Why not: デュアルスタック構成のロードバランサーは同一クライアントに対して
::ffff:10.0.0.1 と 10.0.0.1 のどちらの表記も付与し得る。正規化せずに
比較・返却すると、信頼判定がすり抜けてロックアウトを起こしたり、
lock_address のバケットが表記違いで 2 つに分裂して試行回数上限が
実質倍になったりする。
Parameters
- $addr : string
Return values
stringparseForwardedElements()
RFC 7239 の `Forwarded` ヘッダを要素単位で解釈し、`for` / `proto` / `host` を まとめて取り出す。
public
parseForwardedElements(string $headerValue) : array<int, array{for: string, proto: string|null, host: string|null}>
文法(RFC 7239 §4)は次のとおり。要素はカンマ区切り、要素内のパラメータはセミコロン 区切りで、値は token または quoted-string を取る。
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for="[2001:db8:cafe::17]:4711"
for の値(node、RFC 7239 §6)は IPv4 / [IPv6] / unknown / _ 始まりの難読化
識別子のいずれかで、任意でポートが付く。IP として解釈できない値(unknown や
_hidden)は pickClientAddr() が既に「不正なホップは読み飛ばす」扱いにしているため、
ここでは値をそのまま返して判定を任せる。
for の無い要素も戻り値から除かず for => '' のまま残す。呼び出し元
(resolveHttpsFlag() 等)は「クライアント IP の決定に採用した要素と同じ位置」の
proto / host を読む必要があり、要素を間引くと配列のインデックスが
pickClientAddr() の走査結果とずれてしまう。
Why not: preg_split('/,/') で単純に分割しない。quoted-string の内部にカンマや
セミコロンを含められる(難読化識別子は quoted-string で送られうる)ため、引用の
内外を区別しない分割ではホップ境界を誤り、1 つのホップが 2 つに割れて信頼境界の
判定がずれる。
Why not: proto / host は for と違いポート表記を持たず、IP アドレスでもない
(host は Host ヘッダ相当でポートを含みうる文字列そのもの)。そのため unquote()
(内部で stripPort() を呼ぶ)ではなく、引用符の除去だけを行う unquoteRaw() を使う。
Parameters
- $headerValue : string
-
Forwardedヘッダの生の値
Return values
array<int, array{for: string, proto: string|null, host: string|null}> —出現順の要素列
parseForwardedHeader()
RFC 7239 の `Forwarded` ヘッダから `for` パラメータの値を左から順に取り出す。
public
parseForwardedHeader(string $headerValue) : array<int, string>
parseForwardedElements() の薄い射影で、クライアント IP の決定にしか使わない
呼び出し元(extractHops() 経由の pickClientAddr())向けに for の値だけを返す。
proto / host も必要な場合は parseForwardedElements() を直接使う。
Why not: for が無い要素を空文字として残さない。pickClientAddr() の走査は
「ホップ列=クライアント IP の候補」を前提にしており、for の無い要素を空文字で
混ぜるとそれ自体が「不正なホップ」として読み飛ばされ、信頼境界の判定がずれる
(parseForwardedElements() 側は要素の対応関係を保つためあえて空文字を残す)。
Parameters
- $headerValue : string
-
Forwardedヘッダの生の値
Return values
array<int, string> —for の値(出現順。ポート表記や引用符は剥がした状態)
parseTrustedProxyList()
信頼プロキシ設定文字列を配列に正規化する。
public
parseTrustedProxyList(string $setting) : array<int, string>
Parameters
- $setting : string
-
TRUSTED_PROXY_LIST の値
Return values
array<int, string>pickClientAddr()
X-Forwarded-For のホップ列からクライアント IP を決める。 右端(直近プロキシ)から信頼プロキシを剥がし、最初の非信頼ホップを返す。
public
pickClientAddr(array<int, string> $forwardedList, array<int, string> $trustedProxyList) : string|null
Parameters
- $forwardedList : array<int, string>
-
左→右(クライアント→直近プロキシ)順のホップ
- $trustedProxyList : array<int, string>
-
IP または CIDR
Return values
string|null —決定できなければ null(呼び出し側は接続元へフォールバック)
resolve()
信頼プロキシの設定とリクエスト情報から、プロキシ関連の値をまとめて解決する。
public
resolve(array<string, mixed> $server, mixed $trustedProxySetting, string $proxyIpHeader) : TrustedProxyResult
Application はこの戻り値を定数へ反映するだけにし、クライアント IP・HTTPS・ サーバー名の信頼境界が別々に実装されないようにする。
Parameters
- $server : array<string, mixed>
-
$_SERVER 相当
- $trustedProxySetting : mixed
-
TRUSTED_PROXY_LIST の値(未定義なら null)
- $proxyIpHeader : string
-
PROXY_IP_HEADER の値
Return values
TrustedProxyResultresolveHttpsFlag()
Application::setConstant() が定義する HTTPS 定数の最終値を決定する。
public
resolveHttpsFlag(array<string, mixed> $server, mixed $trustedProxySetting[, string $proxyIpHeader = 'HTTP_X_FORWARDED_FOR' ]) : bool
Parameters
- $server : array<string, mixed>
-
$_SERVER 相当
- $trustedProxySetting : mixed
-
TRUSTED_PROXY_LIST の値(未定義なら null)
- $proxyIpHeader : string = 'HTTP_X_FORWARDED_FOR'
-
PROXY_IP_HEADER の値
Return values
boolresolveRemoteAddr()
$_SERVER と信頼プロキシ設定からクライアント IP 文字列を決める。 グローバル状態(PHP 定数・$_SERVER の直接参照)に一切触れず、引数だけで完結する。
public
resolveRemoteAddr(array<string, mixed> $server, mixed $trustedProxySetting, string $proxyIpHeader) : string
Parameters
- $server : array<string, mixed>
-
$_SERVER 相当
- $trustedProxySetting : mixed
-
TRUSTED_PROXY_LIST の値(未定義なら null)
- $proxyIpHeader : string
-
PROXY_IP_HEADER の値
Return values
string —決定できなければ空文字
resolveServerName()
Application::setConstant() が定義する SERVER_NAME 定数の最終値を決定する。
public
resolveServerName(array<string, mixed> $server, mixed $trustedProxySetting[, string $proxyIpHeader = 'HTTP_X_FORWARDED_FOR' ]) : string
Parameters
- $server : array<string, mixed>
-
$_SERVER 相当
- $trustedProxySetting : mixed
-
TRUSTED_PROXY_LIST の値(未定義なら null)
- $proxyIpHeader : string = 'HTTP_X_FORWARDED_FOR'
-
PROXY_IP_HEADER の値
Return values
stringstripPort()
ホップに付随するポート表記を剥がす。
public
stripPort(string $hop) : string
Why not: 素の IPv6(コロンを複数含む)に対して末尾の :\d+ を単純に取り除くと、
2001:db8::1 の末尾 :1 がポート表記と誤認され 2001:db8: に破壊される。
そのため IPv4:port・[IPv6]:port・[IPv6]・コロン 1 個の IPv4:port のみを
明示的な形で判定し、それ以外(素の IPv6 含む)はそのまま返す。
Parameters
- $hop : string
Return values
stringpickClientIndex()
pickClientAddr() の走査そのもの(採用したホップのインデックス)を返す。
private
pickClientIndex(array<int, string> $forwardedList, array<int, string> $trustedProxyList) : int|null
Why not: pickClientAddr() 単体の再実装にしない。resolveHttpsFlag() 等が
Forwarded ヘッダの proto / host を読む際、「クライアント IP の決定に採用した
のと同じ要素」を指す必要がある。走査を 2 箇所に持つと、片方だけ改修されたときに
「採用したホップ」と「proto を読むホップ」がずれる(多段構成で偽装要素混入時に
誤った proto を信頼してしまう)。走査ロジックを 1 箇所に集約し、両者はこの
インデックスを共有する。
Parameters
- $forwardedList : array<int, string>
-
左→右(クライアント→直近プロキシ)順のホップ
- $trustedProxyList : array<int, string>
-
IP または CIDR
Return values
int|null —決定できなければ null(呼び出し側は接続元・フォールバック値を使う)
resolveAdoptedForwardedField()
PROXY_IP_HEADER が Forwarded を指す環境で、クライアント IP の決定に採用した のと同じ要素(pickClientIndex() が返すインデックス)の `proto` / `host` を返す。
private
resolveAdoptedForwardedField(array<string, mixed> $server, mixed $trustedProxySetting, string $proxyIpHeader, "proto"|"host" $field) : string|null
Why not: for の値が一致する要素を探し直す実装にしない。同じ for 値を持つ要素が 複数あり得る(多段構成で中間プロキシが自身の直近ホップを重複して書く等)ため、 値の一致では誤った要素を拾う余地が残る。pickClientIndex() が返すインデックスを そのまま使えば、pickClientAddr() が実際に採用したのと同じ要素であることが保証される。
Parameters
- $server : array<string, mixed>
-
$_SERVER 相当
- $trustedProxySetting : mixed
-
TRUSTED_PROXY_LIST の値(未定義なら null)
- $proxyIpHeader : string
-
PROXY_IP_HEADER の値
- $field : "proto"|"host"
Return values
string|null —採用要素が無い、または当該フィールドが未指定なら null
splitOutsideQuotes()
quoted-string の外側にある区切り文字だけで分割する。
private
splitOutsideQuotes(string $value, string $delimiter) : array<int, string>
Parameters
- $value : string
- $delimiter : string
-
1 文字の区切り文字
Return values
array<int, string>unquote()
quoted-string を素の値に戻し、`for`(node)向けに stripPort() まで適用する。 引用されていない値はそのまま返す。
private
unquote(string $value) : string
IPv6 の node は RFC 7239 で for="[2001:db8::1]:4711" のように引用が必須なので、
引用を外した後に stripPort() で括弧とポートを剥がす。
Parameters
- $value : string
Return values
stringunquoteRaw()
quoted-string を素の値に戻す(stripPort() は適用しない)。引用されていない値は そのまま返す。`proto` / `host` のように IP アドレスでもポート付きでもない値に使う。
private
unquoteRaw(string $value) : string
Parameters
- $value : string