syslogを向けるだけでAIが機器種別を自動判定して監視を始める仕組みを作った

syslogを向けるだけでAIが機器種別を自動判定して監視を始める仕組みを作った

1 min read

2026.04 / Tech Blog / BASTION

syslogを向けるだけでAIが機器種別を自動判定して監視を始める仕組みを作った #

新しい機器がsyslogを送り始めた瞬間に、LLMがログサンプルを読んで「これはWindowsクライアントだ」「これはファイアウォールだ」と自動判定。適切な監視テンプレートを適用して即座に監視を開始する。機器の手動登録は不要。

従来の監視導入で一番面倒なこと #

監視ツールを導入するとき、最も工数がかかるのは初期設定ではなく「機器ごとの登録作業」です。

Zabbixでもその他のSIEMでも、新しい機器を監視対象に追加するたびに「ホスト登録→テンプレート選択→パーサー設定→テスト→本番適用」の手順が必要です。10台なら2〜3人日、100台なら20〜30人日。しかも機器が増減するたびにこの作業が発生します。

BASTIONではこの工程自体を消しました。

BASTIONのアプローチ:rsyslogの宛先を1行設定するだけ。あとはAIが全部やる。機器種別の判定も、監視テンプレートの適用も、端末の増減追跡も自動。人間の登録作業はゼロ。

仕組みの全体像 #

以下の5つのステップが全自動で動きます。

ステップやること実行タイミング
1. ログ到着新しい機器がsyslogを送信。rsyslogがホスト名でディレクトリを自動作成即時
2. 新規ホスト検出前回のホストリストと比較し、新しいディレクトリを発見1日1回(cron)
3. LLM分類ログサンプルをLLMに送り、機器種別を自動判定新規検出時
4. テンプレート適用判定結果に応じた監視テンプレートをデバイスレジストリに登録分類完了時
5. 監視開始次回の定期分析(15分ごと)でテンプレートが自動的に呼び出される次回cron実行時

つまり、機器がsyslogを送り始めてから最短で15分後には監視レポートがSlackに届きます。

ステップ1: rsyslogによるディレクトリ自動生成 #

BASTIONのrsyslogは、受け取ったsyslogの送信元ホスト名ごとにディレクトリを自動作成します。

/var/log/remote/
  ホスト名A/2026/04/Security-Auditing.log
  ホスト名B/2026/04/sshd.log
  ホスト名C/2026/04/filterlog.log
  ...

新しい機器がsyslogを送り始めると、設定変更なしでディレクトリが出現します。これがすべての自動化の起点です。

ステップ2: 新規ホストの自動検出 #

検出スクリプトが1日1回、ディレクトリの一覧を前回のリストと比較します。

ここで重要なのは「何を監視するか」ではなく「何を除外するか」を管理するという逆転の発想です。既存のサーバーやネットワーク機器(既にsummarize.shで個別にパース処理を書いているもの)は除外リストに入れておき、それ以外は全部「新規クライアント」として扱います。

# 除外リスト(サーバー/NW機器のホスト名パターン)
EXCLUDE_HOSTS="既存サーバー1|既存サーバー2|既存FW|..."

# /var/log/remote/ のホスト一覧から除外リストを引く
# → 残ったものが新規クライアント

検出結果に応じてSlackに通知します。

状況通知
新規ホスト出現「新しいクライアントからログが届き始めました。自動分類して監視を開始します」
ログ停止「このクライアントからログが届かなくなりました。NXLogの状態を確認してください」
48時間以上非アクティブ「48時間以上ログが更新されていません」
変化なし通知しない(ログのみ)

ステップ3: LLMによる自動分類 #

ここが核心です。新規ホストが検出されると、そのホストのログファイルからサンプル(上位5ファイル×末尾20行)を取得し、LLMに分類を依頼します。

何を判定するか #

以下の9カテゴリに分類します。

カテゴリ機器種別ログの特徴(LLMが見るポイント)
win_clientWindows クライアントSecurity-Auditing、LogonType 2/10、PowerShell
win_serverWindows ServerSecurity-Auditing、Kerberos TGT/TGS、Directory Service
linuxLinux サーバーsshd、sudo、systemd、kernel
firewallファイアウォールfilterlog、block/pass、NAT、VPN
switchL2/L3 スイッチlink up/down、STP、loop
loadbalancerロードバランサーbackend、frontend、health check
webserverWeb サーバーHTTP status、GET/POST、access_log形式
routerルーターBGP、OSPF、routing
unknown判定不能上記いずれにも該当しない → 人間にエスカレーション

LLMへの分類依頼 #

GPUStack(ローカルLLMサーバー)のOpenAI互換APIに直接リクエストを送ります。プロンプトにはホスト名、ログファイル一覧、ログサンプルを添付し、JSON形式で分類結果を返すよう指示します。

# 分類リクエスト(概要)
curl -s -X POST "${GPUSTACK_URL}/v1/chat/completions" \
  -H "Authorization: Bearer ${API_KEY}" \
  -d '{
    "model": "qwen2.5-14b-instruct",
    "messages": [{
      "role": "system",
      "content": "You are a device classifier. Classify this host..."
    }, {
      "role": "user",  
      "content": "Hostname: XXX\nLog files: ...\nSample: ..."
    }],
    "temperature": 0.1
  }'

# → 応答例
{
  "category": "win_client",
  "confidence": "high",
  "os_detail": "Windows 10/11 desktop",
  "reasoning": "Security-Auditing logs with LogonType 2..."
}

LLMの応答からJSON部分を抽出し、デバイスレジストリに登録します。

実装で踏んだ罠:OpenClaw経由だと全部unknownになる #

