Tuesday, April 18, 2017

Using cgroups and mitmproxy to listen to traffic on your computer in a transparent proxy scenario

mitmproxy is a great tool to sniff HTTPS traffic but in order to listen to a device you need a separate device running as a transparent proxy. (If you can't or don't want to configure the device to be sniffed.) So you need to do a few extra things if you want to listen to the processes on your own computer without using another one.

I was going to draw some neat diagrams but it is really simple. I guess you already know the problem if you have come this far, but in short:

You have to set some firewall rules to redirect out-going packets back to your computer (and therefore mitmproxy) and now the sniffed / manipulated packets from mitmproxy are also redirected back to mitmproxy and they are re-sniffed and re-manipulated in a loop and no packet can ever leave your computer.

You can write firewall rules specific to processes you want to listen to but they come and go and PIDs change all the time.

Here is my script to setup redirection for a destination host and port and exclude mitmproxy so that the packets can go out after they are processed.
#!/bin/bash

#make sure fw rules are clean before calling

dhost="some_host_without_HSTS.com"
dport="443"
cgroup_cfg_path="/sys/fs/cgroup/net_cls"
cgroup_name="mitm_output"
cgroup_id="0x00110011"

#add new cgroup
sudo mkdir ${cgroup_cfg_path}/${cgroup_name}
sudo sh -c "echo ${cgroup_id} > ${cgroup_cfg_path}/${cgroup_name}/net_cls.classid"

#get first pid returned by ps, which should be our terminal's PID
sudo sh -c "echo $(ps -o pid | sed '2q;d') > ${cgroup_cfg_path}/${cgroup_name}/tasks"

sudo iptables -t nat -A OUTPUT --dst ${dhost} -p tcp --dport ${dport} -m cgroup ! --cgroup ${cgroup_id} -j REDIRECT
#you need to call this with sudo only if you are going to listen a port < 1024
sudo mitmproxy -T -p ${dport}
#now you can quit and start mitmproxy again as many times as you like
Now let’s break it into understandable parts:
mkdir /sys/fs/cgroup/net_cls/new_cgroup_name
echo ${new_cgroup_id} > /sys/fs/cgroup/net_cls/new_cgroup_name/net_cls.classid
This creates a cgroup and assigns a specific id on it. We can put processes inside it and then distinguish their kernel level network behaviour with the cgroup id. We will use this ability to give mitmproxy an exception so that packets can leave OUTPUT chain and go out to the real server.
echo ${pid_of_current_tty} > /sys/fs/cgroup/net_cls/new_cgroup_name/tasks
Add the tty session which is used to run the script to the cgroup. It is much more convenient than starting an mitmproxy process elsewhere and passing its pid because the child processes are also citizens of the cgroup. Once you run the script you will have a terminal and processes you run in it will be able to talk to world without getting redirected.
sudo iptables -t nat -A OUTPUT ${traffic_you_want_to_mitm} -m cgroup ! --cgroup ${new_cgroup_id} -j REDIRECT
In normal transparent proxy scenario you write “-j REDIRECT” rules for PREROUTING chain. That scenario fails when you try to redirect traffic from OUTPUT and then send the same traffic. Here we added an exception rule for our cgroup id. Now the traffic from all the host is redirected back to mitmproxy but traffic from mitmproxy’s cgroup can escape the gravity of iptables.
sudo mitmproxy -T -p ${dport}
Finally start the mitmproxy. You can quit and restart it as much as you want. Just don’t forget to change the arguments to your needs (like adding --insecure if you are mangling SSL traffic for a self-signed certificate). Obviously you don’t need sudo if you will run mitmproxy on a port number larger than 1024. You can also check if the other side of the connection works if you need to.

This neat little trick helped me listen to and debug HTTPS SOAP traffic generated by programs on my computer without needing to redirect between different ports.

I used it to sniff on client programs connecting to a server. I haven’t tried to use it in a reverse proxy scenario but in theory it should work with a little modification. It can be useful to degenerate the traffic to the server for some kinds of stress tests. I will write a sequel if I try and make it work.

This article is inspired by the following blog posts by others:

- How to use mitmproxy to listen your smartphone
- How to use cgroups to make exceptions in network configuration

No comments:

Post a Comment