如何捕获每个 PID 的网络数据包?

Posted

技术标签:

【中文标题】如何捕获每个 PID 的网络数据包?【英文标题】:How can I capture network packets per PID? 【发布时间】:2011-12-12 03:42:06 【问题描述】:

任何人都知道一种简单的方法来要求 Linux“显示每个互联网数据包到/来自谷歌浏览器”或“显示每个互联网数据包到/来自 PID 10275 的 telnet 进程”?

telnet 的例子不太有用,因为我可以使用wireshark 或tcpdump 来查看所有涉及端口23 的TCP 会话。这样就没有人再使用telnet 了。但是嗅探所有进出使用许多端口的复杂应用程序的数据包似乎很有用。

我找到了一些相关的答案,探索不同的方法来证实端口和 PID(或程序名称)等,但没有关于数据包的内容

How to tie a network connection to a PID without using lsof or netstat? How I can get ports associated to the application that opened them? How to do like "netstat -p", but faster?

看起来有人可能愿意为这个答案付费:

http://www.freelancer.com/projects/Perl-CGI-C-C/tcpdump-PID-relation.html

NetHogs 有助于快速查看哪些程序正在通过接口创建流量,但它没有捕获数据包的方法。

【问题讨论】:

Hrm,我应该问服务器故障吗? 这实际上可能属于超级用户。一个有趣的问题。您可以使用 WireShark 过滤 HTTP 请求,但您必须连接到内核驱动程序以根据 PID 过滤数据包 这是一个有点复杂的问题 - 套接字不属于 PID;您可以将它们从一个进程传递到另一个进程。如果进程 A 打开一个套接字,它可以将其传递给进程 B 然后退出 - 如果您正在过滤进程 A 的 PID,现在会发生什么? 我打算建议使用dtrace 来观看像writesendsendto 这样的系统调用,但是AFAIK dtrace 还没有进入Linux。也许您可以使用类似的系统调用日志记录工具? 【参考方案1】:

不是直接的 tcpdump,但可以为您提供有关网络流量的信息,请查看 https://bytefreaks.net/gnulinux/how-to-capture-all-network-traffic-of-a-single-process

strace -f -e trace=network -s 10000 <PROCESS WITH ARGUMENTS>;

如果进程已经启动并且您知道它的 PID,您可以使用以下命令 1

strace -f -e trace=network -s 10000 -p <PID>;

另一种选择更复杂,使用网络命名空间,检查上面的链接或使用工具nsntrace,但要么只能在新进程上工作,你不能改变现有的进程网络命名空间(AFAIK)

更新: 您还可以安装工具 bpfcc-tools(搜索您的发行版,很多已经包含它)并使用命令 sudo tcptracer-bpfcc -v -p (PID) 虽然这不会显示数据包,但它会列出该 pid 的网络连接。您可以删除 -p (PID) 以列出每个进程的所有连接。这可能对那些跟踪短期连接而不是网络负载的人有用。

【讨论】:

【参考方案2】:

我会使用lsof -i 来获取与我想要的应用程序相关联的端口号。 代码是这样的:

进程=火狐 对于 _port 在 `lsof -i | grep $进程 |剪切-d''-f18 |切-d:-f2 |剪切-d'-'-f1` 做 端口=$_port [[ "$_port" == +([a-zA-Z]) ]] && 端口=`cat /etc/services | grep '^$_port' |剪切-d''-f12 |剪切-d'/' -f1 |独特 |头-n 1` echo "tcpdump -w $port.pcap 端口 $port &" tcpdump -w $port.pcap 端口 $port & 完毕

请注意,不同版本/发行版上的命令输出可能会有所不同。因此,在使用脚本之前,您最好检查正确的文件是否被剪切。

此外,此脚本不会监控稍后打开的端口。为此,我会考虑一个更复杂的脚本来定期检查端口(使用类似watch

记得在之后杀死所有的 tcpdump 进程。

【讨论】:

【参考方案3】:

就我而言,我想捕获 syslog 流量,但只能来自 rsyslog。它在lsof -p $(pidof rsyslog) 下只有一个侦听端口,并且始终将其用作源端口,因此我能够使用以下方式获取数据包:

tcpdump -i eth0 -A "host 10.0.0.100 and dst port 514 and src port $(lsof -i 4 -a -p `pidof rsyslogd` | grep -Po '(?<=\*:)[0-9]*') and udp"

grep uses a positive lookbehind assertion 将 *:portnumber 转换为端口号。

【讨论】:

【参考方案4】:

Tcpdump 可以告诉您数据包来自/到的 PID/进程。 在您的选项中添加“-k NP”。

支持的版本:tcpdump 版本 4.3.0 -- Apple 版本 56

【讨论】:

对 Linux 提出了问题。 Linux 的 tcpdump 中没有显示 PID 信息的选项。 tcpdump 4.9.2 在 Linux 上也没有 -k 选项。

以上是关于如何捕获每个 PID 的网络数据包?的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 上,如何在网络层 (IP) 上捕获传入的数据包?

如何用Wireshark捕获USB数据

抓包工具 - Fiddler(如何捕获Android数据包)

基于多核平台的高速网络流量实时捕获方法

java怎么解析Wireshark抓包文件

使用 pcap.net 在同一网络中捕获不同 PC 的网络数据包