境界線は消えた。VPNログを「監視」から「防御」に変えるSIEM連携の極意
「VPNを通しているから安心だ」――かつて、そう信じられていた時代が懐かしい。今のネットワーク境界は、社員の自宅のリビングや、不特定多数が接続するカフェのフリーWi-Fiまで拡張されている。
VPN装置のログをただ眺めているだけの運用は、もはや「ログを記録しているだけの墓場」だ。今回は、現場の泥臭い戦場から得た知見をもとに、VPNの監査ログをSIEM(Security Information and Event Management)へ流し込み、生きた脅威を狩るための実践的な仕組みを解説する。
—
1. なぜVPNログの「可視化」だけでは不十分なのか
VPN装置(IPsec/SSL-VPNゲートウェイ)が吐き出すログには、接続元 IPアドレス、ユーザーID、認証成功/失敗、接続元ISP などの宝の山が眠っている。しかし、管理画面にログインして数値を眺めていても、深夜3時の「ブルートフォース攻撃」や「地理的異常(Impossible Travel)」には気づけない。
真の目的は、ログを「点」として捉えるのではなく、SIEMという「線」に繋ぎ、相関分析によって「面」で脅威を検知することにある。
2. 通信フロー:ログがSIEMに届くまで
VPN装置からSIEMまでの道のりは、一般的に以下のプロセスを辿る。
1. イベント発生: ユーザーが認証を試みる。
2. ログ生成: VPN装置が syslog や API 経由でログを生成。
3. 転送: syslog-ng や Logstash 等のコレクターを経由。
4. インジェスト: SIEM(Splunk, Elastic Stack, Azure Sentinel等)に蓄積。
5. 相関検知: SIEM側で「同一ユーザーが5分以内に3拠点からログイン」といったルールに合致した場合にアラートを発報。
3. 実践:ログをSIEMへ送り込む設定(Logstash例)
現場でよく使う Logstash を例に、VPNログを正規化して送り出すための設定例を示す。ここで重要なのは、geoip プラグインを使用して、IPアドレスから国や都市の情報を付与することだ。
# logstash.conf の設定例
input {
tcp {
port => 5140 # VPN装置からのsyslogを待ち受け
type => "vpn_logs"
}
}
filter {
# VPNのログインログをパースしてユーザー名とIPを取り出す
grok {
match => { "message" => "VPN_AUTH: user=%{USER:username}, src=%{IP:src_ip}, status=%{WORD:status}" }
}
# IPから地理情報を付与(攻撃検知のキーになる)
geoip {
source => "src_ip"
target => "geoip"
}
}
output {
elasticsearch {
hosts => ["https://your-siem-endpoint:9200"]
index => "vpn-audit-%{+YYYY.MM.dd}"
}
}
4. 不正アクセスを検知するPythonスクリプト
SIEMのAPIを叩いて、異常検知を自動化するためのPythonコード例だ。例えば、短時間に失敗が多発している src_ip を特定し、SlackやTeamsに通知するような運用を想定している。
import requests
import json
# SIEMのAPIエンドポイント
SIEM_API_URL = "https://api.siem-service.com/v1/search"
HEADERS = {"Authorization": "Bearer YOUR_API_TOKEN"}
def check_brute_force():
# 過去10分間で認証失敗が10回を超えたIPを抽出するクエリ
query = """
index=vpn-audit
| where status="failed"
| stats count by src_ip
| where count > 10
"""
response = requests.post(SIEM_API_URL, headers=HEADERS, json={"query": query})
if response.status_code == 200:
results = response.json().get("results", [])
for entry in results:
print(f"[ALERT] 異常な接続試行を検知: {entry['src_ip']} (回数: {entry['count']})")
# ここで自動的にファイアウォールのブロックAPIを叩く処理に繋げる
else:
print("SIEM APIの呼び出しに失敗しました")
if __name__ == "__main__":
check_brute_force()
5. 現場のシニアエンジニアからの忠告
最後に、運用で必ず直面する「落とし穴」を伝えておく。
- ログの欠落を許すな: VPN装置の負荷が上がるとログが間引かれることがある。
UDPではなく可能な限りTCPやTLSでの転送を推奨する。 - 地理情報の過信は禁物:
VPNやTorを使えば地理情報は容易に偽装できる。「海外からのアクセスだからNG」ではなく、「普段の業務時間帯と一致しているか」「認証デバイスのIDは正しいか」というコンテキストで判断してほしい。 - アラート疲れを防ぐ: 初期設定ではノイズが多い。まずは「ログイン成功後の異常なIPからの大量トラフィック」など、クリティカルな事象に絞ってチューニングを重ねること。
ゼロトラストにおいて、VPNはあくまで「信頼できないゲートウェイ」の一つに過ぎない。しかし、そのゲートウェイをどう監視するかで、インシデントの芽を摘めるかどうかが決まる。
明日から、君たちのVPNログを見直してみてほしい。そこに「何か」が映り込んでいるはずだ。
コメント