0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【第4回】【侵入検知】CrowdSec + nftables bouncerによる自動脅威ブロックとAuditdによるシステム監査

0
Last updated at Posted at 2026-04-29

🔗 シリーズ構成

第2部 — セキュリティ Lv.1

  • 第4回(本記事): 【侵入検知】自動脅威ブロック(CrowdSec + nftables bouncer + Auditd)

📋 シリーズ全体の構成

📦 設定ファイル一式

はじめに

これまで、Raspberry Pi 5を活用して、IoTデバイス専用の隔離されたWi-Fiネットワークを構築してきました。
家庭内LANから完全に分離し、センサーやIoTモジュールがインターネットへのアウトバウンド通信のみを許可するセキュアな基盤が整いました。
しかし、ネットワークを分離しただけでは不十分です。

脅威モデルの定義 — なぜNAT背後でも防御が必要か

本構成のRaspberry PiはTP-Linkルーター(NAT)配下に配置されています。一見すると「インターネットから直接アクセスできない」ため安全に見えます。しかし、実際の脅威ベクターは以下の通りです:

脅威ベクター 経路 リスクレベル
Netbird VPN経由の攻撃 Internet → Netbird → Pi SSH 高 — 直接到達可能
侵害されたIoTデバイス IoT subnet → Pi 中 — 内部攻撃
LAN内の横移動 LAN → Pi
将来の計画的公開 NAT Port Forward → Mosquitto(第12回) 計画的露出

重要 : Netbird(第3回)はWireGuardトンネルを通じてインターネットから直接Piへのアクセスを可能にします。これはNATを透過します。つまり、本構成のPiはインターネットに対して実質的に露出しています。

実際の検知実績

本セットアップで実際に検知・ブロックされた攻撃:

ssh:bruteforce : 878 bans ← 主にNetbird経由
ssh:exploit : 98 bans
generic:scan : 395 bans
合計 : 1,371 bans

これは理論的なリスクではありません。実際に検知・ブロックされた攻撃です。

公開されたWi-FiアクセスポイントやSSHポートは、ブルートフォース攻撃や既知の脆弱性悪用に狙われやすいためです。
そこで本記事では、リアルタイムで攻撃を検知し、自動的にブロックする仕組みを導入します。
具体的には以下の3つのツールを組み合わせます:

  • CrowdSec:コミュニティ駆動の脅威インテリジェンスを活用した侵入検知エンジン
  • nftables bouncer:検知した悪意あるIPを即座にnftablesでブロックする自動対応
  • Auditd:/etc/shadowへのアクセス、sudo実行、重要なファイル変更などを詳細に監査・記録

この組み合わせにより、「検知 → 自動ブロック → 詳細なフォレンジック記録」 という一貫した多層防御を実現し、Raspberry Pi 5上でも軽快に動作する実践的な侵入検知・防御システムを構築します。
ステップバイステップでインストールから実際の動作確認(ブルートフォース攻撃シミュレーション含む)まで解説していきます。

アーキテクチャ上の決断

決断 却下した代替案 理由
CrowdSec Fail2ban コミュニティCTI(脅威インテリジェンス)を活用することで、未知の攻撃元を事前にブロック。Fail2banは自ホストのログのみに依存し、グローバルな攻撃パターンを把握できない
nftables bouncer iptables bouncer 第1回から構築したnftablesインフラと一貫性を保つ。カーネルレベルでのブロックにより、パケットはユーザー空間に到達しない
Auditd(syscallレベル) syslogのみ rootが侵害された場合でも、Auditdのログはカーネルが直接書き込むため改ざんが困難。syslogはユーザー空間で動作するため、rootによる削除が可能
-p rwa(shadowファイル) -p waのみ ハッシュダンプ攻撃シナリオではreadイベントが検知の鍵。書き込み監視のみでは、パスワードハッシュの読み取り試行を見逃す

インストール

1. CrowdSec

# 公式のCrowdsecのリポジトリを追加
curl -s https://install.crowdsec.net | sudo sh

# CrowdSecをインストール
sudo apt update && sudo apt install -y crowdsec

# 自動起動を設定する
sudo systemctl enable --now crowdsec

# 確認
sudo systemctl status crowdsec
cscli version

コレクション(パーサー、シナリオ)をインストールする :

# ハブのアップデート
sudo cscli hub update

# セットアップのため、必須コレクション
sudo cscli collections install crowdsecurity/linux
sudo cscli collections install crowdsecurity/sshd

# CrowdSecをリロード
sudo systemctl reload crowdsec

# インストールされたコレクションを確認する
sudo cscli collections list
sudo nano /etc/crowdsec/acquis.d/journald.yaml
/etc/crowdsec/acquis.d/journald.yaml
source: journalctl
journalctl_filter:
  - "_SYSTEMD_UNIT=ssh.service"
  - "_SYSTEMD_UNIT=hostapd.service"
  - "_SYSTEMD_UNIT=netbird.service"
labels:
  type: syslog
sudo systemctl reload crowdsec
sudo systemctl status crowdsec

ローカルIPをホワイトリストに登録する(自分自身をブロックしないように):

sudo nano /etc/crowdsec/parsers/s02-enrich/whitelists.yaml
/etc/crowdsec/parsers/s02-enrich/whitelists.yaml
name: crowdsecurity/whitelists
description: "Whitelist events from private ipv4 addresses"
whitelist:
  reason: "private ipv4/ipv6 ip/ranges"
  cidr:
    - "127.0.0.0/8"
    - "192.168.0.0/16"
    - "10.0.0.0/8"
    - "172.16.0.0/12"
    - "x.x.x.x/16"    # Netbird VPN
sudo systemctl reload crowdsec

2. nftables bouncer

# nftablesバウンサーをインストールする
sudo apt install -y crowdsec-firewall-bouncer-nftables

# 有効して、起動する
sudo systemctl enable --now crowdsec-firewall-bouncer

# 確認する
sudo systemctl status crowdsec-firewall-bouncer
sudo cscli bouncers list

3. Auditd

sudo apt install -y auditd audispd-plugins

sudo systemctl enable --now auditd
sudo systemctl status auditd

監査ルールの設定:

/etc/audit/rules.d/audit.rules
## First rule - delete all
-D

## Increase the buffers to survive stress events.
## Make this bigger for busy systems
-b 8192

## This determine how long to wait in burst of events
--backlog_wait_time 60000

## Set failure mode to syslog
-f 1
/etc/audit/rules.d/custom.rules
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p rwa -F auid!=4294967295 -k identity
-w /home/srvpi/.ssh/authorized_keys -p wa -k ssh-keys
-w /etc/ssh/sshd_config -p wa -k ssh-config
-a always,exit -F arch=b64 -S execve -F path=/usr/bin/sudo -k sudo-usage
-w /etc/nftables.conf -p wa -k firewall-rules
-w /etc/crowdsec/ -p rwa -k crowdsec-config

-w /etc/shadow -p rwa -k identity

通常、-p wa(書き込み・属性変更)のみを設定するガイドが多いが、本構成では**r(read)も含める**。

理由:攻撃者がrootを奪取した場合、/etc/shadow変更せずに読み取るだけでパスワードハッシュをダンプできる。johnhashcatによるオフラインクラックに必要なのはreadアクセスのみ。writeを監視してもこのシナリオは検知できない。

トレードオフ:-p rはイベント量が増加する(sudoやsystem processが定期的にshadowを参照するため)。本番環境では-F auid!=4294967295フィルタを追加してシステムプロセスを除外することを推奨する。

sudo nano /etc/audit/rules.d/pi5-iot.rules
/etc/audit/rules.d/pi5-iot.rules
# Monitoring network connections
-a always,exit -F arch=b64 -S connect -k network_connect

# Monitoring hostapd and dnsmasq
-w /etc/hostapd/hostapd.conf -p wa -k hostapd_config
-w /etc/dnsmasq.conf -p wa -k dnsmasq_config

# Monitoring Netbird
-w /etc/netbird/ -p rwa -k netbird_config

# Monitoring Unbound
-w /etc/unbound/ -p rwa -k unbound_config

# Monitoring LUKS/LVM mounts
-a always,exit -F arch=b64 -S mount -k mount_operations
# ルールをリロード
sudo augenrules --load

# リロードされたルールを確認する
sudo auditctl -l

徹底的な確認

CrowdSec

# 概要
sudo cscli metrics

image.png

-> 1.37k 件のIPアドレスを禁止

  • generic:scan 395 bans
  • ssh:bruteforce 878 bans
  • ssh:exploit 98 bans
# CrowdSecエージェントの確認
sudo cscli machines list
# → Status ✅、Last Heartbeat が数秒前であること

# バウンサーの確認(nftablesへの接続)
sudo cscli bouncers list
# → Valid ✅、Type crowdsec-firewall-bouncer であること

image.png

  • machines list → Crowdsecデーモンが実行されていて、LAPIと通信している ✅
  • bouncers list → nftables bouncer が接続され、判定を受け取っている ✅
# コレクション確認
sudo cscli collections list
# → linux・sshd・whitelist-good-actors が enabled であること

# アラート確認
sudo cscli alerts list
# → 攻撃検知時にアラートが表示される

# アクティブな決定(BANリスト)確認
sudo cscli decisions list
# → BANされたIPが表示される(CAPIからの自動BANを含む)

nftables bouncer

# バウンサーが稼働しているか確認する
sudo systemctl status crowdsec-firewall-bouncer

# 手動でテストする — テスト用IPのブロック
sudo cscli decisions add --ip 1.2.3.4 --duration 5m --reason "test"

# IPアドレスがnftablesに含まれていることを確認する
sudo nft list ruleset | grep 1.2.3.4

# テスト後に解除する
sudo cscli decisions delete --ip 1.2.3.4

image.png

1.2.3.4 は nftables に正しく登録されて、タイムアウトは 5 分です ✅
CAPIによってブロックされたその他のIPアドレスは以下の通りです(41.223.40.77など) ✅
bouncerはCrowdSecの決定をnftablesに直接適用している ✅

Auditd

