プロキシを経由したアクセスでは、Apacheのログで %h
にはプロキシサーバのIPアドレスが入る。
代理サーバの代理アクセスなので、常に同じIPアドレスが記録され、エンドユーザのIPアドレスが分からない。
そこで登場するのが、Apacheのアクセスログで言う %{X-Forwarded-For}i
です。
これにより、プロキシサーバ経由でアクセスしてくる元のアクセスIPが分かります。
それを元に、 .htaccess などに
- 修正前
RewriteCond %{REQUEST_URI} (^/admin)
RewriteCond %{HTTP:X-Forwarded-For} !^11\.33\.44\.22$
RewriteCond %{HTTP:X-Forwarded-For} !^11\.33\.44\.23$
RewriteCond %{HTTP:X-Forwarded-For} !^11\.33\.44\.24$
RewriteRule ^(.*)$ ? [F,L]
的な記述をすると、上記に記述したIPアドレス群以外からの /admin
配下へのアクセスに対して 403 Forbidden
を返すことができます。
問題発生
ところが、「11.55.66.21 も対象に追加しておいて」と言われて同様の記述を追加したところ、 11.55.66.21
からのアクセスに 403 Forbidden
が返ります。「???」 良く分かりません。
.htaccess に記述していたので、httpdの再起動等は不要なはずですが、とりあえず可能性の一つとして httpd の reload や restart を試してみました。状況は変わりません。
ssl.conf のアクセスログのフォーマットを、 common に %{X-Forwarded-For}i
を追加したものに変更します。
CustomLog /var/log/httpd/ssl_access_log \
"%h %l %u %t \"%r\" %>s %b \"%{X-Forwarded-For}i\"
すると、 ログの %{X-Forwarded-For}i
にあたる部分に想定と違った値が入っていました。
原因判明
n.n.n.n - - [12/Jan/2024:15:39:25 +0900]
"GET /x.png HTTP/1.1" 200 1049 "19.59.169.17, 11.55.66.21"
「11.55.66.21」でなく「19.59.169.17, 11.55.66.21」が入っていました。 (※ IP値は適当です)
「11.55.66.21」IPの持ち主でないので詳しくは分かりませんが、恐らく多段プロキシ的(多段串とか言われます)なもので、複数のIPが記述されているようです。
これで謎は解けた
上述のRewriteCondで指定していた !^11\.33\.44\.22$
は正規表現でIPアドレスの完全一致をしていたので正しく適用されなかったようです。
完全一致にしないという意図で「^」「$」
を外し、 !11\.33\.44\.22
としてしまうと、「111.33.44.22」「11.33.44.229」などが一致してしまうので、
!(^|[^0-9]11\.33\.44\.22($|[^0-9])
などにする必要がありますね。
- 修正後
RewriteCond %{REQUEST_URI} (^/admin)
RewriteCond %{HTTP:X-Forwarded-For} !(^|[^0-9])11\.33\.44\.22($|[^0-9])
RewriteCond %{HTTP:X-Forwarded-For} !(^|[^0-9])11\.33\.44\.23($|[^0-9])
RewriteCond %{HTTP:X-Forwarded-For} !(^|[^0-9])11\.33\.44\.24($|[^0-9])
RewriteCond %{HTTP:X-Forwarded-For} !(^|[^0-9])11\.55\.66\.24($|[^0-9])
RewriteRule ^(.*)$ ? [F,L]
既存のIPアドレスが多段串経由に変化することはなさそうですが、
最初から正規表現を使っているものについては、
ことさら遅くなることはないような気がするので、全部同じ形にしまって良いのかな、と考えています。