A tool to help determine the (socket) addresses being used by socket syscalls.
This uses aya to attach eBPF tracepoints to some events like:
- Syscalls that involve
sockaddr
types likebind
andconnect
. - The
sock:inet_sock_set_state
event which is called whenever there's a TCP socket changes state.
For every event in the above list it will print a line containing information like the pid, file descriptor, socket address contents (address and port) and the return value for each syscall.
The output looks something like:
Chrome_ChildIOT/135876/53 syscall::bind(0.0.0.0:22317) = 0
Chrome_ChildIOT/135876/53 syscall::connect(127.0.0.53:53) = 0
Chrome_ChildIOT/135876/57 syscall::bind(0.0.0.0:44155) = 0
Chrome_ChildIOT/135876/57 syscall::connect(127.0.0.53:53) = 0
systemd-resolve/912/17 syscall::connect(192.168.0.1:53) = 0
systemd-resolve/912/18 syscall::connect(192.168.0.1:53) = 0
Chrome_ChildIOT/135876 socket::set_state(192.168.0.2:0 <-> 192.30.255.113:443) Close -> SynSent
Chrome_ChildIOT/135876/57 syscall::connect(192.30.255.113:443) = -115 [EINPROGRESS]
While tools like strace
give you great insights into what syscalls a process and all of its children are invoking,
they don't let you get information outside that process tree. For example, if I wanted to see which processes are
attempting to bind to a specific port, I wouldn't be able to spot that via strace.
Tools like perf
allow you to use tracepoints to trace syscalls, but they don't allow expanding the contents of
sockaddr
pointers being passed in to syscalls (at least not yet).
This tool tries to bridge that gap by letting you trace these syscalls globally and providing insights into what's the
socket address behind each sockaddr
parameter.
In order to build sockwho, install rust and run
make release
The output binary will be placed in target/release/sockwho
.
Simply run the binary to hook into all supported syscalls and events. Otherwise pass a subset of them as an argument:
# Only trace connect syscalls
sockwho connect
The formats used for every traced event is:
<process-name>/<pid>/<fd> syscall::<syscall-name>(<socket-address>) = <return code> [errno if applicable]
<process-name>/<pid> socket::set_state(<local-address> <-> <remote-address>) <old-tcp-state> -> <new-tcp-state>