우리는 한다, 개발을.

kubernetes sniff로 패킷 캡쳐하기

⌛ 3 mins

유니서베이 GS인증을 준비하면서 TLS가 정상 작동되는 지 증명이 필요했습니다.

업체에서는 tcpdump등으로 패킷을 캡쳐해서 확인하면 된다고 해서 백앤드 파드에 접근해서 tcpdump를 뜨면 되겠거니 했습니다.

tcpdump를 파드 컨테이너에 직접 접근해 설치하고 dump를 떴지만 파드에는 http로만 전달되고 있었습니다.

유니서베이는 ingress-NGINX controller를 설치해서 운영 중이라

ingress에 https로 전달되고 있었고 ingress nginx controller에서 패킷을 캡쳐해야 했습니다.

# kubectl -n=ingress-nginx get pods

NAME                                        READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-568764d844-925wd   1/1     Running   0          90d

백앤드 파드와 마찬가지로 controller 파드에 tcpdump를 설치하고 dump를 뜨면 된다고 생각했습니다.

하지만 controller 파드에 tcpdump 자체가 설치가 되질 않았습니다. 권한이 없었기 때문입니다.

ingress nginx controller는 linux alpine 기반으로 동작하고 있었고, apk add를 수행할 권한이 없었습니다.

그래서 tcpdump를 설치할 수 있는 다른 방법을 찾아보았습니다.

ksniff

Kubernetes 클러스터의 모든 포드에서 원격 캡처를 시작하기 위해 tcpdump 및 Wireshark를 활용하는 kubectl 플러그인입니다.

ksniff 플러그인을 이용하면 tcpdump를 쉽게 수행할 수 있다는군요.

k8s에서 플러그인 설치는 처음이라 우선 kubectl krew를 설치했습니다.

krew 설치 시 관리자 권한과 context 설정이 필요합니다. 이번 포스트에선 생략하겠습니다.

# kubectl krew install sniff

krew 설치를 하게되면 이제 krew를 통해 설치가 가능합니다.

이제 거의 다 왔습니다.

# kubectl sniff -n=ingress-nginx ingress-nginx-controller-568764d844-925wd -p -f "tcp port 443" -o ingress.pcap

위와 같이 실행하면 ingress-nginx-controller-568764d844-925wd 파드에서 443 포트로 들어오는 패킷을 ingress.pcap 파일로 저장합니다.

time="2023-07-24T19:18:45+09:00" level=info msg="no container specified, taking first container we found in pod."
time="2023-07-24T19:18:45+09:00" level=info msg="selected container: 'controller'"
time="2023-07-24T19:18:45+09:00" level=info msg="sniffing method: privileged pod"
time="2023-07-24T19:18:45+09:00" level=info msg="sniffing on pod: 'ingress-nginx-controller-568764d844-925wd' [namespace: 'ingress-nginx', container: 'controller', filter: 'tcp port 443', interface: 'any']"
time="2023-07-24T19:18:45+09:00" level=info msg="creating privileged pod on node: 'apps-w-2p6r'"
time="2023-07-24T19:18:45+09:00" level=info msg="pod: 'ksniff-lr7z4' created successfully in namespace: 'ingress-nginx'"
time="2023-07-24T19:18:45+09:00" level=info msg="waiting for pod successful startup"
time="2023-07-24T19:18:48+09:00" level=info msg="pod: 'ksniff-lr7z4' created successfully on node: 'apps-w-2p6r'"
time="2023-07-24T19:18:48+09:00" level=info msg="output file option specified, storing output in: 'ingress.pcap'"
time="2023-07-24T19:18:48+09:00" level=info msg="starting remote sniffing using privileged pod"
time="2023-07-24T19:18:48+09:00" level=info msg="executing command: '[/bin/sh -c \n    set -ex\n    export CONTAINERD_SOCKET=\"/run/containerd/containerd.sock\"\n    export CONTAINERD_NAMESPACE=\"k8s.io\"\n    export CONTAINER_RUNTIME_ENDPOINT=\"unix:///host${CONTAINERD_SOCKET}\"\n    export IMAGE_SERVICE_ENDPO
INT=${CONTAINER_RUNTIME_ENDPOINT}\n    crictl pull docker.io/maintained/tcpdump:latest >/dev/null\n    netns=$(crictl inspect dbf5dc62cf7e732a40061cc12b7a899dcd2b330c72cebfbf3f0fb4bc338c7038 | jq '.info.runtimeSpec.linux.namespaces[] | select(.type == \"network\") | .path' | tr -d '\"')\n    exec chroot /host c
tr -a ${CONTAINERD_SOCKET} run --rm --with-ns \"network:${netns}\" docker.io/maintained/tcpdump:latest ksniff-container-hZjHlHJb tcpdump -i any -U -w - tcp port 443 \n    ]' on container: 'ksniff-privileged', pod: 'ksniff-lr7z4', namespace: 'ingress-nginx'"

캡쳐를 어느정도 수행했다고 생각이 되면 ctrl+ c로 종료합니다.

로컬 디렉토리에 ingress.pcap으로 저장이 잘 되었습니다.

NAME                                        READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-568764d844-925wd   1/1     Running   0          90d
ksniff-gzvv2                                1/1     Running   0          13m

ksniff를 수행하면 파드가 생성이 됩니다. 캡쳐가 끝난 파드는 삭제해주시면 됩니다.

참고문서

https://kmaster.tistory.com/105
https://waspro.tistory.com/765
https://jerryljh.tistory.com/58
https://medium.com/codex/capture-tcpdump-with-ksniff-and-wireshark-from-kubernetes-c212b93ff9f9