Skip to content

Perform network trace of a single process by using network namespaces.


Notifications You must be signed in to change notification settings


Folders and files

Last commit message
Last commit date

Latest commit



81 Commits

Repository files navigation


Perform network trace of a single process by using network namespaces.

This application uses Linux network namespaces to perform a network trace of a single application. The trace is saved as a pcap file. And can later be analyzed by for instance Wireshark or tshark.

The nsntrace application is heavily inspired by the askbubuntu reply here. And uses the same approach only confined to a single C program.

What the application does is use the clone syscall to create a new network namespace (CLONE_NEWNET) and from that namespace launch the requested process as well as start a trace using libpcap. This will ensure that all the packets we trace come from the process.

The problem we are left with is that the process is isolated in the namespace and cannot reach any other network. We get around that by creating virtual network interfaces. We keep one of them in the root network namespace and but the other one in the newly created one where our tracing takes place. We set the root namespaced one as the default gateway of the trace namespaced virtual device.

And then to make sure we can reach our intended net, we use iptables and NAT to forward all traffic from the virtual device to our default network interface.

This will allow us to capture the packets from a single process while it is communicating with our default network. A limitation is that our ip address will be the NAT one of the virtual device.

Another limitation is, that since we are using iptables and since we are tracing raw sockets. This application needs to be run as root.

On many systems today the nameserver functionality is handled by an application such as systemd-resolved or dnsmasq and the nameserver address is a loopback address (like where that application listens for incoming DNS queries.

This will not work for us in this network namespace environment, since we have our own namespaced loopback device. To work around this one can use the --use-public-dns option to override resolv.conf in the namespace. Then nsntrace will use nameservers from Quad9 (, Cloudflare (, Google ( and OpenDNS ( to perform DNS queries.


$ nsntrace
usage: nsntrace [options] program [arguments]
Perform network trace of a single process by using network namespaces.

-o file          	send trace output to file (default nsntrace.pcap)
-d device        	the network device to trace
-f filter        	an optional capture filter
-u username      	run program as username/uid
--use-public-dns	override resolv.conf to use public nameservers from
                	Quad9, Cloudflare, Google and OpenDNS


$ sudo nsntrace -d eth1 wget
Starting network trace of 'wget' on interface eth1.
Your IP address in this trace is
Use ctrl-c to end at any time.

--2016-07-15 12:12:17--
Location: [following]
--2016-07-15 12:12:17--
Length: unspecified [text/html]
Saving to: ‘index.html’

index.html                                         [ <=>                                                                                                   ]  10.72K  --.-KB/s   in 0.001s

2016-07-15 12:12:17 (15.3 MB/s) - ‘index.html’ saved [10980]

Finished capturing 42 packets.

$ tshark -r nsntrace.pcap -Y 'http.response or http.request'
16   0.998839 ->    HTTP 229 GET HTTP/1.1
20   1.010671 -> HTTP 324 HTTP/1.1 302 Moved Temporarily  (text/html)
22   1.010898 ->    HTTP 263 GET HTTP/1.1
31   1.051006 -> HTTP 71 HTTP/1.1 200 OK  (text/html)

live capture using tshark

$ sudo nsntrace -f tcp -o - wget  2> /dev/null | tshark -r -
1   0.000000 → TCP 74 51088 → 80 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1362504482 TSecr=0 WS=128
2   0.014010 → TCP 74 80 → 51088 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1430 SACK_PERM=1 TSval=2846449454 Secr=1362504482 WS=256
3   0.014078 → TCP 66 51088 → 80 [ACK] Seq=1 Ack=1 Win=64256 Len=0 TSval=1362504496 TSecr=2846449454
4   0.014221 → HTTP 207 GET / HTTP/1.1

5   0.033935 → TCP 66 80 → 51088 [ACK] Seq=1 Ack=142 Win=66816 Len=0 TSval=2846449475 TSecr=1362504496
6   0.093989 → TCP 1484 HTTP/1.1 200 OK  [TCP segment of a reassembled PDU]
7   0.094022 → TCP 66 51088 → 80 [ACK] Seq=142 Ack=1419 Win=63360 Len=0 TSval=1362504576 TSecr=2846449532
8   0.096447 → TCP 2902 HTTP/1.1 200 OK  [TCP segment of a reassembled PDU]
9   0.096478 → TCP 66 51088 → 80 [ACK] Seq=142 Ack=4255 Win=62208 Len=0 TSval=1362504578 TSecr=2846449532
10   0.099871 → HTTP 9626 Continuation[Packet size limited during capture]
11   0.099936 → TCP 66 51088 → 80 [ACK] Seq=142 Ack=13815 Win=56320 Len=0 TSval=1362504582 TSecr=2846449532
12   0.100743 → TCP 66 51088 → 80 [FIN, ACK] Seq=142 Ack=13815 Win=64128 Len=0 TSval=1362504583 TSecr=2846449532
13   0.113167 → TCP 66 80 → 51088 [FIN, ACK] Seq=13815 Ack=143 Win=66816 Len=0 TSval=2846449554 TSecr=1362504583
14   0.113190 → TCP 66 51088 → 80 [ACK] Seq=143 Ack=13816 Win=64128 Len=0 TSval=1362504595 TSecr=2846449554

building from source

To build nsntrace from source the following steps are needed:

$ ./
$ ./configure
$ make

And to install:

$ sudo make install


The packages needed to build nsntrace are (Debian/Ubuntu style naming):

  • automake
  • docbook-xml
  • docbook-xsl
  • iptables
  • libnl-route-3-dev
  • lippcap-dev
  • pkg-config
  • xsltproc