【AWS】ALB利用時のアクセス元IPの偽装対策 (X-Forwarded-For)

# はじめに
リクエストヘッダーの`X-Forwarded-For`は、Webサーバーやアプリ側でアクセス元IPアドレスを取得する手段としてよく使われています。
本記事では、AWS Application Load Balancer(ALB) の`X-Forwarded-For`の仕様と`X-Forwarded-For`使用時のアクセス元IPアドレスの偽装対策について書いています。

## ALBのX-Forwarded-Forの仕様
- HTTP ヘッダーと Application Load Balancer
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/x-forwarded-headers.html

- [ALB - X-Forwarded-Forのヘッダーの仕様](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/x-forwarded-headers.html#x-forwarded-for)
    - 付加 / append ... アクセス元IPを追加する (default)
    - 保持 / preserve ... X-Forwarded-Forをそのまま中継する（多段ALB向け）
    - 削除 / remove ... X-Forwarded-Forヘッダーを付けないで削除する

    ALB > 属性 >  X-Forwarded-Forヘッダーの設定画面
    ![aws-alb-attribute-xff-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583919/20f0cc8c-d950-0daf-1a43-fd478d575ce7.png)

- デフォルトは`付加(append)`。リクエストヘッダー `X-Forwarded-For` の存在有無で挙動が異なるので注意
    - `X-Forwarded-For`が設定されていない場合は、アクセス元IPアドレスが設定される
    - <font color="red">`X-Forwarded-For`が存在する場合は、カンマ区切りで最後(右端)にアクセス元IPを追加</font>

## アクセス元IPアドレスの偽装対策
ALBの属性でX-Forwarded-Forの設定を **`付加 (append)`** に設定している場合、既にリクエストヘッダーに `X-Forwarded-For` が指定されていると、カンマ区切りで最後にアクセス元IPアドレスが追加される。

- <font color="red">`X-Forwarded-For`に任意のIPアドレスを指定することで、偽装リクエストの送信は可能</font>
- :warning: ALBに限らず、Webサーバーやリバースプロキシなどでも同様に、`X-Forwarded-For`ヘッダーを適切に使用していない場合、セキュリティリスクがある。

:::note warn
参考）X-Forwarded-For - HTTP | MDN (developer.mozilla.org)
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Forwarded-For
- [セキュリティーとプライバシーの懸念](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Forwarded-For#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%BC%E3%81%A8%E3%83%97%E3%83%A9%E3%82%A4%E3%83%90%E3%82%B7%E3%83%BC%E3%81%AE%E6%87%B8%E5%BF%B5)
:::

- 例）リクエストヘッダー **`X-Forwarded-For: 127.0.0.1`** のリクエストをALBに送信した場合に、ALBが付加した結果 (ALBにアクセスしたクライアントのIP: 192.168.123.123)
    ```
    X-Forwarded-For: 127.0.0.1, 192.168.123.123
    ```
    - ALBは既存の値のX-Forwarded-Forの値の最後(右端)に、`アクセス元IPアドレス`を追加
    - X-Forwarded-Forの値には、<font color="red">**任意のIPアドレス、aaaなどの任意の文字列など偽装可能**</font>

- アプリ側では複数の値があった場合、<font color="blue">**最後(右端)の値だけを使う**</font> などの考慮が必要
    - 特に、アクセス元IPアドレスの制限で `X-Forwarded-For`の値を利用している場合、考慮されていないと、アクセス制御が回避される可能性がある

:::note warn
- X-Forwarded-For の値は偽装可能であるため、単純に信頼してはいけない。
- ALBではカンマ区切りで最後(右端)にアクセス元IPアドレスを追加する仕様。
  - X-Forwarded-Forの値でカンマ区切りで複数の値が含まれている場合、最後(右端)の値以外は信頼できない。
:::

## 参考）多段ALB構成の場合の対策
多段ALB構成で`X-Forwarded-For`を使ってアクセス元IPアドレスを伝搬したい場合の設定方法と考慮ポイントについて、簡単ですが書いておきます。

構成例：
`クライアント` → `前段のALB(A)` → `リバースプロキシ(B)` → `後段のALB(C)` → `Web(D)`

①後段のALBで`X-Forwarded-For`ヘッダーを **`保持(preserve)`** に設定する。
  - `前段のALB(A)`では **`付加 (append)`** に設定する。 (デフォルトのまま)
  - `後段のALB(C)`では **`保持 (preserve)`** に設定することで、`前段のALB(A)`にアクセスしたIPアドレスが中継される。

②リバースプロキシやWebサーバーの`X-Forwarded-For` の設定
  - `X-Forwarded-For`ヘッダーをそのまま中継するよう設定する。(ALBの`保持`と同様の設定)
    - `X-Forwarded-For`の値が`リモートIPアドレス`になるように設定している場合、`ALBのIPアドレス`が値に設定されるため、クライアントIPアドレスが伝搬できなくなる。
    - ※具体的な設定については、Webサーバーソフトウェアによって異なるため省略

## まとめ
- ALB利用時の`X-Forwarded-For`の偽装対策として、カンマ区切りで複数の値があった場合、Webサーバー／リバースプロキシ／Webアプリで最後(右端)のIPアドレスのみ取得／中継するなどの対策をしよう。
- 対策するためには、ALBだけでなく、途中のWebサーバー／リバースプロキシ／Webアプリで `X-Forwarded-For` の扱いがどうなっているか理解しておくことが重要。