在Docker容器中tcpdump抓包探秘Traceroute

在上一篇文章《通过Wireshark重新认识Traceroute》中,我在MAC电脑上进行抓包来对MAC上的Traceroute过程进行分析。但是MAC电脑上运行了多个应用,我在抓完报文后,使用过滤器将其他报文过滤掉了,但是也很可能把Traceroute产生的报文给删掉了。

为了打造一个纯净的Traceroute环境,我又使用容器来做一次测试。

本文记录以下内容:

  1. 创建一个包含traceroute、ping、whois等工具的容器,取名traceroute
  2. 创建一个只包含tcpdump的容器,对traceroute容器抓包
  3. 简略的分析抓包文件----不是本文重点

创建Traceroute容器镜像

Dockerfile准备

如果我们执行docker run -it ubuntu,想在该容器中执行ping、traceroute命令,抱歉,找不到该命令。

➜  docker pull ubuntu
➜  docker run -it --rm ubuntu
root@631c227046f7:/# ping 8.8.8.8
bash: ping: command not found
root@631c227046f7:/# traceroute 8.8.8.8
bash: traceroute: command not found
root@631c227046f7:/#

这时候,您可以直接在容器里执行:

root@631c227046f7:/# apt-get update && apt-get install traceroute iputils-ping --no-install-recommends

当然,您也可以创建一个容器镜像,如下:

mkdir traceroute
cd traceroute
touch Dockerfile

Dockerfile 内容如下:

FROM ubuntu:latest

RUN apt-get update && apt-get install -y \
    traceroute \
    iputils-ping \
    whois \
    netbase \
    iproute2 \
    --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

注:上述要安装的软件包,是我经过尝试后,一个个增加的。

  1. 最开始我只安装了traceroute,当我执行traceroute -A 8.8.8.8时,提示如下错误信息:

    whois.radb.net/nicname: Servname not supported for ai_socktype
    
  2. 我想起traceroute可能需要调用whois来查询BGP AS号,于是我继续安装whois,仍然报错。----经过验证,如果不安装whois软件包,traceroute -A 8.8.8.8 可正常工作。

  3. 只能在网上搜索答案了,果然有人遇到过类似问题:

    https://stackoverflow.com/questions/56430294/bash-script-that-uses-whois-command-gets-servname-not-supported-error-on-do
    解决办法:
    apt-get update && apt-get install -y --no-install-recommends netbase
    
  4. 安装iproute2的目的是为了执行ip a, ip link 这些命令。

根据Dockerfile创建容器镜像

根据上述的Dockerfile创建容器镜像,执行命令:docker image build -t traceroute:latest . 注意末尾的小点,表示当前目录。

➜  traceroute docker image build -t traceroute:latest .
[+] Building 48.7s (6/6) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 274B                                                                               0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                   0.0s
 => CACHED [1/2] FROM docker.io/library/ubuntu:latest                                                              0.0s
 => [2/2] RUN apt-get update && apt-get install -y  traceroute  iputils-ping  whois  netbase  iproute2  --no-ins  48.5s
 => exporting to image                                                                                             0.1s
 => => exporting layers                                                                                            0.1s
 => => writing image sha256:bbf499e59136872e8d171fddcd1548497a9e76b96d154dcb340b8326252d97d5                       0.0s
 => => naming to docker.io/library/traceroute:latest                                                               0.0s
 
➜  traceroute docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
traceroute   latest    bbf499e59136   5 seconds ago    77.4MB

如何抓取容器的网络报文

接下来,需要考虑的问题是在MAC电脑上如何抓取容器的网络报文呢?

Wireshark on macOS如何抓包?

我执行了docker run -it --name traceroute traceroute 启动了一个名为tracertoute的容器,打开Wireshark,哪一个接口对应的是这个容器的接口呢?

wireshark-int-list

上面的接口眼花缭乱的,找不出是哪一个接口,en0和lo0上有流量,但是并不是容器连接的端口,只得寻求其他方法。

基于 Container 网络共享机制来抓包

通过搜索"how to tcpdump in docker",找到一篇文章How to TCPdump effectively in Docker,获益匪浅。

该文章介绍了一种Docker的网络模式,container模式。

In the --net=container:id all traffic in/out a specific container (or group of containers) can be captured.

另一篇文章:https://www.freeaihub.com/article/container-module-in-docker-network.html

