KubernetesへのFalcoのデプロイ:コンテナランタイムにおけるリアルタイム不正侵入検知

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

Kubernetesにおけるランタイムセキュリティ手法の比較

先週火曜日の午前2時15分、アラートチャンネルがオンコール担当チーム全員を叩き起こしました。攻撃者が一般向けサービスに存在したパストラバーサルの脆弱性を悪用し、非特権Podの内部で対話型bashセッションを開いて、10.244.0.0/16のPod CIDR全体に対するNmapスキャンを開始したのです。

Trivyはそのわずか2時間前にまったく同じイメージのスキャンを完了しており、クリティカルなCVEはゼロと判定していました。静的スキャンが教えてくれるのはディスク上にどんなソフトウェアの脆弱性が潜んでいるかですが、ランタイム監視は攻撃者がメモリ上で今まさに何を実行しているかを捉えます。

コンテナランタイムの防御に取り組むエンジニアリングチームは、一般的に次の3つの異なるアーキテクチャを評価します。

  • LSMおよびプロファイルの適用(AppArmor / Seccomp):コンテナのセキュリティコンテキストに静的プロファイルを直接アタッチすることで、システムコールやLinuxケーパビリティを事前に制限する手法。
  • Kubernetes監査ログ(Audit Logging):kube-apiserverのイベントをOpenSearchやDatadogにストリーミングし、コントロールプレーン全体の管理操作や変更をキャプチャする手法。
  • カーネルトレーシングエンジン(Falco / eBPF):カーネルのシステムコールに直接フックを仕掛け、プロセスの起動、ソケットの生成、ファイルシステムの書き込みなどを発生した瞬間に検査する手法。

各アプローチのトレードオフ

1. AppArmorとSeccomp

メリット:テレメトリ収集のオーバーヘッドなしでルールを強制できます。単にアラート通知を投げるだけでなく、許可されていないシステムコールをその場で完全にブロックします。

デメリット:急速に進化する80以上のマイクロサービスに対してカスタムプロファイルを管理し続けるのは、多大な開発リソースを消費します。予期せぬclone3やepoll_pwaitシステムコールを1つでもブロックしてしまうと、トラフィックスパイク時に本番Podが無言でクラッシュするリスクがあります。

2. Kubernetes監査ログの収集

メリット:完全にアウトオブバンドで動作します。ワーカーノードにエージェントによる負荷を一切かけずに、RBACの権限昇格やSecretの読み取りを確実に追跡できます。

デメリット:ワークロード内部の挙動を検知できません。攻撃者が既存のTCPソケット経由でステージングバイナリを送り込み、それを実行した場合、Kubernetesのコントロールプレーンには何も記録されません。

3. Falcoによるカーネルトレーシング(eBPF)

メリット:execve、connect、openatなどの生のシステムイベントに対してきめ細かな可視性を提供します。FalcoはすべてのイベントにNamespace、Pod名、コンテナハッシュなどのKubernetesメタデータを付加してくれます。静的なCIチェックでは予測できないゼロデイ攻撃も検知可能です。

デメリット:ノードレベルでのカーネル計測と特権デーモンアクセスが必要です。また、フィルタのチューニングが不十分な場合、ノードのメモリ使用率が急上昇する可能性があります。

推奨アーキテクチャ:Falcosidekickを組み合わせたModern eBPF DaemonSet

従来のカーネルモジュール方式はトラブルの元になりがちでした。UbuntuやAmazon Linuxの軽微なカーネルパッチ適用によって、ノードのオートスケーリング時にドライバのコンパイルが失敗したり、高負荷のI/O下でカーネルパニックを引き起こしたりすることがありました。modern eBPFプローブはこの課題を解消します。Linuxカーネル5.8以降で利用可能なBTF(BPF Type Format)およびCO-RE(Compile Once – Run Everywhere)を活用することで、ほぼ瞬時の起動、安定した計測、そしてワーカーノードあたりCPU 1.5%未満・RAM 150MB未満という予測可能なリソースフットプリントを実現します。

Falcoは各ノードでセンサーエンジンとして機能します。Falcosidekickはその横で軽量なマルチプレクサとして動作し、構造化されたセキュリティイベントをSlack、PagerDuty、あるいはセキュリティデータレイクへとルーティングします。

ランタイムエージェントをインストールする前に、ベースとなるホストアクセスが強固に保護されていることを確認してください。緊急用ルートアクセスや踏み台サーバーのセットアップには、toolcraft.app/ja/tools/security/password-generator のクライアントサイドパスワードジェネレーターで強力なノード認証情報を生成すると便利です。ネットワーク越しにエントロピーを送信することなく、ブラウザ内で完結してパスワードを計算します。基本アクセスを保護した上で、Falcoを導入して境界防御をすり抜けた脅威を確実に捕捉しましょう。

