koide e1686d7acb
All checks were successful
Deploy Docusaurus Site / deploy (push) Successful in 37s
Add: 自宅ネットワークにIDSを導入した話
2026-02-28 07:49:37 +00:00

306 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
sidebar_position: 2
title: 自宅ネットワークにIDSを導入した話 — Proxmox LXC で Suricata + ntopng
description: Proxmox VE の LXC コンテナで Suricata と ntopng を使った自宅ネットワーク監視環境を構築した記録。TEEミラーリング、カスタムルール、Zabbix連携まで。
hide_table_of_contents: false
displayed_sidebar: null
image: ./banner.png
---
# 自宅ネットワークにIDSを導入した話
## きっかけ
自宅サーバーを運用してると、外向きのサービスも増えてくるし、IoTデバイスも増える。リバースプロキシの裏で何が起きてるか、正直あんまり把握できてなかった。
最近 OpenClawAIアシスタント基盤を自宅で動かし始めて、外部APIとの通信も増えてきた。「そろそろネットワークの中身ちゃんと見ないとまずいかも」と思って、とりあえずやってみることにした。
## 構成
うちの環境は Proxmox VE でクラスタを組んでて、サービスは基本 LXC コンテナで動かしてる。専用のミラーリングスイッチとかは持ってないから、Proxmox の機能でなんとかする方針。
### 最終的な構成図
```
インターネット
├─ Nginx Proxy Manager (LXC, 192.168.1.189)
│ │
│ ├─ 各種サービス (Gitea, Docusaurus, etc.)
│ │
│ └─ [TEE mirror] ──→ Suricata + ntopng (LXC, 192.168.1.187)
│ │
│ ├─ eth0: サービスネットワーク (192.168.1.0/24)
│ └─ eth10: データプレーン (192.168.10.0/24)
├─ Proxmox VE ノード x4
│ └─ [TEE mirror] ──→ (同上)
└─ Zabbix (LXC, 192.168.1.172)
└─ Suricata アラート監視
```
### 使ったもの
| コンポーネント | 役割 |
|---|---|
| **Suricata 6.0.4** | IDS侵入検知 |
| **ntopng Community** | トラフィック可視化・フロー分析 |
| **Zabbix 7.4** | アラート集約・通知 |
| **Proxmox TEE** | パケットミラーリング |
## LXC コンテナの作成
Proxmox の Web UI から Ubuntu 22.04 の LXC を作成。ポイントはいくつかある。
### スペック
- CPU: 2コア
- メモリ: 4GBSuricata のルール読み込みで結構食う)
- ディスク: 20GB
- NIC: 2つサービス用 + データプレーン用)
### 特権コンテナにすること(重要)
最初は非特権コンテナで作ったんだけど、**Suricata の af-packetパケットキャプチャが動かない**。ルールの読み込みまでは成功するのに、キャプチャスレッドが起動しない。
ログにはこう出る:
```
48714 rules successfully loaded, 0 rules failed
48719 signatures processed.
```
でも `All AFP capture threads are running.` が出ない。eve.json も更新されない。
原因は af-packet のプロミスキャスモードに必要な権限が非特権コンテナだと制限されるから。
```bash
# /etc/pve/lxc/<CTID>.conf
# unprivileged: 1 ← これを削除
```
特権コンテナにしたら一発で動いた。
### NIC 設定
```
net0: name=eth0,bridge=vmbr0,ip=dhcp,type=veth
net1: name=eth10,bridge=vmbr1,ip=192.168.10.187/24,type=veth
```
- `eth0`: 管理・サービス用192.168.1.0/24
- `eth10`: TEE ミラートラフィック受信用192.168.10.0/24
**ゲートウェイの設定を忘れずに。** DHCPじゃない場合、`gw=192.168.1.1` を net0 に追加しないと外部に出られない(パッケージインストールで詰む)。
## Suricata のインストールと設定
```bash
sudo apt update
sudo apt install -y suricata suricata-update
sudo suricata-update
```
### suricata.yaml の設定ポイント
#### HOME_NET
```yaml
HOME_NET: "[192.168.1.0/24]"
```
#### HTTP_PORTS を拡張する
デフォルトだと `HTTP_PORTS: "80"` だけ。自宅サーバーは 8006Proxmox、3000ntopng/Grafana、8080Zabbixとか色んなポートで HTTP 使ってるから、これを広げないと HTTP の中身をパースしてくれない。
```yaml
HTTP_PORTS: "[80,443,3000,3128,8006,8007,8080,8443,9876]"
```
これに気づくまでかなりハマった。カスタムルールが全然発火しなくて、ログを見たら HTTP イベント自体が記録されてなかった。
#### ルールファイル
```yaml
rule-files:
- suricata.rules
- local.rules
```
`suricata-update` で取得したルールは `/var/lib/suricata/rules/suricata.rules` に保存される。`/etc/suricata/rules/` にシンボリックリンクを作っておくと楽。
```bash
sudo ln -s /var/lib/suricata/rules/suricata.rules /etc/suricata/rules/suricata.rules
```
## カスタムルールの作成
ET Open のルールセットだけだと、よくある Web 探索行為(`.env` を探すボットとか)は検知できない。自分で書く。
```bash title="/etc/suricata/rules/local.rules"
# === 探索行為の検知 ===
alert http any any -> $HOME_NET any (msg:"Scan: wp-admin access"; content:"/wp-admin"; http_uri; sid:2000001; rev:1;)
alert http any any -> $HOME_NET any (msg:"Scan: .env access"; content:"/.env"; http_uri; sid:2000002; rev:1;)
alert http any any -> $HOME_NET any (msg:"Scan: phpmyadmin access"; content:"/phpmyadmin"; nocase; http_uri; sid:2000003; rev:1;)
alert http any any -> $HOME_NET any (msg:"Scan: xmlrpc access"; content:"/xmlrpc.php"; http_uri; sid:2000004; rev:1;)
alert http any any -> $HOME_NET any (msg:"Scan: .git directory access"; content:"/.git/"; http_uri; sid:2000005; rev:1;)
alert http any any -> $HOME_NET any (msg:"Scan: admin panel probe"; content:"/admin"; http_uri; sid:2000009; rev:1;)
# === SQLインジェクション試行 ===
alert http any any -> $HOME_NET any (msg:"SQLi: UNION SELECT attempt"; content:"UNION"; nocase; http_uri; content:"SELECT"; nocase; http_uri; sid:2000011; rev:1;)
# === ディレクトリトラバーサル ===
alert http any any -> $HOME_NET any (msg:"Traversal: ../ attempt"; content:"../"; http_uri; sid:2000013; rev:1;)
# === ブルートフォース ===
alert http any any -> $HOME_NET any (msg:"Brute: login page flood"; content:"/login"; http_uri; threshold:type both, track by_src, count 20, seconds 60; sid:2000014; rev:1;)
```
テストは curl で簡単にできる:
```bash
curl -s http://192.168.1.187:3000/.env
# → eve.json に "Scan: .env access" のアラートが記録される
```
## TEE によるパケットミラーリング
専用のミラーリングスイッチがなくても、Proxmox ホスト上で iptables の TEE ターゲットを使えばパケットをコピーできる。
```bash title="各 Proxmox ホスト上で実行"
# サービスネットワーク経由のトラフィックをデータプレーンにミラー
iptables -t mangle -A PREROUTING -i vmbr0 -j TEE --gateway 192.168.10.187
iptables -t mangle -A POSTROUTING -o vmbr0 -j TEE --gateway 192.168.10.187
```
データプレーンvmbr1, 192.168.10.0/24を別に用意してるのは、ミラートラフィックでサービス帯域を圧迫しないため。
## ntopng でトラフィック可視化
ntopng は Web UI でリアルタイムのトラフィック状況が見れる。Community 版でも十分使える。
```bash
sudo apt install -y ntopng
```
設定ファイル:
```ini title="/etc/ntopng/ntopng.conf"
-i=eth0
-w=3000
-m=192.168.1.0/24
```
### API でホストラベルを設定
ntopng の REST API でホストにわかりやすい名前をつけられる:
```bash
curl -X POST -H "Authorization: Token <API_TOKEN>" \
"http://localhost:3000/lua/rest/v2/set/host/alias.lua" \
-d "host=192.168.1.7&custom_name=db975i"
```
### アラートフローの確認
```bash
curl -H "Authorization: Token <API_TOKEN>" \
"http://localhost:3000/lua/rest/v2/get/flow/active.lua?ifid=2&alert_type=1"
```
:::warning ntopng の Suricata 連携は Enterprise 版のみ
Community 版では ntopng 上で Suricata のアラートを直接表示できない。Zabbix 等の別ツールで集約する必要がある。
:::
## Zabbix 連携
Suricata のアラートを Zabbix で監視・通知する。
### Zabbix Agent2 のインストール
```bash
wget -O /tmp/zabbix-release.deb \
https://repo.zabbix.com/zabbix/7.4/release/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_7.4+ubuntu22.04_all.deb
sudo dpkg -i /tmp/zabbix-release.deb
sudo apt update && sudo apt install -y zabbix-agent2
```
### eve.json パーススクリプト
Zabbix の `log[]` アイテムだと JSON のフィルタが難しいので、UserParameter + スクリプトで対応。
```bash title="/etc/zabbix/scripts/suricata_alerts.sh"
#!/bin/bash
MODE=${1:-count}
SECONDS_AGO=${2:-60}
CUTOFF=$(date -u -d "-${SECONDS_AGO} seconds" +%Y-%m-%dT%H:%M:%S)
case $MODE in
count)
grep '"event_type":"alert"' /var/log/suricata/eve.json | \
awk -F'"timestamp":"' '{print $2}' | cut -d'"' -f1 | \
awk -v c="$CUTOFF" '$0 >= c' | wc -l ;;
custom_count)
grep 'signature_id.*200000' /var/log/suricata/eve.json | \
awk -F'"timestamp":"' '{print $2}' | cut -d'"' -f1 | \
awk -v c="$CUTOFF" '$0 >= c' | wc -l ;;
last)
grep '"event_type":"alert"' /var/log/suricata/eve.json | tail -1 ;;
esac
```
### 監視アイテムとトリガー
| アイテム | 種別 | 間隔 |
|---------|------|------|
| 全アラート数 (60s) | 数値 | 30秒 |
| カスタムルール数 (60s) | 数値 | 30秒 |
| 個別アラートログ | ログ | 10秒 |
トリガーはカスタムルール検知で「警告」、大量アラート100件/分超)で「重大」に設定。
## やってみてわかったこと
### ハマりポイント
1. **非特権 LXC だと af-packet が動かない** — 特権コンテナ必須
2. **HTTP_PORTS がデフォルト 80 のみ** — 自宅サーバーのポートを追加しないと HTTP パースされない
3. **LXC のゲートウェイ設定漏れ** — パッケージインストール時に外に出られなくて詰む
4. **suricata.rules のパス** — `suricata-update` は `/var/lib/` に保存するが、設定は `/etc/suricata/rules/` を見る
### 実際に検知されたもの
初回スキャンで検知されたのは:
- Corosync (UDP:5405) のクラスタ通信
- Proxmox UI (8006/8007) のアクセス
- MDNS、SMB、SSH のプロトコル異常
- Tuya IoT デバイスの通信
**セキュリティ上の脅威はゼロだった。** 自宅ネットワークなので当たり前といえば当たり前だけど、「異常がない」ことを確認できるのが大事。
### Postfix がデフォルトで開いてる問題
Proxmox VE ノードの脆弱性スキャンをしたら、全ノードで SMTP (25/tcp) が外部から到達可能だった。Proxmox はデフォルトで Postfix を入れてる(通知メール用)けど、ローカルのみにリッスンを制限すべき:
```bash
sudo postconf -e 'inet_interfaces = loopback-only'
sudo systemctl restart postfix
```
## まとめ
専用機材なしでも、Proxmox の LXC + TEE ミラーリングで実用的な IDS 環境が作れた。月額コストもゼロ。
「何が起きてるかわからない」状態から「異常があれば検知して通知される」状態になっただけで、だいぶ安心感が違う。自宅サーバー勢にはおすすめ。
## 参考リンク
- [Suricata公式ドキュメント](https://docs.suricata.io/)
- [ntopng公式](https://www.ntop.org/products/traffic-analysis/ntopng/)
- [Proxmox VE ドキュメント](https://pve.proxmox.com/pve-docs/)
---
*この記事は2026年2月時点の情報です。*