Apacheのconfにコメントを書く際に、設定の後ろに書く事はできないのは知られているのかどうかよくわかりませんが、その通りです。例えば

MaxRequestsPerChild 200 #少なめに

これは syntax error になります

% ./local/httpd/bin/apachectl -t
Syntax error on line 12 of /Users/.../local/httpd/conf/httpd.conf:
MaxRequestsPerChild takes one argument, Maximum number of requests a particular child serves before dying.

よくやりがちなんですが、ドキュメントにも

Directives in the configuration files are case-insensitive, but arguments to directives are often case sensitive. Lines that begin with the hash character “#” are considered comments, and are ignored. Comments may not be included on a line after a configuration directive.

書いてありました。

ところで、最近とあるサービスの動いているApacheのhttpd.confで

Order Deny,Allow
Deny from All
Allow from 127.0.0.1
..
Allow from x.y.z.252 #nat
Allow from x.y.z.253 #office1
Allow from x.y.z.254 #office2

という設定がされているのを見ました。設定行にコメントがあるけど、どうやらシンタックスエラーにはなって居ない。では問題ないじゃん、で終わるかというとそうではありません。

実はこれだけで HostnameLookups の設定関係なしに逆引きが行われてしまい、知らないうちにサーバの負荷になってしまうのです。実際にコメント部分を消したところロードアベレージが半分ぐらいに下がりました。

なぜ、シンタックスエラーにもならず、逆引きが行われるのかというと、「Allow」というディレクティブが複数の値を受け入れて、コメントをホスト名として扱ってしまうためです。ソースコードでみると、まずmodauthzhost.c の 174行目

AP_INIT_ITERATE2("allow", allow_cmd, &its_an_allow, OR_LIMIT,
                "'from' followed by hostnames or IP-address wildcards"),
AP_INIT_ITERATE2("deny", allow_cmd, NULL, OR_LIMIT,
                "'from' followed by hostnames or IP-address wildcards"),

ここで「Allow」と「Deny」のディレクティブを定義しています。APINITITERATE2 というディレクティブ処理関数登録マクロは引数を無限に受け取り、それらを1つずつ処理するディレクティブを登録します。

APINITXXXのマクロについてはklabさんの記事が詳しい
DSAS開発者の部屋:[補足記事]ディレクティブ処理関数登録マクロ一覧 (apache module 開発事初め その3-2)

そして、設定を行う「allow_cmd」では

static const char *allow_cmd(cmd_parms *cmd, void *dv, const char *from,
                         const char *where_c)
{
    char *where = apr_pstrdup(cmd->pool, where_c);
    .. 省略 ..
    else if (!strcasecmp(where, "all")) {
        a->type = T_ALL;
    }
    else if ((s = ap_strchr(where, '/'))) {
        *s++ = '\0';
        a->type = T_IP;
    }
    else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->x.ip, where,
                                                        NULL, cmd->pool))) {
        if (rv != APR_SUCCESS) {
            apr_strerror(rv, msgbuf, sizeof msgbuf);
            return apr_pstrdup(cmd->pool, msgbuf);
        }
        a->type = T_IP;
    }
    else { /* no slash, didn't look like an IP address => must be a host */
        a->type = T_HOST;
    }
    return NULL;
}

where に httpd.confで指定した文字列がきます。「#nat」や「#office」はIPアドレスではありませんし、スラッシュも含まないのでホスト名として扱われます。

Host名として扱われると、ここ

Hosts whose names match, or end in, this string are allowed access. Only complete components are matched, so the above example will match foo.apache.org but it will not match fooapache.org. This configuration will cause Apache to perform a double reverse DNS lookup on the client IP address, regardless of the setting of the HostnameLookups directive. It will do a reverse DNS lookup on the IP address to find the associated hostname, and then do a forward lookup on the hostname to assure that it matches the original IP address. Only if the forward and reverse DNS are consistent and the hostname matches will access be allowed.

書いてある通り、HostnameLookupsの設定に関係なく、逆引きを行ってアクセス可否を決めます。なので、「Allow」や「Deny」にはコメントを書くのは危険が危ないです。書かないようにしましょう。



だ が し か し



書きたいですよね。「Allow」行にコメント。なのでパッチ書いてみました。

--- httpd-2.2.22.orig/modules/aaa/mod_authz_host.c  2008-06-14 20:44:19.000000000 +0900
+++ httpd-2.2.22/modules/aaa/mod_authz_host.c   2012-04-04 16:01:10.000000000 +0900
@@ -117,9 +117,17 @@
     char msgbuf[120];
     apr_status_t rv;

+    if (cmd->info && !strncasecmp(cmd->info, "#",1))
+        return NULL;
+
     if (strcasecmp(from, "from"))
         return "allow and deny must be followed by 'from'";

+    if(!strncasecmp(where, "#", 1)) {
+        cmd->info = where;
+        return NULL;
+    }
+
     a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys);
     a->x.from = where;
     a->limited = cmd->limited;

かなり無理矢理ですが、このpatchをあてると、「Allow」と「Deny」の設定に限り「#」以降の文字を無視できます。

Order deny,allow
Deny from all
Allow from 192.168.67.1 #foobar hogehoge
Allow from 127.0.0.1

「#foobar」だけではなく、ちゃんと「hogehoge」もコメントとして扱います。

アクセス制御を細かくやる必要がある場合、コメントを後ろに追加するとわりとわかりやすい設定が書けると思うので、このpatchでhttpd.conf が捗る事間違いなし!…かな

【追記】
社内やIRCでちょっと話をして、コメントがあったらシンタックスエラーにしたほうがいいのではないかとの意見を頂きました。
patchがあたっているApacheとそうでないApache両方があった場合、設定コピペしてはまることがありそうなので、よくないと。
確かにそうなので、上のpatchを試してみようと思う方は、そのあたりを注意して頂けると幸いです。return NULLの代わりにエラーメッセージを返すとシンタックスエラー扱いになるはずです
【/追記】

同じ事を書いている方いた
M.C.P.C.: ApacheでHostnameLookups offでもログにホスト名が記録される場合

このブログ記事について

このページは、Masahiro Naganoが2012年4月 4日 16:18に書いたブログ記事です。

ひとつ前のブログ記事は「Replication Booster for MySQL を試す」です。

次のブログ記事は「「サーバ/インフラエンジニア養成読本 管理/監視編」に寄稿しました」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja