Eavesdropping HTTPS with Haproxy

Sometimes one needs to debug a protocol problem between client and server but what if the connection is encrypted with SSL/TLS? You can use this trick to reveal the unencrypted traffic.

First you need to either get the original certificate/key pair from target server (if you can) or generate selfsigned one using openssl:

$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj '/CN=your.server.com'
Generating a RSA private key
.......................................................................................................................................++++
.................................................++++
writing new private key to 'key.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
$ openssl rsa -in key.pem -out key-np.pem
Enter pass phrase for key.pem:
writing RSA key
$ cat cert.pem key-np.pem > cert-key.pem

Next you need to configure following haproxy backends and frontends:

frontend intercept-in
bind *:443 ssl crt /etc/haproxy/cert-key.pem
default_backend intercept-in

backend intercept-in
balance roundrobin
server app1 127.0.0.1:12345

frontend intercept-out
bind *:12345
default_backend intercept-out

backend intercept-out
balance roundrobin
server app1 <DESTINATION_IP>:443 ssl verify none

Then edit your /etc/hosts to direct the domain to your haproxy IP:

$ grep server /etc/hosts
192.168.0.10 your.server.com

Start tcpdump the on server where your haproxy runs and you can see the traffic:

$ tcpdump -i lo -nn port 12345 -s0 -A
 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
 15:39:19.399062 IP 127.0.0.1.38982 > 127.0.0.1.12345: Flags [P.], seq 3803697607:3803697940, ack 109244106, win 45, options [nop,nop,TS val 2426580586 ecr 2426553224], length 333
 E…..@.@.&……….F09………..-.u…..
 …j..C.GET / HTTP/1.1
 Host: your.server.com
 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:69.0) Gecko/20100101 Firefox/69.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
 Accept-Language: en-US,en;q=0.5
 Accept-Encoding: gzip, deflate, br
 Upgrade-Insecure-Requests: 1
 DNT: 1
 Cache-Control: max-age=0
 15:39:19.441382 IP 127.0.0.1.12345 > 127.0.0.1.38982: Flags [.], ack 333, win 46, options [nop,nop,TS val 2426580628 ecr 2426580586], length 0
 E..40I@.@..y……..09.F………….(…..
 …….j
 15:39:19.491779 IP 127.0.0.1.12345 > 127.0.0.1.38982: Flags [P.], seq 1:449, ack 333, win 46, options [nop,nop,TS val 2426580678 ecr 2426580586], length 448
 E…0J@.@.
 ………09.F……………….
 …….jHTTP/1.1 403 Forbidden
 Date: Sat, 14 Sep 2019 13:39:19 GMT
 Server: Apache/2.4.29 (Ubuntu)
 Content-Length: 287
 Content-Type: text/html; charset=iso-8859-1
 
 403 Forbidden 
 Forbidden
 You don't have permission to access / on this server.
 
 
 Apache/2.4.29 (Ubuntu) Server at your.server.com Port 443
 
 15:39:19.491795 IP 127.0.0.1.38982 > 127.0.0.1.12345: Flags [.], ack 449, win 46, options [nop,nop,TS val 2426580678 ecr 2426580678], length 0
 E..4..@.@.(……….F09………….(…..
 ……..

If you have used the original server cert, everything should work without any issue. If you have used generated selfsigned cert you will need to allow untrusted cert in your browser/client.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.