目次
1. なぜ国別IPブロックが必要なのか
インターネットに公開されたサーバーには、日々膨大な不正アクセスが届きます。 SSH(リモート接続)へのパスワード総当たり攻撃、メールサーバーへの不正ログイン試行、 Webサイトへの脆弱性スキャンなどが代表的です。
これらの攻撃の多くは特定の国・地域から集中して行われます。 日本国内向けのサービスであれば、サービス提供に不要な国からのアクセスを一括でブロックすることで、攻撃の大部分を未然に防ぐことができます。
対策しない場合
- - SSHへの総当たり攻撃でサーバーに高負荷
- - メールサーバーへの不正ログイン試行
- - ログが攻撃で埋まり正常な監視が困難
- - 万が一侵入されると被害甚大
対策した場合
- - 不要な国からのアクセスをカーネルレベルで遮断
- - サーバー負荷の大幅軽減
- - ログが見やすくなり異常を発見しやすい
- - fail2ban と組み合わせて二重防御
2. 仕組みの全体像
国別ブロックと fail2ban は、それぞれ異なるレイヤーでサーバーを守ります。 両方を組み合わせることで、より強固な防御が実現します。
防御の2層構造
外部からのアクセス
│
▼
[第1層] ipset による国別ブロック
│ ブロック対象国 → 即座に DROP(サーバーに負荷をかけない)
│ 許可国 → 通過
▼
[第2層] fail2ban による動的ブロック
│ ログインに3回失敗 → そのIPを自動BAN
│ 繰り返し犯 → 長期BAN
▼
正常なアクセスのみサービスに到達
それぞれの役割
| ツール | 役割 | 特徴 |
|---|---|---|
| ipset | 国単位のIPブロック | 数万件のIPを高速処理。カーネルレベルで動作 |
| fail2ban | 不正アクセスの自動検出・BAN | ログを監視し、攻撃パターンを検出して自動対応 |
| IPintel API | 国別IPリストの提供 | GeoLite2ベースの最新IP範囲を各種形式で出力 |
3. IPintel 国別IP API の使い方
IPintelは、国ごとのIPアドレス範囲をさまざまな形式で提供するAPIを公開しています。 ブラウザで国を選んでダウンロードすることも、curl コマンドで取得してスクリプトに組み込むこともできます。
3.1 APIエンドポイント
| エンドポイント | 説明 |
|---|---|
GET /api/v1/country/list | 国一覧(IPレンジ数・更新日付つき) |
GET /api/v1/country/{code}/export | 1か国分をエクスポート |
GET /api/v1/country/bulk-export | 複数国を一括エクスポート |
3.2 エクスポート形式
format パラメータで出力形式を指定します。 お使いのファイアウォールに合った形式を選んでください。
| 形式 | 用途 | 対象環境 |
|---|---|---|
plain | 1行1CIDRのテキスト | 汎用(スクリプトで加工する場合) |
ipset | ipset restore 形式 | iptables + ipset 環境(本ガイド推奨) |
iptables | ipset作成 + iptablesルール例 | iptables 環境 |
firewalld | firewall-cmd スクリプト | RHEL/Rocky Linux/AlmaLinux(firewalld環境) |
nftables | nft 定義ファイル | 最新Linux(Debian 11+, Ubuntu 22.04+ 等) |
3.3 使用例(curl)
中国(CN)とロシア(RU)のIPをipset形式で取得する例:
# 複数国を一括取得(ipset形式)
curl -s "https://ipintel.daily-techlog.com/api/v1/country/bulk-export?countries=CN,RU&format=ipset"
# 出力例:
# create blocked_countries hash:net family inet hashsize 65536 maxelem 1000000 -exist
# flush blocked_countries
# add blocked_countries 1.0.1.0/24 -exist
# add blocked_countries 1.0.2.0/23 -exist
# ...firewalld形式で取得する例:
# firewalld形式で取得(RHEL/Rocky Linux向け)
curl -s "https://ipintel.daily-techlog.com/api/v1/country/bulk-export?countries=CN,RU&format=firewalld"
# nftables形式で取得(Debian/Ubuntu向け)
curl -s "https://ipintel.daily-techlog.com/api/v1/country/bulk-export?countries=CN,RU&format=nftables"3.4 パラメータ一覧
| パラメータ | 説明 | デフォルト |
|---|---|---|
countries | カンマ区切りの国コード(ISO 3166-1) | 必須 |
format | 出力形式(上記5種類) | plain |
set_name | ipset/nftablesのセット名 | blocked_countries |
download | trueでファイルとしてダウンロード | false |
4. ipset で国別ブロックを設定する
ipset は、Linuxカーネルレベルで大量のIPアドレスを効率的に管理するツールです。 iptablesで1件ずつルールを書くのと比べ、数万件のIPでも高速に判定できます。
ここでは最も一般的な iptables + ipset の組み合わせで解説します。 firewalld・nftables環境の方は、APIからそれぞれの形式で取得して適用してください。
4.1 ipset のインストール
# RHEL/Rocky Linux/AlmaLinux
sudo dnf install ipset ipset-service
# Debian/Ubuntu
sudo apt install ipset4.2 IPintel APIからリストを取得して適用
1コマンドで、IPリストの取得からipsetへの適用まで完了します。
# 中国・ロシアのIPレンジを取得してipsetに適用
curl -s "https://ipintel.daily-techlog.com/api/v1/country/bulk-export?countries=CN,RU&format=ipset" \
| sudo ipset restore -exist-exist オプションにより、 ipsetが既にある場合も上書きではなくマージされます。初回でも2回目以降でも同じコマンドで実行できます。4.3 iptables でブロックルールを追加
# ipset に含まれるIPからのアクセスを DROP
sudo iptables -I INPUT -m set --match-set blocked_countries src -j DROP
# 確認
sudo iptables -L INPUT -n --line-numbers | head -54.4 再起動後もルールを維持する
ipset の内容はサーバー再起動で消えるため、永続化が必要です。
# ipset の内容をファイルに保存
sudo ipset save > /etc/ipset.conf
# ipset-service を有効化(起動時に自動読み込み)
sudo systemctl enable ipset
# iptables ルールの永続化
sudo iptables-save > /etc/sysconfig/iptables # RHEL系
# sudo netfilter-persistent save # Debian/Ubuntu4.5 firewalld 環境の場合
Rocky Linux/AlmaLinux など firewalld を使用している環境では、APIから firewalld 形式で取得して実行します。
# firewalld形式のスクリプトを取得して実行
curl -s "https://ipintel.daily-techlog.com/api/v1/country/bulk-export?countries=CN,RU&format=firewalld" \
| sudo bash
# drop ゾーンに ipset を追加(初回のみ)
sudo firewall-cmd --permanent --zone=drop --add-source=ipset:blocked_countries
sudo firewall-cmd --reload4.6 nftables 環境の場合
最新の Debian/Ubuntu など nftables を使用している環境向けです。
# nftables形式で取得してファイルに保存
curl -s "https://ipintel.daily-techlog.com/api/v1/country/bulk-export?countries=CN,RU&format=nftables" \
> /tmp/blocked_countries.nft
# 適用
sudo nft -f /tmp/blocked_countries.nft
# ブロックルールを追加(初回のみ)
sudo nft add rule inet filter input ip saddr @blocked_countries drop5. fail2ban で不正アクセスを自動ブロック
fail2ban は、サーバーのログを監視して、パスワード総当たりなどの不正アクセスを検出すると、 攻撃元IPを自動的にブロック(BAN)するツールです。 国別ブロックをすり抜けた攻撃や、許可国からの攻撃に対する防御として機能します。
5.1 インストール
# RHEL/Rocky Linux/AlmaLinux
sudo dnf install epel-release
sudo dnf install fail2ban
# Debian/Ubuntu
sudo apt install fail2ban
# サービスを有効化して起動
sudo systemctl enable --now fail2ban5.2 基本的な考え方
fail2ban の設定は「jail(監獄)」という単位で管理します。 各 jail がサービス(SSH、メール等)ごとのログを監視し、不正を検出するとそのIPをBANします。
| 設定項目 | 意味 | 例 |
|---|---|---|
maxretry | 何回失敗でBANするか | 3(3回失敗でBAN) |
findtime | この時間内の失敗回数をカウント | 600(10分) |
bantime | BANする時間(秒) | 86400(24時間) |
ignoreip | BANしないIP | 127.0.0.1/8(自分自身) |
5.3 設定ファイルの作成
デフォルトの jail.conf は直接編集せず、jail.local に設定を書きます(アップデートで上書きされないため)。
sudo vi /etc/fail2ban/jail.local[DEFAULT]
# 自分のIPはBANしない(自分のグローバルIPに変更してください)
ignoreip = 127.0.0.1/8 ::1
# デフォルトのBAN設定
bantime = 3600 # 1時間
findtime = 600 # 10分以内に
maxretry = 5 # 5回失敗でBAN
# --------------------
# SSH ブルートフォース対策
# --------------------
[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 86400 # 24時間
# --------------------
# メールサーバー(Postfix + Dovecot)
# --------------------
[postfix]
enabled = true
port = smtp,465,submission
maxretry = 3
bantime = 3600
[postfix-sasl]
enabled = true
port = smtp,465,submission,imap,imaps
maxretry = 3
bantime = 86400
[dovecot]
enabled = true
port = imap,imaps,pop3,pop3s
maxretry = 3
bantime = 3600
# --------------------
# 繰り返し犯(recidive)
# --------------------
# fail2banに何度もBANされるIPを長期BAN
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 604800 # 1週間
findtime = 86400 # 24時間以内に
maxretry = 3 # 3回BANされたらignoreip に自分の接続元IPを必ず追加してください。 設定ミスで自分がBANされると、SSH接続できなくなります。5.4 設定を反映
# 設定ファイルの構文チェック
sudo fail2ban-client -t
# 再起動して反映
sudo systemctl restart fail2ban
# 状態確認
sudo fail2ban-client status6. 自動更新の設定
国別IPリストは定期的に更新されます。週1回程度の自動更新スクリプトを設定しておくと、 常に最新のリストでブロックできます。
6.1 更新スクリプト
sudo vi /usr/local/bin/update-country-blocklist.sh#!/bin/bash
# 国別IPブロックリスト自動更新スクリプト
set -euo pipefail
# === 設定 ===
API_URL="https://ipintel.daily-techlog.com/api/v1/country/bulk-export"
COUNTRIES="CN,RU,KP,IR" # ブロックする国(カンマ区切り)
FORMAT="ipset" # 出力形式
SET_NAME="blocked_countries" # ipset名
LOG="/var/log/country-blocklist.log"
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG"; }
log "--- 更新開始: countries=$COUNTRIES ---"
# IPintel API からブロックリストを取得
TMP=$(mktemp)
HTTP_CODE=$(curl -s -o "$TMP" -w "%{http_code}" \
"$API_URL?countries=$COUNTRIES&format=$FORMAT&set_name=$SET_NAME")
if [ "$HTTP_CODE" != "200" ]; then
log "ERROR: API HTTP $HTTP_CODE"
rm -f "$TMP"
exit 1
fi
# ipset に適用
ipset restore -exist < "$TMP"
rm -f "$TMP"
# iptables ルールがなければ追加
if ! iptables -C INPUT -m set --match-set "$SET_NAME" src -j DROP 2>/dev/null; then
iptables -I INPUT -m set --match-set "$SET_NAME" src -j DROP
log "iptables ルール追加"
fi
# 永続化
ipset save > /etc/ipset.conf
COUNT=$(ipset list "$SET_NAME" 2>/dev/null | grep -c "^[0-9]" || echo "0")
log "完了: $COUNT エントリ"# 実行権限を付与してテスト実行
sudo chmod +x /usr/local/bin/update-country-blocklist.sh
sudo /usr/local/bin/update-country-blocklist.sh
# ログを確認
cat /var/log/country-blocklist.logCOUNTRIES を変更するだけで、ブロック対象国を自由にカスタマイズできます。 国コードは 国別IPブロックリストページ で確認できます。6.2 cron で定期実行
# root の crontab を編集
sudo crontab -e
# 毎週日曜 5:00 に更新
0 5 * * 0 /usr/local/bin/update-country-blocklist.sh6.3 systemd timer で定期実行する場合
cron の代わりに systemd timer を使うこともできます(ログ管理やエラー通知が便利です)。
# サービスファイル
sudo tee /etc/systemd/system/country-blocklist.service > /dev/null << 'EOF'
[Unit]
Description=Update country IP blocklist from IPintel
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/update-country-blocklist.sh
EOF
# タイマーファイル
sudo tee /etc/systemd/system/country-blocklist.timer > /dev/null << 'EOF'
[Unit]
Description=Weekly country blocklist update
[Timer]
OnCalendar=Sun 05:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
# 有効化
sudo systemctl daemon-reload
sudo systemctl enable --now country-blocklist.timer
# 状態確認
systemctl list-timers | grep country7. 動作確認・トラブルシューティング
7.1 ipset の確認
# ipset 一覧
sudo ipset list -name
# エントリ数の確認
sudo ipset list blocked_countries | grep "Number of entries"
# 特定IPがブロック対象か確認
sudo ipset test blocked_countries 1.2.3.4
# → "1.2.3.4 is in set blocked_countries." ならブロック対象7.2 fail2ban の確認
# 全jail の状態
sudo fail2ban-client status
# 特定jail の詳細(BANされたIP一覧)
sudo fail2ban-client status sshd
# リアルタイムでログを監視
sudo tail -f /var/log/fail2ban.log7.3 よくある問題と対処法
Q: 自分がBANされてSSH接続できなくなった
→ VPS管理画面のコンソールからログインし、sudo fail2ban-client set sshd unbanip 自分のIP で解除してください。 今後のために ignoreip に自分のIPを追加しておきましょう。
Q: fail2ban が起動しない
→ sudo fail2ban-client -t で設定の構文エラーを確認してください。 また journalctl -u fail2ban -e でエラーログが見られます。
Q: ipset がサーバー再起動後に消える
→ sudo ipset save > /etc/ipset.conf で保存し、sudo systemctl enable ipset でサービスを有効化してください。 RHEL系では ipset-service パッケージが必要です。
Q: 特定のIPだけブロックを解除したい
→ sudo ipset del blocked_countries 1.2.3.4/32 でipsetから削除できます。 fail2banのBANは sudo fail2ban-client set sshd unbanip 1.2.3.4 で解除できます。
Q: ブロックが効いているか確認したい
→ sudo iptables -L INPUT -v -n | head -10 で DROP ルールの「pkts」「bytes」が増えていれば、ブロックが機能しています。