UNIXドメインソケットの通信内容をダンプする方法はないかと調べていたところ eBPF(extended Berkley Packet Filter)を用いた sockdump を見つけたので eBPF の勉強も兼ねて試しました。ダンプ結果が見易くカスタマイズもしやすかったので紹介します。
- sockdump
eBPF について
次の記事が分かり易かったです。
eBPF(extended Berkley Packet Filter)は、Linuxカーネル内でのイベント発生時に動作する処理を、安全・手軽に組み込むための仕組みで、現在ではLinuxカーネルの機能として提供されています。
実行環境
$ uname -a
Linux debian11 5.10.0-21-amd64 #1 SMP Debian 5.10.162-1 (2023-01-21) x86_64 GNU/Linux
$ docker --version
Docker version 23.0.4, build f480fb1
実行
Docker の UNIXドメインソケット /run/docker.sock
をダンプします。
sockdump プロジェクトを取得。とてもシンプルなプロジェクトです。
$ git clone https://github.com/mechpen/sockdump.git
$ cd sockdump/
$ tree .
.
├── LICENSE
├── README.md
├── sockdump.py
└── wireshark
├── dummy.lua
└── wireshark.jpg
sockdump.py
を実行しダンプを開始します。実行には BCC ツールキットが必要ですが、環境によってはインストールがすんなりいかず手間取ることがあったので、ここでは BCC コンテナ quay.io/iovisor/bcc
を用います。
$ docker run -d --rm --name sockdump --privileged \
-v /sys/kernel/debug:/sys/kernel/debug:rw \
-v /lib/modules/:/lib/modules:ro \
-v /usr/src:/usr/src:ro \
-v $(pwd):/app/ \
quay.io/iovisor/bcc \
python3 /app/sockdump.py --format string --output /app/dump.log /run/docker.sock
上記は、ダンプ結果をファイル dump.log
に保存します。標準出力に出力するとその出力自体が UNIXドメインソケット /run/docker.sock
を経由しダンプされる再帰的ループに陥るためです。
次のエラーメッセージが表示される場合は多分、Linuxカーネルヘッダが存在しないことが原因です。カーネルヘッダをインストールしてください。
...
modprobe: FATAL: Module kheaders not found in directory /lib/modules/5.10.0-21-amd64
Unable to find kernel headers. Try rebuilding kernel with CONFIG_IKHEADERS=m (module) or installing the kernel development package for your running kernel version.
...
Linux カーネルヘッダをインストール
$ apt update
$ apt install -y linux-headers-$(uname -r)
※ インストール方法は、ご利用の環境により異なります。
Linux カーネルヘッダの有無を確認
$ ls -d /usr/src/*$(uname -r)
/usr/src/linux-headers-5.10.0-21-amd64
ダンプ結果ファイル dump.log
への追記をtail
コマンドで監視
$ tail -f dump.log
別のターミナルで Docker コマンドを実行
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
quay.io/iovisor/bcc latest 80f2833ca697 14 months ago 596MB
ダンプ結果
06:29:35.824 >>> process docker [27806 -> 1] path /run/docker.sock len 80(80)
HEAD /_ping HTTP/1.1
Host: docker
User-Agent: Docker-Client/23.0.4 (linux)
06:29:35.825 >>> process dockerd [2434 -> 27806] path /run/docker.sock len 316(316)
HTTP/1.1 200 OK
Api-Version: 1.42
Builder-Version: 2
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 0
Content-Type: text/plain; charset=utf-8
Docker-Experimental: false
Ostype: linux
Pragma: no-cache
Server: Docker/23.0.4 (linux)
Swarm: inactive
Date: Wed, 26 Apr 2023 06:29:35 GMT
06:29:35.825 >>> process docker [27806 -> 1] path /run/docker.sock len 91(91)
GET /v1.42/images/json HTTP/1.1
Host: docker
User-Agent: Docker-Client/23.0.4 (linux)
06:29:35.832 >>> process dockerd [2434 -> 27806] path /run/docker.sock len 559(559)
HTTP/1.1 200 OK
Api-Version: 1.42
Content-Type: application/json
Docker-Experimental: false
Ostype: linux
Server: Docker/23.0.4 (linux)
Date: Wed, 26 Apr 2023 06:29:35 GMT
Content-Length: 357
[{"Containers":-1,"Created":1645387381,"Id":"sha256:80f2833ca6972eadfb85ea2decf1151f4004ea03d239e5137f18a53a454a7862","Labels":null,"ParentId":"","RepoDigests":["quay.io/iovisor/bcc@sha256:63f8262abfa9e8fc531f23c960b27736c75d1f13fff20d9c34d3387391232dd9"],"RepoTags":["quay.io/iovisor/bcc:latest"],"SharedSize":-1,"Size":595954813,"VirtualSize":595954813}]
UNIXドメインソケット通信内容の HTTPリクエストとレスポンスを確認できました。
試しに最後の HTTPリクエスト GET /v1.42/images/json
を Curlコマンドで UNIXドメインソケットへ送信すると、同じレスポンスが返ってきました。
$ curl --unix-socket /run/docker.sock http://docker/v1.42/images/json
[{"Containers":-1,"Created":1645387381,"Id":"sha256:80f2833ca6972eadfb85ea2decf1151f4004ea03d239e5137f18a53a454a7862","Labels":null,"ParentId":"","RepoDigests":["quay.io/iovisor/bcc@sha256:63f8262abfa9e8fc531f23c960b27736c75d1f13fff20d9c34d3387391232dd9"],"RepoTags":["quay.io/iovisor/bcc:latest"],"SharedSize":-1,"Size":595954813,"VirtualSize":595954813}]
レスポンスボディの JSON をフォーマット
[
{
"Containers": -1,
"Created": 1645387381,
"Id": "sha256:80f2833ca6972eadfb85ea2decf1151f4004ea03d239e5137f18a53a454a7862",
"Labels": null,
"ParentId": "",
"RepoDigests": [
"quay.io/iovisor/bcc@sha256:63f8262abfa9e8fc531f23c960b27736c75d1f13fff20d9c34d3387391232dd9"
],
"RepoTags": [
"quay.io/iovisor/bcc:latest"
],
"SharedSize": -1,
"Size": 595954813,
"VirtualSize": 595954813
}
]
ダンプを終了
$ docker rm -f sockdump
参考文献
- BCC ツールキットのインストール手順