Redirect ALL web traffic through TLS without a VPN

10

4

Assumptions:

Server:

  • I have a Debian Squeeze server, routable on the public Internet, with a static IPv4 address.
  • I have unrestricted access to modify the software on the server.
  • The server can listen on arbitrary ports, reconfigure firewall rules, basically there are no restrictions on what the server can be made to do.

Client:

  • I can run Firefox, Java programs, .NET programs, and some native executables that don't require admin access on my local system (a locked-down Windows desktop with no admin rights).
  • I can install Addons into Firefox.
  • I can listen on any port on the loopback (localhost) interface. So, aforementioned programs can bind to a local port and perform arbitrary network I/O, without going through a proxy.
  • All public Internet access is routed through a restrictive HTTP proxy which blocks many sites, and does careful stateful inspection. On port 80, it allows exclusively HTTP (no TLS/SSL). On port 443, it allows CONNECT based SSL/TLS to remote hosts which are not blocked by domain name / IP address.
  • The restrictive HTTP proxy does not perform deep packet inspection of TLS connections which are allowed through the proxy, and it does not perform Man in the Middle attacks on those connections.
  • The above-mentioned server I have access to, is not blocked by the proxy.

Goal:

I want to route all HTTP and HTTPS requests emitted by Firefox, through the above server, over SSL/TLS.

Other notes about the "Goal":

  • Even if the endpoint site (for example, http://superuser.com) is not using SSL/TLS to my server, I still want to use SSL/TLS from my client to my server, and have my server perform the HTTP request -- whether encrypted or not -- to my desired destination.
  • I do not care if my server is looking at the SSL traffic "in the clear". In other words, I do not require full end-to-end SSL encryption from my local client, all the way to the remote server, if the remote server is being accessed by e.g. https://google.com. In other words, I trust the server to keep my data confidential.
  • I am willing to install any software or Firefox addons that do not require admin rights and can run on 32-bit Windows 7.
  • Open source software is preferred over proprietary, and freeware is preferred over software requiring a license fee.
  • Existing software is preferred over having to code up new software, though I am willing to write code if that is the only way.

I am looking for a loosely described "solution" that describes:

  • What software would be required on the client? If there is a specific software package you are aware of, name it; otherwise, describe what the client software would have to do.
  • What software would be required on the server? If there is a specific software package you are aware of, name it; otherwise, describe what the server software would have to do.
  • If you named specific software packages above, describe what configuration parameters would be necessary to set it up to meet my goal.
  • If for some reason you believe this is not possible, describe why.

Things I've Tried That Don't Work

  • Installing squid on my server, I tried to set up a standard HTTP proxy of my own on my server. This didn't work out, because when I request websites in Firefox over regular HTTP, Firefox tries to access my server over regular HTTP, too! This is not acceptable, because the proxy on my local network can of course observe and/or block the regular HTTP traffic between my client and the server.
  • VPNs don't work, not even OpenVPN over TLS listening on port 443, because I don't have the permissions on the local computer to install a tun network adapter that can perform layer 3 routing, nor can I do any sort of layer 2 routing (e.g. tap). In short: I'd need admin rights to install OpenVPN, and even if I had those admin rights temporarily, the company would be none too pleased if they found it was installed. A Java or .NET program is much less noticeable, especially when it isn't installed in Add/Remove Programs and has no kernel driver component like OpenVPN does.

allquixotic

Posted 2014-08-10T03:18:10.357

Reputation: 32 256

Do you try Socks? you can define it on port 443 in your server. – Ashian – 2014-08-12T05:10:37.920

Can you use the solution described in this article: Poor man’s HTTP VPN? Note that its link to HTTPTunnel is incorrect.

– harrymc – 2014-08-12T06:36:46.503

1http://delegate.org/ might be of help. – Arjan – 2014-08-12T07:47:11.343

@Ashian No, SOCKS will not work, unless it is wrapped in TLS. SOCKS is not an HTTP based protocol, so when it hits the internal proxy, it will be blocked. And if I were able to run it through TLS, I would probably use a different protocol. My first problem is getting the TLS tunnel set up in a way that Firefox can use it. I still haven't seen an explanation of how to do that. – allquixotic – 2014-08-12T11:43:54.493

@harrymc: The question title says through TLS. HTTP Tunnel routes IP packets over HTTP, which is unencrypted and does not use TLS. The article itself says the connection is not encrypted. There's no way my proxy would let that through. Furthermore, I don't have socat or administrative privileges on the Windows client box. – allquixotic – 2014-08-12T11:46:15.663

@Arjan DeleGate could possibly have the functionality I need, but can you find anything in its docs that will let me use it as a SSL/TLS proxy for all web traffic in Firefox, both for HTTP and for HTTPS websites? – allquixotic – 2014-08-12T11:47:56.447

Which ports does the proxy allow? – harrymc – 2014-08-12T15:06:46.400

As I wrote in my post: "On port 80, it allows exclusively HTTP (no TLS/SSL). On port 443, it allows CONNECT based SSL/TLS to remote hosts which are not blocked by domain name / IP address." It only allows those two ports, and it only allows specifically HTTP on port 80, and specifically TLS/SSL sockets on port 443. So, something like SSH or OpenVPN won't work over 443, unless it's first wrapped in TLS (which would defeat the purpose of using a protocol that's already encrypted), because the firewall will know it's not TLS and block it. But it can't tell what's inside the TLS. – allquixotic – 2014-08-12T16:36:11.977

So theoretically, the TLS bitstream could house any conceivable protocol and it would allow it through the firewall. The problem is that "regular" HTTP proxies, like Squid, typically don't encrypt unless you're accessing the remote website over HTTPS. – allquixotic – 2014-08-12T16:38:05.920

Does the proxy block TCP, UDP or both? – harrymc – 2014-08-12T17:48:48.207

And are you sure that the proxy will block TLS over HTTP? Because both HTTPTunnel and GNU httptunnel don't need admin rights on the client.

– harrymc – 2014-08-12T17:54:29.547

Also see this : 9 Ways to Bypass a Firewall or Internet Filter - wikiHow.

– harrymc – 2014-08-12T18:02:11.000

I think Delegate is what you should be looking at. There are a few usage examples here. But this is probably what you're looking for.

– Vinayak – 2014-08-12T18:12:52.747

@harrymc HTTP is over TCP (by definition), so it doesn't block TCP on ports 80 or 443. The TLS sessions it allows on port 443 have to be done using TCP as well. You can probably encapsulate arbitrary packets -- even UDP -- within the tunnel, but as far as the proxy can see, it'll still be raw TCP packets being sent once the end-to-end TLS handshake has completed. – allquixotic – 2014-08-12T19:14:48.427

Answers

5

I figured it out. :D This solution satisfies all of my requirements and meets all of my goals, perfectly. Performance isn't too bad, either, considering the level of indirection that is necessary to achieve this.

The general approach is thus:

  1. Set up a local Certificate Authority (CA), and generate an RSA "server key" and "client key" (I used 256-bit encryption). For this, I used Easy-RSA version 3.0.0-rc2.

  2. Run any bog standard HTTP proxy on the "Debian Box" (the server on the public Internet), making sure to have it listen on localhost only (it should NOT be exposed to the public Internet). For my purposes I used Privoxy, but Squid would've worked just as well. Since it's only listening on localhost, authentication is not necessary (unless there are processes running on your box that you don't trust; in which case, yikes...)

  3. Download stunnel and install it on both the client and server. The process for doing this is going to be OS-specific; in my case, I chose to compile stunnel from source (paranoia...) for Windows, which was a rather involved process I won't detail here. On the server side, it was available in the package manager :)

  4. Stunnel's configuration was quite daunting at first, but it's simpler than it seems! Basically, on the server, you need something like the below "server's stunnel.conf". On the client, you need something like the below "client's stunnel.conf".

  5. Start Privoxy; start stunnel on the server, pointing it to the config file; start stunnel on the client, pointing it to the config file. There's really nothing all that special about Privoxy's config; the default was fine for me.

  6. In Firefox, your browser of choice on the client side, set the HTTP and HTTPS proxy to be the same as the port your client's stunnel is listening on -- probably something like localhost:8080.

I should probably note that if your local network's proxy demands some kind of authentication, you will either have to get stunnel to authenticate for you, or else use another local intercepting proxy and chain them together -- something like Firefox -> stunnel -> local authenticating proxy -> LAN proxy/gateway -> internet -> your server's stunnel -> privoxy.

That's a lot of copying, but it works!

;This is the *client's* stunnel.conf.
[https]
accept = localhost:9020
connect = your.lan.proxy:80
client = yes
protocol = connect
;protocolHost should be the same as the "accept" for the server
protocolHost = 1.2.3.4:443
;Same CAfile, different cert and key pair
CAfile = ca.crt
cert = client.crt
key = client.key
;VERY IMPORTANT!!! Make sure it's really your server and not a MITM attempt by your local network by making sure that the certificate authority "ca.crt" really signed the server's cert
verify = 2
;More performance tweaks...
sessionCachetimeout = 600
sessionCacheSize = 200
TIMEOUTidle = 600

.

;This is the *server's* stunnel.conf.
[https]
;1.2.3.4 is a publicly-routable, static IP address that can be connected to by your box that's under the firewall
accept = 1.2.3.4:443
;localhost:8118 is an example of where your local forwarding HTTP(S) proxy might reside.
connect = localhost:8118
CAfile = ca.crt
cert = server.crt
key = server.key
;VERY IMPORTANT!!! Without this, anyone in the world can use your public stunnel port as an open proxy!
verify = 2
;Set some timeouts higher for performance reasons
sessionCacheTimeout = 600
sessionCacheSize = 200
TIMEOUTidle = 600

Once everything is configured, the end result ends up looking something like this:

  1. Your web browser connects to localhost:9020 (stunnel) and treats it like a proxy that can accept HTTP and/or HTTPS connections.
  2. Once stunnel gets a connection from your browser, it reaches out, through your firewall's proxy/gateway, to establish a TLS session with your remote server. At this point, your client verifies your server's PKI certificate, and vice versa.
  3. Once the TLS session is established with your remote server, stunnel passes along the data coming from your browser, e.g. an HTTP request or an SSL tunnel request, through the local proxy and directly to your server. This channel is encrypted, so your local network can't tell what the data contains, they can only guess by doing traffic analysis.
  4. Once the stunnel instance running on your server starts receiving data, it opens a connection to e.g. localhost:8118, which would be where your HTTP(S) proxy server, in my case Privoxy, is listening.
  5. Privoxy then acts like a normal forwarding HTTP proxy server, and forwards your requests on to the public Internet through the server's ISP.

The amount of sockets and buffers involved makes this method very high overhead, especially if you're nesting an SSL connection through the proxy, but it has the advantage that your local network has no way of knowing which sites you're visiting over SSL. I mean, it knows you're visiting your server, but aside from that, it doesn't know if you're visiting Gmail or SuperUser or whatever. And your local gateway has no way of filtering or blocking you.

allquixotic

Posted 2014-08-10T03:18:10.357

Reputation: 32 256

2

I have tried this setup on my local machine, and I can assure that the "restrictive proxy" would get a CONNECT DEBIAN_IP:443 HTTP/1.1, but it will not see any certificate, so I am not sure if this would work.

Let's asume: your Debian has Apache or Squid to do the proxying and an SSH server. On your client PC, you need putty, which is a program that does not need admin privileges to run, not need for installation and could run from a pendrive.

First your Debian:

Make your SSH listen on port 443, just add (or replace your current port) a Port 443 on /etc/ssh/sshd_config and also allow TCP forwarding (add AllowTcpForwarding yes on that file)

Configure your Squid or Apache to do proxying. As this is going to be used through an SSH tunnel, it would only need to listen on the loopback interface. In case you use an Apache:

Listen 127.0.0.1:8080
ProxyRequests On
<Proxy *>
  Order deny,allow
</Proxy>

Server done, let's configure your client PC:

On putty, configure your Debian's public IP as Host and 443 as port. Make sure SSH is still selected. Change to the Connection -> Proxy settings, select HTTP and fill your "restrictive proxy" settings. Change to the Connection settings and stablish a keepalive of 30-60. Change to the Connection -> SSH -> Tunnels. On source port stablish 8080, and on Destination, localhost:8080. Leave Local selected and press Add. You shoud see in the space above something like L8080 locahost:8080. Change back to the Session settings, write down a name on the first row of Saved sessions and save all these tedious settings to help restablish the connection on following days.

Now you can try to Open the connection to your Debian. If you see the user prompt, we are just a step from finishing with this. If not... we will have to search for another way.

Now, on Firefox, set localhost at port 8080 as your proxy.

NuTTyX

Posted 2014-08-10T03:18:10.357

Reputation: 2 448

Unfortunately, this won't work, because SSH's protocol is not based on SSL/TLS. When the restrictive proxy on my client side does a sniff of the connection going through port 443, it instantly knows that it's not a TLS socket, and drops it. Granted, I could wrap it in TLS, but that isn't what your answer describes. – allquixotic – 2014-08-12T22:49:24.703

I made a test with a HTTP proxy (BURP) and worked, so it was worth the try. Wrapping SSH over TLS and keep it working could get tricky, though... – NuTTyX – 2014-08-12T22:51:40.430

SSH over TLS is unnecessary indirection. If you already have the TLS socket going, you don't really need SSH. See my answer below. (Note: I didn't know about this answer until just recently, so it's not like I baited out your answer and then posted the solution. I literally discovered this about 25 minutes ago.) – allquixotic – 2014-08-12T23:15:09.463

Glad you solved it – NuTTyX – 2014-08-13T00:13:51.217

1

You're halfway there with setting up a proxy on your server. The other half is SSL on the server, and a local proxy on the client using putty to connect to your SSL-enabled HTTP proxy, and set Firefox to proxy everything to 127.0.0.1.

I just did a quick google for a putty setup and found this: https://mariobrandt.de/archives/technik/ssh-tunnel-bypassing-transparent-proxy-using-apache-170/

joe

Posted 2014-08-10T03:18:10.357

Reputation: 316

To be fair, he went into a lot more detail with his post. Thanks for the vote, though. – joe – 2014-08-19T16:33:21.253

@krowe Nowhere in my answer does it say "Apache" or "PuTTY". – allquixotic – 2014-09-11T00:01:58.943

Nope, doesn't bother me that you upvoted this answer! I just interpreted your comment as saying that I was somehow nicking his answer or ripping it off, when in fact I did not really gain much from this answer when I was looking for a solution. In retrospect, the blog linked to seems to be an okay alternative to the answer I posted, though I'm not sure how it would differ in performance, features, etc. (could be better or could be worse). – allquixotic – 2014-09-11T00:29:44.560

+1 I like this one because I run a webserver anyway. – krowe – 2014-09-11T00:46:41.207