Apache+PHPにおけるアクセス元IPの制御
- $_SERVER['REMOTE_ADDR'] は常に直接接続してきたクライアントのIPアドレス(CloudFrontやプロキシサーバーなどを含む)を返し、X-Forwarded-For の値はデフォルトでは使用されません
-
X-Forwarded-For
は、プロキシやロードバランサーを経由した際に、元のクライアントのIPアドレスを伝えるために使用されるHTTPヘッダー -
remoteip_module
は、リクエストのIPアドレスをリバースプロキシやロードバランサーの後ろにあるクライアントの実際のIPアドレスに書き換えるためのApacheモジュール -
RemoteIPHeader X-Forwarded-For
ディレクティブは、X-Forwarded-For ヘッダーの値を使用して、リクエスト元のIPアドレスを上書きすることを指定
AWS PrivateLink → NLB → ALB → Nginx
log_format main '
time_local] " remote_addr - $remote_user [ http_referer" " request" $status $body_bytes_sent " http_x_forwarded_for"'; http_user_agent" "
# 5. Consumer EC2 on Consumer VPCからConsumer VPC上のVPCエンドポイントにアクセス
10.10.0.36 - - [10/Jun/2022:07:52:49 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.79.1" "10.10.0.39"
or
10.10.0.57 - - [10/Jun/2022:07:53:02 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.79.1" "10.10.0.60"
-
remote_addr
はALB IP Address -
http_x_forwarded_for
はNLB IP Address
ALBのX-Forwarded-Forの扱い
- Application Load Balancer がターゲットにHTTPリクエストを送信する前に、リクエストの X-Forwarded-Forヘッダーを変更、保持、または削除できます。
- デフォルトでは、Application Load Balancer は、クライアントの IP アドレスを X-Forwarded-For リクエストヘッダーに格納し、このヘッダーをサーバーに渡します。
- X-Forwarded-For リクエストヘッダーがオリジナルリクエストに含まれていない場合、ロードバランサーはリクエスト値としてクライアント IP アドレスを持つリクエストヘッダーを作成します。
- それ以外の場合、ロードバランサーはクライアント IP アドレスを既存のヘッダーに追加し、 ヘッダーをサーバーに渡します。X-Forwarded-For リクエストヘッダーには、カンマで区切られた複数の IP アドレスを含めることができます。
mod_remoteip
- Apache はデフォルトでは接続の client_ip 値でユーザエージェントを識別し、 接続の remote_host と remote_logname はこの値から派生します。
- mod_remoteip はリクエストの間、プロキシやロードバランサから提供された アドバタイズされたユーザエージェント IP で接続のクライアント IP を上書きします。
- カンマで区切られた複数のユーザーエージェントIPアドレスがヘッダー値に リストされているときは、それらはRight-to-Leftの順番で処理されます。 与えられたユーザーエージェントIPアドレスが、先行するIPアドレスの提示 を信頼できない場合、処理は停止する。
- ヘッダーフィールドは、この未確認のIPアドレスの残りのリストに更新され るか、すべてのIPアドレスが信頼された場合、このヘッダーはリクエストから 完全に取り除かれる。
RemoteIPHeader X-Forwarded-For
- mod_remoteip が指定されたヘッダフィールドヘッダの値を
ユーザエージェント IP アドレス
、または中間ユーザエージェント IP アドレスのリスト
として 扱うようにします - 他のディレクティブが使用されない限り、 mod_remoteip は RemoteIPHeader の IP 値を提示するすべてのホストを信頼します
RemoteIPHeader X-Client-IP
RemoteIPInternalProxy 10.0.2.0/24 or RemoteIPInternalProxyList conf/trusted-proxies.lst
- 一つ以上のアドレス (またはアドレスブロック) を、 ユーザエージェント IP の有効な RemoteIPHeader の値として信頼するように 追加します。
-
RemoteIPInternalProxy
が設定されていない場合、mod_remoteip はプライベートIPアドレスを持つプロキシのX-Forwarded-For ヘッダーを無視します。
RemoteIPHeaderがX-Forwarded-Forで置き換える順序
X-Forwarded-For
ヘッダーに複数のIPアドレスが含まれている場合、RemoteIPHeader
の設定によって $_SERVER['REMOTE_ADDR']
に置き換わるIPアドレスが決まります。X-Forwarded-For
ヘッダーには通常、最も左にクライアントの実際のIPアドレスがあり、その後にプロキシを通過した順番でIPアドレスが追加されます。
X-Forwarded-For
の構造
X-Forwarded-For
ヘッダーに複数のIPアドレスがある場合、次のようになります:
X-Forwarded-For: clientIP, proxy1IP, proxy2IP, ...
ここで、clientIP
がクライアントの実際のIPアドレス、proxy1IP
が最初のプロキシのIPアドレス、proxy2IP
が次のプロキシのIPアドレスという順番で記録されています。
RemoteIPHeader
による置き換えの順番
Apacheの mod_remoteip
が有効になっていて、RemoteIPHeader
が X-Forwarded-For
に設定されている場合、以下の順番で処理が行われます。
-
最初のIP(左端)から順に処理:
-
RemoteIPHeader
に設定されたX-Forwarded-For
ヘッダーのIPアドレスは、最初に出現するIP(最も左側のIP)から順に処理されます。 - Apacheはこのヘッダーを左から右に読み込み、最初に有効で信頼できるIPアドレスを
$_SERVER['REMOTE_ADDR']
に設定します。
-
-
信頼されたプロキシが設定されている場合:
-
RemoteIPInternalProxy
またはRemoteIPInternalProxyList
が設定されている場合、これらの信頼できるプロキシのIPアドレスを認識し、信頼できるプロキシを通過した後の最初のIPアドレス(つまり、クライアントのIPアドレス)を$_SERVER['REMOTE_ADDR']
に設定します。
-
-
信頼されていないプロキシがある場合:
- 信頼されていないプロキシを通過したIPアドレスが存在する場合、その後ろのIPアドレスは無視されます。信頼されていないプロキシのIPが先に見つかった場合、そのIPが
$_SERVER['REMOTE_ADDR']
に設定される可能性があります。
- 信頼されていないプロキシを通過したIPアドレスが存在する場合、その後ろのIPアドレスは無視されます。信頼されていないプロキシのIPが先に見つかった場合、そのIPが
例
例えば、次のような X-Forwarded-For
ヘッダーがあるとします。
X-Forwarded-For: 203.0.113.1, 198.51.100.1, 192.0.2.1
- 203.0.113.1: クライアントのIP
- 198.51.100.1: 最初のプロキシのIP
- 192.0.2.1: 2番目のプロキシ(信頼されたプロキシとして設定)
信頼されたプロキシがある場合
もし RemoteIPInternalProxy 192.0.2.1
が設定されている場合、Apacheは X-Forwarded-For
の最初のIPである 203.0.113.1
をクライアントのIPアドレスと見なし、$_SERVER['REMOTE_ADDR']
に設定します。
信頼されたプロキシがない場合
RemoteIPInternalProxy
の設定がない場合、$_SERVER['REMOTE_ADDR']
は通常、最も右端(最新のプロキシ)のIPアドレスである 192.0.2.1
が設定されるか、信頼できると判断された最初のIP(198.51.100.1
)が設定されることになります。
まとめ
-
X-Forwarded-For
のIPアドレスは、左から右へ順番に処理されます。 -
RemoteIPInternalProxy
が設定されている場合、信頼できるプロキシを通過した後の最初のIPアドレスが$_SERVER['REMOTE_ADDR']
に設定されます。 - 信頼されていないプロキシのIPアドレスが見つかると、その後のIPアドレスは無視されるか、信頼されていないプロキシのIPが使用されることがあります。
これにより、正確なクライアントIPアドレスを取得するためには、適切に RemoteIPInternalProxy
を設定することが非常に重要です。