Skip to content

Instantly share code, notes, and snippets.

@jeremiahsnapp
Last active November 14, 2023 07:48
Show Gist options
  • Star 47 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save jeremiahsnapp/6426298 to your computer and use it in GitHub Desktop.
Save jeremiahsnapp/6426298 to your computer and use it in GitHub Desktop.
Man In The Middle (MITM) SSL Proxies - Simple ways to see traffic between an SSL server and client in clear text.

HTTP(S) specific MITM SSL Proxies

mitmproxy

mitmproxy is an excellent console app written in Python.

It is easy to use on Linux and OS X.

Use brew install mitmproxy to install it on OS X.

  1. Run mitmproxy

  2. Set the following in knife.rb or client.rb.

     https_proxy "https://127.0.0.1:8080"
    
  3. If you are using Chef 12 then you will need to copy ~/.mitmproxy/mitmproxy-ca-cert.pem to Chef's trusted_certs directory so chef-client and knife will trust the SSL connection to mitmproxy.

     cp ~/.mitmproxy/mitmproxy-ca-cert.pem .chef/trusted_certs/
    
  4. Run knife commands or chef-client.

  5. Monitor or manipulate the cleartext traffic using mitmproxy's console.

mitmproxy has a number of dependencies that need to be installed if you aren't using a prebuilt package. This can be inconvenient especially in a support situation. The stunnel solution given below is a lightweight alternative.

Fiddler

Fiddler is for use on Windows platform.

Protocol Agnostic MITM SSL Proxies

stunnel

stunnel is a tool that can be used as a MITM proxy for SSL encrypted protocols such as HTTPS, LDAPS and IMAPS. stunnel has minimal dependencies making it a very lightweight solution.

Installation:

  • OS X - brew install stunnel
  • Most Linux distributions can easily install stunnel using their respective package management systems.
    • RHEL/CentOS - sudo yum install stunnel
    • Debian/Ubuntu - sudo apt-get install stunnel
  • Windows - stunnel downloads web page has an executable binary available.

Use openssl to create a self signed certificate server.pem.

openssl req -batch -new -x509 -days 365 -nodes -out server.pem -keyout server.pem

Download the simple configuration file stunnel-mitm-proxy.conf to the same directory as the server.pem.

This configuration causes the stunnel server to bind to the privileged port 443 so be sure to run stunnel as either the root user or with the sudo command. Binding to port 443 simplifies usage with knife and chef-client since some of their code will not use a port other than 443. (e.g. knife cookbook upload sandbox API requests)

Then start stunnel. If you are running stunnel on Debian or Ubuntu then replace the stunnel command with stunnel4.

sudo stunnel stunnel-mitm-proxy.conf

Replace the domain name in knife.rb or client.rb chef_server_url parameter with 127.0.0.1:443.

Now you can use tools like tcpdump or wireshark to capture the cleartext traffic to a file or watch it in real time.

sudo tcpdump -ilo0 -s0 -w ./captured.pcap 'port 4434'

Run the following command on Linux or OS X to stop stunnel.

sudo pkill -f stunnel-mitm-proxy

openssl

As a proof of concept, the openssl tool can be used on Linux or OS X to create a rudimentary MITM SSL proxy.

The openssl s_client used below will terminate after an API request-response completes since the Chef API protocol closes the client-server connection after each response. That means this MITM SSL Proxy is only good for one API request-response at a time. You would have to start the openssl s_client again to achieve another successful API request-response. Other methods could be used to automatically restart the openssl s_client but that is out of scope for this proof of concept.

Use openssl to create a self signed certificate server.pem.

openssl req -batch -new -x509 -days 365 -nodes -out server.pem -keyout server.pem

Create two named pipes.

mkfifo request response

Run the following command lines in separate terminal windows.

openssl s_server -quiet -cert server.pem -accept 4433 < response | tee -a request
openssl s_client -quiet -connect api.opscode.com:443 < request | tee -a response

Replace the domain name in knife.rb or client.rb chef_server_url parameter with 127.0.0.1:4433.

Now you can use tools like tcpdump or wireshark to capture the cleartext traffic to a file or watch it in real time.

sudo tcpdump -ilo -s0 -w ./captured.pcap 'port 4434'

When you are done you can delete the named pipes using the following command.

rm request response
debug = 3
#foreground = yes
pid =
[server]
client = no
cert= ./server.pem
accept = 127.0.0.1:443
connect = 127.0.0.1:4434
[client]
client = yes
accept = 127.0.0.1:4434
connect = api.opscode.com:443
@mrtuborg
Copy link

mrtuborg commented Mar 6, 2015

Hi,
thanks for this interesting example. I trying to add SSL to the service, that has not own SSL implementation (client have it). So I just want to use stunnel to recieve SSL traffic from client, decrypt it and send to another port to the service as a plain traffic.

Could you please explain me how is it possible to tune-up this configuration to encrypt responce from the service and return it back to SSL client? As I see, there is [client] section, but uses specified hostname for the connection. Is it possible to make it for any connected client? Yes, sure, for my development purposes I can use only one client and specify it in this configuration, but I look smething more general, just to setup once and share inside the team.

@azrdev
Copy link

azrdev commented Mar 11, 2015

@mrtuborg the configuration for stunnel has things reversed: the [client] section specifies how it should act (as a client) towards the proxied application. In [server] it is specified how it should act towards connecting clients (like your browser).
This setup should do what you want out of the box, however, for a website you could also use an normal webserver like apache or nginx, have it serve SSL and act as a reverse proxy for your application.

@azrdev
Copy link

azrdev commented Mar 11, 2015

@jeremiahsnapp In this stackexchange thread there are some more ideas for doing MITM. Especially one extending your use of openssl, by using socat that guy avoids the "s_client does only one connection" issue.

@famedoro
Copy link

famedoro commented Feb 5, 2016

@jeremiahsnapp Is it possible log to file all packet traffic coming from a wss web socket on come from serverpush.dot.it:7072 using stunnel, openssl and tcpdump ?

my idea is

  1. to redirect traffic from serverpush.dot.it:7072 on localhost: 1234
  2. put tcpdump listening on port 1234 in order to write the decrypted data to file
  3. redirect traffic from localhost: 1234 to serverpush.dot.it:7072

@samsonkolge
Copy link

samsonkolge commented Mar 28, 2017

@jeremiahsnapp thanks for this post.
I wanted to read the packets on my remote node.
I tried using the mitm-proxy route I coped the mitm-ca-cert.pem from the mitm dir into the trusted cert dir on the remote node

Below is my client.rb conf:
chef_server_url "https://xxxx.net/organizations/abc"
validation_client_name "chef-validator"
log_location STDOUT
client_key "/etc/chef/client.pem"
node_name "xxxx.net"
trusted_certs_dir "/etc/chef/trusted_certs"
ssl_verify_mode :verify_peer
http_proxy "https://127.0.0.1:8080"
https_proxy "https://127.0.0.1:8080"
ssl_ca_file "/root/.mitmproxy/mitmproxy-ca-cert.pem"

I am getting a 502 error:
[2017-03-28T13:28:19+00:00] INFO: Platform: x86_64-linux
[2017-03-28T13:28:19+00:00] INFO: Chef-client pid: 109522
[2017-03-28T13:28:25+00:00] ERROR: Connection refused connecting to https://xxxx.net/organizations/dcia/nodes/xxxx.net, retry 1/5

Please advise....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment