Giter VIP home page Giter VIP logo

nginx_mitm_docker's Introduction

Nginx HTTP Request Interception Container

Overview

This docker image stands up a copy of Nginx, using a predefined configuration that you can modify using environment variables at run time.

The default configuration is to have a plaintext-listener which proxies onwards (normally to a HTTPS destination), so that you can view/capture requests whilst still having them placed against a HTTPS origin (that you presumably do not control).

This implies some control over the client, as you'll need to be able to do at least one of the following

  • Reconfigure the client to use HTTP rather than HTTPS and
  • Reconfigure the client to connect to a destination of your choosing or
  • Reconfigure local DNS and/or routing so that the client connects to your destination thinking it's going to the original

If you have the ability to install a root certificate on the client or find that it doesn't validate cert chains, then you can also perform a HTTPS-to-plain attack (see Advanced usage for an example)

IMPORTANT: The default behaviour is to run an open proxy


Running

Docker Hub

The image is on Docker Hub so you can run

docker run -p 8080:80 -e SERVER_NAME=repro.bentasker.co.uk -e DEST=https://www.google.com bentasker12/nginx_simple_mitm

Locally

Or, to run from a copy of this repo

docker build -t nginx_mitm .
docker run -p 8080:80 -e SERVER_NAME=repro.bentasker.co.uk -e DEST=https://www.google.com nginx_mitm

Config etc

Environment Vars

The Nginx configuration is influenced by a set of environment variables:

  • SERVER_NAME: The HTTP host header the config should answer to (default is _ - which answers everything)
  • DEST: Where requests should be sent on to, this must include scheme (e.g. https://example.com not just example.com). Nginx variables can be used here for more advanced usage.
  • DNS_RESOLVER: A DNS server that Nginx should use when resolving upstream names. Defaults to 8.8.8.8

Logging

Logs are written to stdout and have the following format:

log_format  main  '$remote_addr\t-\t$remote_user\t[$time_local]\t$server_name\t"$request"\t'
                '$status\t$body_bytes_sent\t"$http_referer"\t'
                '"$http_user_agent"\t"$http_x_forwarded_for"\t$request_time\t"$http_host"\tForwarded to:\t$upstream_addr\t'
                '\t$upstream_bytes_received\t"$upstream_http_server"\t$upstream_connect_time\t$upstream_status\t$upstream_response_time\t';

Ports

The Dockerfile lists TCP 80 and TCP 443 as being exposed.

However, at runtime you can publish these to whatever port you need to (you'll need to be a privileged user to publish to port numbers < 1024).

In the examples given, port 80 is published to 8080 on the host: -p 8080:80


Usage

Using a custom server name and forwarding to Google:

docker run -p 8080:80 -e SERVER_NAME=repro.bentasker.co.uk -e DEST=https://www.google.com bentasker12/nginx_simple_mitm
curl http://127.0.0.1:8080 -H "Host: repro.bentasker.co.uk"

Giving log-line:

172.17.0.1	-	-	[25/Aug/2021:09:58:30 +0000]	repro.bentasker.co.uk	"GET / HTTP/1.1"	200	15174	"-"	"curl/7.74.0"	"-"	0.100	"repro.bentasker.co.uk"	Forwarded to:	142.250.180.4:443		15772	"gws"	0.040	200	0.100

Accepting anything and forwarding to Google

docker run -p 8080:80 -e DEST=https://www.google.com bentasker12/nginx_simple_mitm

Using as a wildcard proxy

This is the default configuration, this section exists simply to explain how it works

To do this, we pass an Nginx variable in the DEST env var:

docker run -p 8080:80 -e DEST='https://$http_host' bentasker12/nginx_simple_mitm

Any HTTP request will then be proxied onto it's destination:

curl http://127.0.0.1:8080 -H "Host: snippets.bentasker.co.uk"

Giving logline

172.17.0.1	-	-	[25/Aug/2021:10:07:13 +0000]	_	"GET / HTTP/1.1"	200	8116	"-"	"curl/7.74.0"	"-"	0.193	"snippets.bentasker.co.uk"	Forwarded to:	195.181.164.178:443		9177	"BunnyCDN-UK1-656"	0.072	200	0.140

If 8.8.8.8 isn't reachable by the docker container, you'll need to specify an alternate DNS resolver with -e DNS_RESOLVER=[ip:[port]]. Acceptable format is detailed in the Nginx docs


Advanced

Providing additional configuration files

The default config stands up a single server block on port 80.

You might want to be able to do more than this though. The Nginx configuration is set up to pull in any files ending in .conf within /etc/nginx/conf.d so you can tell Docker to export this directory from your local filesystem

docker run -v /full/path/to/dir:/etc/nginx/conf.d -p 8080:80 bentasker12/nginx_simple_mitm

Note: there must be at least 1 .conf file present, even if it's empty, otherwise some versions of Nginx will fail to start.

This allows you to achieve a variety of ends, including setting up a simple HTTPS mitm:

server {
        listen 443;

        server_name snippets.bentasker.co.uk;

        ssl on;
        ssl_certificate /etc/nginx/conf.d/mycert.crt;
        ssl_certificate_key /etc/nginx/conf.d/mycert.key;

        root /usr/share/nginx/empty;
        index index.php index.html index.htm;

        location / {
            proxy_set_header Host plaintext_proxy;
            proxy_pass http://127.0.0.1:9080;
        }
}

server {
        listen   127.0.0.1:9080;

        root /usr/share/nginx/empty;
        index index.php index.html index.htm;

        server_name plaintext_proxy;

        location / {
            proxy_pass https://snippets.bentasker.co.uk;
        }
}

Where your exported directory also contains mycert.crt and mycert.key (assuming you can have the client app trust the certs).

Traffic could then be captured as follows

docker run --name=nginx_mitm -v /home/ben/tmp/nginxconfs:/etc/nginx/conf.d -v /home/ben/tmp/pcaps:/root/pcaps bentasker12/nginx_simple_mitm
docker exec -it nginx_mitm tcpdump -i lo -s0 -w /root/pcaps/cap.pcap -v port 9080

(In our example config, the plaintext version of the traffic is sent to port 9080 on loopback, so that's what we filter for)

Packet Capturing inside the container

It's alluded to in the example above, but tcpdump is installed in the container.

For convenience, a directory /root/pcaps is also created, so that you can map a local directory to it:

docker run --name=nginx_mitm -v /home/ben/tmp/nginxconfs:/etc/nginx/conf.d -v /home/ben/tmp/pcaps:/root/pcaps bentasker12/nginx_simple_mitm

You can then exec tcpdump:

docker exec -it nginx_mitm tcpdump -i lo -s0 -w /root/pcaps/cap.pcap -v port 9080

And the packetcaptures will get written out into your local directory

nginx_mitm_docker's People

Contributors

bentasker avatar btasker avatar abalone23 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.