ちゃんと公式ドキュメントを読めっていう話なのですが HAProxy にて X-Forwarded-For をセットするという options forwardfor
設定は通常期待される動作とは違います。ググって見つけた答えはちゃんと検証しましょう。
X-Forwarded-For: xxx.xxx.xxx.xxx
がすでにリクエストに入っていた場合、次のように HAProxy の動作するサーバーの IP アドレスがカンマ区切りで追加されることを期待しますが
X-Forwarded-For: xxx.xxx.xxx.xxx, yyy.yyy.yyy.yyy
実際には次のようにヘッダーの最後に新たに X-Forwarded-For ヘッダーが追加されます。
X-Forwarded-For: xxx.xxx.xxx.xxx
その他の Header
X-Forwarded-For: yyy.yyy.yyy.yyy
これを受け取ったサーバーがどのように扱うかは実装依存っぽいですね。 Rails 5.0.2 で確認すると
HTTP_X_FORWARDED_FOR:xxx.xxx.xxx.xxx, yyy.yyy.yyy.yyy
となりました。Flask 0.12.1 では最後の X-Forwarded-For だけになりました。HAProxy のドキュメントには同名ヘッダーを受け取ったサーバーは最後値を使うべきだと書いてあるから Flask の方が正しいのかな。 他のサーバーでどのように処理されるかどうかは不明。後で調べて追記予定。
option forwardfor [ except ] [ header ] [ if-none ]
という構文なので except
で X-Forwarded-For を追加しない条件を指定したり、header
でヘッダー名を X-Forwarded-For ではないものにしたり、if-none
で X-Forwarded-For が存在しない場合にのみ追加するといった指定が可能です。