8. Transparent Encryption
Host traffic/endpoint traffic encryption
To secure communication inside a Kubernetes cluster Cilium supports transparent encryption of traffic between Cilium-managed endpoints either using IPsec or WireGuard® .
Task 8.1: Increase cluster size
By default Minikube creates single-node clusters. Add a second node to the cluster:
minikube -p cluster1 node add
Task 8.2: Move frontend app to a different node
To see traffic between nodes, we move the frontend pod from Chapter 3 to the newly created node:
Create a file patch.yaml with the follwing content_
spec:
template:
spec:
nodeSelector:
kubernetes.io/hostname: cluster1-m02 You can patch the frontend deployment now:
kubectl patch deployments.apps frontend --type merge --patch-file patch.yaml
We should see the frontend now running on the new node cluster1-m02:
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
backend-65f7c794cc-hh6pw 1/1 Running 0 22m 10.1.0.39 cluster1 <none> <none>
deathstar-6c94dcc57b-6chpk 1/1 Running 1 (10m ago) 11m 10.1.0.207 cluster1 <none> <none>
deathstar-6c94dcc57b-vtt8b 1/1 Running 0 11m 10.1.0.220 cluster1 <none> <none>
frontend-6db4b77ff6-kznfl 1/1 Running 0 35s 10.1.1.7 cluster1-m02 <none> <none>
not-frontend-8f467ccbd-4jl6z 1/1 Running 0 22m 10.1.0.115 cluster1 <none> <none>
tiefighter 1/1 Running 0 11m 10.1.0.185 cluster1 <none> <none>
xwing 1/1 Running 0 11m 10.1.0.205 cluster1 <none> <none>
Task 8.3: Sniff traffic between nodes
To check if we see unencrypted traffic between nodes we will use tcpdump.
Let us filter on the host interfce for all packets containing the string password:
CILIUM_AGENT=$(kubectl get pod -n kube-system -l k8s-app=cilium -o jsonpath="{.items[0].metadata.name}")
kubectl debug -n kube-system -i ${CILIUM_AGENT} --image=nicolaka/netshoot -- tcpdump -ni eth0 -vv | grep password
In a second terminal we will call our backend service with a password. For those using the Webshell a second Terminal can be opened using the menu Terminal then Split Terminal, also don’t forget to ssh into the VM again. Now in this second terminal run:
FRONTEND=$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}')
for i in {1..10}; do
kubectl exec -ti ${FRONTEND} -- curl -Is backend:8080?password=secret
done
You should now see our string password sniffed in the network traffic. Hit Ctrl+C to stop sniffing but keep the second terminal open.
Task 8.4: Enable node traffic encryption with WireGuard
Enabling WireGuard based encryption with Helm is simple:
helm upgrade -i cilium cilium/cilium --version 1.12.10 \
--namespace kube-system \
--set ipam.operator.clusterPoolIPv4PodCIDRList={10.1.0.0/16} \
--set cluster.name=cluster1 \
--set cluster.id=1 \
--set operator.replicas=1 \
--set upgradeCompatibility=1.11 \
--set kubeProxyReplacement=disabled \
--set hubble.enabled=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set prometheus.enabled=true \
--set operator.prometheus.enabled=true \
--set hubble.enabled=true \
--set hubble.metrics.enabled="{dns,drop:destinationContext=pod;sourceContext=pod,tcp,flow,port-distribution,icmp,http:destinationContext=pod}" \
`# enable wireguard:` \
--set l7Proxy=false \
--set encryption.enabled=true \
--set encryption.type=wireguard \
--set encryption.wireguard.userspaceFallback=true \
--wait
Afterwards restart the Cilium DaemonSet:
kubectl -n kube-system rollout restart ds cilium
Currently, L7 policy enforcement and visibility is not supported with WireGuard, this is why we have to disable it.
Task 8.5: Verify encryption is working
Verify the number of peers in encryption is 1 (this can take a while, the number is sum of nodes - 1)
kubectl -n kube-system exec -ti ds/cilium -- cilium status | grep Encryption
You should see something similar to this (in this example we have a two-node cluster):
Encryption: Wireguard [cilium_wg0 (Pubkey: XbTJd5Gnp7F8cG2Ymj6q11dBx8OtP1J5ZOAhswPiYAc=, Port: 51871, Peers: 1)]
We now check if the traffic is really encrypted, we start sniffing again:
CILIUM_AGENT=$(kubectl get pod -n kube-system -l k8s-app=cilium -o jsonpath="{.items[0].metadata.name}")
kubectl debug -n kube-system -i ${CILIUM_AGENT} --image=nicolaka/netshoot -- tcpdump -ni eth0 -vv | grep password
Now in the other terminal generate traffic:
FRONTEND=$(kubectl get pods -l app=frontend -o jsonpath='{.items[0].metadata.name}')
for i in {1..10}; do
kubectl exec -ti ${FRONTEND} -- curl -Is backend:8080?password=secret
done
As you should see the traffic is encrypted now and we can’t find our string anymore in plaintext on eth0. To sniff the traffic before it is encrypted replace the interface eth0 with the WireGuard interface cilium_wg0.
Hit Ctrl+C to stop sniffing. You can close the second terminal with exit.
Task 8.6: CleanUp
To not mess up the next ClusterMesh Lab we are going to disable WireGuard encryption again:
helm upgrade -i cilium cilium/cilium --version 1.12.10\
--namespace kube-system \
--reuse-values \
--set l7Proxy=true \
--set encryption.enabled=false \
--wait
and then restart the Cilium Daemonset:
kubectl -n kube-system rollout restart ds cilium
Verify that it is disabled again:
kubectl -n kube-system exec -ti ds/cilium -- cilium status | grep Encryption
Encryption: Disabled
remove the second node and move backend back to first node
kubectl delete -f simple-app.yaml
minikube node delete cluster1-m02 --profile cluster1
kubectl apply -f simple-app.yaml