Skip to content

Instantly share code, notes, and snippets.

@DaikiSuganuma
Last active August 3, 2025 23:47
Show Gist options
  • Save DaikiSuganuma/feec839c3fade0053044aa39d2fe0261 to your computer and use it in GitHub Desktop.
Save DaikiSuganuma/feec839c3fade0053044aa39d2fe0261 to your computer and use it in GitHub Desktop.
日本国以外からのPOSTを拒否するNginx設定をGeoIPで自動化: https://blog.dksg.jp/2025/08/postnginxgeoip.html
#!/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