如何确定在Linux上进行UDP流量的进程?


39

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

TCP连接中的常规方法是使用netstat / lsof并在pid处获取关联的进程。

是UDP的连接是否为Stateles,因此,当我调用netastat / lsof时,只有在UDP套接字已打开并且正在发送流量的情况下,我才能看到它。

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

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

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

有人可以帮助我吗?

我在这台机器上扎根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

Answers:


48

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

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

稍等片刻,查看审核记录。(可选)您可以通过对网络上的主机进行ping操作来强制发送几个数据包,这将导致发生使用UDP的DNS查找,这将使我们的审核警报失效。

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流量,那么这将不够好,您将不得不使用OProfileSystemTap,这两种方法目前都超出了我的专业知识。

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

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

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

我会尝试的,但是我认为这是正确的答案。

至少对我来说,这不是增加iptables丢弃的流量。
2rs2ts

1
与systemtap方法相比,+ 1更为简便(它更具分析性,但需要内核devel软件包)
basos

23

您可以使用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

希望这是有用的。


真的很好!:thumbup:
ThorstenS

2
不过有一个陷阱。如果问题是由外壳程序脚本产生的,而该脚本产生了执行DNS查找的子进程,并且该进程迅速退出,则源端口(上面的57550)将一直保持更改状态。在这种情况下,该技术将无效,您将不得不采取更严厉的措施。另外,您的netstat应该已经完成​​了,grep -w 57550因为多个进程可能正在对同一服务器进行DNS查找。您的方法无法区分它们。
zerolagtime

1
我同意您的两个反对意见,zerolagtime(但是无论如何,还是谢谢您,ThorstenS!)。
MadHatter支持Monica 2010年

17

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

我的一些服务器的流量流向了Google DNS地址,8.8.8.8并且8.8.4.4。现在,我的网络管理员的OCD轻微,他希望清除所有不必要的流量,因为我们有内部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并没有接受更改。


希望这可以帮助 :)


5

这是一个systemtap选项,使用stap verson 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

4

我会使用网络嗅探器(例如tcpdump或wireshark)来查看DNS请求。查询的内容可以让您了解正在发布它们的程序。


没有信息在流量中嗅到我刚刚已经查看。

没有信息?空包?我的意思是,如果某事试图解决update.java.sun.com或rss.cnn.com,您可能会有用地从中推断出一些东西。
RedGrittyBrick

dns查询搜索内部代理。现在我发现过程是这样,但是对于一般的问题解决技术来说,这个问题仍然存在

lsof -i | awk'/ UDP /'
c4f4t0r

3

请注意,在使用autitctl时,例如在进行DNS查询时,nscd在套接字系统调用中使用的参数稍有不同:

socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP)

因此,为确保除上述查询之外还捕获了这些查询,可以添加其他过滤器,如果需要,可以使用相同的名称:

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

这里2050是SOCK_DGRAM(2)和SOCK_NONBLOCK(2048)的按位或。

然后搜索将找到两个具有相同键的过滤器SOCKET

ausearch -i -ts today -k SOCKET

我在这里找到的套接字常量的十六进制值:https : //golang.org/pkg/syscall/#pkg-constants

由于我没有评论的声誉点,因此添加了此内容。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.