Could mitmproxy be used for reverse proxy for multi sites?

I saw mitmproxy could be used as reverse proxy for one single site using the following command:

mitmproxy -R http://www.test.com -p 80

But I’m not sure could this be used for multi site in one command. For example, I want it as reverse proxy for www.test.com and img.test.com and static.test.com, but when I read the docs, it says: only one site could be used one time.

So, may I do this by the script of mitmproxy?

Thanks very much.

You can re-route requests to different servers in reverse proxy mode. That being said, most of the time you probably want to run mitmproxy as a regular proxy then. If you are unsure, please take a look at http://docs.mitmproxy.org/en/stable/modes.html. :slight_smile:

If you know what you are doing and you still want to run as a reverse proxy, take a look at this:

Hi, Hils.

Thanks for your reply.

The reason I use reverse proxy is that suppose Evil and Victim is in under same route, Evil is able to change the DNS setting of the route. So, Victim got the wrong DNS result of some website like *.test.com point to the same IP: Evil’s IP.

So now it’s turn of mitmproxy. I want mitmproxy serve as a website which could response the request of a.test.com, b.test.com, c.test.com and so on. So I think I should use reverse proxy mode as the other modes could not act as a webserver. But I’m not sure whether I am understanding correctly.

The command I run is:

mitmdump -R http://us.yahoo.com -p 80 -s redirect.py

I run it on my computer for experiment. And I set the DNS on my computer:

127.0.0.1 it.yahoo.com
127.0.0.1 news.yahoo.com

Then I just visit news.yahoo.com on my computer, and I was getting the result of us.yahoo.com

What I want is I visit it.yahoo.com, mitmproxy give me the result of it.yahoo.com. And when I visit news.yahoo.com, mitmproxy give me the result of news.yahoo.com.

I tried https://github.com/mitmproxy/mitmproxy/blob/master/examples/complex/dns_spoofing.py and found that when I was visiting news.yahoo.com, the script shows that in request flow.request.pretty_host is not news.yahoo.com but us.yahoo.com in the command line.

I tried read the source and found in mitmproxy\protocol\http.py:194

        # update host header in reverse proxy mode
        if self.config.options.mode == "reverse":
            if six.PY2:
                flow.request.headers["Host"] = self.config.upstream_server.address.host.encode()
            else:
                flow.request.headers["Host"] = self.config.upstream_server.address.host
        # set upstream auth
        if self.mode == "upstream" and self.config.upstream_auth is not None:
            flow.request.headers["Proxy-Authorization"] = self.config.upstream_auth
        self.process_request_hook(flow)

This means before process_request_hook, the host in header was replace by self.config.upstream_server.address.host which is us.yahoo.com. So I don’t think the script dns_spoofing.py will work.

So, could I read the raw header in request stub in scripting? So I can replace the host header correctly. I didn’t found a proper way to do this. I’m not sure if flow.client_conn could be used for this.

Thanks very much!

hello @mhils could you help to have a look?

Thanks very much.

Thanks for investigating this. You should still be able to see the original header in requestheaders instead of request. If that’s the case, I’d be more than happy if you could send a quick PR that fixes the example!

Thanks,
Max

Sorry for the late reply.

I searched “requestheaders” in mitmproxy, found the following:

Occurrences of ‘requestheaders’ in Directory Lib\site-packages\mitmproxy with mask '*.py’
Lib\site-packages\mitmproxy\controller.py
"requestheaders",
Lib\site-packages\mitmproxy\flow\master.py
yield “requestheaders”, f
def requestheaders(self, f):
Lib\site-packages\mitmproxy\protocol\http.py
self.channel.ask(“requestheaders”, flow)

But requestheaders could not be visited in the context of request function in my custom script.

So is there another way to find the raw header from client in the context of request function?

My script is very simple and looks just like this:

def request(flow):
print(flow.requestheaders)

hello @mhils could you please have a look? Thanks very much.

Hello, dns_spoofing.py is now fixed on mitmproxy master branch :sunglasses:

1 Like