Last active
August 3, 2025 23:47
-
-
Save DaikiSuganuma/feec839c3fade0053044aa39d2fe0261 to your computer and use it in GitHub Desktop.
日本国以外からのPOSTを拒否するNginx設定をGeoIPで自動化: https://blog.dksg.jp/2025/08/postnginxgeoip.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # ================================================================= | |
| # MaxMind GeoLite2 DBから特定の国のIPリストを抽出し、 | |
| # nginxの allow ルールファイルを生成するスクリプト (Python 3.11 対応版) | |
| # | |
| # 依存関係: pkg install py311-maxminddb | |
| # ================================================================= | |
| # --- 設定 (ご利用の環境に合わせて変更してください) --- | |
| MAXMIND_LICENSE_KEY="YOUR_LICENSE_KEY_HERE" | |
| COUNTRY_CODE="JP" | |
| # 生成される .inc ファイルを保存するディレクトリ | |
| OUTPUT_DIR="/usr/local/etc/nginx/conf.d/include/allow" | |
| # 作業用ディレクトリ | |
| WORK_DIR="/tmp/geoip_update" | |
| # Pythonコマンド | |
| PYTHON_CMD="python3.11" | |
| # --- スクリプト本体 --- | |
| echo "=========================================" | |
| echo "Nginx allowルール更新処理を開始します: $(date)" | |
| echo "=========================================" | |
| # ライセンスキーのチェック | |
| if [ "$MAXMIND_LICENSE_KEY" = "YOUR_LICENSE_KEY_HERE" ] || [ -z "$MAXMIND_LICENSE_KEY" ]; then | |
| echo "エラー: MAXMIND_LICENSE_KEYが設定されていません。スクリプトを編集してください。" >&2 | |
| exit 1 | |
| fi | |
| # 必須コマンドのチェック | |
| for cmd in fetch tar find ${PYTHON_CMD} mkdir nginx; do | |
| if ! command -v $cmd >/dev/null 2>&1; then | |
| echo "エラー: 必要なコマンド '$cmd' が見つかりません。" >&2 | |
| exit 1 | |
| fi | |
| done | |
| # 出力ディレクトリが存在しない場合に作成 | |
| if [ ! -d "$OUTPUT_DIR" ]; then | |
| echo "-> 出力ディレクトリ '$OUTPUT_DIR' を作成します..." | |
| mkdir -p "$OUTPUT_DIR" | |
| if [ $? -ne 0 ]; then | |
| echo "エラー: 出力ディレクトリの作成に失敗しました。権限を確認してください。" >&2 | |
| exit 1 | |
| fi | |
| fi | |
| # 作業ディレクトリの準備 | |
| rm -rf "$WORK_DIR" | |
| mkdir -p "$WORK_DIR" | |
| # 1. データベースのダウンロード | |
| DOWNLOAD_URL="https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=${MAXMIND_LICENSE_KEY}&suffix=tar.gz" | |
| DOWNLOAD_FILE="${WORK_DIR}/GeoLite2-Country.tar.gz" | |
| echo "-> 手順1: MaxMindからデータベースをダウンロードしています..." | |
| fetch -q -o "$DOWNLOAD_FILE" "$DOWNLOAD_URL" | |
| if [ $? -ne 0 ] || [ ! -s "$DOWNLOAD_FILE" ]; then | |
| echo "エラー: データベースのダウンロードに失敗しました。" >&2 | |
| rm -rf "$WORK_DIR"; exit 1 | |
| fi | |
| echo "ダウンロード完了。" | |
| # 2. ファイルの展開 | |
| echo "-> 手順2: ダウンロードしたファイルを展開しています..." | |
| tar -xzf "$DOWNLOAD_FILE" -C "$WORK_DIR" | |
| MMDB_FILE=$(find "$WORK_DIR" -type f -name 'GeoLite2-Country.mmdb') | |
| if [ -z "$MMDB_FILE" ]; then | |
| echo "エラー: 'GeoLite2-Country.mmdb' が見つかりませんでした。" >&2 | |
| rm -rf "$WORK_DIR"; exit 1 | |
| fi | |
| echo "MMDBファイルを発見: $MMDB_FILE" | |
| # 3. nginx設定ファイルの生成 | |
| OUTPUT_FILENAME="${COUNTRY_CODE}.inc" | |
| TEMP_CONF_FILE="${WORK_DIR}/${OUTPUT_FILENAME}" | |
| echo "-> 手順3: Pythonを使用してallowリスト '${TEMP_CONF_FILE}' を生成しています..." | |
| # ヘッダーコメントの生成 (geoディレクティブはなし) | |
| cat << EOF > "$TEMP_CONF_FILE" | |
| # Generated by update_geoip_rules.sh on $(date) | |
| # Allow rules for country: ${COUNTRY_CODE} | |
| EOF | |
| # Pythonスクリプトの出力形式を 'allow ...;' に変更 | |
| ${PYTHON_CMD} -c ' | |
| import sys | |
| import maxminddb | |
| mmdb_file = sys.argv[1] | |
| target_code = sys.argv[2] | |
| try: | |
| with maxminddb.open_database(mmdb_file) as reader: | |
| for prefix, data in reader: | |
| if data and "country" in data and "iso_code" in data["country"]: | |
| if data["country"]["iso_code"] == target_code: | |
| print(f"allow {prefix.with_prefixlen};") | |
| except Exception as e: | |
| print(f"An error occurred: {e}", file=sys.stderr) | |
| sys.exit(1) | |
| ' "$MMDB_FILE" "$COUNTRY_CODE" >> "$TEMP_CONF_FILE" | |
| # 生成されたファイルが空でないかチェック | |
| if [ ! -s "$TEMP_CONF_FILE" ]; then | |
| echo "エラー: 生成された設定ファイルが空です。処理を中断します。" >&2 | |
| rm -rf "$WORK_DIR"; exit 1 | |
| fi | |
| echo "設定ファイルの生成が完了しました。" | |
| # 4. 新しい設定ファイルを配置 | |
| NGINX_CONF_FILE="${OUTPUT_DIR}/${OUTPUT_FILENAME}" | |
| echo "-> 手順4: 新しい設定ファイルを '${NGINX_CONF_FILE}' に配置します..." | |
| mv "$TEMP_CONF_FILE" "$NGINX_CONF_FILE" | |
| if [ $? -ne 0 ]; then | |
| echo "エラー: 設定ファイルの配置に失敗しました。権限を確認してください。" >&2 | |
| rm -rf "$WORK_DIR"; exit 1 | |
| fi | |
| # 5. nginxの設定をテスト | |
| echo "-> 手順5: nginxの設定をテストしています..." | |
| if ! nginx -t; then | |
| echo "★★★ 重大なエラー: nginxの設定テストに失敗しました。 ★★★" >&2 | |
| echo "nginxはリロードされませんでした。設定を確認してください。" >&2 | |
| rm -rf "$WORK_DIR"; exit 1 | |
| fi | |
| echo "設定テストに成功しました。" | |
| # 6. nginxをリロード | |
| echo "-> 手順6: nginxをリロードして設定を適用します..." | |
| service nginx reload | |
| if [ $? -ne 0 ]; then | |
| echo "エラー: nginxのリロードに失敗しました。" >&2 | |
| rm -rf "$WORK_DIR"; exit 1 | |
| fi | |
| echo "nginxのリロードが完了しました。" | |
| # 7. クリーンアップ | |
| echo "-> 手順7: 一時ファイルをクリーンアップしています..." | |
| rm -rf "$WORK_DIR" | |
| echo "" | |
| echo "✅ GeoIPルール更新処理が正常に完了しました。" | |
| echo "" | |
| echo "--- Nginxでの設定例 ---" | |
| echo "サイト全体、または特定のlocationで、生成されたファイルをインクルードします。" | |
| echo "" | |
| echo "例1: サイト全体を日本からのみ許可する場合 (serverブロック内)" | |
| echo "server {" | |
| echo " ..." | |
| echo " # 日本のIPリストを読み込み" | |
| echo " include ${NGINX_CONF_FILE};" | |
| echo " # 上記リストにマッチしないIPをすべて拒否" | |
| echo " deny all;" | |
| echo " ..." | |
| echo "}" | |
| echo "" | |
| echo "例2: 特定のディレクトリのみを日本から許可する場合 (locationブロック内)" | |
| echo "location /admin/ {" | |
| echo " include ${NGINX_CONF_FILE};" | |
| echo " deny all;" | |
| echo " # proxy_passやfastcgi_passなどの設定" | |
| echo " ..." | |
| echo "}" | |
| echo "" | |
| echo "設定変更後は 'sudo nginx -t && sudo service nginx reload' で設定を反映してください。" | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment