SSL Relay Proxy: A Creative Solution to a Complex Issue
SSL Relay Proxy: A Creative Solution to a Complex Issue
SSL Relay Proxy: A Creative Solution to a Complex Issue
SSL Relay Proxy: A Creative Solution to a Complex Issue
I ran into a situation recently where I needed an SSL interception proxy. I was testing a thick client that spoke with a server (not HTTP) over SSL. I couldn't find anything on the Internet about a female-to-male (relay) non-HTTP SSL proxy. The situations where an SSL interception/relay proxy would be useful are fairly slim, but so are things that I can't find anything about on the Internet, so here you go.
The Restrictions
I didn't have the private key, and I was in an environment that wouldn't allow me to use any tools except BackTrack and Windows (which the client was running). I also could not actively man-in-the-middle the traffic (e.g., ARP Poison). The only things going for me were that I could tell the app what server to use and that the app was not validating the SSL certificate.
Dead Ends
A lot of tools assume that the traffic will be MITM'd (ettercap, SSL sniff), so packet forwarding just needs to be enabled and it will get to its destination. My iptables skills were probably limiting me, but I wasn't able to get the traffic routed to the server and get my backtrack box to see it. There may be a way to do this, but I couldn't figure it out. Iptables gets hard quickly (for me at least). I tried NCAT and Open SSL, but neither of them allow multi-thread connections -- basically they are only good for one TCP session. So, everything would be fine until the second TCP session decided to ruin things. NCAT has a "keep open" mode, but it never closes the output stream, so the client program would hang because it's waiting for the TCP session to close.
The Solution
Finally, I tried using stunnel, which is multi-threaded and would take care of the SSL striping, then a second instance would re-add SSL to keep the server happy. To get that working, I'd use two configuration files, one to bring it in, strip SSL and drop it on a port, then another to pick it up on a listening port and replay the traffic over SSL to the server. Yes, we'll need something in-between those two to actually log the traffic. More on that later. Here are the configuration files I ended up using. I also generated an SSL cert to be used (stunnel.pem, self-signed of course).
Generate stunnel.pem Certificate
openssl req -new -x509 -days 365 -nodes -out stunnel.pem -keyout stunnel.pem
listener.conf
client = no
debug = 3
foreground = yes
#chroot = /var/run/stunnel
#setuid = nobody
#setgid = nobody
pid = /stunnel.pid
cert= ./cert.pem
[MyApp]
accept = 3800
connect = 3801
client.conf
client = yes
debug = 3
foreground = yes
#chroot = /var/run/stunnel
#setuid = nobody
#setgid = nobody
pid = /stunnel.pid
cert= ./stunnel.pem
[MyApp]
#change to 3801 to just relay the traffic without using the ruby tunnel
accept = 3802
#this is where the server is listening
connect = 192.168.1.87:3800
The Logger
So everything is complete at this point, except we have to get the traffic logged, which is why we left the gap between ports 3801 and 3802. I got pretty far on a ruby proxy, but when I was working on the multi-threading, I found one that did exactly what I needed here by Amnon. Ruby threading is beautiful, by the way. I only added two lines, one to dump each "direction" of data to the console.
OK, now we are finally ready to do something that shouldn't be that hard in the first place. All we need to do is run the stunnel with the two conference files and then run the ruby proxy to dump the traffic.
stunnel listener.conf & stunnel client.conf & ruby tunnel.rb 127.0.0.1:3802 3801 127.0.0.1 > logfile
Of course, you can tee your log file if you want to view it on the fly. There are limitless solutions to this (e.g., implementing SSL in ruby -- probably isn't hard), but this is what I ended with. Let me know if you come up with a different solution. I'd love to hear about it.