I tried the Auditd framework, and initially it didn't look very promising, as all I thought it was telling me was that process sent a UDP packet.
Then tried SystemTap, and initially it worked, but then it started reporting the destination port and address as 0.0.0.0 and 0 on some packets, but not others. Others have had that problem too. Rebooting and clearing caches didn't help, gave up.
Then looked into Dtrace, and quickly transitioned to Perf (thanks, Brendan Gregg!) However, couldn't figure out how to do the same task.
Then found another Auditd solution and apparently Auditd does actually record the destination ports and addresses, but embedded in hex:
$ sudo bash
# date +%s; \
auditctl -a exit,always -F arch=b64 -S connect -k sendmsg; \
nslookup serverfault.com 8.8.8.8 > /dev/null; \
auditctl -d exit,always -F arch=b64 -S connect -k sendmsg;\
date +%s
1664829661
1664829661
# grep 1664829661 /var/log/audit/audit.log | grep -C1 -m1 08080808
type=SYSCALL msg=audit(1664829661.285:24390): arch=c000003e syscall=46 success=yes exit=33 a0=14 a1=7f0c3b3f59b0 a2=0 a3=7f0c41415170 items=0 ppid=1523 pid=10483 auid=1003 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="isc-worker0000" exe="/usr/bin/nslookup" key="sendmsg"
type=SOCKADDR msg=audit(1664829661.285:24390): saddr=02000035080808080000000000000000
type=PROCTITLE msg=audit(1664829661.285:24390): proctitle=6E736C6F6F6B7570007365727665726661756C742E636F6D00382E382E382E38
The saddr=02000035080808080000000000000000 breaks down into:
- 0200 -- PF_INET
- 0035 -- port 53 (DNS)
- 08080808 -- ip address 8.8.8.8
The proctitle decodes as:
# echo 6E736C6F6F6B7570007365727665726661756C742E636F6D00382E382E382E38 | xxd -p -r | xargs -0
nslookup serverfault.com 8.8.8.8
Also confirmed it with arbitrary destination ip 1.2.3.4:
type=SOCKADDR msg=audit(1664830858.835:24624): saddr=02000035010203040000000000000000
* 0200 -- PF_INET
* 0035 -- port 53 (DNS)
* 01020304 -- ip address 1.2.3.4
So... go have fun tracking down processes that send UDP packets! :-)
EDIT: Apparently ausearch
is a darn useful tool; it converts the arguments to something approximately human-readable:
# ausearch -i -ts today -k sendmsg | more
...
type=PROCTITLE msg=audit(2022-10-03 13:58:51.203:24596) : proctitle=nslookup serverfault.com 8.8.4.4
type=SOCKADDR msg=audit(2022-10-03 13:58:51.203:24596) : saddr={ fam=inet laddr=8.8.4.4 lport=53 }
type=SYSCALL msg=audit(2022-10-03 13:58:51.203:24596) : arch=x86_64 syscall=sendmsg success=yes exit=33 a0=0x15 a1=0x7f42723ba2e0 a2=0x0 a3=0x7f42723ba520 items=0 ppid=1523 pid=15000 auid=randomuser uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=pts0 ses=2 comm=isc-worker0000 exe=/usr/bin/nslookup key=sendmsg
...
EDIT2:
Here's live printing of the requests, filtered to just destination port 53 (IDK why destination addr+port is laddr
and lport
, it just is):
# tail -f /var/log/audit/audit.log \
| ausearch -i -k sendmsg \
| grep -B1 --line-buffered 'lport=53 ' \
| sed 's/ : / :\n /'
type=PROCTITLE msg=audit(02/14/2023 16:20:05.022:135695) :
proctitle=dig +short www.google.com @8.8.8.8
type=SOCKADDR msg=audit(02/14/2023 16:20:05.022:135695) :
saddr={ fam=inet laddr=8.8.8.8 lport=53 }
EDIT3:
And here's the TCP version, since DNS can do UDP or TCP:
# auditctl -a exit,always -F arch=b64 -S connect -k MYCONNECT
# tail -f /var/log/audit/audit.log \
| ausearch -i -k MYCONNECT \
| grep -B1 --line-buffered 'lport=53 ' \
| sed 's/ : / :\n /'
type=PROCTITLE msg=audit(02/14/2023 16:32:18.168:208235) :
proctitle=/usr/bin/python3 /home/user/run_test.py
type=SOCKADDR msg=audit(02/14/2023 16:32:18.168:208235) :
saddr={ fam=inet laddr=127.0.0.1 lport=53 }
Making it ignore 127.0.0.1 is left as an exercise for the reader. :-)