例如,我看到传入的数据包在,但对于正在监听适当套接字的程序来说tcpdump
却不在。strace
我如何在 Linux 上追踪这个传入数据包的“命运”?
我希望得到这样的报告:
- ✓ 网络接口接收到数据包;
- ✓ 数据包成功解码为 IPv4 数据包(校验和正确等);
- ✓ 数据包通过 iptables(未被 DROP 掉);
- ✘ 数据包路由到本地套接字(不,这不是我们的 IP 地址);
- 数据包通过流量控制(没有因为过载而丢失);
- 本地套接字接收到数据包
我可以在哪里获得汇总信息,而不必手动调查每个可能的停止点(也许我甚至不知道全部停止点)?
答案1
tcpdump 只是利用原始套接字复制经过网卡的数据,工作在操作系统的 TCP/IP 堆栈中。能够通过 tcpdump 捕获数据意味着数据包确实到达了网卡。
strace 只是打印每个系统调用。无法在 strace 中捕获它意味着read
没有write
进行系统调用。例如,read
系统调用调用 NIC 驱动程序将数据从 NIC 移动到与套接字文件描述符关联的内核内存,然后将它们复制到用户空间缓冲区。strace 可以检查read
调用中的参数,然后打印它们。
此外,如果是流套接字,我认为accept
系统调用已经完成,文件描述符也已分配,因此客户端可以发送数据包,tcpdump 可以捕获这些数据包。我在这里有一个实例。
15:21:25.285198 IP (tos 0x0, ttl 55, id 0, offset 0, flags [DF], proto TCP (6), length 597)
10.93.235.127.51524 > 10.225.131.26.8040: Flags [P.], cksum 0xefc8 (correct), seq 1:546, ack 1, win 2052, options [nop,nop,TS val 633828071 ecr 2357545597], length 545
POST /api/query HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.15.2
Accept: */*
Cache-Control: no-cache
Postman-Token: e5584554-5747-4f2c-84c4-8e621b3bfeb2
Host: 10.225.131.26:8040
Accept-Encoding: gzip, deflate
Content-Length: 256
Connection: keep-alive
{"start":1567397847315,"end":1567398147315,"queries":[{"aggregator":"avg","metric":"endpoint.status.ok","rate":true,"rateOptions":{"counter":false,"diff":false},"tags":{"dc":"*","host":"n225"},"topK":""}],"allowCoprocessor":false}
15:21:25.285210 IP (tos 0x0, ttl 64, id 17260, offset 0, flags [DF], proto TCP (6), length 52)
10.225.131.26.8040 > 10.93.235.127.51524: Flags [.], cksum 0x83fe (incorrect -> 0xb98e), ack 546, win 7513, options [nop,nop,TS val 2357545605 ecr 633828071], length 0
5 packets captured
但是 strace 显示只有accept
ed 而不是read
,所以没有看到数据包。
2524390 accept4(9, {sa_family=AF_INET6, sin6_port=htons(51524), inet_pton(AF_INET6, "::ffff:10.93.235.127", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [128->28], SOCK_CLOEXEC|SOCK_NONBLOCK) = 178687
2524390 getsockname(178687, {sa_family=AF_INET6, sin6_port=htons(8040), inet_pton(AF_INET6, "::ffff:10.225.131.26", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [128->28]) = 0
2524390 setsockopt(178687, SOL_TCP, TCP_NODELAY, [1], 4) = 0
2524390 getsockopt(178687, SOL_SOCKET, SO_SNDBUF, [65536], [4]) = 0
2524390 getsockopt(178687, SOL_SOCKET, SO_SNDBUF, [65536], [4]) = 0
2524390 setsockopt(178687, SOL_SOCKET, SO_SNDBUF, [131072], 4) = 0
2524390 getsockopt(178687, SOL_SOCKET, SO_SNDBUF, [262144], [4]) = 0
2524390 getsockopt(178687, SOL_SOCKET, SO_SNDBUF, [262144], [4]) = 0
2524390 setsockopt(178687, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
2524390 setsockopt(178687, SOL_TCP, TCP_NODELAY, [1], 4) = 0
2524390 setsockopt(178687, SOL_SOCKET, SO_RCVBUF, [131072], 4) = 0
数据报套接字也类似。