如何识别 Linux 上哪些进程正在生成 UDP 流量?

如何识别 Linux 上哪些进程正在生成 UDP 流量?

我的机器正在不断地发出 udp dns 流量请求。我需要知道的是生成此流量的进程的 PID。

TCP 连接的正常方式是使用 netstat/lsof 并获取与 pid 关联的进程。

UDP 连接是无状态的,因此,当我调用 netastat/lsof 时,只有当 UDP 套接字打开并且正在发送流量时,我才能看到它。

我尝试过使用lsof -i UDPnestat -anpue,但我找不到哪个进程正在执行该请求,因为我需要在发送 udp 流量时准确调用 lsof/netstat,如果我在发送 udp 数据报之前/之后调用 lsof/netstat 则无法查看打开的 UDP 套接字。

在发送 3/4 udp 数据包时准确调用 netstat/lsof 是不可能的。

我如何识别臭名昭著的进程?我已经检查了流量,试图从数据包的内容中识别发送的 PID,但无法从流量的内容中识别它。

有人能帮助我吗?

我是这台机器的 root FEDORA 12 Linux noise.company.lan 2.6.32.16-141.fc12.x86_64 #1 SMP Wed Jul 7 04:49:59 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux

答案1

Linux 审计可以提供帮助。它至少可以定位建立数据报网络连接的用户和进程。UDP 数据包就是数据报。

首先,auditd在您的平台上安装框架并确保auditctl -l返回某些内容,即使它说没有定义规则。

然后,添加一条规则来监视系统调用socket()并对其进行标记以便以后轻松找到(-k)。我需要假设您使用的是 64 位架构,但如果不是,您可以用b32代替。b64

auditctl -a exit,always -F arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET

您必须仔细阅读手册页和头文件才能构建它,但它捕获的内容本质上是此系统调用:socket(PF_INET, SOCK_DGRAM|X, Y),其中第三个参数未指定但通常为零。 PF_INET是 2 并且SOCK_DGRAM是 2。TCP 连接将使用SOCK_STREAM将设置a1=1。(SOCK_DGRAM第二个参数可以与或进行SOCK_NONBLOCK或运算SOCK_CLOEXEC,因此&=进行比较。)-k SOCKET是我们稍后搜索审计线索时要使用的关键字。它可以是任何东西,但我喜欢保持简单。

稍等片刻,查看一下审计线索。您也可以选择通过 ping 网络上的主机来强制发送几个数据包,这将导致 DNS 查找,该查找使用 UDP,这应该会触发我们的审计警报。

ausearch -i -ts today -k SOCKET

然后会出现类似下面的输出。我将其缩写以突出重要部分

type=SYSCALL ... arch=x86_64 syscall=socket success=yes exit=1 a0=2 a1=2 ... pid=14510 ... auid=zlagtime uid=zlagtime ... euid=zlagtime ... comm=ping exe=/usr/bin/ping key=SOCKET

在上面的输出中,我们可以看到该ping命令导致套接字打开。然后我可以strace -p 14510在该进程上运行(如果它仍在运行)。ppid如果它是一个经常生成问题子进程的脚本,则还会列出(父进程 ID)。

现在,如果你有大量的 UDP 流量,这将不够好,你必须求助于配置文件或者系统水龙头,这两项目前都超出了我的专业知识范围。

这应该有助于在一般情况下缩小问题范围。

完成后,使用创建审计规则时使用的同一行删除该审计规则,只需用 替换-a即可-d

auditctl -d exit,always -F arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET

答案2

您可以使用 netstat,但您需要正确的标志,并且它仅在发送数据的进程仍然处于活动状态时才有效。它不会找到短暂活动、发送 UDP 流量然后消失的某些东西的踪迹。它还需要本地 root 权限。也就是说:

这是我在本地主机上启动 ncat,将 UDP 流量发送到(不存在的)机器 10.11.12.13 上的端口 2345:

[madhatta@risby]$ ncat -u 10.11.12.13 2345 < /dev/urandom

以下是一些 tcpdump 输出,证明流量正在进行:

[root@risby ~]# tcpdump -n -n port 2345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:41:32.391750 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.399723 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.401817 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.407051 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.413492 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.417417 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192

这是有用的部分使用 netstat 的 -a 标志(查看端口详细信息)和 -p 标志查看进程 ID 详细信息。 -p 标志需要 root 权限:

[root@risby ~]# netstat -apn|grep -w 2345
udp        0      0 192.168.3.11:57550          10.11.12.13:2345            ESTABLISHED 9152/ncat     

如您所见,pid 9152 被指与指定远程主机上的端口 2345 建立连接。Netstat 还通过 ps 运行该命令并告诉我进程名称是ncat

希望这能有所帮助。

答案3

我也遇到了完全一样的问题并且不幸的是它auditd并没有给我带来什么帮助。

我的一些服务器的流量流向谷歌 DNS 地址,8.8.8.8并且8.8.4.4。现在,我的网络管理员有轻微的强迫症,他想清理所有不必要的流量,因为我们有内部 DNS 缓存。他想禁用除这些缓存服务器之外的所有服务器的传出端口 53。

因此,在失败之后auditctl,我深入研究systemtap。我想出了以下脚本:

# cat >> udp_detect_domain.stp <<EOF
probe udp.sendmsg {
  if ( dport == 53 && daddr == "8.8.8.8" ) {
    printf ("PID %5d (%s) sent UDP to %15s 53\n", pid(), execname(), daddr)
  }
}
EOF

然后只需运行:

stap -v udp_detect_domain.stp

这是我得到的输出:

PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3506 (python) sent UDP to  8.8.8.8 53

就是这样!更改resolv.conf这些 PID 后,没有反映出变化。


希望这可以帮助 :)

答案4

我会使用 tcpdump 或 wireshark 之类的网络嗅探器来查看 DNS 请求。查询的内容可以让您了解哪个程序正在发出这些请求。

相关内容