mitmproxy on a transparent bridge on Linux
Most of the time, when I am using mitmproxy, I am running in transparent mode - the network is routing packets to the proxy, and the proxy is intercepting them without intentional configuration on the client. This usually requires that I add a router in the path to point at the mitmproxy. However, it should be possible to do this entirely on one box with dual NICs, using a bridge, and then using ebtables (or nftables) to push packets we want to intercept up to the IP layer.
So, here is a script to do just that.
Script⌗
#!/bin/sh
# Transparent bridge with TCP/443 interception via mitmproxy.
UP_IF=enp2s0 # upstream interface (towards the router)
DOWN_IF=enp1s0 # downstream interface (towards the victim)
BR=br0
PROXY_PORT=8080
set -e
# Stop managing devices with NM, clear addresses on those ifaces
nmcli device set "$UP_IF" managed no
nmcli device set "$DOWN_IF" managed no
ip addr flush dev "$UP_IF"
ip addr flush dev "$DOWN_IF"
# Create the bridge and add both interfaces to it
ip link add "$BR" type bridge
ip link set "$UP_IF" master "$BR"
ip link set "$DOWN_IF" master "$BR"
# Bring everything up
ip link set "$UP_IF" up
ip link set "$DOWN_IF" up
ip link set "$BR" up
# Get IPs for the bridge - v6 via accept_ra and v4 via dhclient or static
sysctl -w net.ipv6.conf."$BR".disable_ipv6=0
sysctl -w net.ipv6.conf."$BR".accept_ra=2
#dhclient "$BR"
ip addr add 192.168.0.67/24 dev "$BR"
# Make bridged traffic pass through iptables
modprobe br_netfilter
sysctl -w net.bridge.bridge-nf-call-iptables=1
sysctl -w net.bridge.bridge-nf-call-ip6tables=1
# Get bridge's MAC
BR_MAC=$(cat /sys/class/net/"$BR"/address)
# Redirect traffic to our host at layer 2 - ebtables BROUTE is the old way of doing this, if you've heard of ebtables
nft add table bridge mitm
nft add chain bridge mitm prerouting '{ type filter hook prerouting priority -300; policy accept; }'
nft add rule bridge mitm prerouting meta protocol ip tcp dport 443 meta pkttype set host ether daddr set "$BR_MAC"
nft add rule bridge mitm prerouting meta protocol ip6 tcp dport 443 meta pkttype set host ether daddr set "$BR_MAC"
# Redirect that traffic to mitmproxy's listening port at layer 3
iptables -t nat -A PREROUTING -i "$BR" -p tcp --dport 443 -j REDIRECT --to-port "$PROXY_PORT"
ip6tables -t nat -A PREROUTING -i "$BR" -p tcp --dport 443 -j REDIRECT --to-port "$PROXY_PORT"
# Start mitmproxy in transparent mode in the foreground
# Using emudhra's compromised certificate "4"
mitmproxy --mode transparent --showhost --listen-port "$PROXY_PORT" --emudhra
# Cleanup
nft delete table bridge mitm
ip link del dev "$BR"
read other posts