1. はじめに
- VPS業者から突然の連絡
- 「外部の特定IPアドレスへ攻撃的なトラフィックを検知しました」
- Webサーバー用途なのに なぜか海外IP宛通信で停止
- ログを調べても「何が海外に出ているのか分からない」
- iptables 直書きは避けたい
- firewalld + ipset で 「海外だけ可視化」したかった
2. 環境
OS: AlmaLinux 10
Firewall: firewalld
IP管理: ipset
用途: Webサーバー(SMTPなし)
3. firewalld の落とし穴
❌ よくやりがちな発想
rule destination NOT ipset:JP log
👉 firewalld では書けない
- NOT ipset はサポートされていない
- rich-rule は集合演算が弱い
4. firewalld の思想:ゾーン先決めモデル
firewalld はこう動く
- 通信が発生
- どのゾーンかを先に決定
- ゾーン内ルールを評価
ここが iptables 思考との違い。
5. 解決策:ゾーン分割で「NOT」を表現する
発想の転換
NOT ipset を書かない
「日本だけ明示」して、残りをデフォルトにする
6. 実装手順(ログだけ出す段階)
6.1 日本IPセット(JP)
firewall-cmd --get-ipsets
JP
6.2 海外通信ログ専用ゾーン
firewall-cmd --permanent --new-zone=log-outbound
firewall-cmd --set-default-zone=log-outbound
6.3 海外通信をログに出す
firewall-cmd --permanent --zone=log-outbound \
--add-rich-rule='rule family="ipv4" log prefix="OUTBOUND_FOREIGN " level="info"'
6.4 日本IPは別ゾーンで許可
firewall-cmd --permanent --new-zone=jp
firewall-cmd --permanent --zone=jp --add-source=ipset:JP
firewall-cmd --permanent --zone=jp --add-service=ssh
firewall-cmd --permanent --zone=jp --add-service=http
firewall-cmd --permanent --zone=jp --add-service=https
6.5 反映
firewall-cmd --reload
7. なぜこれで海外通信だけがログに出るのか(仕組み)
ゾーン判定フロー図(文章 or 図)
通信発生
↓
ipset:JP に一致?
├ YES → jp(ログなし)
└ NO → default = log-outbound(LOG)
👉 NOT ipset を ゾーン設計で表現している
8. 実際のログ例
OUTBOUND_FOREIGN SRC=133.xxx.xxx.xxx DST=207.xxx.xxx.xxx PROTO=TCP ...
- 宛先IP
- ポート
- プロセス特定への足がかり
9. 学んだこと・教訓
- firewalld は iptables の上位抽象
- 「書けない」より「どう設計するか」
- デフォルトゾーンは 最強の NOT
- 可視化 → 遮断 の順が安全
- まとめ
- firewalld で海外通信は制御できる
- NOT ipset がなくても問題ない
- ゾーン分割は実運用向き
- VPS業者トラブルの再発防止に有効