ss program is using a
sock_diag(7) netlink socket to retrieve information about sockets. But the
sock_diag interface doesn't support a "monitor"/watching/listening mode, as
rtnetlink(7) does. You can only do queries via a
You can however capture the tcp syn (=connect) packets via pcap/tcpdump and use to
sock_diag interface to find process info about them.
But there are at least three serious problems with this:
all the command line utilities able to query and display that info (
lsof) are very rigid, and it's hard to impossible to configure their output format or let them act as a filter. From the command line all you can possibly do is run a separate
ss instance for each packet.
it's racy; the process may have already finished in the time between capturing the packet and querying information about the process.
tcpdump itself is as easy to use from a script as
Keeping all this in mind, something like this may do, or at least may be a start:
script /dev/null -qc "tcpdump -qn -iany '
((tcp[tcpflags] & tcp-syn) != 0 or (ip6 and (ip6[13 + 40] & 2) == 2)) and ($*)
' 2>/dev/null" </dev/null |
perl -ne 'print; next unless /(\S+)\.(\d+) >/; print qx(ss -Hp src "[$1]:$2") =~ s/.*users:/\t/r'
>>> socmon dst port 9999
07:14:59.700995 IP6 fe80::89c8:7f7c:29f5:78df.50720 > fe80::89c8:7f7c:29f5:78df.9999: tcp 0
07:15:08.868555 IP 127.0.0.1.42784 > 127.0.0.1.9999: tcp 0
07:15:17.055518 IP 172.31.255.1.39700 > 172.31.255.1.9999: tcp 0
script /dev/null ... </dev/null forces
tcpdump to use line buffering;
tcpdump -l will NOT do without an artificial delay between capturing the packet and printing it.
(ip6 and (ip6[13 + 40] & 2) == 2) checks if it's a SYN packet BY HAND because
tcp[tcpflags] & tcp-syn doesn't work with IPv6.
The perl thing extracts the source address and port from the tcpdump output, calls
ss with them as a filter argument, and trims the
ss output to show only the process info.
A better idea, not developed here
You could redirect the ports with iptables or nftables to another port, where a listening program could retrieve info about its peer before accepting the connection, and then will forward the connection to the destination. This would fix both the race, and won't be confused by processes which connect somewhere, then either pass or leak the socket file descriptor to other processes.