SPDY & Secure Proxy Support in Google Chrome

One of the unique features of Google Chrome is the built-in support for SSL-based proxies. Although HTTP proxies can tunnel SSL, the initial connection to the proxy is done in plain text, which allows an intruder to eavesdrop on the hosts you are navigating to. Historically, to address this limitation we have had to rely on additional client-side software to create a VPN tunnel (ex, OpenVPN), or route our connections via SSH (ex, SOCKS tunnels over SSH with ssh -D).

With Chrome, you can simply give the browser a URL of an HTTPS proxy, and the rest is taken care of: a TLS tunnel is established to the proxy, and the proxied requests are sent over a secure link. No eavesdropping allowed!

SPDY Proxy via SSL NPN

The added benefit of supporting HTTPS proxies is that we can use SSL's Next Protocol Negotiation (NPN) to upgrade our connection to speak SPDY! Once the tunnel is established, the browser and the proxy can multiplex multiple SPDY streams over the same connection, allowing us to minimize latency and optimize throughput - especially useful on mobile device. In fact, this is precisely how Amazon's Silk browser operates: single SPDY connection to an AWS proxy!

If your browser needs to fetch an HTTP resource, it uses the same SPDY connection, but in its SPDY frame it allocates a new "Stream ID", which indicates to the proxy that this is an independent request. The proxy can then fetch the HTTP resource on your behalf and stream it back over SPDY. Best of all, this same workflow also works for HTTPS, which means that we can tunnel SSL over SSL, and hence we can tunnel SPDY over SPDY:

If we inspect chrome://net-internals#spdy, we can see that in the example above we are connected to a local SPDY v2 proxy, running on port 44300. However, when we request https://www.google.com, the browser negotiates a SPDY v3 session with the Google servers. We are tunneling an SSL session within another SSL session! The proxy only knows that we are connected to google.com, but cannot inspect any of the encrypted data. Perhaps slightly meta, but this is a very powerful feature - read more about HTTPS tunneling.

DIY SPDY Proxy with node.js

One way to see SPDY proxy in action is to pickup a Kindle Fire device. Alternatively, we can reproduce our own local "Silk proxy" setup in just a few lines of code and configuration:

node-spdyproxy - SPDY forwarding proxy - fast and secure.
$> npm install -g spdyproxy
$> spdyproxy -k keys/mykey.pem -c keys/mycert.pem -p 44300 -v

You will need node.js 0.8.x+ for NPN support (follow instructions in the readme). Once spdyproxy is installed, you can give it your SSL keys and launch a local instance. Now we just need to tell Google Chrome when to use our proxy. For that, we can create a proxy auto-configuration (PAC) file, which consists of a single JavaScript function:

function FindProxyForURL(url, host) {
  // Route all HTTP requests to our proxy
  if (shExpMatch(url, "http:*"))  return "HTTPS localhost:43000";

  // HTTPS requests go directly to the host (Amazon's Silk setup)
  // See: http://www.amazon.com/gp/help/customer/display.html/?nodeId=200775440
  if (shExpMatch(url, "https:*")) return "DIRECT";

  // Alternatively, we can route *all* traffic through our SPDY
  // proxy by simply providing one rule in our PAC file:
  return "HTTPS localhost:43300";
}

Save the above file, and we can now start Chrome with the --proxy-pac-url flag:

$> /path/to/Chrome --proxy-pac-url=file:///path/to/config.pac --use-npn

The above scenario only scratches the surface of what we can do:

All that and much more, all accessible directly in your browser and without a need to install or configure any additional software. In fact, with a little bit of extra work, we can even extend spdyproxy to perform on-the-fly content optimization to deliver faster page loads for mobile or tablet devices, ala Opera Turbo or Amazon Silk.

Ilya GrigorikIlya Grigorik is a web ecosystem engineer, author of High Performance Browser Networking (O'Reilly), and Principal Engineer at Shopify — follow on Twitter.