tools-tcp

本文最后更新于:2022年5月27日 晚上

tools-tcp/ip

之前阅读掘金小册时一直没实战,这里就补一下

tcpdump

参考网站: 博客园

默认情况下tcpdump抓第一个网卡上的数据包

监听特定网卡使用-i参数

1
tcpdump -i wlo1

监听特定本机和特定ip的通信使用host参数:

1
tcpdump host 111.111.11.11

监听来源/目标地址通信:

1
2
tcpdump src host 111.111.11.11
tcpdump dst host 111.111.11.11

监听特定端口:

1
tcpdump port 3000

可以指定tcp/udp

1
tcpdump tcp

监听特定主机之间的通信(需要有权限)

1
tcpdump ip host 210.27.48.1 and 210.27.48.2

稍微详细点的例子

1
tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap

(1)tcp: ip icmp arp rarp 和 tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型 (2)-i eth1 : 只抓经过接口eth1的包 (3)-t : 不显示时间戳 (4)-s 0 : 抓取数据包时默认抓取长度为68字节。加上-S 0 后可以抓到完整的数据包 (5)-c 100 : 只抓取100个数据包 (6)dst port ! 22 : 不抓取目标端口是22的数据包 (7)src net 192.168.1.0/24 : 数据包的源网络地址为192.168.1.0/24 (8)-w ./target.cap : 保存成cap文件,方便用ethereal(即wireshark)分析

strace

参考网站: 博客园

strace用来跟踪进程执行时的系统调用以及所接收的信号,如:

1
2
3
4
5
6
7
8
9
10
strace cat /dev/null 
execve("/usr/bin/cat", ["cat", "/dev/null"], 0x7ffc3650b2a8 /* 80 vars */) = 0
brk(NULL) = 0x560885cd5000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd61de71d0) = -1 EINVAL (无效的参数)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8cb41e5000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=132945, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 132945, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8cb41c4000
close(3) = 0

每一行都是一个系统调用

strace的参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-c 统计每一系统调用的所执行的时间,次数和出错的次数等. 
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-r 打印出相对时间关于,,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-e trace=set
只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
-e trace=file
只跟踪有关文件操作的系统调用.
-e trace=process
只跟踪有关进程控制的系统调用.
-e trace=network
跟踪与网络有关的所有系统调用.
-e strace=signal
跟踪所有与系统信号有关的 系统调用
-e trace=ipc
跟踪所有与进程通讯有关的系统调用
-o filename
将strace的输出写入文件filename
-p pid
跟踪指定的进程pid.
-u username
以username 的UID和GID执行被跟踪的命令

这个佬的博客写的很详细,案例也不错,建议看看。

strace给我的感觉是如果不加参数过滤一些信息,给出的信息实在太多了。

如在我的电脑上strace -o 1.txt pkill goldendict,strace就给出了3287行的信息。。。如果加上参数-e trace=process,那么就只有4行:

1
2
3
4
execve("/usr/bin/pkill", ["pkill", "goldendict"], 0x7ffc17024708 /* 83 vars */) = 0
kill(340891, SIGTERM) = 0
exit_group(0) = ?
+++ exited with 0 +++

我后来又试了试了,sudo strace -e trace=close -f -d -uheeler -o 1.txt pkill goldendict,发现kill这个goldendict的调用的close是真多 😃

packetdrill

安装:github

1
2
cd gtests/net/packetdrill
sudo apt-get install -y bison flex

为避免 offload 机制对包大小的影响,修改 netdev.c 注释掉 set_device_offload_flags 函数所有内容

1
./configure

修改 Makefile,去掉第一行的末尾的 -static 执行 make 命令编译 可以在目录下尝试packetdrill是否正常生成 加入环境变量:

1
sudo vim /etc/profile

加入你的路径即可。之后任意打开一个命令行。packetdrill查看是否成功 由于packetdrill需要sudo权限,因此需要更改/.zshrc (我用的zsh解释器),在里面加入

1
alias sudo='sudo env PATH="$PATH"'

之后保存, source /.zshrc 即可

packetdrill实际上方便了程序员以确定的时间安排系统调用。他可以执行系统调用函数、把数据包注入到内核协议栈,并且支持py、shell,

来看一个张师傅给出的简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
//在第0秒创建一个socket
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0

//TCP three-way handshake
+0 < S 0:0(0) win 4000 <mss 1000>
//<表示输入数据包
+0 > S. 0:0(0) ack 1 <...>
//>表示预期协议栈响应的包
+.1 < . 1:1(0) ack 1 win 1000

+0 accept(3, ..., ...) = 4
+0 write(4, ..., 10) = 10
+0 > P. 1:11(10) ack 1
+.1 < . 1:1(0) ack 6 win 1000

上述代码可以通过tcpdump抓到8080端口的包

packetdrill实际上是通过创建一个虚拟网卡来模拟协议的执行。

其他内容建议参考: developpaper


本文作者: Heeler-Deer
本文链接: https://heeler-deer.github.io/2022/02/25/tools-tcp/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!