Docker网络container模式是指,创建新容器的时候,通过--net container参数,指定其和已经存在的某个容器共享一个 Network Namespace。如下图所示,右方黄色新创建的container,其网卡共享左边容器。因此就不会拥有自己独立的 IP,而是共享左边容器的 IP 172.17.0.2,端口范围等网络资源,两个容器的进程通过 lo 网卡设备通信。

但这两个容器在其他的资源上,如文件系统、进程列表等还是隔离的。

专门创建一个安装了tcpdump的容器,对上文创建的traceroute容器进行抓包。

参考How to TCPdump effectively in Docker,在Terminal中执行以下命令,创建一个tcpdump的容器镜像

docker build -t tcpdump - <<EOF 
FROM ubuntu 
RUN apt-get update && apt-get install -y tcpdump 
CMD tcpdump -i eth0 -w /var/traceroute-ubuntu.pcapng
EOF

创建过程如下:

[+] Building 0.1s (6/6) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 159B                                                                               0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                   0.0s
 => [1/2] FROM docker.io/library/ubuntu                                                                            0.0s
 => CACHED [2/2] RUN apt-get update && apt-get install -y tcpdump                                                  0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:d5d8942d4836fabbb0343a082d9aa0009c6dd5071c70a54ae57baf6728462562                       0.0s
 => => naming to docker.io/library/tcpdump                                                                         0.0s

镜像列表:

➜  traceroute docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
tcpdump      latest    d5d8942d4836   3 minutes ago    109MB
traceroute   latest    bbf499e59136   35 minutes ago   77.4MB
ubuntu       latest    9873176a8ff5   11 days ago      72.7MB

启动traceroute容器:

➜ docker run -it --name traceroute traceroute
root@fbe3eb98ae63:/#

启动tcpdump容器,进行抓包:

➜  ~ docker run -it --net=container:traceroute tcpdump
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

在traceroute容器发起traceroute:

root@fbe3eb98ae63:/# traceroute -A -q 1 -N 1 -z 500 -e 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  localhost (172.17.0.1) [*]  0.129 ms
 2  localhost (10.39.101.1) [*]  3.716 ms
 3  localhost (192.168.1.1) [*]  3.926 ms
 4  222.129.32.1 (222.129.32.1) [AS4808]  6.837 ms
 5  61.148.163.181 (61.148.163.181) [AS4808]  9.247 ms
 6  219.232.11.65 (219.232.11.65) [AS17431]  7.049 ms
 7  61.149.203.205 (61.149.203.205) [AS4808]  7.650 ms
 8  219.158.7.22 (219.158.7.22) [AS4837]  40.815 ms
 9  219.158.103.218 (219.158.103.218) [AS4837]  64.771 ms
10  219.158.103.30 (219.158.103.30) [AS4837]  50.402 ms
11  219.158.10.30 (219.158.10.30) [AS4837]  53.261 ms
12  219.158.33.174 (219.158.33.174) [AS4837]  55.503 ms
13  108.170.241.65 (108.170.241.65) [AS15169]  54.876 ms
14  142.251.64.173 (142.251.64.173) [AS15169]  45.966 ms
15  dns.google (8.8.8.8) [AS15169]  52.492 ms

traceroute -A -q 1 -N 1 -z 500 -e 8.8.8.8 参数解释如下:

  • -A: 向radb.net查找对应节点IP所在的AS Path信息,并将查询信息输出
  • -q 1: 将缺省发送3个探测包改为1个
  • -N 1: 将并发16个探测改为一次一个,以便于逐个分析
  • -z 500: 表示每次等待500毫秒再发出下一个探测
  • -e: 显示ICMP的扩展消息,如果有的话

按下CTRL+C,停止tcpdump容器的抓包:

➜  ~ docker run -it --net=container:traceroute tcpdump
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C237 packets captured
237 packets received by filter
0 packets dropped by kernel

该容器在抓完包后自动停止,并将抓包文件存储在容器内部的/var/traceroute-ubuntu.pcapng,通过docker cp命令将抓包文件拷贝出来。

➜  ~ docker ps -a
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS                        PORTS     NAMES
f397f50267ae   tcpdump      "/bin/sh -c 'tcpdump…"   2 minutes ago    Exited (130) 20 seconds ago             condescending_cori
fbe3eb98ae63   traceroute   "bash"                   48 minutes ago   Up 48 minutes                           traceroute
➜  ~ docker cp f397f50267ae:/var/traceroute-ubuntu.pcapng ./