# 有効なauditdルール
sudo auditctl -l
# テスト — 監視対象ファイルにアクセスする
sudo cat /etc/shadow

# アクセスが記録されていることを確認する
sudo ausearch -k identity -ts recent -m SYSCALL -c cat

image.png

image.png

  • key="identity"
  • exe="/usr/bin/cat"
  • name="/etc/shadow"
  • auid=...

exe="/usr/bin/cat" ➝ 絶対パス(ファイルを読み込むcatコマンド自体)
auid=<user> ➝ 元のユーザー(試行ユーザー)

# sudoをテスト
sudo ls /root

# 確認
sudo ausearch -k sudo-usage -ts recent --just-one

image.png

  • key="sudo-usage"
  • comm="sudo"
  • exe="/usr/bin/sudo"
  • auid=...
# sudoコマンドの追跡
sudo touch /etc/nftables.conf
sudo ausearch -k firewall-rules -ts recent --just-one

image.png

  • key="firewall-rules"
  • name="/etc/nftables.conf"
# 本日トレースされたすべてのSSH接続を表示する
sudo ausearch -m USER_LOGIN -ts today --just-one

image.png

  • type=USER_LOGIN
  • exe="/usr/sbin/sshd"
  • res=success

ゼロトラストの包括的テスト

スマホでのテストを行うため、CIDRを一時的にホワイトリストから除外する:

/etc/crowdsec/parsers/s02-enrich/whitelists.yaml
name: crowdsecurity/whitelists
description: "Whitelist events from private ipv4 addresses"
whitelist:
  reason: "private ipv4/ipv6 ip/ranges"
  cidr:
    - "127.0.0.0/8"
    - "192.168.0.0/16"
    - "10.0.0.0/8"
    - "172.16.0.0/12"
    - "x.x.x.x/16"
# CrowdSecに現在有効なセキュリティ上の決定(IPブロックなど)を表示する
sudo cscli decisions list

image.png

# スマホからSSHのブルートフォース攻撃をシミュレート
for i in {1..15}; do ssh wronguser@x.x.x.x; done

image.png

# もう一回有効なセキュリティ上の決定(IPブロックなど)を表示する
sudo cscli decisions list              # CrowdSecが検知した

image.png

sudo nft list set ip crowdsec crowdsec-blacklists-crowdsec  # nftablesにbouncerがブロックした

image.png

sudo ausearch -m USER_LOGIN -ts recent --just-one # auditdが記録した

image.png

  • type=USER_LOGIN ➝ ログインのイベント
  • res=failed ➝ ブルートフォース攻撃(シミュレーション)による失敗の結果
  • msg='op=login acct=... ➝ 存在しないユーザーのため拒否される
  • exe="/usr/sbin/sshd" ➝ 元 : SSHデーモン
  • addr=... ➝ 攻撃が外部またはローカルのIPから発生していることを確認・証明する
  • time-> ... ➝ 現在のテスト
# セキュリティの決定を解消する
sudo cscli decisions delete --ip <banned_ip>

制限事項と今後の改善

現在の制限

Auditdルールの永続性
augenrules --loadは現在のセッションにルールをロードするが、一部の環境では再起動後に適用されないケースがある。本番環境ではExecStartPost=/sbin/augenrules --loadをauditd.serviceに追加することを推奨する。

sudo mkdir -p /etc/systemd/system/auditd.service.d

sudo tee /etc/systemd/system/auditd.service.d/load-rules.conf << 'EOF'
[Service]
ExecStartPost=/sbin/augenrules --load
EOF

sudo systemctl daemon-reload

CrowdSecのCAPI依存
本構成はCrowdSecのCentral API(クラウド)に接続して脅威インテリジェンスを取得している。オフライン環境やエアギャップ環境では、CAPIなしのLocal-onlyモードへの切り替えが必要。その場合、コミュニティのIPレピュテーションは利用できない。

Auditdのイベント量
-S connect(全ネットワーク接続の監視)は高負荷環境では大量のイベントを生成する。現在はRaspberry Pi 5の低負荷環境のため許容範囲内だが、スケールアウト時にはフィルタリング戦略(-F uid!=0等)の見直しが必要。

終わりに

本記事では、CrowdSec + nftables bouncer + Auditd を組み合わせることで、
リアルタイム侵入検知 → 自動ブロック → 詳細なシステム監査 という多層防御を構築しました。

Raspberry Pi 5上で実際に動作を確認し、ブルートフォース攻撃に対しても検知・ブロック・ログ記録が正常に機能することを検証できました。

これで 第2部 — セキュリティ Lv.1 の主要な防御策は完了です。
IoTネットワークのセキュリティが大幅に強化されました。

次回(第5回)では、観測性(Observability) の基盤として InfluxDB 2 + Grafana を構築します。
今回構築したセキュリティ基盤(CrowdSec、Auditd)のメトリクスとログも、後の第8回・第9回でGrafanaダッシュボードに統合し、CLIなしで監視できる環境を目指します。

セキュリティと可観測性は別々のレイヤーではなく、同じプラットフォームの上で連携して初めて意味を持ちます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?