Setting Up a Man In The Middle Raspberry Pi Monitor

Originally published December 19, 2020 on Medium.com

Summary

This article assumes you have a running Raspberry Pi (Pi 3 or newer) server running either Ubuntu Server or Raspbian. This guide was written using Ubuntu 20.04 - but you can also use Raspbian and its built-in raspi-config if you choose.

What we are going to set up is a Raspberry Pi that is configured to act as a “man in the middle” (MITM) for anything that is connected to its LAN port. This can be useful if you want to connect something like a wireless router to the Pi so you can capture wireless traffic from a target IOT device. The Pi will act as a router of its own over the Ethernet port, and will forward all traffic to the router that the Pi itself is connected to over WiFi .

Connecting the Pi to WiFi

First, lets update our Pi to the most recent software versions:

ubuntu@ubuntu:~$ sudo apt update
ubuntu@ubuntu:~$ sudo apt upgrade -y

Now we will set up the WIFI. Grab the interface names:

eth0 lo wlan0

Then we will want to modify the netplan init file:

ubuntu@ubuntu:~$ sudoedit /etc/netplan/50-cloud-init.yaml

Modify it so that it looks like this, but with your WiFi information filled out (you must keep the SSID and password in quotes):

network:
    ethernets:
        eth0:
            dhcp4: true
            optional: true
    version: 2
    wifis:
        wlan0:
            optional: true
            access-points:
                "SSID-NAME-HERE":
                    password: "PASSWORD-HERE"
            dhcp4: true

Go ahead and reload the netplan and check your network interfaces:

ubuntu@ubuntu:~$ sudo netplan apply
ubuntu@ubuntu:~$ ifconfig

You should be able to see your WiFi interface now has an IP address:

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.19  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::ba27:ebff:fea5:79b0  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:a5:79:b0  txqueuelen 1000  (Ethernet)
        RX packets 12  bytes 1152 (1.1 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 13  bytes 2088 (2.0 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Great! These changes should persist through reboots. I suggest logging into your main WiFi router and setting a static DHCP reservation for the MAC address of your Pi’s wireless network interface. Doing so will make it easy for you since you will only ever need to memorize one IP address for your Pi (at least on this network).

Configure DHCP Server

This portion is heavily from this article, I suggest you give them a click. You will need to configure the Raspberry Pi’s ethernet interface to run DHCP. Start with installing an application to assist us:

ubuntu@ubuntu:~$ sudo apt install isc-dhcp-server

After this has been installed we will go back to our netplan file and configure the ethernet port to be static:

network:
    ethernets:
        eth0:
            addresses:
            - 10.10.10.1/24
            dhcp4: false
            optional: true
            nameservers:
                addresses:
                - 8.8.8.8
                - 8.8.4.4
                search: []
    version: 2
    wifis:
        wlan0:
            optional: true
            access-points:
                "SSID-NAME-HERE":
                    password: "PASSWORD-HERE"
            dhcp4: true

Now backup your config and apply:

ubuntu@ubuntu:~$ cp /etc/netplan/50-cloud-init.yaml ~
ubuntu@ubuntu:~$ sudo netplan generate
ubuntu@ubuntu:~$ sudo netplan apply

Now we need to mess with the DHCP application settings. We will need to tell it which IP interface to use:

ubuntu@ubuntu:~$ sudo vi /etc/default/isc-dhcp-server

Set it up as shown, leaving IPv6 commented out for now:

INTERFACESv4="eth0"
#INTERFACESv6="eth0"

I followed the guide for reference [2] for this portion of the setup, and I ended up using/un-commenting these settings:

option domain-name "lel.co";
option domain-name-servers 8.8.8.8, 8.8.4.4;
default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;
authoritative;
subnet 10.10.10.0 netmask 255.255.255.0 {
    range 10.10.10.2 10.10.10.254;
    option subnet-mask 255.255.255.0;
    option routers 10.10.10.1;
    option broadcast-address 10.10.10.255;
}

Connect something to your ethernet port on your Pi (or ensure eth0 is “up” in another fashion) After the lights on the port turn on check that it has an IP address, then go ahead and start up dhcpd:

ubuntu@ubuntu:~$ ip a | grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
 inet 10.10.10.1/24 brd 10.10.10.255 scope global eth0
ubuntu@ubuntu:~$ sudo systemctl restart isc-dhcp-server
ubuntu@ubuntu:~$ sudo systemctl status isc-dhcp-server

You will need to start this application manually after something has “lit up” your ethernet port lights. Connect something that wants DHCP to this port, then run the restart command.

Acting as a router

Next we will configure the firewall to forward requests appropriately. First enable Uncomplicated Firewall and edit the configuration:

ubuntu@ubuntu:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
ubuntu@ubuntu:~$ sudo vi /etc/ufw/sysctl.conf

Un-comment this line: net/ipv4/ip_forward=1

When you are done with this, ensure to enable ssh access in ufw otherwise you will need to physically connect to your Pi for access after your next reboot:

ubuntu@ubuntu:~$ sudo ufw allow ssh

Then, modifying a script supplied here, we place a script at /etc/rc.local. Here is my modified version for wlan0:

#!/bin/bash
# /etc/rc.local
# Default policy to drop all incoming packets.
iptables -P INPUT DROP
iptables -P FORWARD DROP
# Accept incoming packets from localhost and the LAN interface.
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT
# Accept incoming packets from the WAN if the router initiated the connection.
iptables -A INPUT -i wlan0 -m conntrack \
 - ctstate ESTABLISHED,RELATED -j ACCEPT
# Forward LAN packets to the WAN.
iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
# Forward WAN packets to the LAN if the LAN initiated the connection.
iptables -A FORWARD -i wlan0 -o eth0 -m conntrack \
 - ctstate ESTABLISHED,RELATED -j ACCEPT
# NAT traffic going out the WAN interface.
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
# rc.local needs to exit with 0
exit 0

Make the script executable and reboot the machine. Ensure you set ssh to allow in ufw:

ubuntu@ubuntu:~$ sudo chmod 755 /etc/rc.local
ubuntu@ubuntu:~$ sudo reboot

MITM Monitoring

Now you will want to connect some ethernet capable device, that uses DHCP, to the ethernet port on your Raspberry Pi. Then while that is doing its business, run this command and press Ctrl-C after about a minute:

ubuntu@ubuntu:~$ sudo tcpdump -w test.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C41 packets captured
41 packets received by filter
0 packets dropped by kernel

Now if we open this test.pcap file we will see the traffic from both interfaces on the Pi. In my below example, I successfully capture the traffic from my Valve Steam Link device.

https://miro.medium.com/max/1400/1*aBRHkAhBNKS7Qenrix_P4w.png

There are plenty of uses for such a setup, including connecting the WAN port of a secondary WiFi router to the ethernet port on your Pi, starting up dhcpd, and capturing packets from whatever IOT devices you then connect to the secondary router.

Bibliography

[1] https://linuxconfig.org/ubuntu-20-04-connect-to-wifi-from-command-line

[2] https://www.ascinc.com/blog/linux/how-to-build-a-simple-router-with-ubuntu-server-18-04-1-lts-bionic-beaver/

More Reading

Like this? Maybe you will want to read my CTF writeups! This post also appeared on my professional blog at https://medium.com/lets-eat-labs-blog