February 25, 2004

mod_rpaf でアドレス変換

[ Linux & UNIX ]
mod_rpaf は、RPAFproxy_ips に書かれているIPアドレスからアクセスがあったときのみ、リクエストヘッダ中の X-Forwarded-For: に書かれている内容を信用し、 Apache内部の r->connection->remote_ip のアドレスを書き換えるといった処理を実行してくれます。

Pound などのリバースプロキシを使った場合、ウェブサーバへアクセスをプロ棋士サーバが肩代わりするため、先のような構成だとたとえばアクセスログのリモートホストのアドレスがすべて 127.0.0.1 になってしまうといった問題があります。

このとき、X-Forwarded-For という環境変数に本来のリモートアドレスが記録されているので、これを使うことで問題を解決できます。それを実現するのが mod_rpaf。早速導入しました。

いい具合に動いてるなと思ったのですが、どうもときどきリモートアドレスが

<DL>\n     <DT><SAMP>example_post_read_request()</SAMP>\n

となぞの文字列が入ることがあります。

PC関係のメモによると、KeepAlive が On な環境でこの現象が発生するそうですが、そもそも KeepAlive を On に設定したいがために Pound を導入したというのもあるので、Off にすることは避けたいなあ。

mod_rpaf.c の 143 行目からの

if (fwdvalue = ap_table_get(r->headers_in, "X-Forwarded-For")) {
    array_header *arr = ap_make_array(r->pool, 0, sizeof(char*));
    while (*fwdvalue && (val = ap_get_token(r->pool, &fwdvalue, 1))) {
        *(char **)ap_push_array(arr) = ap_pstrdup(r->pool, val);
        if (*fwdvalue != '\0')
            ++fwdvalue;
    }
    r->connection->remote_ip = ap_pstrdup(r->pool, ((char **)arr->elts)[((arr->nelts)-1)]);
    r->connection->remote_addr.sin_addr.s_addr = inet_addr(r->connection->remote_ip);
    if (cfg->sethostname) {
        const char *hostvalue;
        if (hostvalue = ap_table_get(r->headers_in, "X-Forwarded-Host")) {
            /* 2.0 proxy frontend or 1.3 => 1.3.25 proxy frontend */
            ap_table_set(r->headers_in, "Host", ap_pstrdup(r->pool, hostvalue));
            r->hostname = ap_pstrdup(r->pool, hostvalue);
            ap_update_vhost_from_headers(r);
        } else if (hostvalue = ap_table_get(r->headers_in, "X-Host")) {
            /* 1.3 proxy frontend with mod_proxy_add_forward */
            ap_table_set(r->headers_in, "Host", ap_pstrdup(r->pool, hostvalue));
            r->hostname = ap_pstrdup(r->pool, hostvalue);
            ap_update_vhost_from_headers(r);
        }
    }
}

のコードが X-Forwarded-For を取得して云々という処理なんだと思うのですが、Apache API に詳しくないのでちょっとよくわからず。

そういえば mod_proxy でリバースプロキシした場合はアドレスは生IPが記録されていたような。mod_proxy は mod_rpaf と同じようなことを内部で実行しているのかな。

Posted by naoya at February 25, 2004 01:13 AM | トラックバック (0)  b_entry.gif
トラックバック [0件]
TrackBack URL: http://mt.bloghackers.net/mt/suck-tbspams.cgi/893
コメント [2件]

> プロ棋士サーバ
受けました (^^;

「なぞの文字列」ですが、TOMCAT な環境で同じ文字列を見たことがあるので、Apache 関係のどれかのモジュールに原因があるのだと思います。いつの間にか出なくなったので、それ以上原因を追求していませんが。

[1] Posted by: tsupo at February 25, 2004 02:00 AM [返信]

ふむ。どうもほかのサイトを見ていると Apache2 ではエラーも出ない様子。んー。

KeepAlive On/Off で振る舞いが変わるモジュール、あるいは API をあたって探りをつけるのが早いのかなあ。

[2] Posted by: naoya at February 26, 2004 12:26 AM [返信]