7億円当てるまで書き続けるブログ

石油王のみなさーん! お知恵拝借!

ロードバランサの配下にあるApache2.4系のアクセス制限

あけましておめでとうございます、今年も一年Apache2.4系でリクエストヘッダの値によってアクセス制御をしようとしたところ、いくつか嵌ったのでメモです。AWSでELB使いながらその下のApacheでアクセス制限したいみたいなときにあるヤツですね。

f:id:kiyooka:20180315004641j:plain
写真はこないだ牛久に行ってきたときに撮ってきた牛久大仏の表面です。特に意味は無いです。

ロードバランサ等の配下にApache2.4のサーバがあり、このサーバで端末のIPアドレスによって制限をかけたい場合、下記のように書くことができます。 ロードバランサはクライアントのIPアドレスを、リクエストヘッダに「X-Forwarded-For」として付加してリクエストを投げているものとします。 X-Forwarded-Forというリクエストヘッダの値が12.34.56.78や123.45.0.0/16のうちどれかにマッチしていればOKという設定です。

<Location />
    Require expr req('X-Forwarded-For') -ipmatch '12.34.56.78'
    Require expr req('X-Forwarded-For') -ipmatch '123.45.0.0/16'
</Location>

Apache2.2だとSetEnvIfでX-Forwarded-Forの値が正規表現にマッチしているかどうかをみて環境変数をセットして環境変数がセットされていれば許可、みたいにすることが多かったので、断然わかりやすくなっていますね。

ヘッダの値が正規表現にマッチしているかどうかを見て制限をかけることもできます。 X-Forwarded-Forというリクエストヘッダの値が/^123.45./や12.34.56.78のうちどれかにマッチしていればOKという設定です。

<Location />
   Require expr req('X-Forwarded-For') =~ /^123\.45\./
   Require expr req('X-Forwarded-For') =~ /^12\.34\.56\.78$/
</Location>

もちろんX-Forwarded-For以外のヘッダでも同様です。たとえばUser-Agentでオタクアピールしてくる特異なオタクだけにアクセスを許可したい場合、下記のようになります。 今時UAでもろもろ制御なんてすることもあんまないかと思いますが、ヘルスチェックだけ許可するとかの用途には、まあまあ覚えておくと便利そうです。

<Location />
   Require expr req('User-Agent') =~ /(i am|we are) otaku/i
</Location>

またこのRequire expr、各種変数/関数をもつことができ、たとえば特定の時間にしかアクセスを許可しないみたいな設定もできます。 記法は https://httpd.apache.org/docs/2.4/expr.html を見ればわかる。

<Location />
Require expr %{TIME_HOUR} -gt 9 && %{TIME_HOUR} -lt 17
</Location>

で、嵌った所なんですけども。 正規表現で制御する設定をしようとしていたところ、 https://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#requiredirectives に記載の通り""で囲んで記載したらパースできないと怒られてしまい、無駄に時間を使いました。 よくわかんないですが、たぶん僕の理解が足りていないのだと思います。悲しいですね。 あと、表題みたいな用途にはX-Forwarded-Forヘッダの値使うより、RemoteIPHeader指定してCONN_REMOTE_ADDRの値使うほうがよいんですかね? これもよくわかんない。