firewalldで国別アクセス制限

2021/06/01 追記

https://ipv4.fetus.jp/ さんの作成されたツールは広域ルートからの判定なので稀に正しく国を判定できないことがあるようです。
inetnumベースでリスト化されているサービスがあればいいのですが・・・

IPSETを使用して定義する
国別IPの定義は、
https://ipv4.fetus.jp/[国名].txt
から取得する。
下記コマンドでIPSETを登録する

# firewall-cmd --permanent --new-ipset=[国名] --type=hash:net
# firewall-cmd --permanent --ipset=[国名] --add-entries-from-file=[国名].txt
# firewall-cmd --reload

登録した国だけ許可したい場合、IPSETをexternalゾーンに登録し対象プロトコルをpublicゾーンから外す
(ゾーンはexternal限定ではないので違うところ使う時は読みかえて)

# firewall-cmd --permanent --zone=external --add-source=ipset:[国名]
# firewall-cmd --permanent --zone=public --remove-service=[プロトコル名]
# firewall-cmd --permanent --zone=external --add-service=[プロトコル名]
# firewall-cmd --reload

登録した国だけ拒否したい場合、IPSETをdropゾーンに登録する

# firewall-cmd --permanent --zone=drop --add-source=ipset:[国名]
# firewall-cmd --reload

IPSETのリストを最新に更新する

# wget https://ipv4.fetus.jp/[国名].txt
# firewall-cmd --permanent --delete-ipset=[国名]
# firewall-cmd --permanent --new-ipset=[国名] --type=hash:net
# firewall-cmd --permanent --ipset=[国名] --add-entries-from-file=[国名].txt
# firewall-cmd --reload

IPSETのリスト更新を自動化するには、更新スクリプトを用意する

/usr/local/bin/reallocate_ipset

#!/bin/bash
# コマンドの異常終了と未定義変数を参照した場合、中断する設定
set -eu
  
# 引数が一つもなかったらエラー
[ $# -lt 1 ]&& exit 1
  
# 現在設定されてるセットのリストを取得する
IPSETS=(`firewall-cmd --get-ipsets`)
  
for COUNTRY in "$@"; do
  # https://ipv4.fetus.jpから国別のIPリストを取ってくる
  wget https://ipv4.fetus.jp/${COUNTRY}.txt -P /tmp -q
  for EXIST_COUNTRY in "${IPSETS[@]}"; do
    [ "$COUNTRY" != "$EXIST_COUNTRY" ]&& continue
    # 登録済みなら一旦削除する
    firewall-cmd --quiet --permanent --delete-ipset=$COUNTRY
  done
  # 国別IPSETを登録する
  firewall-cmd --quiet --permanent --new-ipset=$COUNTRY --type=hash:net
  firewall-cmd --quiet --permanent --ipset=$COUNTRY --add-entries-from-file=/tmp/$COUNTRY.txt
  # 使用したファイルを削除
  rm -f /tmp/${COUNTRY}.txt
done
exit $?

systemdで自動実行する場合、サービスとタイマーを作る

/etc/systemd/system/reallocate-ipset.service

[Unit]
Description=Reallocate ip sets for countrys
 
[Service]
Type=oneshot
ExecStart=/usr/local/bin/reallocate_ipset [国名(複数可)]
ExecStartPost=/bin/firewall-cmd --quiet --reload

/etc/systemd/system/reallocate-ipset.timer

[Unit]
Description=Reallocate country’s ip sets every week
 
[Timer]
OnCalendar=weekly
Persistent=true
 
[Install]
WantedBy=timers.target

タイマー起動と自動実行設定を忘れずに

# systemctl daemon-reload
# systemctl start reallocate-ipset.timer
# systemctl enable reallocate-ipset.timer