简略分析抓包文件

以下是本次抓取的237个报文的头36个报文,如下:

上图中,Wireshare直接分析出来Whois报文。

过程概述如下:

  1. 向8.8.8.8发起UDP报文,目的端口为33434,TTL设置为1
  2. 收到路由器的ICMP TTL超时消息,获取路由器对应的IP地址
  3. 尝试向DNS服务器查询路由器IP地址的反向域名解析,如果得到域名,就将其显示在Traceroute的输出结果中。
  4. 发起DNS查询,查询whois.radb.net域名,得到应答为198.108.0.18
  5. 发起TCP连接请求,与198.108.0.18建立TCP连接。
  6. whois.radb.net发起查询,询问路由器IP地址对应的AS号,并得到回应,如果是私有地址,其AS号为0。
  7. 重复上述第1、2、3、6步,每次将TTL加1,直至目标地址接收到探测报文,并返回ICMP Port Unreachable消息。

抓包文件下载

番外篇

ThousandEyes的介绍可参考这篇文章《在AWS上部署TE Agent并进行测试》

ThousandEyes可将探针部署到容器中,而且安装十分简单,从ThousandEyes的Cloud & Enterprise Agents中,选择Agent Settings,再选择Enterprise Agents,再点击Add New Enterprise Agent,切换到Docker这个TAB。

将下面的文字复制粘贴到Terminal终端:

docker pull thousandeyes/enterprise-agent > /dev/null 2>&1
docker stop 'TEagent' > /dev/null 2>&1
docker rm 'TEagent' > /dev/null 2>&1
docker run \
  --hostname='TEagent' \
  --memory=2g \
  --memory-swap=2g \
  --detach=true \
  --tty=true \
  --shm-size=512M \
  -e TEAGENT_ACCOUNT_TOKEN=lje1co39qi       8b5oviy \
  -e TEAGENT_INET=4 \
  -v '/Users/werao/thousandeyes/TEagent/te-agent':/var/lib/te-agent \
  -v '/Users/werao/thousandeyes/TEagent/te-browserbot':/var/lib/te-browserbot \
  -v '/Users/werao/thousandeyes/TEagent/log/':/var/log/agent \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_ADMIN \
  --name 'TEagent' \
  --restart=unless-stopped \
  thousandeyes/enterprise-agent /sbin/my_init

安装完后,ThousandEyes即可使用该Agent进行测试了。

创建一个简单的探测如下:

在ThousandEyes的界面,可观测上述的探测结果:

时延比较稳定,维持在50ms左右。

thousandeyes-path.png

路径可视化分析中,当我们把鼠标落在某个节点上,网页会弹出交互式的信息,包括:

  • 网络前缀信息,如:124.65.192.0/18
  • 运营商AS信息,如:CNCGROUP Beijing Province (AS 4808)
  • 地理位置,如:Beijing, Beijing, China
  • DSCP
  • 平均时延,指从探测的Agent到对应节点的平均时延

ThousandEyes的探针所收集的数据是常规的网络工具都能收集到的,ThousandEyes的平台对收集到的数据进行存储、分析、交叉关联,为用户的数字体验提供全方位的洞见。

本节是突发奇想的内容,故而放到番外篇。

全文完。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容

  • 本文整理了在实践过程中使用的Linux网络工具,这些工具提供的功能非常强大,我们平时使用的只是冰山一角,比如lso...
    老夫刘某阅读 3,519评论 0 7
  • ping 这个命令不用多说,我们通常使用这个命令判断网络的连通性以及网速,偶尔还顺带当做域名解析使用(查看域名的 ...
    LeaForest阅读 1,568评论 0 1
  • (ab) - Apache服务器的性能测试工具[https://tool.p2hp.com/tool-find-l...
    括儿之家阅读 932评论 0 1
  • Linux常用网络工具简单整理一下。 ping 检查网络连通性以及网速,域名解析。 默认一直发送ICMP包(Int...
    悠扬前奏阅读 707评论 0 0
  • 常用判断网络是否中断的方法: 1.Traceroute,Tracert traceroute命令用于追踪数据包在网...
    TimLi_51bb阅读 1,433评论 0 1