Ollamaで作るAI-SOC|Webログを自動でトリアージ
クラウドGPU(さくらの高火力)に Ollama を載せ、自分のWebサイトのアクセスログを“一次仕分け”するミニSOCを作ります。鍵は 「安いルールでふるい分け → 怪しい分だけGPU」 というコスト設計と、機微ログを無防備に外へ出さない守りの作法。図解・コスト試算・実コードつきの実装ガイドです。
📑 このページの歩き方
AI-SOCとは/なぜローカルLLMで作るのか
ログの山を、AIが“一次仕分け”する。ただし機微データは外に出さずに。
SOC(セキュリティ運用)の悩みは「量」
Webサーバのアクセスログには、攻撃の偵察・スキャン・侵入試行の痕跡が日々大量に流れます。SOC(Security Operations Center)の現実的な課題は「人手では全部見きれない」こと。そこで LLMに一次トリアージ(仕分け)を手伝わせ、人は“怪しい”に集中する——これが本記事で作る「AI-SOC」です。
ではなぜ ChatGPT 等のクラウドAIではなく、ローカルLLM(Ollama)で作るのか。理由は データ主権です。アクセスログにはIPアドレス・リクエスト内容・ときにセッション情報など、外部に送りたくない情報が含まれます。クラウドAIに丸ごと貼り付けるのは、情報の取り扱いとして筋が悪い。Ollamaなら、推論を自分の管理下で動かせます。この「防御者がLLMを“守りの道具”として、データを外に出さずに使う」考え方は、当サイトの ローカルLLMセキュリティ完全ガイド の中心テーマでもあります。本記事はその実装編にあたります。
🛰️ 図1:AI-SOC の全体像(ログ→仕分け→解析→人)
ポイントは図の ①一次仕分け です。全アクセスをAIに読ませると遅く・高くつくため、まず 安価なルール(正規表現や Sigma的な検知)で“候補”だけを絞り、GPUにはその分だけを渡します。AIの役割は「これは何の攻撃か、どれくらい危ないか」を読みやすい形に整える一次トリアージで、遮断などの最終判断は人と既存の仕組みが担います。
不審アクセスの自動仕分け
スキャン・脆弱性探索・ログイン試行などの“候補”を拾い、benignなノイズと分けて、人が見るべき件数を一気に減らします。
攻撃種別とATT&CKの推定
SQLi・XSS・パストラバーサル等の分類と、対応するMITRE ATT&CK技術IDの当たりを付け、調査の入口を示します。
優先度つきレポート
深刻度で並べたレポートを自動生成。人は medium 以上に集中でき、見逃しと“アラート疲れ”の両方を抑えられます。
文脈の要約
大量のログ列や、見慣れないUA・ペイロードを、人間が読みやすい日本語の要約に。一次解釈の手間を肩代わりします。
本記事は 自分が運営するWebサイト・自分が管理する正規のログ を守るための解説です。他者のサイトやログを無断で収集・解析することは対象外です。また「クラウドGPUにログを送る」=データが自社の手元を離れる行為でもあります。後述のとおり PIIを最小化・マスク し、送る情報を絞ってください。
設計の肝:コストが構成を決める(常時 vs バッチ)
GPUは秒課金。だから「常時起動」か「バッチ実行」かで、月額が100倍変わる。
さくらの高火力GPUは 秒単位の従量課金です(例:NVIDIA V100 が 0.016 円/秒、H100 が 0.28 円/秒)。とくにコンテナ型の 高火力DOK は、Dockerイメージを「タスク」として実行し、走った秒数だけ課金される仕組み。ここを理解しないと、AIサーバを“立てっぱなし”にして請求に驚くことになります。
| 使い方 | V100(0.016円/秒) | H100(0.28円/秒) | 向き |
|---|---|---|---|
| 常時起動(24時間立てっぱなし) | 57.6円/時 → 約4.1万円/月 | 1,008円/時 → 約72万円/月 | ❌ もったいない+公開リスク |
| バッチ(15分毎に約60秒解析) | 約92円/日 → 約2,800円/月 | 約1,600円/日 → 約4.8万円/月 | ○ 現実的 |
| イベント駆動(怪しい時だけ起動) | さらに安い(実際に走った秒数のみ) | ◎ 推奨 | |
コストの結論:一次仕分け+小型モデル+バッチ
一次仕分けの精度は 3B〜7B級の小型モデルで十分なことが多く、これは V100でも快適に動きます。「安いルールで候補を絞る → 小型モデルで → バッチ/イベント駆動」を組み合わせれば、ナイーブに常時H100(約72万円/月)だった処理が 月数千円〜数万円 に収まります。精度が要る深掘りだけ H100・大型モデルに回す“二段構え”が賢い設計です。
なお高火力DOKは「タスクごとに最低利用時間」があり、V100は最低1秒・H100は最低60秒です。つまり 細かく頻繁に回すなら V100、まとめて重い処理を回すなら H100、と粒度で選ぶのがコツ。モデルをイメージに焼き込んでおくと、毎回のダウンロード時間(=課金)を無くせます。
モデル選定では「速さ・安さ」と「読み解く力」のバランスを取ります。ログ分類のような定型タスクは小型モデルでも実用的で、まずは llama3.2:3b や qwen2.5:7b あたりで精度を見て、物足りなければ一段大きくする、という進め方が無駄がありません。大事なのは“最初から最大GPU”ではなく、自分のログで小さく試して必要量を測ること。これはコストにも精度にも効きます。
アーキテクチャ全体図
“司令塔は安いサーバ、GPUは必要なときだけ”。推論エンドポイントは公開しない。
コストと安全を両立する構成はこうです。常時起動の安いマシン(GPUなし=司令塔)がログ収集と一次仕分けを担い、GPUは解析の瞬間だけ動かす。Ollamaの推論APIは外部に公開せず、結果はオブジェクトストレージ経由でやり取りします。
🗺️ 図2:バッチ型 AI-SOC のデータフロー
この形の良いところは2つ。(1) コスト=GPUは解析の秒だけ課金。(2) 安全=Ollamaの推論APIを外向きに開かないので、ピラー記事で詳説した「ノーガード公開」(無認証のOllamaがインターネットにさらされLLMjackingやRCEの的になる事故)を、構造的に避けられます。タスクは「ストレージから入力を読む→推論→結果を書く→終了」という自己完結バッチなので、開いたエンドポイント自体が存在しません。
作る①:Ollama設置と“公開しない”設定
導入はコマンド数行。だが最初に「外に開かない」を固めるのが防御者の作法。
まずGPUサーバ(さくらの高火力など)にOllamaを入れます。重要なのは、導入直後に 推論APIを 127.0.0.1 に固定しておくこと。Dockerや一部の既定では OLLAMA_HOST=0.0.0.0(全公開)になりがちで、これが事故の元です。
$ curl -fsSL https://ollama.com/install.sh | sh $ ollama --version # 最新か(CVE対策。更新を運用に組み込む) # ★APIを 127.0.0.1 に固定(外部公開しない) $ sudo mkdir -p /etc/systemd/system/ollama.service.d $ sudo tee /etc/systemd/system/ollama.service.d/override.conf >/dev/null <<'EOF' [Service] Environment="OLLAMA_HOST=127.0.0.1:11434" EOF $ sudo systemctl daemon-reload && sudo systemctl restart ollama $ ss -tlnp | grep 11434 # 127.0.0.1:11434 ならOK(0.0.0.0 はNG) # 一次トリアージ用の軽量モデル(V100でも快適・激安) $ ollama pull llama3.2:3b
バッチ(高火力DOK)で動かすなら、上記を Dockerイメージに焼き込み、タスクとして実行します。モデルをイメージに含めておけば、毎タスクのダウンロード時間(=課金)が消えます。
FROM ollama/ollama:latest RUN apt-get update && apt-get install -y python3 python3-pip && \ pip3 install --break-system-packages boto3 # モデルをイメージに焼く=毎回のpull課金を無くす ENV OLLAMA_MODEL=llama3.2:3b RUN ollama serve & sleep 8 && ollama pull ${OLLAMA_MODEL} COPY soc_analyzer.py /app/soc_analyzer.py # タスクとして実行→処理して終了(=秒課金停止)。APIは外に出さない。 ENTRYPOINT ["python3", "/app/soc_analyzer.py"]
“公開しない”はクラウドGPUで特に重要
DOKタスクには公開URL(UUID.container.sakurausercontent.com)が割り当たり得ます。ここでOllamaのAPIを無認証公開すれば、世界中から叩かれます。バッチ型ならそもそも推論エンドポイントを開かないので安全。詳しい設定論は ローカルLLMセキュリティ完全ガイド の「多層防御」章をどうぞ。
作る②:解析プログラムとプロンプト
全行をAIに回さない。安く絞り、伏せて渡し、構造化して受け取る。
解析プログラムは3つの仕事をします。①安いルールで“候補”だけ抽出(GPU代の節約)→ ②PIIをマスク(外に出す情報の最小化)→ ③Ollamaで構造化トリアージ(深刻度・攻撃種別・ATT&CKをJSONで)。核心部分はこれだけです。
import os, re, json, urllib.request OLLAMA = "http://127.0.0.1:11434/api/generate" MODEL = os.environ.get("OLLAMA_MODEL", "llama3.2:3b") # ① 安いルールで“候補”だけ拾う(全行をAIに回さない) SUSPICIOUS = re.compile( r"\.\./|/etc/passwd|union\s+select|<script|onerror=|sqlmap|nikto|" r"/wp-login|xmlrpc\.php|/\.env|%00|base64_decode|/bin/sh|cmd=|\bOR\b\s+1=1", re.I) # ② PIIマスク(外に出す情報を最小化=データ最小化) def mask(s): s = re.sub(r"(\d+\.\d+\.\d+)\.\d+", r"\1.x", s) # IP末尾を丸める s = re.sub(r"(token|sid|session|authorization)=[^\s&\"]+", r"\1=***", s, flags=re.I) return s # ③ Ollamaで構造化トリアージ(format=json で安定したJSON出力) def triage(line): body = json.dumps({"model": MODEL, "prompt": PROMPT.format(line=line), "stream": False, "format": "json", "options": {"temperature": 0}}).encode() req = urllib.request.Request(OLLAMA, body, {"Content-Type": "application/json"}) out = json.loads(urllib.request.urlopen(req, timeout=300).read()) try: return json.loads(out["response"]) except Exception: return {"severity": "unknown"} # 候補だけAIへ。medium以上を“要確認”として集計・通知(コスト安全弁で上限も) rank = {"critical":4, "high":3, "medium":2, "low":1, "none":0} cands = [mask(l) for l in new_lines if SUSPICIOUS.search(l)][:200] hits = [r for r in map(triage, cands) if rank.get(r.get("severity"), 0) >= 2]
「新着行だけを読む」処理は、前回読んだ位置(オフセット)を状態ファイルに保存しておけば実現できます(ログローテートはファイルサイズの減少で検知)。一次仕分けのルールは、Sigma検知ルールの考え方で育てると堅牢になります。肝心のプロンプトは、防御者の役割を与え、構造化(JSON)で・保守的に出させるのがコツです。
あなたはWebアクセスログを見る防御側のセキュリティアナリストです。
対象は自分が管理する正規サイトのログで、目的は攻撃の早期検知です。
次の1行を評価し、必ず次のJSONだけを出力(説明文は不要):
{"severity":"none|low|medium|high|critical",
"attack_type":"短い分類(SQLi, XSS, path_traversal, scanner...)",
"mitre":"該当ATT&CK技術ID(不明は空)",
"confidence":0.0,
"evidence":"そう判断した根拠を短く",
"action":"担当者向けの推奨対応を短く"}
判定は保守的に。確証がなければ severity を下げること。
これは一次トリアージであり、最終判断と遮断は人間と既存の仕組みが行う。
ログ: {line}
コストをさらに詰めるなら、1行ずつではなく複数行を1回の推論にまとめると、モデルのロード待ちや往復回数を減らせます。Ollamaは一度モデルを読み込むとしばらく常駐する(keep_alive)ため、連続処理ほど1件あたりが速く・安くなります。精度と取り回しのバランスを見つつ、1プロンプトに載せる件数を調整してください。
作る③:アウトプットと運用(通知・人の判断)
結果は“人が動ける形”で。通知は要確認だけ。遮断はあくまで人と仕組み。
解析結果はレポート(JSON+人間用のMarkdown要約)として保存し、深刻度 medium 以上だけをSlack等へ通知します。通知を絞るのは「アラート疲れ」を避けるため。常時起動の安いサーバでcron実行する例がこちらです。
# 10分ごとに新着ログを解析
*/10 * * * * OLLAMA_MODEL=llama3.2:3b SLACK_WEBHOOK=https://hooks.slack.com/xxx \
/usr/bin/python3 /opt/ai-soc/soc_analyzer.py >> /var/log/ai-soc.log 2>&1
レポートの一件は、たとえば次のように整います——『severity: high / attack_type: path_traversal / mitre: T1083 / evidence: リクエストに ../ を含むパス操作 / action: 該当IPの傾向を確認し、必要ならWAFで遮断』。深刻度順に並べておけば、担当者は上から確認するだけで済みます。AIが“読み下し”と当たり付けをしてくれるぶん調査の初速が上がり、定型的な仕分けに使っていた時間を、本当に危ないものの深掘りへ振り向けられます。さらに、同じ攻撃が続くなら、その特徴を一次仕分けルールに取り込めば、次回からはGPUを使わず(=無料で)弾けます。学ぶほど安くなる、という好循環です。
収集
Webサーバのログを司令塔へ集約(同一サーバなら直読み、別なら Fluent Bit 等で暗号化して転送)。
一次仕分け+マスク
安いルールで候補を抽出し、IP末尾やトークンをマスク。GPUに渡す量と情報を最小化。
AI解析(必要分だけ)
Ollamaが候補を構造化トリアージ。バッチ/イベント駆動で、走った秒だけ課金。
通知
medium以上だけをSlack/メールへ。レポートは保存して後追い可能に。
人が判断・対応・改善
遮断は 対応手順・WAF・fail2ban・手動で。誤検知/見逃しはルールへ反映(改善ループ)。
LLMには幻覚・誤判定があり、攻撃者がログに細工して判断を狂わせるプロンプトインジェクションも起こり得ます(外部入力=データであって命令ではない)。だからAIは一次トリアージに留め、遮断・通報などの最終判断は人と既存の仕組みに。エージェントやツール接続で自動アクションまで握らせるほどリスクは増えます(参考:AIエージェント/MCPセキュリティ)。
✅ 運用チェックリスト
- Ollamaは
127.0.0.1固定+ファイアウォールで 11434 を塞いだか - ログ転送は暗号化(TLS/VPN/SSH)したか/平文で公衆網に流していないか
- GPUに渡す前にPII(IP・トークン・Cookie等)をマスクしたか
- 通知は medium 以上に絞ったか(アラート疲れ対策)
- コストは「バッチ/イベント駆動/アイドル停止」で抑えているか
- Ollama・モデルは最新か(CVE追従)
セキュリティ・用語集・FAQ・次に読む
安く・安全に回すための要点と、次の一歩。
公開しない
Ollama APIは127.0.0.1+FW。開かない構成に
データ最小化
PIIマスク。送る情報を絞る
コスト最適化
仕分け→必要分だけGPU→停止
「クラウドGPUにログを送る」ことは、データが自社の手元を離れる選択でもあります。さくらは国内事業者でデータは国内に留まり法令面では有利ですが、“完全ローカル”ではない以上、何を送るかは意識的に絞るのが防御者の作法です。最高機密のログはオンプレGPUや隔離環境という選択肢も。判断の土台は ローカルLLMセキュリティ完全ガイド に集約しています。要は 「何を外に出すかを自分で決める」 こと。一次仕分けでデータ量を絞り、PIIをマスクし、出せないものはオンプレに残す——この線引きを運用ルールとして明文化しておくと、チームでも判断が揺れません。これは「ローカルでも、クラウドでも」共通する防御者の基本姿勢です。
📚 用語集
| SOC | Security Operations Center。監視・検知・対応を担う運用機能。 |
| トリアージ | 大量の事象を「危なさ」で仕分け、優先順位を付けること。 |
| 高火力DOK | さくらのコンテナ型GPUサービス。Dockerイメージをタスクとして秒課金で実行。 |
| Ollama | ローカルでLLMを動かすツール。推論APIを提供(既定は 127.0.0.1:11434)。 |
| 一次仕分け(プレフィルタ) | AIに渡す前に安いルールで候補を絞る処理。コストと速度の要。 |
| PIIマスク | 個人情報・秘密を伏せ字化して外部処理に渡す情報を最小化すること。 |
| プロンプトインジェクション | 入力データに紛れた指示文がAIの命令に化ける攻撃(OWASP LLM01)。 |
| 構造化出力(format=json) | OllamaにJSON形式で返させ、後段プログラムで扱いやすくする機能。 |
❓ よくある質問(FAQ)
どのGPU・モデルを選べばいい?
ログの一次トリアージなら 3B〜7B級の小型モデル+V100 で十分なことが多く、最も安く回せます。難しい深掘りだけ H100・大型モデルに回す“二段構え”が費用対効果に優れます。
常時起動とバッチ、どちらがいい?
SOC用途は基本 バッチ/イベント駆動を推奨。秒課金のGPUを立てっぱなしにすると高額(H100なら24時間で約2.4万円)。一次仕分けで候補を絞り、走る秒数を最小化しましょう。
ログをクラウドに送って大丈夫?
“絶対に外に出せない”データはオンプレが安全です。出せる範囲でも PIIをマスクし、送る情報を絞るのが原則。国内事業者を選べばデータの所在は国内に保てます。
AIの判断をそのまま遮断に使える?
使わないでください。幻覚・誤判定・プロンプトインジェクションのリスクがあります。AIは一次トリアージに留め、遮断は人・WAF・fail2ban等の確定的な仕組みで行います。
Ollamaを外部公開して複数台から使いたい
APIに認証は無いため、直接公開は厳禁です。リバースプロキシ+TLS+認証を前段に置くか、本記事のように公開しないバッチ型にしてください(詳細はピラー記事)。
まず何から試せばいい?
サンプルの access.log を用意し、ローカルのDockerでOllama+解析スクリプトを動かして“流れ”を確認 → うまくいったらDOKタスク化、が安全で安上がりです。
✅ はじめの一歩
- サンプル access.log で
soc_analyzer.pyをローカル実行し流れを掴む - Ollamaを
127.0.0.1固定+FWで塞ぐ(公開しない) - 一次仕分けルールを自サイトに合わせて調整(Sigmaの考え方で)
- medium以上だけ通知 → 人が確認する運用に
- コストはバッチ/イベント駆動で最小化、まずV100+3Bから
🧭 次に読む
🦙 ローカルLLMの守り
🛡️ 検知と対応
🏠 全体像と実習
📚 主な参考・一次情報
- さくらインターネット「高火力 DOK」製品ページ/さくらのクラウド マニュアル(料金体系・はじめに・ストレージ連携)
- さくらのナレッジ「コンテナー型GPUクラウドサービス 高火力 DOK で Ollama を実行する」
- Ollama 公式ドキュメント(
OLLAMA_HOST/API/api/generate/構造化出力 format) - OWASP Top 10 for LLM Applications(LLM01: Prompt Injection ほか)
- MITRE ATT&CK(攻撃手法の共通言語)/ SigmaHQ(検知ルール)
※料金・仕様は変更され得ます。利用前に各サービスの公式情報(最新の料金・最低利用時間・リージョン)を必ずご確認ください。

コメント