LinuxでZeek Network Security Monitorをインストール:エージェント不要でトラフィック分析と異常行動の検出

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Zeekを5分でインストール――まず試して、後で考える

Zeek(旧名Bro)はSuricataやSnortとはまったく異なります。トラフィックをブロックせず、シグネチャルールも不要——Zeekはネットワーク上で起こるすべての出来事を構造化ログとして記録し、後から分析できます。1か所に設置するだけでシステム全体を監視でき、各マシンに手を加える必要はありません。

Ubuntu 22.04/24.04へのインストール

Zeekの公式リポジトリを使います——最も速くて安定した方法です:

# Zeekリポジトリを追加
echo 'deb http://download.opensuse.org/repositories/security:/zeek/xUbuntu_22.04/ /' | \
  sudo tee /etc/apt/sources.list.d/zeek.list

curl -fsSL https://download.opensuse.org/repositories/security:zeek/xUbuntu_22.04/Release.key | \
  gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/zeek.gpg > /dev/null

# Zeekをインストール
sudo apt update && sudo apt install -y zeek

# バージョン確認
/opt/zeek/bin/zeek --version

使いやすくするためにZeekをPATHに追加します:

echo 'export PATH=/opt/zeek/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

すぐに試す――60秒キャプチャ

マシンのネットワークインターフェースを確認します:

ip link show
# 出力例:eth0、ens3、enp0s3...

Zeekを起動してパケットを60秒間キャプチャします:

mkdir -p /tmp/zeek-test && cd /tmp/zeek-test
zeek -i eth0 -C local &
sleep 60
kill %1

ls -la  # 作成されたログファイルを確認

conn.logdns.loghttp.logなどのファイルが確認できれば、Zeekは正常に動作しています。ここからが面白いところです。

ZeekはほかのIDSと何が違う?

Zeekを理解するための最も良い問いかけは「なぜチームにはZeekとSuricataの両方が必要なのか?」です。

Suricataは「警察官」のように動作します:ルールあり→検出→アラートまたはブロック。一方Zeekは「防犯カメラ」のようなもの——リアルタイムで判断せず、すべての出来事を記録します。インシデント発生後のトレースや、シグネチャベースのIDSが見逃す異常パターンを検出するアナリティクスにZeekのログを活用できます。

最大の強みは:監視対象マシンにエージェントをインストールする必要がないことです。ポートミラー、TAP、またはゲートウェイなど、トラフィックが見える場所にZeekを1か所配置するだけで、システム全体をカバーできます。

把握すべき重要なログ

Zeekは数十種類のログを生成しますが、実際に注目すべきファイルはこれだけです:

ログファイル 内容 使用タイミング
conn.log すべてのTCP/UDP/ICMP接続 あらゆる調査の出発点
dns.log DNSクエリとレスポンス DNSトンネリング、C2コールバックの検出
http.log 完全なHTTPリクエスト Webトラフィックの監視、マルウェアダウンロードの検出
ssl.log TLS/SSLハンドシェイク 自己署名証明書、期限切れ証明書の検出
files.log ネットワーク経由のファイル転送 ファイルのダウンロード/アップロードの追跡
weird.log Zeekが自動検出した異常トラフィック インシデント発生時に最初に確認すべき場所

conn.logを読む――どの接続がインターネットに出ているか?

# 外部へのすべての接続をバイト数でソートして表示
cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p proto orig_bytes resp_bytes | \
  sort -k5 -n -r | head -20

# 異常なポート(80、443、22、53以外)への接続を検索
cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p service | \
  awk '$3 != 80 && $3 != 443 && $3 != 22 && $3 != 53' | sort | uniq -c | sort -rn

DNS分析――DNSトンネリングの検出

# 最も多くクエリされたトップドメイン
cat dns.log | zeek-cut query | sort | uniq -c | sort -rn | head -20

# 異常に長いサブドメインのクエリ(DNSトンネリングの兆候)
cat dns.log | zeek-cut query | awk 'length($0) > 50' | sort | uniq -c | sort -rn

本番環境向けZeekの設定

実際のトラフィックでZeekを安定して動かすには、node.cfgnetworks.cfgで設定が必要です:

sudo nano /opt/zeek/etc/node.cfg
[zeek]
type=standalone
host=localhost
interface=eth0
# トラフィックが多い場合はワーカーを増やす
# workers=4

ZeekがローカルトラフィックとエクスターナルトラフィックをZeekが区別できるよう、内部IPレンジを宣言します:

