s_tajima:TechBlog

渋谷で働くインフラエンジニアのTechブログです。

mod_remoteipのリモートアドレスの扱いに関する不具合の修正について

httpd2.4では、X-Forwarded-Forを取り扱うためにmod_remoteipというモジュールがあります。
httpd2.2系でいうところのmod_rpaf, mod_extract_forwardedの代わりとなるモジュールです。
今回は、このmod_remoteipの不具合が修正された話です。

前置き

(mod_remoteip, X-Forwarded-Forについての説明です。知ってる方は読み飛ばしてください。)

これらのモジュールは、主にロードバランサ, リバースプロキシ配下のWebサーバで使われ、
リクエストのリモートアドレスを、X-Forwarded-Forというヘッダの値を元に書き換えてくれます。
(これをしないとWebサーバに残るリモートアドレスは、ロードバランサやリバースプロキシのものになってしまう。)

複数のロードバランサやリバースプロキシを経由してくることを考慮して、
X-Forwarded-Forヘッダには ,(カンマ)区切りで複数IPアドレスを記述できるようになっています。

X-Forwarded-Forヘッダに複数の値が入っている場合に、
Webサーバでリモートアドレスとして使われるのは基本的には一番右側の(最後に付与された)IPアドレスになります。
ただし、それだけでは多くのケースでロードバランサやリバースプロキシのIPアドレスが記録されてしまいます。

そのため、これらのモジュールの多くは、
リモートアドレスとして採用しないIPアドレス(のレンジ)を指定することができるようになっています。

例えば、mod_remoteipの設定として、以下の記述がされているケースで、

RemoteIPInternalProxy 192.0.2.0/24

以下のようなリクエストを受信したケースでは、

X-Forwarded-For: 198.51.100.1, 198.51.100.2, 192.0.2.1

198.51.100.2 がリモートアドレスとして記録されます。

この方法でリモートアドレスを取得すれば、
最後に経由したRemoteIPInternalProxyに記述されていないアドレス(≒ 自分たちの管理化にないアドレス)
をリモートアドレスとして記録することができるようになります。

不具合の内容

前置きが長くなりましたが、今回修正されたのはこのリモートアドレスの算出方法の不具合です。
この不具合が修正されるまで、mod_remoteipではRemoteIPInternalProxy, RemoteIPTrustedProxyの設定にかかわらず
一番 左側IPアドレスがリモートアドレスとして記録される状態になっていました。

不具合による影響

X-Forwarded-Forは単なるHTTPのヘッダなので、悪意のあるクライアントは簡単に偽装して付与することができます。

以下のようにX-Forwarded-Forを付与した状態でリクエストをかけます。

X-Forwarded-For: 192.0.2.2

すると、Webサーバには以下のようなX-Forwarded-Forヘッダが届きます。

X-Forwarded-For: 192.0.2.2, 198.51.100.1, 198.51.100.2, 192.0.2.1

今回の不具合では、一番 左側IPアドレスがリモートアドレスとなるので、
192.0.2.2 がリモートアドレスとなります。

結果として、ログに残るリモートアドレスを偽装したり、
リモートアドレスを元にアクセス制限をかけている環境等でアクセスの制限を回避したりすることが可能になります。

不具合の修正

この不具合、Red Hat Bugzillaに 2015/01/06 に報告されたあとしばらく修正されずにいたのですが、
2015/11/18 にようやくRedHatで修正がリリースされました。
https://bugzilla.redhat.com/show_bug.cgi?id=1179306

RedHatのAdvisoryはこちら。
https://rhn.redhat.com/errata/RHBA-2015-2194.html

そして、この修正がCentOSにも降りてくるのを待っていたのですが、
先日リリースされた CentOS Linux 7 (1511) でようやくこの修正が取り込まれました。
該当する環境をお使いの方は早いうちにアップデートをすることをおすすめします。

以上、今回はmod_remoteipの不具合についてでした。