/ Tech

VPN through HTTPS Proxy with SSH

If you are in a situation where you are locked in a network which has all ports closed to the outside, but there is a HTTP(S) proxy available, then you're lucky and can create a VPN easily using some nice tricks.

Prerequisites

You need to have access to a SSH daemon which can be configured to listen on port 443. And you need root rights for everything described here.

To configure a SSH daemon to listen on port 443, just add Port 443 to the configuration file /etc/ssh/sshd_config (this directive can be there multiple times).

Furthermore you need to enable some sort of routing and masquerading on the SSH server. Here is a simple example:

sysctl net.ipv4.ip_forward=1
iptables -P FORWARD ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

A little tool (besides the SSH client) is needed on the client: corkscrew.

corkscrew is a simple tool to tunnel TCP connections through an HTTP proxy supporting the CONNECT method.
It reads stdin and writes to std- out during the connection, just like netcat. It can be used for instance to connect to an SSH server running on a remote 443 port through a strict HTTPS proxy.

Connecting SSH through a HTTP proxy

The proxy needs to accept the HTTP CONNECT method, most proxies are supporting this. Connecting to the remote SSH server is done using the ProxyCommand option.

Here is an example SSH client configuration (replace PROXYIP and PROXYPORT):

Host myremotehost.mydomain.tld
   ProxyCommand corkscrew PROXYIP PROXYPORT %h %p
   Port 443

This opens a SSH connection to your remote host through the HTTP proxy. If your HTTP proxy does deep SSL inspection (breaking the SSL encryption), then we must use another tool (see later in this blog post). To add proxy authentication, add one more parameter after %p pointing to a file which contains the auth parameters in the form username:password.

Now that we have an SSH connection, we can do many nice things (SSH rocks!).

Variant 1: PPP over SSH

Creating a simple point-to-point link can be done using the ancient PPP protocol. The advantage of this variant is that the PPP tool takes care of doing the link configuration. Just start pppd on your local using the following syntax (hint: pppd must be installed on the local and remote machine):

pppd updetach noauth silent nodeflate pty "ssh -F PATHTOSSHCONFIGFILE myremotehost.mydomain.tld /usr/sbin/pppd nodetach notty noauth" ipparam vpn 10.0.8.2:10.0.8.1

You now have a point-to-point link over which you can route your networks (see later).

Variant 2: SSH layer 3 tunnel

If you don't like PPP (like me), there is an even easier way to create a point-to-point link: OpenSSH is able to create a tunnel by itself! Have I already mentioned that I really like SSH? =)

The remote SSH server must have the option PermitTunnel yes configured. Here is a complete example of a SSH client configuration (including corkscrew):

Host myremotehost.mydomain.tld
  ProxyCommand corkscrew PROXYIP PROXYPORT %h %p
  Port 443
  PermitLocalCommand yes
  LocalCommand /usr/bin/sudo ifconfig tun0 10.0.8.2 pointopoint 10.0.8.1 netmask 255.255.255.0
  ServerAliveInterval 60
  Tunnel yes
  TunnelDevice 0:0
  RequestTTY no

Call SSH with this command (as root or with sudo): ssh -f myremotehost.mydomain.tld 'ifconfig tun0 10.0.8.1 pointopoint 10.0.8.2 netmask 255.255.255.0'

Now you have a point-to-point link tun0 which can be used f.e. for routing.

Routing tricks

As we now have a point-to-point link up and running, the next step is to route everything over this link. Example:

ip route add IPOFMYREMOTEHOST via ORIGINALDEFAULTGW
ip route replace default via 10.0.8.1

Note: The host route is very important!

Other ways to break out

If corkscrew is not working because the HTTP proxy does not allow HTTP CONNECT or is doing some nasty HTTPS deep inspection, there are some other ways (untested by me atm), f.e. the nice httptunnel.

Of course we could also do some OpenVPN tunneling or use other VPN tools which are able to somehow bypass the firewall through the proxy, but I've chosen this approach because SSH is installed on probably every linux machine.

Another nice addition to this toolset would be to multiplex the SSL connection on the remote host, so you could run a HTTPS server, SSH server, OpenVPN server and other SSL enabled daemons on the same port. F.e. sslh is able to do protocol demultiplexing.