日本国外からのPOSTを拒否するNginx設定
自動でPOSTするスパムボットの対象になってしまったので対応したときの覚書。
WEBサーバーは海外からのアクセスのうちPOSTだけ拒否する方針でその方法を調査。
環境: CentOS Stream 9, Nginx 1.20.1
既に日本のIPアドレスの一覧はファイル化してある。
参考: nginxで国単位のIPアドレス制限
1. limit_except でHTTPメソッド制限
limit_exceptディレクティブ(directive=指示を与えるための要素)を使用すると、指定したHTTPメソッド以外のリクエストに対してアクセス制御ルールを適用できる。
参考: Module ngx_http_core_module
Nginxのconf設定に追記する。
location / {...# Deny POST methodlimit_except GET {# Include the list of Japanese IP addresses.# If the client's IP/CIDR matches an entry in this list, access is allowed.include conf.d/include/allow/JP.inc;deny all;}...}
Nginx再読み込み。
# nginx -t
# systemctl reload nginx
この手法のデメリットはIPアドレスの一覧をメンテナンスしないといけないこと。
その他AIに聞いて試したこと。
- mapモジュールは大量のIPリストを読み込むと時間が掛かる。
- geoモジュールはNginxをコンパイルしないといけないので諦めた(パッケージマネージャーの利便性を失いたくない)。
2. 国外からPOSTして動作確認
まず思いついたのはCloud Shellを使う方法。
参考: SSHクライアントとしてのCloud Shell
Cloud Shellを起動してIPアドレスを確認する。
# curl ipinfo.io
{"ip": "34.81.78.xxx","hostname": "127.78.81.xx.bc.googleusercontent.com","city": "Taipei","region": "Taiwan","country": "TW","loc": "25.0531,121.5264","org": "AS396982 Google LLC","timezone": "Asia/Taipei","readme": "https://ipinfo.io/missingauth"}
台湾のデータセンターなのでちょうどよかった。
WEBサーバー側はログファイルを監視しておく。
# tail -f /var/log/nginx/error.log
Cloud ShellでPOSTする。
# curl -X POST https://hoge.jp/
<html><head><title>403 Forbidden</title></head><body><center><h1>403 Forbidden</h1></center><hr><center>nginx/1.20.1</center></body></html>
# curl -X GET https://hoge.jp/
無事POSTだけ拒否できた。
2025/06/12追記
POSTすると404 Not foundエラー。
192.168.10.102 - - [12/Jun/2025:09:06:29 +0900] "POST /forum/ HTTP/1.1" 403 186 "http://dev.hoge.jp/forum/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" "-"
limit_exceptがあるとtry_filesが効かなくてエラーになる。
リダイレクト先のディレクティブで記述すれば404 Not foundにならない。
参考: nginx で location の中に limit_except と try_files を併記すると 404 Not Found になる件 #nginx - Qiita
# Pass all .php files onto a php-fpm/php-fcgi server.location ~ [^/]\.php(/|$) {try_files $uri =404;# Deny POST methodlimit_except GET {# Include the list of Japanese IP addresses.# If the client's IP/CIDR matches an entry in this list, access is allowed.include conf.d/include/allow/JP.inc;deny all;}}