Weekly - issue 44

How to know which program sent a network request

sudo tcpdump -i any -n -k INPD port 53

We can also write captured network packets to a file, then read it later.

sudo tcpdump -i any -n -k INPD port 53 -w /<file path>/tcpdump-output.pcap

tcpdump -n -k INPD -r /<file path>/tcpdump-output.pcap

-i any, tcpdump listens on all interfaces.

-n, tcpdump doesn’t convert addresses (e.g., host addresses, port numbers) to names.

-k, control the display of packet metadata via an optional argument (e.g., INPD).

port 53, a packet filter expression. Here we only capture DNS packets.

The metadata arguments:

  • I: interface name.

  • N: process name.

  • P: process ID.

  • D: direction.

The sample output of tcpdump:

10:57:45.835947 (eth0, proc dig:3437, out) IP 192.168.1.20.57959 > 192.168.1.1.53: 33994+ [1au] A? gitlab.com. (39)
10:57:45.842205 (eth0, proc dig:3437, in) IP 192.168.1.1.53 > 192.168.1.20.57959: 33994 1/0/0 A 172.65.251.78 (44)

The sample packets generated by a shell command dig gitlab.com.

eth0, proc dig:3437, out, eth0, proc dig:3437, in are what we want.

  • eth0 is the interface name

  • dig is the process name

  • 3437 is the process ID

  • out indicates the network request is send by the device

  • in indicates the network request is received by the device

Python subprocess and stderr

Pipe output of cmd1 into cmd2 and capture the stderr.

p1 = subprocess.Popen(cmd1,
  stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
p2 = subprocess.Popen(cmd2, stdin=p1.stdout,
  stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
p1.stdout.close()
p1_stderr = p1.communicate()
p2_stderr = p2.communicate()
return p1.returncode or p2.returncode, p1_stderr, p2_stderr

The above saves the p1.stdout in memory, if the amount piped becomes large enough, we should use the following code:

with tempfile.TemporaryFile() as errfile:
    p1 = subprocess.Popen(cmd1,
      stdout=subprocess.PIPE, stderr=errfile, close_fds=True)
    p2 = subprocess.Popen(cmd2, stdin=p1.stdout,
      stdout=subprocess.PIPE, stderr=errfile, close_fds=True)
    p1.stdout.close()
    p2.communicate()
    p1.wait()
    errfile.seek(0)
    px_stderr = errfile.read()
return p1.returncode or p2.returncode, px_stderr