如何找出发送数据包(产生网络流量)的进程的 PID?

如何找出发送数据包(产生网络流量)的进程的 PID?

几周前,我遇到了一个问题,我在大约 300 个节点的大型网络中更改了 DNS 地址。之后,一些节点仍然继续询问旧的 DNS 服务器,尽管 resolv.conf 没问题,并且 host/nslookup 正在查询新的 DNS 服务器。

查看 tcpdump 并尝试使用 iptables 日志记录请求,我确认确实有一些主机仍在向旧的名称服务器发送查询。

我把其中一台主机从生产中撤出,并开始关闭服务/跟踪进程,试图找出罪魁祸首。

最后 - 它是 lldpd 守护进程,它显然在启动时缓存了名称服务器,甚至没有注意到 resolv.conf 中的变化。

所以,我的问题是 - 有没有更智能的方法来找出哪个 PId 正在生成特定类型的流量?我尝试使用 auditctl,但没有成功。CentOS 6 有问题,但如果有任何 Linux 发行版的解决方案,我将不胜感激。

答案1

auditctl 有什么问题?

你会这样做

1) 定义审计规则以审计 sendmsg 和 sendto 系统调用。这些系统调用在名称解析期间使用。

auditctl -a exit,always -F arch=b64 -S sendmsg -S sendto -k send

2)现在搜索您的审计记录。您可以在此处根据远程 DNS IP 进行 grep

ausearch -k send -i|grep -A2 "serv:53"

在下面的例子中,你可以看到负责系统调用的应用程序名为 dig

ausearch -k send -i|grep -A2 "serv:53"
type=SOCKADDR msg=audit(10/31/2016 15:24:56.264:176998) : saddr=inet host:172.16.0.23 serv:53 
type=SYSCALL msg=audit(10/31/2016 15:24:56.264:176998) : arch=x86_64 syscall=sendmsg success=yes exit=29 a0=14 a1=7fa1919f9ac0 a2=0 a3=7fa1919f9780 items=0 ppid=31729 pid=32047 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts5 ses=52 comm=dig exe=/usr/bin/dig subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=send


comm=dig exe=/usr/bin/dig

区分向哪个远程 DNS 请求发送的方法就在这里。因此,您只需 grep 特定的 DNS 主机即可。

saddr=inet host:172.16.0.23 serv:53 

或者更好的是 - 查看使用了哪些 DNS 主机(在这个例子中我只有一个)

ausearch -k send -i|grep "serv:53"|awk '{print $6}'|sort|uniq -c
      3 host:172.16.0.23

然后缩小使用这些特定主机的应用程序的范围。

编辑 1:实际上我只是对主机进行了简单的 ping 操作。似乎 sendmsg 并不总是被使用。以下是我所看到的

socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.16.0.23")}, 16) = 0
gettimeofday({1477929832, 712018}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0)    = 1 ([{fd=4, revents=POLLOUT}])
sendto(4, "\3\326\1\0\0\1\0\0\0\0\0\0\tvkontakte\2ru\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
poll([{fd=4, events=POLLIN}], 1, 5000)  = 1 ([{fd=4, revents=POLLIN}])
ioctl(4, FIONREAD, [62])                = 0
recvfrom(4, "\3\326\201\200\0\1\0\2\0\0\0\0\tvkontakte\2ru\0\0\1\0\1\300\f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.16.0.23")}, [16]) = 62
close(4)                                = 0

我之前的示例基于 dig 应用程序,它在系统调用方面采用了略有不同的路线。
因此,在大多数情况下,看起来应该是这个规则

auditctl -a exit,always -F arch=b64 -S connect -k connect

随后是 ausearch

ausearch -k connect -i|grep saddr|grep "serv:53"|awk '{print $6}'|sort|uniq -c

答案2

几天前,我也遇到了同样的问题,并想出了一个非常简单的方法。它基于以下事实:发送进程将在发送请求的同一端口上等待 DNS 响应

  1. 使用以下命令找出传出 DNS 请求的源端口:iptables -j LOG
  2. 用于lsof -i UDP:<source_port>找出哪个进程正在该端口上等待响应。

当然,由于响应会在几毫秒内到达,因此您无法手动执行此操作;此外,即使自动执行,也无法保证您能够在 DNS 响应到达之前查询系统,并且发送过程会终止。这就是为什么在执行上述步骤之前,我还将内核流量控制器配置为延迟传出数据包定向到特定的 IP/端口(使用模块tcnetem。这样,我就可以控制查询系统哪个 PID 正在等待 DNS 响应的时间窗口,在步骤 1 中获得的源 UDP 端口上。

tc我已经在一个名为的小脚本中自动执行了上述步骤(包括延迟)。陷阱(这是一个更通用的解决方案,不仅限于 DNS 请求,因此可以使用任何基于 TCP/UDP 的协议检测进程)。借助它,我发现,在我的例子中,联系旧 DNS 服务器的服务是 sendmail。

答案3

atop。有一个内核模块(netatop)和守护进程可以atop跟踪进程的网络使用情况。

您应该首先安装atop

以下是安装内核模块的方法。在撰写本文时,这种方法是有效的,但可能会过时:

sudo apt install linux-headers-$(uname -r) make zlib1g-dev
wget https://www.atoptool.nl/download/netatop-2.0.tar.gz
tar xvf netatop-2.0.tar.gz
cd netatop-2.0
make
sudo make install
sudo modprobe -v netatop

netatopd.service如果你有 systemd,请在 中创建服务文件/etc/systemd/system/。它将包含:

[Unit]
Description=NetAtop Daemon

[Service]
Type=forking
ExecStart=/usr/sbin/netatopd

[Install]
WantedBy=multi-user.target

现在您可以启用守护进程:

sudo systemctl enable netatopd

要查看每个进程的实时网络使用情况:

sudo atop -n

要查看一天中网络占用最大的前 3 个时间:

atopsar -N

man atopsar以获得更多选项。

答案4

有许多选项可以netstat显示通过 tcp/udp/both 监听/打开套接字的组合。例如:

$> sudo netstat -pan
Active Internet connections (servers and established)
Proto  Recv-Q Send-Q Local Addr            Foreign Addr           State       PID/Program name
...
tcp    0      1      192.168.66.1:39219    192.168.66.139:2003    SYN_SENT    2045/logstash-forwa

...会给你很多输出,但包括源、目标、端口号和拥有这些端口的进程的 PID。

相关内容