Ciliumサービスメッシュの相互認証と暗号化 (実装編)

執筆者 : 浜島 大介


はじめに

前回の Ciliumサービスメッシュの相互認証と暗号化 (解説編) に続く 実装編 となる。

CiliumのmTLS (相互認証と暗号化通信) を試してみる

解説編で説明したCiliumの相互認証暗号化の両機能を有効化してmTLS通信を実装する。

最初はプレーンな状態でCiliumをインストールした後に相互認証と暗号化の機能を順番に有効化してそれぞれの動作検証を行う。

Cilium自体のインストールの手順は割愛するが、現時点でのStable版 (v1.17.1) をCilium Quick Installation に従い Cilium CLI にてインストールしている。

用意した環境
今回Ciliumを試した環境の概要は以下

  • ubuntu 22.04 (kernel 5.15.0-133)
  • kubernetes v1.32.2
    • 2ノード構成
  • Cilium 1.17.1

上記環境にてノードを跨いだPod間通信の相互認証と暗号化通信を検証する。

WireGuardによる暗号化設定と動作検証

まずは暗号化の設定/動作検証を実施する。
繰り返しになるが、相互認証と暗号化の機能は独立していて両機能に依存関係性はなくどちらを先に設定しても良い。

WireGuardによる暗号化設定

暗号化の方式はより新しい WireGuardを試してみる。
- 参考URL: WireGuard Transparent Encryption

パラメーター enable-wireguard の設定

# cilium config set enable-wireguard true

上記を実施すると Cilium-Agent の再起動が行われ、仮想ネットワークインターフェース cilium_wg0 が各ノード上に追加される。
(下記実行例では No8 のインターフェース)

# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 00:50:56:23:36:03 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
3: cilium_net@cilium_host: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 16:0b:11:e1:4e:9f brd ff:ff:ff:ff:ff:ff
4: cilium_host@cilium_net: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 7e:7e:40:ac:60:02 brd ff:ff:ff:ff:ff:ff
5: cilium_vxlan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 22:5a:ad:b1:82:43 brd ff:ff:ff:ff:ff:ff
8: cilium_wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/none
10: lxc_health@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 62:b4:4e:dc:ce:c8 brd ff:ff:ff:ff:ff:ff link-netnsid 1

cilium_wg0 は WireGuardトンネルのための仮想インターフェースでありノード間通信時のパケットの流れは以下のようになる。

  • 送信側ノード
    • CiliumのeBPFプログラムが対象パケットをcilium_wg0にルーティング する
    • WireGuardのカーネルモジュールがcilium_wg0を経由したパケットを暗号化 (カプセル化) する
    • 暗号化されたパケットをUDPパケットとして物理ネットワークインターフェース から送信する
  • 受信側ノード
    • 物理ネットワークインターフェースで暗号化されたUDPパケットを受信する
    • WireGuardカーネルモジュールがパケットを復号し、cilium_wg0を通じて再度受信する
    • 復号済みのパケットをCiliumのeBPFプログラムがエンドポイント (Pod等) に転送する

WireGuardによる暗号化の動作検証

実際にノード間の通信を行って暗号化が行われているかを確認してみる。
ノード間の通信は送信側ノード (cks-node01) のPod (curl) から 受信側ノード (cks-node02) のPod (nginx) に対してcurlコマンドによるhttpリクエストを行う。


ノード状況

# kubectl get node -o wide
NAME         STATUS   ROLES           AGE    VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
cks-node01   Ready    control-plane   5d9h   v1.32.2   192.168.152.11   <none>        Ubuntu 22.04.5 LTS   5.15.0-133-generic   containerd://2.0.3
cks-node02   Ready    <none>          5d9h   v1.32.2   192.168.152.12   <none>        Ubuntu 22.04.5 LTS   5.15.0-133-generic   containerd://2.0.3


送受信用Podのマニフェストファイル
.spec.nodeName にて 異なるノードにPodを配置する

## 送信側のPod (curl)
apiVersion: v1
kind: Pod
metadata:
  name: curl
  labels:
    app: curl
spec:
  containers:
  - image: nicolaka/netshoot
    name: curl
    command: [ "sleep","infinity" ]
  nodeName: cks-node01
---
## 受信側のPod (nginx)
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - image: nginx
    name: nginx
  nodeName: cks-node02


マニフェストデプロイ後のPodの状態

# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
curl    1/1     Running   0          29s   10.0.1.120   cks-node01   <none>           <none>
nginx   1/1     Running   0          29s   10.0.0.245   cks-node02   <none>           <none>


HTTPリクエスト (curl) とパケットキャプチャの実施
送信側Podからcurl コマンドにて 受信側Pod 宛に HTTPリクエストを実施するとnginxのデフォルトページが正常に取得できる。
それと並行して受信側ノードにて tcpdump によるパケットキャプチャをトンネル用のインターフェース (cilium_wg0) と物理インターフェース (ens33) それぞれに対して行い、暗号化有無を確認する。

#  kubectl exec curl -- curl -s 10.0.0.245

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>


トンネル用インターフェース (cilium_wg0) のパケット
cilium_wg0 のパケットを確認すると暗号化は行われておらずペイロードの内容が確認できてしまう。
パケットヘッダの情報から、VXLAN (OTV) によりオーバーレイネットワーク (10.0.0.245 ⇒ 10.0.1.120) をカプセル化して物理ネットワーク (192.168.152.12 ⇒ 192.168.152.11) で転送 していることがわかる。
トンネル用インターフェースは暗号前/復号後のパケットが流れるインターフェースであり、平文のパケットが視認できるのはWireGuardとしては正しい動作となる。

# tcpdump -n -i cilium_wg0 -X
(一部抜粋)
20:56:07.034536 IP 192.168.152.12.40928 > 192.168.152.11.8472: OTV, flags [I] (0x08), overlay 0, instance 35718
IP 10.0.0.245.80 > 10.0.1.120.32840: Flags [P.], seq 239:854, ack 74, win 504, options [nop,nop,TS val 181367072 ecr 4097595796], length 615: HTTP
        0x0000:  4500 02cd ceea 0000 4011 f7cc c0a8 980c  E.......@.......
        0x0010:  c0a8 980b 9fe0 2118 02b9 0000 0800 0000  ......!.........
        0x0020:  008b 8600 5283 5271 7419 2268 e309 6c83  ....R.Rqt."h..l.
        0x0030:  0800 4500 029b 7da8 4000 4006 a448 0a00  ..E...}.@.@..H..
        0x0040:  00f5 0a00 0178 0050 8048 cdc6 ef78 5eb9  .....x.P.H...x^.
        0x0050:  72f7 8018 01f8 18fa 0000 0101 080a 0acf  r...............
        0x0060:  7120 f43c 5994 3c21 444f 4354 5950 4520  q..<Y.<!DOCTYPE.
        0x0070:  6874 6d6c 3e0a 3c68 746d 6c3e 0a3c 6865  html>.<html>.<he
        0x0080:  6164 3e0a 3c74 6974 6c65 3e57 656c 636f  ad>.<title>Welco
        0x0090:  6d65 2074 6f20 6e67 696e 7821 3c2f 7469  me.to.nginx!</ti
        0x00a0:  746c 653e 0a3c 7374 796c 653e 0a68 746d  tle>.<style>.htm
        0x00b0:  6c20 7b20 636f 6c6f 722d 7363 6865 6d65  l.{.color-scheme
        0x00c0:  3a20 6c69 6768 7420 6461 726b 3b20 7d0a  :.light.dark;.}.
        0x00d0:  626f 6479 207b 2077 6964 7468 3a20 3335  body.{.width:.35
        0x00e0:  656d 3b20 6d61 7267 696e 3a20 3020 6175  em;.margin:.0.au
        0x00f0:  746f 3b0a 666f 6e74 2d66 616d 696c 793a  to;.font-family:
        0x0100:  2054 6168 6f6d 612c 2056 6572 6461 6e61  .Tahoma,.Verdana
        0x0110:  2c20 4172 6961 6c2c 2073 616e 732d 7365  ,.Arial,.sans-se
        0x0120:  7269 663b 207d 0a3c 2f73 7479 6c65 3e0a  rif;.}.</style>.
        0x0130:  3c2f 6865 6164 3e0a 3c62 6f64 793e 0a3c  </head>.<body>.<
        0x0140:  6831 3e57 656c 636f 6d65 2074 6f20 6e67  h1>Welcome.to.ng
        0x0150:  696e 7821 3c2f 6831 3e0a 3c70 3e49 6620  inx!</h1>.<p>If.
        0x0160:  796f 7520 7365 6520 7468 6973 2070 6167  you.see.this.pag
        0x0170:  652c 2074 6865 206e 6769 6e78 2077 6562  e,.the.nginx.web
        0x0180:  2073 6572 7665 7220 6973 2073 7563 6365  .server.is.succe
        0x0190:  7373 6675 6c6c 7920 696e 7374 616c 6c65  ssfully.installe
        0x01a0:  6420 616e 640a 776f 726b 696e 672e 2046  d.and.working..F
        0x01b0:  7572 7468 6572 2063 6f6e 6669 6775 7261  urther.configura
        0x01c0:  7469 6f6e 2069 7320 7265 7175 6972 6564  tion.is.required
        0x01d0:  2e3c 2f70 3e0a 0a3c 703e 466f 7220 6f6e  .</p>..<p>For.on
        0x01e0:  6c69 6e65 2064 6f63 756d 656e 7461 7469  line.documentati
        0x01f0:  6f6e 2061 6e64 2073 7570 706f 7274 2070  on.and.support.p
        0x0200:  6c65 6173 6520 7265 6665 7220 746f 0a3c  lease.refer.to.<
        0x0210:  6120 6872 6566 3d22 6874 7470 3a2f 2f6e  a.href="http://n
        0x0220:  6769 6e78 2e6f 7267 2f22 3e6e 6769 6e78  ginx.org/">nginx
        0x0230:  2e6f 7267 3c2f 613e 2e3c 6272 2f3e 0a43  .org</a>.<br/>.C
        0x0240:  6f6d 6d65 7263 6961 6c20 7375 7070 6f72  ommercial.suppor
        0x0250:  7420 6973 2061 7661 696c 6162 6c65 2061  t.is.available.a
        0x0260:  740a 3c61 2068 7265 663d 2268 7474 703a  t.<a.href="http:
        0x0270:  2f2f 6e67 696e 782e 636f 6d2f 223e 6e67  //nginx.com/">ng
        0x0280:  696e 782e 636f 6d3c 2f61 3e2e 3c2f 703e  inx.com</a>.</p>
        0x0290:  0a0a 3c70 3e3c 656d 3e54 6861 6e6b 2079  ..<p><em>Thank.y
        0x02a0:  6f75 2066 6f72 2075 7369 6e67 206e 6769  ou.for.using.ngi
        0x02b0:  6e78 2e3c 2f65 6d3e 3c2f 703e 0a3c 2f62  nx.</em></p>.</b
        0x02c0:  6f64 793e 0a3c 2f68 746d 6c3e 0a         ody>.</html>.


