Docker创建这些虚拟以太网接口veth[唯一标识符]
,列在ifconfig
中。我该如何找出哪个接口属于特定的Docker容器?
我想监听TCP流量。
Docker创建这些虚拟以太网接口veth[唯一标识符]
,列在ifconfig
中。我该如何找出哪个接口属于特定的Docker容器?
我想监听TCP流量。
定位接口
在我的情况下,从容器中获取值的方式是这样的(请检查eth0
):
$ docker exec -it my-container cat /sys/class/net/eth1/iflink
123
然后:
$ ip ad | grep 123
123: vethd3234u4@if122: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default
使用tcpdump -i vethd3234u4
命令进行检查。
http://lxr.free-electrons.com/source/Documentation/ABI/testing/sysfs-class-net中有关神秘的iflink
的参考信息:
150 What: /sys/class/net/<iface>/iflink
151 Date: April 2005
152 KernelVersion: 2.6.12
153 Contact: netdev@vger.kernel.org
154 Description:
155 Indicates the system-wide interface unique index identifier a
156 the interface is linked to. Format is decimal. This attribute is
157 used to resolve interfaces chaining, linking and stacking.
158 Physical interfaces have the same 'ifindex' and 'iflink' values.
ip addr show | grep 63293
没有返回任何结果,那么值得检查一下63292和63294周围的接口。 - Sysanin根据提供的答案(对我有效),我编写了这个简单的bash脚本:
#!/bin/bash
export containers=$(sudo docker ps --format "{{.ID}}|{{.Names}}")
export interfaces=$(sudo ip ad);
for x in $containers
do
export name=$(echo "$x" |cut -d '|' -f 2);
export id=$(echo "$x"|cut -d '|' -f 1)
export ifaceNum="$(echo $(sudo docker exec -it "$id" cat /sys/class/net/eth0/iflink) | sed s/[^0-9]*//g):"
export ifaceStr=$( echo "$interfaces" | grep $ifaceNum | cut -d ':' -f 2 | cut -d '@' -f 1);
echo -e "$name: $ifaceStr";
done
78334270b8f8
然后我们需要获取该容器化应用程序的PID
(我假设您只运行了一个与网络相关的进程,并且想要捕获其流量。否则,该方法很难适用):
sudo docker inspect 78334270b8f8 | grep -i pid
例如,pid
的输出将是 111380
- 这是您容器化应用程序的 ID,您还可以通过 ps
命令检查它:ps aux | grep 111380
,只是出于好奇。
下一步是检查您在容器内拥有哪些网络接口:
sudo nsenter -t 111380 -n ifconfig
此命令将返回容器化应用程序的网络命名空间中的网络设备列表(您不应该在容器中安装 ifconfig
工具,只需在节点/机器上安装即可)
例如,您需要在接口 eth2
上捕获流量,并使用以下命令过滤到 tcp 目标端口 80(当然可能会有所不同):
sudo nsenter -t 111380 -n tcpdump -nni eth2 -w nginx_tcpdump_test.pcap 'tcp dst port 80'
请记住,在这种情况下,您不需要在容器内安装 tcpdump
工具。
.pcap
文件将可在您的机器/节点上使用,您可以使用任何您喜欢的工具来读取它:tcpdump -r nginx_tcpdump_test.pcap
方法的优点:
nsenter
工具docker inspect <id> --format '{{.State.Pid}}'
而不是使用 grep。 - Dave@pbaranski的解决方案一句话概括:
num=$(docker exec -i my-container cat /sys/class/net/eth0/iflink | tr -d '\r'); ip ad | grep -oE "^${num}: veth[^@]+" | awk '{print $2}'
如果您需要在不包含cat
命令的容器上查找信息,则可以尝试使用此工具:https://github.com/micahculpepper/dockerveth
#!/bin/bash
NAME=$1
PID=$(docker inspect $NAME --format "{{.State.Pid}}")
while read iface id; do
[[ "$iface" == lo ]] && continue
veth=$(ip -br addr | sed -nre "s/(veth.*)@if$id.*/\1/p")
echo -e "$NAME\t$iface\t$veth"
done < <(</proc/$PID/net/igmp awk '/^[0-9]+/{print $2 " " $1;}')
eth0
变成eth1
、eth2
等。#!/bin/bash
export containers=$(sudo docker ps --format "{{.ID}}|{{.Names}}")
export interfaces=$(sudo ip ad);
for x in $containers
do
export name=$(echo "$x" |cut -d '|' -f 2);
export id=$(echo "$x"|cut -d '|' -f 1)
export ethNum="$(echo $(sudo docker exec -it "$id" ls /sys/class/net) | grep -oP 'eth[0-9]')"
export ifaceNum="$(echo $(sudo docker exec -it "$id" cat /sys/class/net/$ethNum/iflink) | sed s/[^0-9]*//g):"
export ifaceStr=$( echo "$interfaces" | grep $ifaceNum | cut -d ':' -f 2 | cut -d '@' -f 1);
echo -e "$name: $ifaceStr";
done