【入門編】 KubernetesにおけるPod間通信の暗号化とネットワークポリシー – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

こんにちは!セキュリティの世界へようこそ。

今回は、近年多くのシステムで導入されている「Kubernetes(クーバネティス、以下K8s)」のセキュリティについて、初心者の方にも分かりやすく解説していきます。

「K8sって便利だけど、セキュリティの設定はどうすればいいの?」
「サービスメッシュやネットワークポリシーって難しそう…」

そんな不安を抱えている方も多いのではないでしょうか。今回は、難しい専門用語を「家の防犯や泥棒対策」に例えながら、一歩ずつ丁寧に紐解いていきます。安全なシステムを構築するための第一歩を、一緒に踏み出しましょう!

—

1. 初期状態のKubernetesは「仕切りのないシェアハウス」?

まず、K8sのデフォルト(初期状態)がどのようなネットワーク環境なのか、イメージから理解していきましょう。

K8sの内部では、「Pod(ポッド)」と呼ばれる小さなコンテナ(アプリが動く部屋のようなもの)が複数動いています。実は、初期状態のK8sは、「すべての部屋のドアが開いていて、廊下を通れば誰でもどの部屋にも自由に行き来できるシェアハウス」のような状態なのです。

もし、このシェアハウスに1人でも怪しい人(乗っ取られたコンテナ)が紛れ込んでしまったらどうなるでしょうか?
その「泥棒」は、何の遮りもなく隣の部屋(データベースや個人情報を扱うPod)に侵入し、データを盗み放題になってしまいます。

攻撃者はこの「仕切りのなさ」を突き、1つの脆弱性からシステム全体へ被害を広げていきます(これを専門用語で「ラテラルムーブメント(横展開)」と呼びます)。

これを防ぐための2大防犯対策が、今回ご紹介する「通信の暗号化(mTLS)」と「ネットワークポリシー(Default Deny)」です。

—

2. 対策①:通信の暗号化(mTLS)で「盗聴」を防ぐ

まずは、部屋同士のやり取り(通信)を守る対策です。

泥棒は「糸電話」を盗み聞きしている?

初期状態のPod同士の通信は、暗号化されていない「平文(ひらぶん)」で行われることが多いです。これは、まるで「廊下で糸電話を使って内緒話をしている」ようなもの。廊下にいる泥棒(悪意あるPod)には、会話の内容が丸聞こえです。

ここで登場するのが、Istio(イスティオ)などの「サービスメッシュ」と呼ばれる仕組みが提供する「mTLS(相互TLS)」です。

mTLSは「お互いに身分を証明し、解読できない暗号ボックスで手紙を渡す」仕組み

mTLSを導入すると、通信は以下のように変わります。

1. お互いの身元確認: 通信するPod同士が「私は本物のWebアプリです」「私は本物のデータベースです」と、お互いの「身分証明書(クライアント証明書)」を見せ合います。
2. 暗号化: 会話の内容はすべて、高度な暗号でカギがかけられた箱に入れられて送られます。万が一、廊下で泥棒に箱を盗まれても、カギ(秘密鍵)を持っていない泥棒には箱を開けることができません。

実践!IstioでmTLSを強制する設定例

それでは、実際のK8s環境で「このエリアの通信はすべてmTLS(暗号化)を必須にする!」と宣言する設定(YAMLファイル)を見てみましょう。

以下の設定ファイルを適用することで、指定した名前空間(my-secure-namespace)の中の通信がすべて暗号化されます。

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: my-secure-namespace # 対策を適用したいエリア(名前空間)を指定します
spec:
  mtls:
    mode: STRICT # 「STRICT(厳格)」にすることで、暗号化されていない通信を一切禁止します!

この設定を1枚入れるだけで、エリア内の糸電話はすべて「頑丈な暗号ボックス」へと早変わりします。

—

3. 対策②:ネットワークポリシーで「勝手な立ち入り」を防ぐ

通信を暗号化して盗聴を防いだら、次は「誰がどの部屋に入ってよいか」というルール(立ち入り制限)を決めましょう。

ゼロトラストの基本は「Default Deny(デフォルト拒否)」

防犯の基本は、「基本的に全員立ち入り禁止。許可された人だけが鍵を開けて入れる」という状態にすることです。これをセキュリティの世界では「Default Deny(デフォルト・デニー)」と呼びます。

「何も設定していない状態」が「全員ウェルカム」なら、「Default Deny」は「全てのドアに頑丈な自動ロック付きの鍵をかけ、誰も通れなくした状態」です。この状態を作った上で、「Webアプリからデータベースへの移動だけを許可する」というように、必要なルートだけを1つずつ開通させていきます。

実践!「まずは全員立ち入り禁止」にする設定

まずは、対象のエリアの通信をすべてシャットアウトする「Default Deny」の設定サンプルです。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: my-secure-namespace # 対象のエリア(名前空間)
spec:
  podSelector: {} # 空っぽ「{}」にすることで、このエリア内の「すべてのPod」を対象にします
  policyTypes:
  - Ingress # 入ってくる通信(インバレス)を制限対象にします
  - Egress  # 出ていく通信(エグレス)を制限対象にします
  # ingress と egress の具体的な許可ルール(fromやto)を何も書かないことで、
  # 「すべて拒否(Deny)」という状態を作り出します。

実践!「必要な通信だけを通す」許可の設定

すべてのドアに鍵をかけたら、今度は「Webアプリ(frontend)」から「データベース(backend)」への通信だけを特別に許可してみましょう。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: my-secure-namespace
spec:
  # 【対象の部屋】このルールを適用する宛先(今回はbackend)を指定します
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress # 入ってくる通信のルールを定義します
  ingress:
  # 【鍵を開ける条件】どこの部屋からの通信なら入れてあげるかを指定します
  - from:
    - podSelector:
        matchLabels:
          app: frontend # 「frontend」という名札(ラベル)がついたPodからの通信だけを通します!
    # 【通すポート番号】データベースが使っている特定のポート(例: 5432)だけを通します
    ports:
    - protocol: TCP
      port: 5432

このように、「基本は全員立ち入り禁止(Default Deny)」にしつつ、「必要なルートだけをピンポイントで開ける」というアプローチをとることで、もしどこか1つのPodが泥棒に乗っ取られても、そこから他の部屋へ被害が拡大するのを防ぐことができます。

—

4. まとめ:一歩ずつ進める安全なネットワーク作り

最後に、今回学んだ防犯対策をおさらいしてみましょう。

| 防犯の課題 | 現実世界での例え | Kubernetesでの対策技術 |
| :— | :— | :— |
| 通信を盗み聞きされる | 廊下での糸電話 | mTLS(相互TLS)による通信の暗号化 |
| 誰でも自由に移動できる | 全員の部屋のドアが開いている | NetworkPolicy(Default Deny)による立ち入り制限 |

セキュリティ対策は、一度にすべてを完璧にやろうとすると難しく感じてしまうものです。まずは、

1. 「Default Deny」で全体の鍵を閉める
2. 必要な通信だけを少しずつ「NetworkPolicy」で許可していく
3. 大事な通信は「Istio」などのmTLSで暗号化する

というように、身近な防犯対策と同じように、できるところから一歩ずつ進めていきましょう!

あなたの開発するシステムが、より安全で素敵なものになりますように。これからも一緒に、セキュリティの知識を深めていきましょうね!

コメント

タイトルとURLをコピーしました