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

boo*_*oos 46 linux traffic udp process

我的机器不断发出 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

zer*_*ime 58

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

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

然后,添加一个规则来监视系统调用socket()并标记它以便以后查找(-k)。我需要假设您使用的是 64 位架构,但如果不是,您可以替换b32b64

auditctl -a exit,always -F arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET
Run Code Online (Sandbox Code Playgroud)

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

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

ausearch -i -ts today -k SOCKET
Run Code Online (Sandbox Code Playgroud)

将出现类似于以下部分的输出。我将其缩写以突出重要部分

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
Run Code Online (Sandbox Code Playgroud)

在上面的输出中,我们可以看到该ping命令导致套接字被打开。然后我可以运行strace -p 14510该进程,如果它仍在运行。该ppid(父进程ID)的情况下还列出这是一个脚本,产卵孩子问题很多。

现在,如果您有大量 UDP 流量,这还不够好,您将不得不求助于OProfileSystemTap,这两者目前都超出了我的专业知识。

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

完成后,使用创建它时使用的同一行删除审核规则,仅替换-a-d

auditctl -d exit,always -F arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET
Run Code Online (Sandbox Code Playgroud)


Mad*_*ter 24

您可以使用 netstat,但您需要正确的标志,并且它仅在发送数据的进程仍然存在时才有效。它不会找到短暂出现、发送 UDP 流量然后消失的东西的踪迹。它还需要本地 root 权限。那说:

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

[madhatta@risby]$ ncat -u 10.11.12.13 2345 < /dev/urandom
Run Code Online (Sandbox Code Playgroud)

这是一些 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
Run Code Online (Sandbox Code Playgroud)

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

[root@risby ~]# netstat -apn|grep -w 2345
udp        0      0 192.168.3.11:57550          10.11.12.13:2345            ESTABLISHED 9152/ncat     
Run Code Online (Sandbox Code Playgroud)

如您所见,pid 9152 被认为在指定的远程主机上打开了到端口 2345 的连接。Netstat 也有用地通过 ps 运行它并告诉我进程名称是ncat.

希望这有点用。

  • 不过有一个问题。如果问题是由 shell 脚本产生的子进程引起的,该子进程执行 DNS 查找并且该进程快速退出,那么源端口(上面的 57550)将一直更改。在这种情况下,该技术将不起作用,您将不得不采取更严厉的措施。此外,您的 netstat 应该已经执行了 `grep -w 57550`,因为多个进程可能正在对同一台服务器进行 DNS 查找。你的方法不会区分它们。 (2认同)

Jak*_*sic 22

我遇到了完全相同的问题,不幸的auditd是没有为我做太多。

我的一些服务器有流量流向 google 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
Run Code Online (Sandbox Code Playgroud)

然后只需运行:

stap -v udp_detect_domain.stp
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

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
Run Code Online (Sandbox Code Playgroud)

就是这样!更改resolv.conf这些 PID 后没有发现更改。


希望这可以帮助 :)


小智 7

这是一个 systemtap 选项,使用 stap 版本 1.8 及更高版本中提供的 netfilter 探针。另见man probe::netfilter.ip.local_out

# stap -e 'probe netfilter.ip.local_out {
  if (dport == 53) # or parametrize
      printf("%s[%d] %s:%d\n", execname(), pid(), daddr, dport)
}'
ping[24738] 192.168.1.10:53
ping[24738] 192.168.1.10:53
^C
Run Code Online (Sandbox Code Playgroud)