前言
在k8s 中对 Pod 进行抓包一文中,通过找 veth 网卡方式进行抓包。还有另一个更强大命令同样可以达到抓包的目的。
简介
nsenter
是一个可以进入到其他进程的命名空间(Namespace)的程序。
比如进入到一个不含网络调试工具的容器的 Network 命名空间中,使用宿主机的进行各种调试命令甚至抓包工具对这个 Network Namespace 进行操作,从而达到对这个容器的网络调试。nsenter
还可以进入 Mount、UTS、IPC、PID、User 等命名空间,以及指定根目录和工作目录。
nsenter
命令位于 util-linux 软件包中。
基本用法
Usage:
nsenter [options] [<program> [<argument>...]]
Run a program with namespaces of other processes.
Options:
-a, --all 进入所有命名空间
-t, --target <pid> 从目标进程获取命名空间
-m, --mount[=<file>] 进入 mount 命名空间
-u, --uts[=<file>] 进入 UTS 命名空间(主机名等)
-i, --ipc[=<file>] 进入 System V IPC 命名空间
-n, --net[=<file>] 进入 network 命名空间
-p, --pid[=<file>] 进入 pid 命名空间
-C, --cgroup[=<file>] 进入 cgroup 命名空间
-U, --user[=<file>] 进入 user 命名空间
-S, --setuid <uid> 进入命名空间时设置 uid
-G, --setgid <gid> 进入命名空间时设置 gid
--preserve-credentials 不更改 uid 或 gid
-r, --root[=<dir>] 设置根目录
-w, --wd[=<dir>] 设置工作目录
-F, --no-fork 在执行<程序>之前不创建子进程
-Z, --follow-context 根据目标 PID 设置 SELinux 上下文
示例用法
比如在 Kubernetes 的 default 命名空间下存在一个 busybox 容器,使用nsenter
进入到 Network Namespace 中进行抓包。
pod 信息如下:
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 59s 10.104.157.89 k8s-node01 <none> <none>
获取容器的 containerID:
# kubectl get pods busybox -o yaml | grep -i " containerid"
- containerID: containerd://c6ebc5c1b3dae94ef81fe40607a853d8f7fd35f8db886ea7b3788a5d776c6815
找到 containerID 后,登录到容器的宿主机(k8s-node01)上,查看 busybox 容器的 PID:
# ctr -n k8s.io tasks ls | grep c6ebc5c1b3dae94ef81fe40607a853d8f7fd35f8db886ea7b3788a5d776c6815
c6ebc5c1b3dae94ef81fe40607a853d8f7fd35f8db886ea7b3788a5d776c6815 3224184 RUNNING
查看到 PID 是 3224184 后,使用nsenter
进入到 busybox 的 Network 命名空间中:
nsenter -n -t 3224184
此时查看 IP 已不再是宿主机的 IP,而是 busybox 的 IP:
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: eth0@if463: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1480 qdisc noqueue state UP group default qlen 1000
link/ether 16:67:cd:1f:5b:74 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.104.157.89/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::1467:cdff:fe1f:5b74/64 scope link
valid_lft forever preferred_lft forever
#
# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1480
inet 10.104.157.89 netmask 255.255.255.255 broadcast 0.0.0.0
inet6 fe80::1467:cdff:fe1f:5b74 prefixlen 64 scopeid 0x20<link>
ether 16:67:cd:1f:5b:74 txqueuelen 1000 (Ethernet)
RX packets 5 bytes 446 (446.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 13 bytes 1006 (1006.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
现在就可以通过宿主机的 tcpdump 命令对这个命名空间进行抓包:
tcpdump -i eth0 -vv -w /tmp/busybox.cap
操作完后,执行exit
命令就可以退出这个 Network 命名空间:
# exit
logout
退出回到宿主机的命名空间后便可以使用scp
等工具把/tmp/busybox.cap 这个文件拷贝出来,利用 wireshark 分析。