最初はOpenClaw(AIエージェント基盤)経由でLLMを呼んでいましたが、分類プロンプト内の「win_client」「firewall」等のキーワードがAGENTS.md(システムプロンプト)のキーワードマッピングに干渉し、LLMが分類の代わりにツール呼び出し文字列を返してしまいました。解決策はシンプルで、分類処理だけはOpenClawを経由せず、GPUStackのAPIを直接curlで叩くようにしました。プロンプトも英語化してキーワード干渉を排除しています。

もう1つの罠:bashのheredocとpipeのstdin衝突 #

LLM応答のJSON抽出をPythonで書いたところ、bashのheredoc(<<'EOF')がpipeの標準入力を奪い、Python側のjson.load(sys.stdin)がPythonコード自体を読もうとする問題が発生。常に空の分類結果が返っていました。Python部分を外部スクリプトに切り出して解決。見た目は正しいのに動かない、再現性100%のバグで、デバッグに時間を取られました。

ステップ4: テンプレートベースの監視 #

デバイスレジストリ #

分類結果はJSONファイル(デバイスレジストリ)に蓄積されます。

{
  "devices": [
    {
      "hostname": "CLIENT-001",
      "category": "win_client",
      "template": "win_client.sh",
      "confidence": "high",
      "os_detail": "Windows 10/11 desktop",
      "active": true
    },
    ...
  ],
  "exclude_hosts": ["既存サーバー1", "既存FW", ...],
  "last_scan": "2026-04-21T06:00:00+09:00"
}

監視テンプレート #

各カテゴリに対応するテンプレートスクリプトを用意しています。テンプレートは2つの関数を提供します。

# templates/win_client.sh

# 要約出力(summarize.shから呼ばれる)
template_summarize_win_client() {
    # 認証異常、PowerShell、USB、アカウント変更のカウント
}

# 詳細分析(analyze-detail.shから呼ばれる)
template_detail_win_client() {
    # ログイン失敗の端末別内訳、特権ログオン詳細、LOLBin検知...
}

既存のsummarize.sh(定期分析スクリプト)の末尾に、デバイスレジストリを読んでテンプレートを動的に呼び出すブロックを追記しています。

# summarize.sh 末尾に追記
jq -r '.devices[] | select(.active==true) | ...' device-registry.json \
| while read HOST CATEGORY TEMPLATE; do
    source "templates/${TEMPLATE}"
    template_summarize_${CATEGORY} "$HOST" ...
done

既存のハードコード部分には一切触れず、追記だけで拡張しています。

ステップ5: 全自動の結果 #

初回スキャンで14台のWindowsクライアントを自動検出しました。LLMが各端末のログサンプルを読み、「Security-Auditingログにログオンイベントがある→Windowsクライアント」と判定。win_clientテンプレートが自動適用され、認証異常・PowerShell実行・USB接続・アカウント変更の4カテゴリの監視が即座に開始されました。

検出から監視開始までの人間の作業:ゼロ。NXLog(ログ転送エージェント)はGPOで全社クライアントに自動展開済みなので、新しいPCがドメインに参加した時点でログ転送が始まり、BASTIONが自動的に拾い上げます。

LLM分類の精度 #

14台中、13台がconfidence: highで正しく分類されました。1台だけconfidence: highで「win_server」と判定されましたが、実際にはWindowsクライアントでした。ホスト名にサーバーを連想させる文字列が含まれていたことが原因と推定されます。

win_clientとwin_serverで監視テンプレートは共通にしてあるため、実害はありません。ただし、カテゴリの正確性が重要な場合は、デバイスレジストリのcategoryフィールドを手動で修正するオーバーライド機能を検討中です。

既存の監視との共存 #

BASTIONでは既にファイアウォール・認証基盤・ロードバランサー・スイッチ・Webサーバーの分析処理をsummarize.shにハードコードしています。自動分類の対象はこれらの既存機器を除外した残りです。

既に動いているものを壊すリスクは取りません。将来的には既存のハードコード部分もテンプレート化して統合可能ですが、現時点では「既存機器=ハードコード」「新規機器=テンプレート自動適用」の二層構成です。

今後の拡張 #

現在はwin_clientテンプレートと汎用(unknown)テンプレートの2種類ですが、顧客導入のたびにテンプレートが増えていきます。

テンプレート状態主な監視項目
win_client / win_server実装済み認証異常、PowerShell、USB、アカウント変更
generic(unknown用)実装済みerror/warning/criticalのカウント
linux計画中SSH認証、sudo実行、systemdサービス、OOM
firewall計画中ブロック数、攻撃元IP、ポート分布、VPN
switch計画中リンクダウン、STP変更、ループ、ストーム

テンプレートのライブラリが増えるほど「syslogを向けるだけ」で対応できる機器の範囲が広がり、これがそのまま蓄積型の競争優位になります。

まとめ #

BASTIONの自動機器分類は、rsyslogのディレクトリ自動生成 → ホスト検出 → LLMログ分類 → テンプレート自動適用 → 監視開始を全自動で行います。syslogの宛先を設定するだけで、機器の種別判定も監視ルールの選択も端末の増減管理も自動化されます。

従来の監視導入における最大のボトルネック「機器ごとの登録・設定」を構造的に消す仕組みです。10台でも100台でも、人間の作業は同じ(syslog宛先の1行設定のみ)。「知らないうちに監視対象外の機器が増えていた」という問題が構造的に発生しません。

BASTIONは閉域環境でAIセキュリティ監視を実現するサービスです。

BASTION サービスページ
お問い合わせ

Updated on 2026年4月21日

What are your feelings

  • Happy
  • Normal
  • Sad