Hatena::ブログ(Diary)

うまい棒blog このページをアンテナに追加 RSSフィード Twitter

2009-06-22

リバースプロキシ環境下のapacheではmod_extract_forwardedよりもやっぱりmod_rpaf?

2011/12/04 追記

このエントリ内でmod_rpaf v0.6 では変換したIPアクセス制御 (allow, deny) が可能と書いてますが、間違っている可能性大ですすいません。 昔すぎて環境も設定もログも残ってないので何とも言えないのですが、勘違いしていただけかもしれません。

というのも、最近になってdebian 6.0 / apache 2.2.21 でこのエントリと同じことしようとしたら、ログのIP変換は出来てもアクセス制御はreverse proxyIPでしか出来なかった。ブコメで

masa_matya  httpd, reverse-proxy
mod_extract vs. mod_rpaf。自環境だとmod_rpafのv0.6でもアクセス制限が出来なかっ

ともらっているようにmod_rpaf では出来ないっぽいです。

嘘紛らわしいのはよくないので、しばらくしたらこのエントリは削除しようとおもいます 追記終わり


apacheの前段にproxyサーバ(Nginx,Squid,mod_proxyなど)を置いていると、apacheに届くRemote_AddrはリバースプロキシサーバIPアドレスになる。この状態だとapacheでは

  • ログ解析が出来ない
  • アクセス制限ができない

という問題が起きるので、これを回避するモジュールmod_rpafmod_extract_forwarded


両方ともRemote_AddrをX-Forwarded-Forヘッダ(設定で変更できる)で上書きしてくれる。で、mod_rpafの以前のversionでは、アクセスログは変更できるけど、アクセス制限は出来なかったらしい。

バックエンドapache 2.0 + mod_rpaf な環境.htaccess によるアクセス制限をかけようとしても、接続元の IP アドレスではなく、pound の IP アドレスで制限がかかってしまう、という現象に悩まされました。

じゃあ、mod_extract_forwardedを使えばいいかなと思ったけど、apache2.2ではそのまま動かないらしい。

Apache 2.2 での mod_proxy の scheme_handler のフック API がちょっと変更になっているので,Apache 2.2 ではおそらく動きません。

これはこれで面倒だなー。どっちにしよう、と悩んだ。


mod_rpaf

今回はNginxをリバースプロキシに使っていて、アクセス制限はNginxで可能。ログにオリジナルのRemote_Addrが残せれば良かったので、とりあえずmod_rpafを使ってダメ元で試したところ最新のmod_rpaf 0.6ではアクセス制限も可能になっていた。

mod_rpaf-0.6のCHANGESを見ると

Move the `change_remote_ip' handler from being APR_HOOK_MIDDLE to

APR_HOOK_FIRST to make the module run before modules like mod_geoip.

とあるので、hookする場所が変わってアクセス制限もできるようになったぽい。

mod_rpafの設定
RPAFenable      On
RPAFsethostname On
RPAFproxy_ips   127.0.0.1 10.0.0.1

RPAproxy_ipsで指定しているホスト以外からはX-Forwarded-Forヘッダを指定してもRemote_addrは変更できない。

ヘッダについて

X-Forwarded-Forではなくて他のヘッダを使う場合はRPAFheaderで指定。例えば、Nginxproxyのsamplet設定に

proxy_set_header        X-Real-IP       $remote_addr;

というように記述しているので、この通り設定する場合は

RPAFheader      X-Real-IP

とする。

追記

VirtualHostで設定している場合、そのVirtualHostディレクティブ内に書かないと有効にならない。globalのhttpd.confに書いてもダメだった。

追記2

RPAFproxy_ipsにはCIDRで書けない。

ver 0.5からの変更点

CHANGESに書いてる該当箇所。

  • mod_rpaf 0.5
197 static void register_hooks(apr_pool_t *p) {
198     ap_hook_post_read_request(change_remote_ip, NULL, NULL, APR_HOOK_MIDDLE);
199 }
  • mod_rpaf 0.6
240 static void register_hooks(apr_pool_t *p) {
241     ap_hook_post_read_request(change_remote_ip, NULL, NULL, APR_HOOK_FIRST);
242 }

mod_rpaf vs mod_extract_forwarded

似たようなモジュールなので、結局のところどちらを使えばいいかっていう。


アクセス制限について

上にも書いたようにmod_rpaf 0.6からはアクセス制限可能になったので、どちらでもいい。


更新頻度

sourceの日付を見ると

3月 9 2004 mod_extract_forwarded.c

1月 1 2008 mod_rpaf-2.0.c

なので、mod_rpafのほうが新しい。まぁ新しけりゃいいってもんでもないけど


apache 2.2の対応

mod_rpaf

実際にinstallしてみて問題なく動いた。上に書いたようにver. 0.6ではアクセス制限も問題ない。

mod_extract_forwarded

mod_rpaf のかわりに mod_extract_forwarded なるものがあるらしい - daily dayflower 上で引用してるように

Apache 2.2 での mod_proxy の scheme_handler のフック API がちょっと変更になっているので,Apache 2.2 ではおそらく動きません。

などなど、色々詳しく書かれている。patch適用などしないと動かないらしい。


負荷/オーバヘッド

調べてないのでわかりまへん。


まとめ

とりあえず上記の理由から、しばらくmod_rpafを使ってみようということで。


おまけ moduleを使わずに解決する方法

ログ

LogFormatの"%h"を"%{X-Forwarded-For}i"に変更する

アクセス制限

mod_rewriteのRewriteCondとかで%{HTTP:X-Forwarded-For}を判別してごにょごにょする。


おまけの追記

yshh おまけの部分、「ヘッダは偽装可能」ということを意識しないと危険

というブコメもらったけど、clientが直接backendサーバに接続できないなら、ヘッダを偽装されても問題ない。

client <----> nginx <----> apache

この場合、clientがnginxアクセスするときにX-Forwarded-For(X-Real-IP) を偽装してアクセスしても、nginxapacheに接続する際のX-Forwarded-For(X-Real-IP)はclientから送信されたrequest headerを使うのではなくてremote_addr を利用するから。(偽装された値をそのまま投げるようならreverse proxy serverとして使いものにならない)

当然clientがapacheに直接接続できる場合にヘッダを偽装した場合、"%{X-Forwarded-For}i" のように直接ヘッダを見ている部分は改ざんされることになる。が、直接接続できるような環境なら、そもそもreverse proxyやmod_rpafの話がいらなくて通常のapacheの設定で良いわけで。

masa_matyamasa_matya 2011/12/05 22:28 わざわざフォローくださりありがとうございます。
今回はアクセス制御は出来ませんでしたが、とても勉強になりました。
そして、いつも色々な記事をとても参考にさせていただいておりますm(_ _)m
これからも更新、楽しみにしております!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/hogem/20090622/1245675445