The nsntrace application uses Linux network namespaces and iptables magic to perform network traces of a single application. The traces are saved as pcap files and can be analyzed by for instance wireshark or tshark
In May of 2020 nsntrace moved to a collaborative maintenance model and to its own GitHub organisation. This helped a lot with my guilt for neglecting its maintenance. We even managed to get some pull requests merged and some issues solved.
For the new release we landed some notable pull requests.
On many systems the nameserver functionality is handled by an application such as systemd-resolved or dnsmasq and the nameserver address in resolv.conf is a loopback address (like 127.0.0.53) where that application listens for incoming DNS queries.
This would not work for us since the network namespace we create has its own separate loopback device and cannot reach the one where systemd-resolved or dnsmasq listens. If somebody reading this has a solution to this problem, please let us know in the comments or via GitHub!
What we ended up doing were two things. First we added a warning output for when we detect only loopback nameservers. And second we offer a new --use-public-dns command line option to override the system resolv.conf in our namespace.
In order to have our own nameservers for our network namespace we will bind mount our own resolv.conf file, with public nameservers from Cloudflare, OpenDNS and Quad9, over the one in /etc/resolv.conf.
But we do not want to affect other applications outside of our namespaced application, so we enter a mount namespace (CLONE_NEWNS) before we do the bind mount.
This, however, is not enough. Before the bind mount we need to remount the root partition with special mount flags to make sure our changes to the subtree are not propagated to the outside mount namespace.
This is basically how the ip-netns tool allows for namespace specific nameservers as well.
This started as an issue from a user that reported:
I am using nsntrace to dump and analyze a processes network traffic in real time. In order to do that, I need to get the network dump piped to another process, not written to a file.
We got this implemented and we made sure to write all non-pcap output to stderr in the case of a lone dash filename being detected. We also made sure that the application under trace behaves by replacing its stdout file descriptor with stderr, using the dup2 syscall.
This change enables us to do live packet capture using tshark.
To give a network namespace a name in the eyes of tools like ip-netns we need to bind mount /proc/<pid>/net/ns/ to /run/netns/NAME. It is described in the man page of ip-netns:
By convention a named network namespace is an object at /run/netns/NAME that can be opened. The file descriptor resulting from opening /run/netns/NAME refers to the specified network namespace. Holding that file descriptor open keeps the network namespace alive. The file descriptor can be used with the setns(2) system call to change the network namespace associated with a task.
By implementing this, the nsntrace network namespace will show up when we use ip-netns.
And we might even use ip-netns to enter the same network namespace as a running nsntrace process.
By adding a snapcraft.yaml file we enable building a snap package of nsntrace and adding it to the snapcraft app store. Which might mean more people can find nsntrace, and that the maintenance team get a bit more control of distribution of nsntrace.
Thanks for reading! And check out the new release!