Virtual Public Network

This document describes the method I've used to step past the http proxy at the office and gain unfettered access to the outside world.

In order to make this method of accessing the outside world possible - you need a few things :

Setting up stunnel to encapsulate ssh

This bit was shamelessly ripped from the shsc wiki, and is required if the proxy you're tunneling through is evil enough to check and make sure that you're really using your HTTP CONNECT method for proper SSL traffic, and not something else. You'll need OpenSSL installed on your PC at home to do the certificate generation too, which the articile on the shsc wiki just assumes you'll know.

Run the following command to generate the certificate:

openssl req -new -x509 -days 999999 -nodes -out sshd.pem -keyout /etc/ssh/sshd.pem 
openssl gendh >> /etc/ssh/sshd.pem

You'll also need a line like this :

stunnel -d 443 -r 22 -p /etc/ssh/sshd.pem -P none -N sshd -s nobody -g nogroup -O l:TCP_NODELAY=1 -O r:TCP_NODELAY=1

placed into one of your start up scripts. To me, it made perfect sense to put it into /etc/init.d/ssd since I want the stunnel running whenever ssh is running, so it saved writing a whole new script for it.

Preparation

First, make sure the sshd running on your home PC has the following options enabled in it's config file (usually called sshd_config, and usually located in either /etc/ssh, or /etc itself):

X11Forwarding yes
AllowTcpForwarding yes
TCPKeepAlive yes
PermitTunnel yes

You also need to make sure the kernel on your home PC either has the tun/tap driver compiled in directly, or available as a module. If it's compiled in as a module - make sure it's loaded with "modprobe tun". You should also make sure that the file /proc/sys/net/ipv4/ip_forward contains the value 1.

Next, set up your ~/.ssh/config file on the office PC to include a section which looks like this:

# SOCKS proxy config
Host home
 Hostname yourhost.dyndns.org
 Port 443
 ProxyCommand stunnel -c -f -l corkscrew -- corkscrew your.office.proxy.ip proxy_port %h %p
 TCPKeepAlive yes
 User username_on_your_home_pc
 ForwardX11 yes
 Compression yes
 CompressionLevel 6

This will allow you to issue a short command to get the ball rolling from your office PC. All you type is "ssh home", and the ssh client will take care of starting corkscrew with the right parameters, and connecting through to your home PC for you.

The next thing you need to do is work out how you're going to keep your office PC talking to it's internal LAN after you remove it's default route. Currently it's very likely it's default route points to a router on the subnet it's on. E.g :

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.1.10.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        0 lo
0.0.0.0         10.1.10.1       0.0.0.0         UG    0      0        0 eth0

The above routing table is set so that any address not on the local subnet (10.1.10.0) is sent to the gateway 10.1.10.1 for onward routing. Whilst your PC is not currently talking to the internet this is fine - but once you get your VPN going - it'll need to know how to talk to the internal LAN (which your proxy server is on remember!) without a default route. In the above case, we'd do the follwing :

route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.1.10.1

This means that we can now safely delete the current default route without our office PC suddenly finding it doesn't know how to talk to the rest of the office internal LAN. N.B. I've done this in the wrong order a few times before I was truly used to doing this little hack, and the connection to your home PC will drop instantly if you've forgotten to do it!

Finally, we need to set up some DNS name resolution on our office PC which will be clever enough to resolve addresses on both the internal office LAN, and the outside world. This one took me a little while to figure out - I just couldn't make the entries in /etc/resolv.conf clever enough to consult two different sets of DNS servers.

Briefly, all I'm doing here is setting up a forwarding name server. There is already an excellent HOWTO on this at The Linux Documentation Project which is what I followed. I recommend starting with sections 3 and 4, and then going on to section 5 when you want to set up zones for your internal LAN.

Just so you have an idea of what my personal setup is like I include the following directory listing of my /var/bind/pri directory (with filenames changed to protect the innocent/guilty!)

10.1.224.zone
10.1.226.zone
127.zone
business-name.com.zone
business-name.com.zone.jnl
qa-domain.com.zone
qa-domain.com.zone.jnl
localhost.zone

...and also a sample entry from my /etc/bind/named.conf...

zone "another.internal.domain.com" IN {
        type slave;
        file "pri/business-name.com.zone";
        masters { 10.1.10.254; 10.1.2.254; };
};

Using the VPN

Okay - that's all the preparation out of the way - so now to use the link.

Issue the ssh home command from your Office PC. If you've set up everything as above, you should eventually get a prompt on your home PC. Now you need to configure the network interface (the tun/tap one) on both machines so that the virtual network comes up.

One the office PC issue these commands :

ifconfig tun0 192.168.10.2 netmask 255.255.255.0 up
route del default
route add default gw 192.168.10.1

The final state of the routing table on the office PC should now look something like this :

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.1.10.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 tun0
10.0.0.0        10.1.10.1       255.0.0.0       UG    0      0        0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        0 lo
0.0.0.0         192.168.10.1    0.0.0.0         UG    0      0        0 tun0

Now on the home PC issue this command :

ifconfig tun0 192.168.10.1 netmask 255.255.255.0 up

That is enough to get your PC at home talking to your office PC over a "genuine" network connection, rather than just the ssh connection. Now, you need to get your PC at home doing NAT, so that your office PC can use the home PC as a router out to the internet. Issue the follwing commands on the home PC:

iptables -t nat -F
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

N.B. In the example above I've assumed that the home PC's network interface which connects to the internet is called eth0. If that's not true - just change the interface name to whatever the right one is.

Making it all easy

I actually set up a shell script at each end to make running all those commands a bit less painful, here they are :

First, the office PC's script, run it as soon as ssh home has completed.

#!/bin/bash
/sbin/modprobe tun
/sbin/ifconfig tun0 192.168.10.2 netmask 255.255.255.0 up
/sbin/route del default
/sbin/route add default gw 192.168.10.1
# The following line isn't necessary, it just tests that DNS is working
/usr/bin/host www.google.com

And now the home PC's script - also run as soon as ssh home has completed.

#!/bin/bash
/sbin/modprobe tun
/sbin/ifconfig tun0 192.168.10.1 netmask 255.255.255.0 up
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -F
iptables -t nat -A POSTROUTING -o ath0 -j MASQUERADE

That's it kids.