sudo nano /opt/zeek/etc/networks.cfg
10.0.0.0/8          プライベートネットワーク 10.x
172.16.0.0/12       プライベートネットワーク 172.x
192.168.0.0/16      プライベートネットワーク 192.168.x

デプロイと起動:

sudo /opt/zeek/bin/zeekctl deploy
sudo /opt/zeek/bin/zeekctl status

デフォルトでZeekは1時間ごとにログをローテーションし、/opt/zeek/logs/に日時構造で保存し、gzip圧縮を自動で行います。

応用:ポートスキャン検出Zeekスクリプト

Zeekにはカスタム検出ロジックを記述するための独自のスクリプト言語があります。ポートスキャン検出の例:

sudo nano /opt/zeek/share/zeek/site/detect-portscan.zeek
@load base/frameworks/notice

module PortScan;

export {
    redef enum Notice::Type += {
        Port_Scan_Detected
    };
    global scan_threshold = 20 &redef;
}

global scan_counts: table[addr] of count &read_expire=1min &default=0;

event new_connection(c: connection) {
    local orig = c$id$orig_h;
    ++scan_counts[orig];

    if (scan_counts[orig] == scan_threshold) {
        NOTICE([$note=Port_Scan_Detected,
                $msg=fmt("ポートスキャン検出:%s(%d 接続/分)", orig, scan_counts[orig]),
                $src=orig,
                $identifier=cat(orig)]);
    }
}

このスクリプトをZeekの設定に読み込みます:

echo '@load detect-portscan' >> /opt/zeek/share/zeek/site/local.zeek
sudo /opt/zeek/bin/zeekctl deploy

運用時の実践的なヒント

1. 素早い分析の三種の神器:zeek-cut + awk + sort

ELKやSplunkがない状況で素早く調査が必要な場合、この3つの組み合わせが非常に有効です:

# 最もトラフィックを生成したトップIP(バイト数順)
cat conn.log | zeek-cut id.orig_h orig_bytes | \
  awk '{sum[$1]+=$2} END {for(ip in sum) print sum[ip], ip}' | \
  sort -rn | head -10

# 長時間接続の検出――C2ビーコンの兆候(異常に長い接続)
cat conn.log | zeek-cut id.orig_h id.resp_h id.resp_p duration | \
  awk '$4 > 3600' | sort -k4 -rn | head -10

2. ELK Stackとの統合によるビジュアライズ

トラフィックが多い場合、Zeekのプレーンテキストログは読みにくくなります。FilebeatでElasticsearchに送信しましょう:

# /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  paths:
    - /opt/zeek/logs/current/*.log
  fields:
    type: zeek
  json.keys_under_root: true

output.elasticsearch:
  hosts: ["localhost:9200"]

3. Zeekサーバーのセキュリティ

ZeekサーバーはすべてのトラフィックをモニタリングするためAttackerにとって魅力的なターゲットになります。セットアップ時にはSSHをキー認証のみに制限しtoolcraft.app/ja/tools/security/password-generatorでSSHキーのパスフレーズを生成しています——このツールは100%ブラウザ上で動作し、サーバーへの送信は一切ないため情報漏洩の心配がありません。ZeekサーバーはVLANを分離し、管理ポート以外のインバウンドはファイアウォールでブロックすることをお勧めします。

4. 毎日のログレビューで確認すべき3つの質問

私はZeekのログを確認する際、毎朝この3つの質問から始めます:

  • 内部IPが異常なポートでインターネットに接続していないか?
  • 異常な頻度でクエリされているドメインや、異常に長いサブドメインがないか?
  • 今日のweird.logには何か記録されていないか?

この3つの質問で、中小企業環境でよく起きるインシデントの80%をカバーできます。

5. ZeekとSuricataの組み合わせ――最善のセットアップ

SuricataはIPSとしてリアルタイムブロックを担当し、Zeekはフォレンジックのためのフルログを並行して記録します。SuricataがAlertを出した際、Zeekのログを使って遡及トレースを行います:Alert前のアクティビティは何か、Alert後に何かが起きていないか、ラテラルムーブメントはないか。2つのツールは互いを補完するものであり、代替するものではありません。

Zeekは「インストールして終わり」のツールではありませんが、ログフォーマットと基本的なクエリに慣れれば、システムにおける最も重要なビジビリティレイヤーになります——多くのチームがその価値に気づくのは、実際のインシデントが発生した後です。

Share: