以前、ECサービスのプロジェクトでマイクロサービスをデプロイしていたとき、あるコンテナがスパムメール送信に悪用されていることを発見するまで2日近くかかったことがある。アプリのログはまったく正常、CPUも異常なし——しかしコンテナは見知らぬIPへの接続を繰り返し開いていた。あのときFalcoがあれば、アラートは最初の1分から届いていたはずだ。
Falcoはコンテナのシステムコールをリアルタイムで追跡する——アプリのログでもCPU/RAMメトリクスでもなく、カーネルへの一つひとつの呼び出しを監視する。ハードニング設定やセキュリティのベストプラクティス(静的な状態を確認するだけのもの)とは異なり、Falcoは今まさに起きている動作を監視する:どのファイルが盗み読みされているか、どの不審なプロセスがスポーンされているか、どの外部接続が開かれているか。FalcoはCNCFのグラデュエイテッドプロジェクト——KubernetesやPrometheusと同じ成熟度レベルにある。
5分でFalcoを起動する
最も手軽な試し方は、userspace driverを使ってDockerでFalcoを実行することだ——カーネルモジュールのインストールが不要で、ローカルマシンや開発環境でのテストに適している:
# userspaceモードでFalcoを実行(カーネルモジュール不要)
docker run --rm -it \
--privileged \
-v /var/run/docker.sock:/host/var/run/docker.sock \
-v /proc:/host/proc:ro \
-v /boot:/host/boot:ro \
-v /lib/modules:/host/lib/modules:ro \
-v /usr:/host/usr:ro \
-v /etc:/host/etc:ro \
falcosecurity/falco-no-driver:latest
Starting internal webserver, listening on port 8765という行が表示されたらFalcoが起動している。別のターミナルを開いてアラートをトリガーする:
# 実行中のコンテナにシェルでアクセス — Falcoが即座に検知
docker exec -it $(docker ps -q | head -1) /bin/sh
Falcoのログがすぐに表示される:
Warning evt_type=execve user=root container.id=abc123 container.name=my-app \
proc.name=sh proc.cmdline="sh" \
rule="Terminal shell in container" \
output="A shell was spawned in a container with an attached terminal"
Falcoをホストに直接インストールしてProduction運用する
本番運用で使うなら、コンテナには入れずホストに直接Falcoをインストールすること。カーネルモジュールまたはeBPFがOSの最低レベルでシステムコールをキャプチャするため、コンテナの再起動やイメージ変更の影響を受けない。
Ubuntu / Debian
# Falcoリポジトリを追加
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | \
sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] \
https://download.falco.org/packages/deb stable main" | \
sudo tee /etc/apt/sources.list.d/falcosecurity.list
sudo apt-get update && sudo apt-get install -y falco
インストーラーがどのドライバーを使うか質問する:
- Kernel module:高速で安定している——カーネルアップグレード後に再ビルドが必要
- eBPF:より現代的でアップグレード後の再ビルドが不要。カーネル ≥ 4.14 が必要
- Modern eBPF:カーネル ≥ 5.8 なら最善の選択。モジュール不要で組み込み済み
# Falcoを有効化して起動
sudo systemctl enable --now falco
sudo systemctl status falco
# リアルタイムでログを監視
sudo journalctl -fu falco
ルール構造を理解する——検知ロジックの核心
RuleのYAMLが、Falcoが何を検知するかを正確に定義する場所だ。各ルールには4つの主要コンポーネントがある:condition(いつトリガーするか)、output(アラートの内容)、priority(深刻度)、tags(MITRE ATT&CKによる分類):
# Falcoルールの構造
- rule: Read sensitive file untrusted
desc: 信頼されていないプロセスが機密ファイルを読み取ることを検知
condition: >
sensitive_files and open_read
and not proc.name in (trusted_binaries)
and not container.image.repository in (trusted_images)
output: >
Sensitive file opened for reading
(user=%user.name command=%proc.cmdline
file=%fd.name container_id=%container.id
image=%container.image.repository)
priority: WARNING
tags: [filesystem, mitre_credential_access]
よく使われるoutput変数:
%container.id— 違反したコンテナのID%container.image.repository— 悪用されているイメージ%proc.cmdline— その時点で実行されているコマンド%fd.rip:%fd.rport— ネットワーク接続の宛先IPとポート
実際のユースケース向けにカスタムルールを作成する
Falcoのデフォルトルールはかなり汎用的だ——実際のプロダクション環境ではカスタマイズが必要になる。/etc/falco/rules.d/custom_rules.yamlを作成すると、Falcoは起動時にこのディレクトリ内の全ファイルを自動でロードする:
# ホワイトリストにないポートへのコンテナのアウトバウンド接続を検知
- rule: Unexpected outbound connection
desc: 予期しないポートへのアウトバウンド接続をコンテナが開いている
condition: >
outbound and container
and not fd.sport in (80, 443, 3306, 5432, 6379, 27017)
and not proc.name in (curl, wget, apt, pip, npm)
output: >
Unexpected outbound (container=%container.name
dest=%fd.rip:%fd.rport proto=%fd.l4proto
command=%proc.cmdline)
priority: NOTICE
# 実行中のコンテナでのパッケージインストールを検知
- rule: Package manager in running container
desc: productionコンテナでapt/yum/pipが実行されている——侵害の兆候
condition: >
spawned_process and container
and proc.name in (apt, apt-get, yum, dnf, pip, pip3, npm, yarn)
output: >
Package manager detected (command=%proc.cmdline
container=%container.name
image=%container.image.repository)
priority: ERROR
FalcosidekickでSlack通知を統合する
Falco自体はログを記録するだけだ。Slackにアラートを送りたい場合——PagerDuty、Elasticsearch、webhookなど50以上の宛先も含め——Falcosidekickが必要だ。これはFalcoからイベントを受け取って転送する軽量なサイドカーだ。Docker Composeでセットアップする:
# docker-compose.yml
services:
falco:
image: falcosecurity/falco-no-driver:latest
privileged: true
volumes:
- /var/run/docker.sock:/host/var/run/docker.sock
- /proc:/host/proc:ro
- /boot:/host/boot:ro
- /lib/modules:/host/lib/modules:ro
- /usr:/host/usr:ro
- /etc:/host/etc:ro
- ./falco.yaml:/etc/falco/falco.yaml
depends_on:
- falcosidekick
falcosidekick:
image: falcosecurity/falcosidekick:latest
environment:
- SLACK_WEBHOOKURL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
- SLACK_CHANNEL=#security-alerts
- SLACK_MINIMUMPRIORITY=warning
- CUSTOMFIELDS_ENVIRONMENT=production
- CUSTOMFIELDS_TEAM=devops
ports:
- "2801:2801"
- "2802:2802" # Web UI
次にFalcoをFalcosidekickに接続する——falco.yamlに追加する:
http_output:
enabled: true
url: "http://falcosidekick:2801/"
user_agent: "falcosecurity/falco"
json_output: true
json_include_output_property: true
# スタックを起動
docker compose up -d
# テストトリガー: コンテナにシェルアクセス → 数秒でSlackにアラートが届く
docker exec -it some-container bash
Slackでの表示はこのようになる:
[WARNING] Terminal shell in container
Container : my-webapp (id: abc123def456)
Image : nginx:latest
Command : bash
User : root
Host : prod-server-01
Time : 2024-01-15 14:32:11 UTC
実際の運用経験から学んだTips
Falcoはメモリリークを直接デバッグするわけではない——ただし、早期に症状を検知する:メモリをダンプするための不審なプロセスのスポーンや、コンテナが/tmpに異常な速度で書き込むケースなどだ。そこから根本原因をトレースバックする方が、ログを1行ずつ読むよりもはるかに早い。
Falcoをproductionでチューニングした後の実践的なポイント:
- WARNING以上のpriorityから始める:Falcoにはデフォルトルールが数百ある——フィルタなしで実行するとすぐにアラートが溢れる。まず
SLACK_MINIMUMPRIORITY=warningを設定してから、徐々に調整していく。 - 信頼できるイメージを最初からホワイトリストに登録する:社内レジストリのイメージは独自の権限が必要なことが多い。
trusted_imagesマクロを早めに作成してfalse positiveを防ぎ、チームの疲弊を避けよう。 - IDではなくコンテナ名を使う:コンテナIDは再起動のたびに変わる。
container.nameやラベルでフィルタする方がはるかに安定している。 - Falcosidekick Web UI:ポート2802のダッシュボードが非常に便利だ——リアルタイムでイベントを確認し、priorityでフィルタして、最もアラートを発生させているコンテナをすばやく特定できる。
# 最も頻繁にトリガーされているルールを確認(priorityのチューニング用)
sudo journalctl -u falco --since "1 hour ago" | \
grep -oP 'rule="[^"]+"' | sort | uniq -c | sort -rn | head -20
# Falcoのヘルスチェック
curl -s http://localhost:8765/healthz
# {"status": "healthy"}
ファイアウォールとネットワークポリシーがネットワークフローを保護する——Falcoは内側を保護する:実行中のコンテナ内の各プロセスの動作だ。コンテナ管理にPortainerを組み合わせ、ランタイムの動作監視にFalcoを使えば、高価な商用ソフトウェアなしに堅固なセキュリティレイヤーが構築できる。
