Skip to content

Instantly share code, notes, and snippets.

@sbimikesmullin
Created January 28, 2017 17:49
Show Gist options
  • Save sbimikesmullin/2be7d2d1f989506fc910605bbd76d615 to your computer and use it in GitHub Desktop.
Save sbimikesmullin/2be7d2d1f989506fc910605bbd76d615 to your computer and use it in GitHub Desktop.
MITM proxy iptables easy setup
./forward.sh 192.30.253.113 80 172.1.9.1 9000
./forward.sh 192.30.253.113 443 172.1.9.1 9000
vim forward.sh
# setup virtual ips
# detect os
if [ "$(uname -a | cut -d' ' -f1)" == "Linux" ]; then # Ubuntu
sudo ifconfig eth0:1 172.1.9.1 up
sudo ifconfig eth0:2 172.1.9.2 up
elif [ "$(uname -a | cut -d' ' -f1)" == "Darwin" ]; then # OS/X
#sudo ifconfig lo0 alias 172.1.9.1 # alternate version for os/x
#sudo ifconfig lo0 alias 172.1.9.2
fi
# setup MITM itercept
dest=$1
dport=$2
via=$3
vport=$4
sudo iptables -t nat -A OUTPUT -p tcp \
-d $dest --dport $dport -j DNAT --to-destination 127.0.0.1:$vport
sudo iptables -t nat -I OUTPUT -p tcp \
-d $via --dport $dport -j DNAT --to-destination $dest:$dport
:wq
# easy way to reset and test firewall rules
iptables -F -tnat; iptables -F; iptables-restore < table
# the complexity of these rules is unnecessary; there are at least three options
# A) (most complex) besides the actual host:ip, and the mitm proxy host:ip,
# you create a third host using a virtual ip--one per possible actual host:ip
# (also considering DNS resolution of hostnames), so that you have a
# 1:1 NAT of vip->actual ip. this works but has many drawbacks
# B) (medium complexity) create a single vip but give it many ports and map a unique
# port to each possible actual ip (like port forwarding). also works but we can do
# it simpler.
# NOTICE: this may be the only way if you cannot control where the original application
# is connecting. actually (A) might be the only way but i think this will work still.
# basically you can use /etc/hosts to hijack the DNS to point at the MITM ip (localhost)
# but then you can't pick the port. or you can forward the output traffic for every possible
# ip:port that real dns resolves to at the MITM ip, but then the trick is that you make
# the very FIRST rule in the OUTPUT chain the one that if they try to use your vip or
# unique localhost port, then that goes out to destination (end of chain) otherwise
# any attempt to reach the external host is rerouted.
# C) (simplest) do not create any vip. just open ports on localhost and map them to
# other ports on localhost (for mitm tunnel service) or to the final destination.
# e.g.,
# 127.0.0.1:9000 (mitm service)
# 1.2.3.4:443 (actual service)
# 127.0.0.1:9001 (mitm's destination that will succeed to deliver to actual service)
# order rules appear in chain is important
# rule 1: -t nat -A OUTPUT -p tcp -d 127.0.0.1 --dport 9001 -j DNAT --to-destination 1.2.3.4:443 # secret out
# rule 2: -t nat -A OUTPUT -p tcp -d 1.2.3.4 --dport 443 -j DNAT --to-destination 127.0.0.1:9000 # redirected out
# use OUTPUT chain if the traffic would be going out of the box but you want it redirected to localhost
#iptables -t nat -A OUTPUT -p tcp -d 172.17.0.1 --dport 80 -j DNAT --to-destination 172.17.0.1:8090 #failed from inside docker container
# ise PREROUTING chain if the traffic would be incoming to the adapter (which includes docker0 when a container is trying to talk to another container or the host box)
iptables -t nat -A PREROUTING -i docker0 -p tcp -m tcp --dport 80 -j REDIRECT --to-port 8090 # works from inside docker container!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment