Updated 8 Feb 2008 to check certificates at both endsOur new office is behind NAT but we want to be able to connect into it from the outside world. What to do? Set up a VPN of course.
We have a webserver with a public IP address which we can SSH into. We'll use that as one
end of the VPN, so we can ssh into that and then ssh out again into our office.
Here's what you'll need:
First create a "vpn" directory on your server with the public IP address (the "server"), and the same directory on the machine behind the NAT firewall (the "client"). Change into that directory on both boxes, then create a keypair to encrypt the exchange:
openssl req -new -newkey rsa:1024 -days 365 -nodes -x509 -keyout vpn.pem -out vpn.pemand put a copy of "vpn.pem" in the "vpn" directory on both the client and server. It doesn't matter what fields you put in the certificate.
Next, on the server create the "vpn.conf" file so it looks like this:
CAfile = vpn.pem cert = vpn.pem key = vpn.pem output = vpn.log verify = 2 #debug = 7 client = no foreground = no [vpn] accept = 9871 exec = /usr/bin/sudo execargs = /usr/bin/sudo /usr/sbin/pppd debug noauth 192.168.254.254:192.168.254.253 pty = yesWe're going to put the endpoint for our VPN on port 9871, but it doesn't matter what it is so long as it's not firewalled. We're also going to use the two addresses 192.168.254.254 and 192.168.254.253 as the endpoints for our VPN. Check you have sudo access for this, or run it as root.
Then, on the client, create a "vpn.conf" that looks like this:
CAfile = vpn.pem cert = vpn.pem key = vpn.pem verify = 2 #debug = 7 output = vpn.log foreground = no client = yes connect = public.server.com:9871
Change "public.server.com" to your public web server and make sure the port matches your server part. That's it! To fire up the ppp link, run this command on the client:
pppd noccp novj novjccomp nopcomp noaccomp noauth debug dump logfd 2 passive updetach name -client linkname vpn1 pty "stunnel vpn.conf"This should bring up a link and background it. You can now ssh onto your public server and then ssh out again to 192.168.254.253 to get behind the NAT. In fact, any ports open on the client will be accessible unless you've firewalled them. You're checking certificates at both ends (that's the "verify=2"), so anyone else connecting to the port won't be able to do anything with it. If you have trouble, set the "debug" parameter in the conf files to something useful.
If you're on a flakey connection, run a cron job on the client to bring the link up if it drops. Something like this worked for us (running on Debian Etch)
cd /root/stunnel && /sbin/ifconfig ppp0 > /dev/null 2>&1 || /usr/sbin/pppd noccp novj novjccomp nopcomp noaccomp noauth debug dump logfd 2 passive updetach name -client linkname vpn1 pty "/usr/bin/stunnel4 vpn.conf"
For bonus points, set up a port forward on the server to forward to the client, so you can ssh directly into the client from the public internet. Something like this in fact:
iptables -t nat -A PREROUTING -p tcp --dport 2022 -j DNAT --to-destination 192.168.254.253:22 iptables -t nat -A POSTROUTING -d 192.168.254.253 -j SNAT --to 192.168.254.254The first line routes packets from 2022 on the server to 22 on the client, and the second line rewrites the response to make sure they can get back. Then simply
ssh public.webserver.com -p 2022and watch as layers of expensive firewalls are neatly sidestepped and you connect directly through to the client. Have fun, and remember - if your internal network gets hosed, it's entirely your fault.
mike at bfo dot co dot uk