當docker容器的網絡模式不是--net=host(如果啟動容器的時候使用host模式,那么這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主
機的IP和端口)時,容器和宿主機的網絡互相獨立,而容器一般也不會有安裝tcpdump。因此,無法直接抓取容器內的包。
一、docker 獲取容器的相關信息
1、查看docker容器的網絡類型
docker inspect --format='{{json .NetworkSettings.Networks}}' pgadmin {"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"NetworkID":"f64b74cb9fa4ba72d6c041e6ccebfeaf4de028b8d665fbd353bcd489b3c092cf","EndpointID":"2fe58fec718f546b752e45e3dcca6099bb365d3b628df37b7589d6c59c785681","Gateway":"172.17.0.1","IPAddress":"172.17.0.3","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:03","DriverOpts":null}}
2、獲取容器的pid
docker inspect --format "{{.State.Pid}}" container_id/name 獲取PID
二、tcpdump和nsenter抓包
1、在docker容器內安裝tcpdump工具來直接抓包
-
獲取docker id
docker ps | grep xxx
-
copy tcpdump安裝包和依賴包到容器內
docker cp libpcap0-0.9.8-50.10.1.x86_64.rpm container_id:/tmp/ docker cp tcpdump-3.9.8-1.21.x86_64.rpm container_id:/tmp/
-
進入容器 安裝tcpdump后進行抓包
docker exec -it -u root container_id bash rpm -ivh *.rpm
也可直接使用這個tcpdump文件(已編譯好 免安裝 可直接使用)
docker cp /file/to/path/tcpdump container_id:/tmp/ sh /tmp/tcpdump -i any -s 0 host x.x.x.x
2、使用宿主機上的tcpdump工具對容器進程抓包
如果宿主機上已安裝了tcpdump抓包工具,那我們就可以通過宿主機上的nsenter工具來對docker容器進行抓包。
nsenter 包含在絕大部分 Linux 發行版預置的 util-linux 工具包中。
使用它可以進入指定進程的關聯命名空間。包括文件命名空間(mount namespace)、主機名命名空間(UTS namespace)、IPC 命名空間(IPC namespace)、網絡命名空間
(network namespace)、進程命名空間(pid namespace)和用戶命名空間(user namespace)。
what is nsenter
It is a small tool allowing to enter into namespaces. Technically, it can enter existing namespaces, or spawn a process into a new set of namespaces. "What are those namespaces you're blabbering about?" We are talking about container namespaces. nsenter can do many useful things, but the main reason why I'm so excited about it is because it lets you enter into a Docker container.
參數
nsenter --help 用法: nsenter [options] <program> [<argument>...] Run a program with namespaces of other processes. 選項: -t, --target <pid> 要獲取名字空間的目標進程 -m, --mount[=<file>] enter mount namespace -u, --uts[=<file>] enter UTS namespace (hostname etc) -i, --ipc[=<file>] enter System V IPC namespace -n, --net[=<file>] enter network namespace -p, --pid[=<file>] enter pid namespace -U, --user[=<file>] enter user namespace -S, --setuid <uid> set uid in entered namespace -G, --setgid <gid> set gid in entered namespace --preserve-credentials do not touch uids or gids -r, --root[=<dir>] set the root directory -w, --wd[=<dir>] set the working directory -F, --no-fork 執行 <程序> 前不 fork -Z, --follow-context set SELinux context according to --target PID -h, --help 顯示此幫助並退出 -V, --version 輸出版本信息並退出 更多信息請參閱 nsenter(1)。
如何使用nsenter來抓包
-
獲取容器進程id,即PID
docker ps | grep xxx 獲取容器id/name docker inspect --format "{{.State.Pid}}" container_id/name 獲取PID
-
使用nsenter切換網絡命名空間
nsenter -n -t container_id/name 可在切換前后執行ifconfig來對比變化
現在就已進入容器的網絡命名空間,就可以使用宿主機上的tcpdump來對容器進行抓包了
三、通過iflink找到網卡對應關系
1. 在宿主機上執行命令ip link
ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens33: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:c3:35:79 brd ff:ff:ff:ff:ff:ff 3: ens37: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:c3:35:79 brd ff:ff:ff:ff:ff:ff 4: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 00:0c:29:c3:35:79 brd ff:ff:ff:ff:ff:ff 5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default link/ether 02:42:f7:6d:1c:51 brd ff:ff:ff:ff:ff:ff 7: veth5092b87@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether 32:79:aa:d3:7f:2c brd ff:ff:ff:ff:ff:ff link-netnsid 0 9: veth34be698@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether ae:d6:54:b3:50:93 brd ff:ff:ff:ff:ff:ff link-netnsid 1
2、在容器內查看iflink文件
docker exec -it pgadmin sh /pgadmin4 $ cat /sys/class/net/eth0/iflink 9 或者通過ethtool來查看 在容器中執行:ethtool -S eth0 root@336043b07211:/# ethtool -S eth0 NIC statistics: peer_ifindex: 9
這樣就可以確定:
pgadmin這個容器在物理機上對應的veth pair是veth34be698@if8
(9對應宿主機9:)
容器外查看 ps -ef 查看端口
ps -ef | grep 5080 root 2053 1356 0 17:05 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5080 -container-ip 172.17.0.3 -container-port 80 root 2059 1356 0 17:05 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 5080 -container-ip 172.17.0.3 -container-port 80 root 2348 1913 0 17:24 pts/1 00:00:00 grep --color=auto 5080
容器內通過netstat -r 查看連接情況
/pgadmin4 $ netstat –r Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 5b7f4fff015b:32830 192.168.40.132:postgresql ESTABLISHED tcp 0 0 5b7f4fff015b:32834 192.168.40.132:postgresql ESTABLISHED tcp 0 0 5b7f4fff015b:32838 192.168.40.132:postgresql ESTABLISHED tcp 0 0 5b7f4fff015b:32842 192.168.40.132:postgresql ESTABLISHED tcp 0 0 5b7f4fff015b:http ::ffff:192.168.40.200:6165 TIME_WAIT tcp 0 0 5b7f4fff015b:http ::ffff:192.168.40.200:6461 ESTABLISHED Active UNIX domain sockets (w/o servers) Proto RefCnt Flags Type State I-Node Path
tcpdump -i any
tcpdump -i any tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 22:01:27.432382 IP 192.168.40.200.10859 > root.http: Flags [P.], seq 2426513533:2426514255, ack 2732166892, win 4106, length 722: HTTP: GET /dashboard/dashboard_stats/1/16384?chart_names=session_stats,tps_stats,ti_stats,to_stats,bio_stats HTTP/1.1 22:01:27.433384 IP root.49538 > public1.114dns.com.domain: 16551+ PTR? 3.0.17.172.in-addr.arpa. (41) 22:01:27.444500 IP root.32834 > 192.168.40.132.postgres: Flags [P.], seq 1629397589:1629399809, ack 3287353308, win 1424, options [nop,nop,TS val 17857857 ecr 17856872], length 2220 22:01:27.444595 IP 192.168.40.132.postgres > root.32834: Flags [.], ack 2220, win 1432, options [nop,nop,TS val 17857857 ecr 17857857], length 0 22:01:27.457255 IP 192.168.40.132.postgres > root.32834: Flags [P.], seq 1:394, ack 2220, win 1432, options [nop,nop,TS val 17857870 ecr 17857857], length 393 22:01:27.457263 IP root.32834 > 192.168.40.132.postgres: Flags [.], ack 394, win 1424, options [nop,nop,TS val 17857870 ecr 17857870], length 0 22:01:27.458350 IP public1.114dns.com.domain > root.49538: 16551 NXDomain 0/1/0 (118) 22:01:27.458360 IP root.http > 192.168.40.200.10859: Flags [P.], seq 1:419, ack 722, win 1432, length 418: HTTP: HTTP/1.1 200 OK 22:01:27.458485 IP root.http > 192.168.40.200.10859: Flags [P.], seq 419:673, ack 722, win 1432, length 254: HTTP 22:01:27.458568 IP 192.168.40.200.10859 > root.http: Flags [.], ack 673, win 4103, length 0 22:01:27.459127 IP root.33689 > public1.114dns.com.domain: 20618+ PTR? 200.40.168.192.in-addr.arpa. (45) 22:01:27.487509 IP public1.114dns.com.domain > root.33689: 20618 NXDomain* 0/1/0 (80) 22:01:27.487691 IP root.46946 > public1.114dns.com.domain: 55017+ PTR? 114.114.114.114.in-addr.arpa. (46) 22:01:27.514467 IP public1.114dns.com.domain > root.46946: 55017 1/0/0 PTR public1.114dns.com. (78) 22:01:27.514595 IP root.49870 > public1.114dns.com.domain: 5779+ PTR? 132.40.168.192.in-addr.arpa. (45) 22:01:27.551436 IP public1.114dns.com.domain > root.49870: 5779 NXDomain 0/1/0 (122) 22:01:28.442007 IP 192.168.40.200.10859 > root.http: Flags [P.], seq 722:1444, ack 673, win 4103, length 722: HTTP: GET /dashboard/dashboard_stats/1/16384?chart_names=session_stats,tps_stats,ti_stats,to_stats,bio_stats HTTP/1.1
tcpdump -i docker0 -vvv -w ip.txt
將抓包結果放到文本中