はじめに
OpenShift上のコンテナのトラフィックを解析するにあたり、色々と模索したので備忘録として残します。
ここでは以下の2つの方法でパケットキャプチャファイルを取得し、Wiresharkでの解析を行いました。
- サイドカーコンテナー(対象のコンテナと同じPodに存在)
- ksniff
まだまだ勉強中であるため、間違い等あるかと思いますが、ご了承ください。
参考情報
- Packet capture inside Pod using community ksniff with OpenShift 4
- Network Capture on OpenShift 4 with tcpdump and ksniff
環境情報
OpenShift Container Platform 4.7
パケットキャプチャファイル取得方法1: サイドカーコンテナ
同じPod内であれば、コンテナはネットワーク的に分離されておらず、IPアドレスを共有しています。
そのため、パケットキャプチャの取得対象のコンテナに対して、パケットをサイドカーコンテナからキャプチャすることができます。
サイドカーコンテナを使用してパケットキャプチャファイルを取得するためには、それ用にイメージを自作する、もしくは、既存のパブリックなコンテナイメージを使用します。
今回は、tcpdump
コマンドなどネットワークデバッグに必要なコマンドがインストールされているnicolaka/netshootというパブリックのコンテナイメージを使用しています。
ログ
- 全文は省略しますが、yamlファイルでキャプチャしたいコンテナと合わせてサイドカーコンテナを定義します。
- ここでは、debugという名前でサイドカーコンテナを作成します。
spec:
template:
spec:
containers:
# MQ Container
- image: 'ibmcom/mq:9.2.2.0-r1'
name: qmgr
:
# Sidecar Container for tcpdump
- image: nicolaka/netshoot
name: debug
command:
- /bin/sh
- -c
- sleep 3600
:
- yamlファイルの作成など必要な準備が完了したら、Podをデプロイします。
oc process -f ./xxx.yml | oc apply -f -
- debugコンテナに
tcpdump
コマンドが存在することを確認します。
$ oc exec -it oqm1-0 -c debug -- tcpdump -h
tcpdump version 4.99.1
libpcap version 1.10.1 (with TPACKET_V3)
OpenSSL 1.1.1k 25 Mar 2021
Usage: tcpdump [-AbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count]
[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
[ -i interface ] [ --immediate-mode ] [ -j tstamptype ]
[ -M secret ] [ --number ] [ --print ] [ -Q in|out|inout ]
[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]
[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]
[ --time-stamp-precision precision ] [ --micro ] [ --nano ]
[ -z postrotate-command ] [ -Z user ] [ expression ]
- サービスアカウントの作成とSCCの付与します。
- debugコンテナはrootで動作するため
- ここでは
anyuid
のsccを持つサービスアカウントdebug
を作成する。
$ oc adm policy add-scc-to-user anyuid -z default
clusterrole.rbac.authorization.k8s.io/system:openshift:scc:anyuid added: "default"
=> Podを再起動し、適用します。
-
tcpdump
コマンドを実行してみます。
$ oc exec -it oqm1-0 -c debug -- tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel
=> これで、パケットをキャプチャできることが確認できました。
- パケットキャプチャの取得
- 対象のコンテナを動作させ、その間のパケットをキャプチャし、パケットキャプチャファイルを生成します。
$ oc exec -it oqm1-0 -c debug -- tcpdump -w /tmp/tcpdump.hb60.cap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
:(パケットキャプチャ中)
// 終了する場合には「ctl+c」
$ oc exec -it oqm1-0 -c debug -- tcpdump -w /tmp/tcpdump.hb60.cap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C
39 packets captured
39 packets received by filter
0 packets dropped by kernel
- debugコンテナにパケットキャプチャファイルが作成されていることを確認します。
$ oc exec -it oqm1-0 -c debug -- ls -l /tmp/
total 12
-rw-r--r-- 1 root root 11292 Aug 25 12:24 tcpdump.hb60.cap
- 今回は、ローカル環境のWiresharkで解析したいため、OpenShiftからローカル環境(~/Desktop)にパケットキャプチャファイルをコピーします。
$ oc cp -c debug oqm1-0:/tmp/tcpdump.hb60.cap Desktop/tcpdump.hb60.cap
tar: removing leading '/' from member names
- ローカル環境にコピーできました。
$ ls -l Desktop | grep tcp
-rw-r--r--@ 1 xxxxxxxxx staff 11292 8 25 21:26 tcpdump.hb60.cap
=> これで、Wiresharkに取り込んで、解析することができます。
パケットキャプチャファイル取得方法2: oc sniff
yamlが変更できない(サイドカーコンテナを起動できない)場合でも、パケットキャプチャをしたかったので、サイドカーコンテナ以外の方法がないかも検討しました。
Packet capture inside Pod using community ksniff with OpenShift 4で紹介されているksniffを使用すれば、サイドカーコンテナがなくてもパケットキャプチャができそうなので試してみました。
ただし、「ksniffはコミュニティプロジェクトであるため、Red Hatが直接メンテナンスしているわけではありません。何か問題が発生した場合や使い勝手について質問がある場合は、GitHubでissueを作成」とのことです。
ログ
参考情報を元にインストールしていきます。
- まず、ksniffのzipファイルをダウンロードします。
$ wget https://github.com/eldadru/ksniff/releases/download/v1.6.0/ksniff.zip
--2021-08-31 20:31:08-- https://github.com/eldadru/ksniff/releases/download/v1.6.0/ksniff.zip
github.com (github.com) をDNSに問いあわせています... 52.69.186.44
github.com (github.com)|52.69.186.44|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 302 Found
場所: https://github-releases.githubusercontent.com/137678747/1b61f880-821d-11eb-8933-e9e362793cd9?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20210831%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210831T113109Z&X-Amz-Expires=300&X-Amz-Signature=e8f12167ab7cbc40d6db9f412a8176c317dec818bd4db5ff3c3b221db6a0fb06&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=137678747&response-content-disposition=attachment%3B%20filename%3Dksniff.zip&response-content-type=application%2Foctet-stream [続く]
--2021-08-31 20:31:08-- https://github-releases.githubusercontent.com/137678747/1b61f880-821d-11eb-8933-e9e362793cd9?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20210831%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210831T113109Z&X-Amz-Expires=300&X-Amz-Signature=e8f12167ab7cbc40d6db9f412a8176c317dec818bd4db5ff3c3b221db6a0fb06&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=137678747&response-content-disposition=attachment%3B%20filename%3Dksniff.zip&response-content-type=application%2Foctet-stream
github-releases.githubusercontent.com (github-releases.githubusercontent.com) をDNSに問いあわせています... 2606:50c0:8001::154, 2606:50c0:8002::154, 2606:50c0:8003::154, ...
github-releases.githubusercontent.com (github-releases.githubusercontent.com)|2606:50c0:8001::154|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 53497723 (51M) [application/octet-stream]
`ksniff.zip' に保存中
ksniff.zip 100%[=====================================================================>] 51.02M 7.51MB/s 時間 6.3s
2021-08-31 20:31:15 (8.09 MB/s) - `ksniff.zip' へ保存完了 [53497723/53497723]
- ダウンロードしたzipファイルを
unzip
します。
$ unzip ksniff.zip
Archive: ksniff.zip
inflating: kubectl-sniff
inflating: kubectl-sniff-windows
inflating: kubectl-sniff-darwin
inflating: static-tcpdump
inflating: Makefile
inflating: plugin.yaml
inflating: LICENSE
$ mv kubectl-sniff /usr/local/bin/
$ oc plugin list
The following compatible plugins are available:
/usr/local/bin/kubectl-sniff
-
make install
コマンドでインストールします。
$ make install
mkdir -p /usr/local/bin
cp kubectl-sniff-darwin /usr/local/bin/kubectl-sniff
cp plugin.yaml /usr/local/bin
cp static-tcpdump /usr/local/bin
- これで、
oc sniff
コマンドが使用可能になりました。
$ oc sniff
Usage:
sniff pod [-n namespace] [-c container] [-f filter] [-o output-file] [-l local-tcpdump-path] [-r remote-tcpdump-path] [flags]
Examples:
kubectl sniff hello-minikube-7c77b68cff-qbvsd -c hello-minikube
Flags:
-c, --container string container (optional)
-x, --context string kubectl context to work on (optional)
-f, --filter string tcpdump filter (optional)
-h, --help help for sniff
--image string the privileged container image (optional)
-i, --interface string pod interface to packet capture (optional) (default "any")
-l, --local-tcpdump-path string local static tcpdump binary path (optional)
-n, --namespace string namespace (optional)
-o, --output-file string output file path, tcpdump output will be redirect to this file instead of wireshark (optional) ('-' stdout)
--pod-creation-timeout duration the length of time to wait for privileged pod to be created (e.g. 20s, 2m, 1h). A value of zero means the creation never times out. (default 1m0s)
-p, --privileged if specified, ksniff will deploy another pod that have privileges to attach target pod network namespace
-r, --remote-tcpdump-path string remote static tcpdump binary path (optional) (default "/tmp/static-tcpdump")
--socket string the container runtime socket path (optional)
-v, --verbose if specified, ksniff output will include debug information (optional)
- パケットキャプチャファイルを取得します。
$ oc sniff -p oqm1-0 -n xxxxxxxx -o test.pcap
INFO[0000] no container specified, taking first container we found in pod.
INFO[0000] selected container: 'qmgr'
INFO[0000] sniffing method: privileged pod
INFO[0000] sniffing on pod: 'oqm1-0' [namespace: 'xxxxxxxx', container: 'qmgr', filter: '', interface: 'any']
INFO[0000] creating privileged pod on node: '10.244.128.7'
INFO[0000] pod created: &Pod{ObjectMeta:{ksniff-bzp6p ksniff- xxxxxxxx /api/v1/namespaces/xxxxxxxx/pods/ksniff-bzp6p 14c7fcae-4095-401d-9d34-b42652b407aa 42044091
:
INFO[0000] waiting for pod successful startup
INFO[0005] pod: 'ksniff-bzp6p' created successfully on node: '10.244.128.7'
INFO[0005] executing command: '[chroot /host crictl inspect --output json f809f4e48680c26f38853f15bc5af7d2ae21c126706ae8c4c6a16de3c41cf2c8]' on container: 'ksniff-privileged', pod: 'ksniff-bzp6p', namespace: 'xxxxxxxx'
INFO[0006] command: '[chroot /host crictl inspect --output json f809f4e48680c26f38853f15bc5af7d2ae21c126706ae8c4c6a16de3c41cf2c8]' executing successfully exitCode: '0', stdErr :''
INFO[0006] output file option specified, storing output in: 'test.pcap'
INFO[0006] starting remote sniffing using privileged pod
INFO[0006] executing command: '[nsenter -n -t 193742 -- tcpdump -i any -U -w - ]' on container: 'ksniff-privileged', pod: 'ksniff-bzp6p', namespace: 'xxxxxxxx'
^C
-
oc sniff
コマンドを実行すると、専用のPodが自動作成されます。
$ oc get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ksniff-bzp6p 1/1 Running 0 21m 172.17.18.132 10.244.128.7 <none> <none>
oqm1-0 2/2 Running 156 6d11h 172.17.56.181 10.244.128.5 <none> <none>
-
oc sniff
コマンドではパケットキャプチャファイルをローカル環境に直接作成できるので、少し便利です。