実装ガイド:Falcoのインストールとチューニング

ステップ1:FalcoのHelmリポジトリを登録

公式チャートを取得し、ローカルのインデックスキャッシュを更新します。

helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update

ステップ2:Helm Valuesの設定

falco-values.yamlを作成します。modern eBPFプローブを設定し、構造化JSON出力を有効化して、Falcosidekick経由でチームのチャンネルへアラートを送信するように設定します。

driver:
  kind: modern_ebpf

falco:
  json_output: true
  log_stderr: true
  log_level: notice
  priority: notice
  rules_file:
    - /etc/falco/falco_rules.yaml
    - /etc/falco/falco_rules.local.yaml
    - /etc/falco/rules.d

falcosidekick:
  enabled: true
  webui:
    enabled: true
  config:
    slack:
      webhookurl: "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
      minimumpriority: "warning"

ステップ3:DaemonSetのデプロイ

分離された専用のNamespaceにチャートをインストールします。

kubectl create namespace falco
helm install falco falcosecurity/falco \
  --namespace falco \
  --values falco-values.yaml

すべてのワーカーノードでプローブPodが稼働状態になっていることを確認します。

kubectl get pods -n falco -o wide

ステップ4:本番Namespace向けのターゲットルールの作成

デフォルトのコミュニティルールは、クラスタ内で起動するすべてのターミナルシェルにフラグを立てます。しかし実際には、バックグラウンドのCIランナー、サイドカーの同期スクリプト、保守ジョブなどが毎日何十件もの誤検知(フォールスポジティブ)を引き起こします。そのため、決済処理やデータベース層など、重要度の高い環境に絞って適用するのが賢明です。

custom-rules.yamlにオーバーライド設定を定義します。

customRules:
  rules-payments.yaml: |-
    - rule: 決済Namespaceにおける不正なシェル起動
      desc: paymentsワークロードの境界内でシェルプロセスが起動した際にトリガー
      condition: >
        spawned_process and
        container and
        k8s.ns.name = "payments" and
        shell_procs
      output: >
        CRITICAL: 制限されたワークロード内でシェルが起動されました
        (user=%user.name cmd=%proc.cmdline pod=%k8s.pod.name
        ns=%k8s.ns.name container=%container.name image=%container.image.repository)
      priority: CRITICAL
      tags: [container, execution, pci_dss]

Helm upgradeを使用して更新した設定を適用します。

helm upgrade falco falcosecurity/falco \
  --namespace falco \
  --reuse-values \
  -f custom-rules.yaml

ステップ5:脅威検知の動作検証

アラートパイプラインは、実際に発火するのを確認するまで決して正常に動作していると思い込んではいけません。対象のNamespace内に軽量なテストコンテナを起動し、シェルセッションを実行してみましょう。

kubectl run validation-target --image=alpine:3.19 --namespace payments -- sleep 600
kubectl exec -it validation-target --namespace payments -- /bin/sh

別のシェルウィンドウからFalcoのアクティブなログストリームを追跡します。

kubectl logs -n falco -l app.kubernetes.io/name=falco -c falco --tail=10

Falcoは15ミリ秒以内にイベントを検出し、整流化されたJSON形式で出力します。

{
  "output": "CRITICAL: 制限されたワークロード内でシェルが起動されました (user=root cmd=/bin/sh pod=validation-target ns=payments container=validation-target image=alpine:3.19)",
  "priority": "Critical",
  "rule": "決済Namespaceにおける不正なシェル起動",
  "time": "2026-10-25T02:18:12.312918451Z"
}

ステップ6:マクロの例外設定によるアラート疲弊の解消

ノイズばかり生み出すセキュリティツールは、最終的に通知をミュートされてしまいます。自動バックアップ用のCronJobが午前3時に正規のシェルスクリプトを実行するような場合でも、検知ルール自体を無効化してはいけません。特定バイナリと実行パスを除外するためのマクロフィルタを追加しましょう。

- macro: allowed_backup_executions
  condition: >
    (proc.cmdline startswith "/opt/scripts/backup.sh" and
     k8s.pod.name startswith "postgres-backup-")

- rule: 決済Namespaceにおける不正なシェル起動
  condition: >
    spawned_process and
    container and
    k8s.ns.name = "payments" and
    shell_procs and
    not allowed_backup_executions

導入後の最初の2週間は、アラートを毎日確認してください。マクロの除外範囲を適切にチューニングすることで、Falcoは単なる騒がしいログ生成ツールから、信頼性の高い超低レイテンシの不正侵入防御壁へと変貌を遂げます。

Share: