mkiesel.ch

Setup Raspberry Pi & mitmproxy

21. Feb 2023, by manu in posts

Sometimes programs do not have a proxy option and/or ignore the system-wide proxy. In this case, you can try a tool like proxychains↗. Despite this, some developers want to hide something so badly that they even ignore or circumvent such options. For those cases, or just for convenience, you need to interact with the traffic after it has left your client. This guide will show you how to set up mitmproxy↗ on a Raspberry Pi 4 to sniff both ethernet and Wi-Fi traffic.

This guide is largely based on dinofizzottis guide↗.

Requirements #

Older Raspberry Pi’s and alternative Linux SBCs should also work. Keep in mind that you need two ethernet and one Wi-Fi card for this setup. Also, this is not a beginner’s guide and was written with some Raspberry Pi & Linux know-how in mind!

Flash SD Card #

First, you need to flash the SD card with the “Raspberry Pi OS”. For this use the official Raspberry Pi Imager↗. Download and install the software based on your own operating system.

Inside the imager choose “Raspberry Pi OS Lite 64bit” as the OS option. Also under advanced options, edit the settings to your needs. I changed the hostname and added a user and my SSH key. Add a user here or you’ll need a keyboard and monitor upon booting the Pi for the first time.

Pi in the Middle Build

Updates & Prerequisites #

After flashing the SD card:

After that, get a shell onto the Pi. First, update the operating system and install dependencies. Service startup errors can be ignored for now.

sudo apt update
sudo apt full-upgrade -y
sudo apt autoremove -y
sudo apt install iptables hostapd isc-dhcp-server iptables-persistent -y

Configuration #

isc-dhcp-server #

If the Pi acts as a DHCP server, it’s not needed to set static IP on clients that you want to sniff. For this to work, you need to configure the DHCP server that was installed before. First, identify your network interfaces. The built-in ethernet should be eth0 and the built-in Wi-Fi should be wlan0. You need to remember the interface name of your USB dongle. Normally this should be eth1. For the rest of this guide, eth1 will be used when referencing the USB ethernet dongle.

Give both wlan0 and eth1 a static IP address. For this edit the file /etc/dhcpcd.conf with your favorite text editor. Append to the file the following lines. This will give wlan0 the static IP 192.168.45.1/24 and eth1 the static IP 192.168.46.1/24. Restart the network service or just boot the Pi after adding those lines.

interface wlan0
static ip_address=192.168.45.1/24
nohook wpa_supplicant

interface eth1 
static ip_address=192.168.46.1/24
nohook wpa_supplicant

To configure the DHCP server itself, edit the file /etc/dhcp/dhcpd.conf:

# comment out
#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

# uncomment
authoritative;

# append
include "/etc/dhcp/dhcpd_wlan0.conf";
include "/etc/dhcp/dhcpd_eth1.conf";

Create /etc/dhcp/dhcpd_wlan0.conf:

subnet 192.168.45.0 netmask 255.255.255.0 {
    range 192.168.45.10 192.168.45.254;
    option broadcast-address 192.168.45.255;
    option routers 192.168.45.1;
    option domain-name "local";
    option domain-name-servers 9.9.9.9, 9.9.9.11;
}

And also create /etc/dhcp/dhcpd_eth1.conf:

subnet 192.168.46.0 netmask 255.255.255.0 {
    range 192.168.46.10 192.168.46.254;
    option broadcast-address 192.168.46.255;
    option routers 192.168.46.1;
    option domain-name "local";
    option domain-name-servers 9.9.9.9, 9.9.9.11;
}

Those files will make the DHCP server give out addresses on both subnets with dynamic addresses from .10 to .254. You can set the DNS servers to servers of your choice.

After those two config files have been made, you need to tell the DHCP server on which interface to listen and answer. This can be configured inside /etc/default/isc-dhcp-server:

# uncomment and edit
INTERFACESv4="wlan0 eth1"

The DHCP server will throw an error upon starting the Pi. This is normal since the interfaces are not ready when the service for the DHCP server starts. To get around this issue, here is a solution from StackExchange↗.

Inside /etc/systemd/system/isc-dhcp-server.service edit:

# change
Restart=on-failure
RestartSec=5

# append
[Install]
WantedBy=multi-user.target

Then reload the service with:

sudo systemctl daemon-reload
sudo systemctl disable isc-dhcp-server
sudo systemctl enable isc-dhcp-server

hostapd #

# copy the default config
sudo cp /usr/share/doc/hostapd/examples/hostapd.conf /etc/hostapd/hostapd.conf

This will manage the Wi-Fi hotspot for wireless devices to connect to. After copying the default config with the command above, edit the config file /etc/hostapd/hostapd.conf. This file is quite big and contains many settings. Below are the relevant lines. Search them and change them accordingly. Some lines will be commented out, uncomment them. driver=nl80211 did not yet exist on my Pi, so I added it to the top.

The Wi-Fi channel can be 1,6 or 11. (2.4GHz). Change ssid and wpa_passphrase to your liking and set the country code to your country.

interface=wlan0
driver=nl80211

country_code=CH
channel=6

wpa=2
ssid=mitmproxy
wpa_passphrase=mitmproxy
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Specify the config path for the file you just edited inside /etc/default/hostapd:

# uncomment and edit
DAEMON_CONF="/etc/hostapd/hostapd.conf"

Unmask the service and add it to the startup:

sudo systemctl unmask hostapd.service
sudo systemctl enable hostapd.service

mitmproxy #

Once the Pi is rebooted, log back in. Now you need to install the proxy itself. Without compiling the software yourself, the installation via pipx of the only option since there are currently no precompiled binaries for arm64. To install via pipx, install some Python dependencies first:

sudo apt install python3-pip python3-venv -y

Then switch to a root shell with sudo su and install pipx and mitmproxy with:

pip install pipx
pipx install mitmproxy

To automatically start the proxy, add a small bash script. Edit /opt/mitm.sh

#!/bin/sh
/root/.local/bin/mitmweb --mode transparent --web-port 9090 --web-host 0.0.0.0 &

Make the script executable with chmod +x /opt/mitm.sh and add it as a cronjob. To edit cronjobs, still, as the root user, run crontab -e, select your favorite text editor, and append:

@reboot /opt/mitm.sh

Reboot the Pi. After logging back in, check that the web interface is reachable via port 9090. If not, try to start the proxy by hand with sudo sh /opt/mitm.sh and look for error messages.

Webinterface Screenshot

iptables #

To forward incoming traffic on both interfaces some IP table rules need to be configured. Execute the following commands to enable the required rules.

# forward traffic coming from wlan0 to eth0
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

# forward traffic coming from eth1 to eth0
sudo iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

# turn on masquerading or your client wont have internet access
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# force the traffic from ports 80,443,8080,8443 into the http proxy
# you can add more ports here with a line each for wlan0 and eth1
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
sudo iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8080
sudo iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8080
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp -m tcp --dport 8080 -j REDIRECT --to-ports 8080
sudo iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 8080 -j REDIRECT --to-ports 8080
sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp -m tcp --dport 8443 -j REDIRECT --to-ports 8080
sudo iptables -t nat -A PREROUTING -i eth1 -p tcp -m tcp --dport 8443 -j REDIRECT --to-ports 8080

Those rules are by default reset upon reboot so you’ll need to make them permanent. This is done by saving them into the file /etc/iptables/rules.v4 which is reloaded at boot when you have iptables-persistent installed.

sudo iptables-save | sudo tee /etc/iptables/rules.v4

As a final step on the Pi, general traffic forwarding needs to be enabled by editing /etc/sysctl.conf. Reboot the Pi when done.

# uncomment
net.ipv4.ip_forward=1

Client Setup #

To set up a client connect it first via ethernet or the Wi-Fi access point. It should get an IP address from the DHCP server configured before. Some warning of SSL errors may appear and in some cases, the device will even think that it has no internet connection. This is because the device does not yet trust the generated certificate of the proxy.

To install this certificate, visit “http://mitm[.]it” with the connected device. On this site, you will find a guide on how to install the certificate for all common devices and operating systems. This certificate is unique per installation of mitmproxy. This means that your device will not trust the certificate of another installation.

Install Certificate Guide Screenshot

With the certificate trusted, you should now be able to see traffic inside the management web interface of the proxy as long as the sender does not rely on certificate pinning.

Traffic Flow Screenshot