物理インターフェース (ens33) のパケット
Cilium における WireGuard の物理インターフェースの通信は UDP/51871 を使用する。
パケットの内容はバイナリデータ (暗号化済) となっており、意味のある内容を確認することはできない。

# tcpdump -n -i ens33 udp port 51871 -X
(一部抜粋)
20:56:07.034616 IP 192.168.152.12.51871 > 192.168.152.11.51871: UDP, length 752
        0x0000:  4500 030c ceeb 0000 4011 f78c c0a8 980c  E.......@.......
        0x0010:  c0a8 980b ca9f ca9f 02f8 b472 0400 0000  ...........r....
        0x0020:  453d 69f8 0400 0000 0000 0000 1184 cdb9  E=i.............
        0x0030:  f7c9 9e08 365b 2c7d 0a77 9643 e781 2215  ....6[,}.w.C..".
        0x0040:  513a 75ee bf3e 8819 0a14 8ea5 149b 4794  Q:u..>........G.
        0x0050:  0ab4 d84f 7773 4658 9fa9 d212 9bbb 7534  ...OwsFX......u4
        0x0060:  3c79 f6be 5ae8 83ea cb65 ffa3 260b e2ff  <y..Z....e..&...
        0x0070:  07cd a215 81b7 5438 1022 4190 bee4 d5aa  ......T8."A.....
        0x0080:  a451 ba5a d1f8 5d1c b95c 30a3 6819 0f1b  .Q.Z..]..\0.h...
        0x0090:  e750 d45e 83d9 21fa e532 eb88 d799 570e  .P.^..!..2....W.
        0x00a0:  23cd 953c 9c39 19db 6ea3 da16 6dd0 d1d7  #..<.9..n...m...
        0x00b0:  e2cb a170 8f68 d1b3 9257 0270 9ce0 f2c5  ...p.h...W.p....
        0x00c0:  c318 0fda 13d0 0769 50a2 4fb8 2c0c 252f  .......iP.O.,.%/
        0x00d0:  a8d4 c932 8041 4850 2b7c 352d 03c5 3468  ...2.AHP+|5-..4h
        0x00e0:  74ce 66bc 9d79 19d6 9a41 f693 8620 8bbb  t.f..y...A......
        0x00f0:  4a7d 3f91 18ef 5a2c 5c4a b191 5a32 050a  J}?...Z,\J..Z2..
        0x0100:  ac1c f0df 8f27 6f62 6286 fcf3 0f0c 4058  .....'obb.....@X
        0x0110:  cc38 13df 0ffa 75f5 e76f 0462 643f 79fe  .8....u..o.bd?y.
        0x0120:  3b67 8209 cf57 8ef1 501b dd86 d562 91ec  ;g...W..P....b..
        0x0130:  fc56 a745 5df0 460a 6099 7676 5fc4 86ff  .V.E].F.`.vv_...
        0x0140:  c6b6 3a7e 1a22 d40e c611 96c9 757f 4a13  ..:~."......u.J.
        0x0150:  b411 af0d fff4 77cc f067 ed63 1dc4 67c9  ......w..g.c..g.
        0x0160:  2517 79e2 551d 6fab d690 3f94 6a5b 8883  %.y.U.o...?.j[..
        0x0170:  aafe aff7 8805 f54d 1468 c2fc 7e3d b22d  .......M.h..~=.-
        0x0180:  e771 c78d 4008 688b 65c1 2292 41f0 c3f2  .q..@.h.e.".A...
        0x0190:  f2c8 6374 4790 603c 283b 13c7 7ee3 dff3  ..ctG.`<(;..~...
        0x01a0:  28b4 b1d5 d39b b5a0 599b 9115 aafb fa92  (.......Y.......
        0x01b0:  f381 ce17 7163 4ad6 cb3b 2168 891d 228b  ....qcJ..;!h..".
        0x01c0:  b944 0808 36ee dac1 0af8 34f4 834d f1f8  .D..6.....4..M..
        0x01d0:  19ac 9d48 43a6 558f ba7c 75ee e8b2 014f  ...HC.U..|u....O
        0x01e0:  48b7 7ad9 0059 dad0 dbaa c12d c9f1 f62c  H.z..Y.....-...,
        0x01f0:  a8eb 11bb e72c 44e7 a344 f5a9 abf4 5c15  .....,D..D....\.
        0x0200:  1d7a 8e0a ce27 3288 8716 2b2a 43f1 a9ce  .z...'2...+*C...
        0x0210:  32b8 5e51 31b4 94c0 e825 3f7e 8aee 2394  2.^Q1....%?~..#.
        0x0220:  331b 6ff2 8d52 0326 2eb2 87b6 b954 d343  3.o..R.&.....T.C
        0x0230:  a7f5 edf2 b1af c706 9d2d 37df 9562 fc47  .........-7..b.G
        0x0240:  5129 c67e 2462 65b9 fd49 31d4 acd3 6fe9  Q).~$be..I1...o.
        0x0250:  51dd a352 112e 1341 c752 6164 71c0 daba  Q..R...A.Radq...
        0x0260:  e313 5910 5629 540c 0685 6460 0203 ca50  ..Y.V)T...d`...P
        0x0270:  e8ec 49fb b6c3 6f21 cefd 6936 59ce f687  ..I...o!..i6Y...
        0x0280:  2a2c 225c 35ca 5244 46f3 201b 1c31 1211  *,"\5.RDF....1..
        0x0290:  4ba9 02c7 dae3 0333 54d4 3d90 425c 97f2  K......3T.=.B\..
        0x02a0:  e01d e05a 95ec ad43 c9df 7f89 016a 6918  ...Z...C.....ji.
        0x02b0:  7d91 cd90 86d8 dabd 4cfc d7ba 2b11 b8c6  }.......L...+...
        0x02c0:  8b96 3297 438a efce 10a0 ef09 4403 2853  ..2.C.......D.(S
        0x02d0:  896a 7fe3 7f79 0040 8f33 8301 5ae3 2680  .j...y.@.3..Z.&.
        0x02e0:  570a 7efb 2d68 56c4 67b5 5e68 980d 7257  W.~.-hV.g.^h..rW
        0x02f0:  3079 add0 7480 cbf0 4382 b12e ac84 0724  0y..t...C......$
        0x0300:  4e26 a655 4219 0f80 0954 67ac            N&.UB....Tg.


以上からWireGuardによる暗号化通信は正常動作している。
なお、結果は割愛するがノード内のPod通信ではcilium_wg0は使用されず、暗号化は行われないことも併せて確認している。

相互認証の設定と動作確認

暗号化に続いて相互認証 (Mutual Authentication) の設定と動作検証を行う。
- 参考URL: Mutual Authentication

相互認証の設定

PV (Persistent Volume) 設定
Ciliumの相互認証ではIDおよび証明書を管理するためのフレームワーク SPIRE を使用する。
SPIRE の使用にあたって SPIRE-Server用のデータストレージとしてPV (Persistento Volume) の設定が事前に必要となる。
簡易設定として authentication.mutual.spire.install.server.dataStorage.enabled=false とすることでインメモリストレージを使用することもできるが、今回は Host-Path によるローカルストレージのPV設定を行う。

PVマニフェストファイル

apiVersion: v1
kind: PersistentVolume
metadata:
  name: spire-volume
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: "/mnt/data"    ## ローカルノードの /mnt/data ディレクトリをマウントして使用する


相互認証有効化

相互認証の有効化は cilium upgrade にて行う。
また、動作検証のために Cilium のログレベルを degug に変更することも併せて実施する。

cilium upgrade --version 1.17.1 --set authentication.mutual.spire.enabled=true --set authentication.mutual.spire.install.enabled=true
cilium config set debug true


SPIRE関連のPodがネームスペースcilium-spire上に新たに起動される。

# kubectl get pod -A -o wide
NAMESPACE      NAME                                 READY   STATUS    RESTARTS AGE    IP               NODE         NOMINATED NODE   READINESS GATES
cilium-spire   spire-agent-lvxlv                    1/1     Running   0        65s    192.168.152.12   cks-node02   <none>           <none>
cilium-spire   spire-agent-nl9xv                    1/1     Running   0        65s    192.168.152.11   cks-node01   <none>           <none>
cilium-spire   spire-server-0                       2/2     Running   0        65s    10.0.0.40        cks-node02   <none>           <none>
default        curl                                 1/1     Running   0        20m    10.0.1.120       cks-node01   <none>           <none>
default        nginx                                1/1     Running   0        20m    10.0.0.245       cks-node02   <none>           <none>
kube-system    cilium-envoy-cwf4l                   1/1     Running   0        5d9h   192.168.152.11   cks-node01   <none>           <none>
kube-system    cilium-envoy-ttzr6                   1/1     Running   0        5d9h   192.168.152.12   cks-node02   <none>           <none>
kube-system    cilium-gpmxn                         1/1     Running   0        58s    192.168.152.11   cks-node01   <none>           <none>
kube-system    cilium-operator-7f86c59b6f-8dsxc     1/1     Running   0        65s    192.168.152.11   cks-node01   <none>           <none>
kube-system    cilium-zfbbm                         1/1     Running   0        58s    192.168.152.12   cks-node02   <none>           <none>
kube-system    coredns-668d6bf9bc-bq94l             1/1     Running   0        5d9h   10.0.0.155       cks-node02   <none>           <none>
kube-system    coredns-668d6bf9bc-kx5s6             1/1     Running   0        5d9h   10.0.0.30        cks-node02   <none>           <none>
kube-system    etcd-cks-node01                      1/1     Running   0        5d9h   192.168.152.11   cks-node01   <none>           <none>
kube-system    kube-apiserver-cks-node01            1/1     Running   0        5d9h   192.168.152.11   cks-node01   <none>           <none>
kube-system    kube-controller-manager-cks-node01   1/1     Running   0        5d9h   192.168.152.11   cks-node01   <none>           <none>
kube-system    kube-proxy-46qks                     1/1     Running   0        5d9h   192.168.152.11   cks-node01   <none>           <none>
kube-system    kube-proxy-msvdw                     1/1     Running   0        5d9h   192.168.152.12   cks-node02   <none>           <none>
kube-system    kube-scheduler-cks-node01            1/1     Running   0        5d9h   192.168.152.11   cks-node01   <none>           <none>


ネットワークポリシー設定
相互認証を実際に動作させるには Cilium Network Policy の設定が必要となる。
Cilium Network Policy は kubernetes の Network Policy と同様にエンドポイント (主にPod) 間通信の許可する条件を定義するものであり、Cilium固有の拡張設定が行えるようになっている。

今回使用するネットワークポリシーは通信制限は設けずに 通信時には認証を行うことのみを条件とした。

Cilium Network Policy マニフェストファイル

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: allow-all-with-mtls
  namespace: default    ## "default"ネームスペースの通信が対象
spec:
  endpointSelector: {}
  ingress:
  - fromEntities:
    - all
    authentication:
      mode: "required"  ## ingress通信における 認証プロセスの実施
  egress:
  - toEntities:
    - all
    authentication:
      mode: "required"  ## egress通信における 認証プロセスの実施

上記マニフェスト内容から判るとおり、"相互" に認証を行うためには ingressegress 双方で認証を強制する必要がある。
一般的なTLS通信のように サーバ認証のみを行わせたい場合は egress のみ認証設定を行えばよい。

相互認証の動作検証

ID確認
相互認証の動作確認を行うにあたり、作成済みの送信側Pod (curl) と受信側Pod (nginx) に割り当てられているID (Cilium-ID) を確認する。
出力結果から、送信側Podは 15651, 受信側Podは 35718 であることが確認できる。

# kubectl get ciliumendpoint
NAME    SECURITY IDENTITY   ENDPOINT STATE   IPV4         IPV6
curl    15651               ready            10.0.1.120
nginx   35718               ready            10.0.0.245


HTTPリクエスト(curl)の実施
暗号化の検証時と同様にnginxのPodにcurl コマンドにてHTTPリクエストを行う。
初回通信時のみTLSハンドシェイクによる相互認証が行われるため、体感できるレベルでコマンド結果が返るまでに時間がかかった。(3秒程度)

#  time kubectl exec curl -- curl -s 10.0.0.245
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

real    0m3.125s
user    0m0.032s
sys     0m0.028s


Pod(Cilium-Agent)ログの確認
送受信ノードそれぞれのCilium-AgentのPodログを確認すると認証が正常完了している旨のログが出力されている。
(初回通信時のみ出力され、2回目以降の通信では出力されていない)


送信側ノードのログ
nginx(35718) に対しての認証 (サーバ認証) が行われている。

# kubectl -n kube-system -c cilium-agent logs cilium-gpmxn | grep "Policy is requiring authentication\|Validating Server SNI\|Validated certificate\|Successfully authenticated"
time=2025-03-08T12:21:08Z level=debug msg="Policy is requiring authentication" module=agent.controlplane.auth key="localIdentity=15651, remoteIdentity=35718, remoteNodeID=10153, authType=spire"
time=2025-03-08T12:21:08Z level=debug msg="Validating Server SNI" module=agent.controlplane.auth SNI_ID=35718
time=2025-03-08T12:21:08Z level=debug msg="Validated certificate" module=agent.controlplane.auth uri-san=[spiffe://spiffe.cilium/identity/35718]
time=2025-03-08T12:21:08Z level=debug msg="Successfully authenticated" module=agent.controlplane.auth key="localIdentity=15651, remoteIdentity=35718, remoteNodeID=10153, authType=spire" remote_node_ip=192.168.152.12


受信側ノードのログ
curl(15651) に対しての認証 (クライアント認証) が行われている。

# kubectl -n kube-system -c cilium-agent logs cilium-zfbbm | grep "Policy is requiring authentication\|Validating Server SNI\|Validated certificate\|Successfully authenticated"
time=2025-03-08T12:21:09Z level=debug msg="Policy is requiring authentication" module=agent.controlplane.auth key="localIdentity=35718, remoteIdentity=15651, remoteNodeID=16144, authType=spire"
time=2025-03-08T12:21:09Z level=debug msg="Validating Server SNI" module=agent.controlplane.auth SNI_ID=15651
time=2025-03-08T12:21:09Z level=debug msg="Validated certificate" module=agent.controlplane.auth uri-san=[spiffe://spiffe.cilium/identity/15651]
time=2025-03-08T12:21:09Z level=debug msg="Successfully authenticated" module=agent.controlplane.auth key="localIdentity=35718, remoteIdentity=15651, remoteNodeID=16144, authType=spire" remote_node_ip=10.0.1.237

以上から相互認証 (Mutual Authentication) も正常動作している。

まとめ

暗号化と相互認証の機能を併用することで mTLS通信が実現できていることが検証できた。