找出哪个网络接口属于 docker 容器

Find out which network interface belongs to docker container

Docker 创建 ifconfig 中列出的这些虚拟以太网接口 veth[UNIQUE ID]。我如何找出哪个接口属于特定的 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


关于神秘 iflink 的参考来自 http://lxr.free-electrons.com/source/Documentation/ABI/testing/sysfs-class-net:

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.

根据提供的答案(对我有用),我制作了这个简单的 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

我的回答更像是对该重要主题的改进,因为它无助于“找出哪个网络接口属于 docker 容器”,但是,作为作者注意到,他“想监听 docker 容器内的 tcp 流量 ” - 我会在您对网络进行故障排除时尽力提供帮助。

考虑到 veth network devices are about network namespaces, it is useful to know that we can execute program in another namespace via nsenter 工具如下(记住 - 您需要特权权限 (sudo/root) 才能这样做):

获取您对捕获流量感兴趣的任何容器的 ID,例如它将是 78334270b8f8

然后我们需要获取该容器化应用程序的 PID(我假设您 运行 在容器内只有 1 个与网络相关的进程并希望捕获其流量。否则,该方法是很难合适):

sudo docker inspect 78334270b8f8 | grep -i pid

例如,pid 的输出将是 111380 - 这是容器化应用程序的 ID,您也可以通过 ps 命令检查它:ps aux | grep 111380 就在好奇.

下一步是检查容器中有哪些网络接口:

sudo nsenter -t 111380 -n ifconfig

此命令将 return 您在容器化应用程序的网络命名空间中列出网络设备(您的容器不应该有 ifconfig 工具,只能在您的 node/machine )

例如,您需要使用以下命令捕获接口 eth2 上的流量并将其过滤到 tcp 目标端口 80(当然可能有所不同):

sudo nsenter -t 111380 -n tcpdump -nni eth2 -w nginx_tcpdump_test.pcap 'tcp dst port 80'

请记住,在这种情况下,您不需要在容器中安装 tcpdump 工具。

然后,在捕获数据包后,.pcap 文件将在您的 machine/node 上可用,并使用您喜欢的任何工具读取它 tcpdump -r nginx_tcpdump_test.pcap

方法的优点:

  • 容器内不需要网络工具,只在docker节点上
  • 无需在容器和节点中搜索网络设备之间的映射

缺点:

  • 您需要拥有 node/machine 到 运行 nsenter 工具
  • 的特权用户

来自@pbaranski 的解决方案的一行

num=$(docker exec -i my-container cat /sys/class/net/eth0/iflink | tr -d '\r'); ip ad | grep -oE "^${num}: veth[^@]+" | awk '{print }'

如果您需要在不包含 cat 的容器上查找,请尝试使用此工具:https://github.com/micahculpepper/dockerveth

您还可以通过 /proc/PID/net/igmp 读取接口名称,例如(容器名称作为参数 1):

#!/bin/bash

NAME=
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.*//p")
    echo -e "$NAME\t$iface\t$veth"
done < <(</proc/$PID/net/igmp awk '/^[0-9]+/{print  " " ;}')