28 August 2012

How to set up a real, encrypted VPN through your Raspberry Pi

Well isn't it always this way... the very day after I post on how to use the Raspberry Pi as a secure Internet proxy by working around a missing element in its variant of Linux, that missing element becomes available in the stock OS!

Here's how it went.  On a whim, even though I'd just given my Raspi a full software update just two days ago when I made that earlier post, I repeated the process again today:

sudo apt-get update
sudo apt-get upgrade

...and lo, there were some important packages that updated.  Sniffing further, I attempted the first step of the installation process for installing a "real" PPTP VPN onto Debian Linux:

sudo modprobe ppp-compress-18 && echo success

No error was reported!  The formerly-missing MPPE module has been added to the kernel.

Well now.  This poses the tantalizing possibility of setting up a real, Point To Point Protocol (PPTP) Virtual Private Network using the Raspberry Pi as a gateway.

A VPN strategy for every situation

Among the highly non-trivial benefits of the PPTP VPN versus the ssh proxy tunnel I documented previously include compatibility with iPhones, iPads and other mobile devices which might not offer ssh port forwarding capabilities in their operating systems.  That was the basic trick of the ssh proxy tunnel.

On the other hand, PPTP VPNs utilize the GRE 47 protocol which is some routers find indigestible while others can accommodate only one GRE 47 connection at a time and will block all others-- a recipe for trouble in hotels and public hotspots.  By comparison, the ssh proxy trick I documented--which leveraged the https or other common port for the ssh proxy tunnel--will be more likely to always work as you travel, at least for your laptops.  Frankly, at this point I have both the ssh proxy tunnel and the PPTP VPN set up on my Raspberry Pi, and I might as well leave it that way so I'm covered for just about any circumstances.

Here's how

There are many tutorials available for setting up the PPTP server daemon (pptpd) on a generic Debian Linux machine.  However, I've found that the Raspberry Pi presents a few quirks and needs its own instructions.  The following steps worked for me and resulted in a robust VPN that has held up to my usage so far-- this blog post was constructed entirely while connected via my Raspberry Pi's new PPTP VPN.

  1. Open port 1723 on your router, pointing it to your Raspberry Pi's IP address on your LAN. 
  2. Your Raspberry Pi should have a static IP address on your LAN.  Good instructions for that are here.
  3. Next, if your home ISP does not give you a static IP address on the Internet, you'll need to set up an account with a dynamic DNS (DDNS) service.  This will give you a URL which will always point to your router.  My D-Link DIR-655 router (a truly excellent router, by the way) earns me a free DDNS account on D-Link's service; there are plenty of alternatives.  In D-Link's case, the url will look like [username].dlinkddns.com.  UPDATE: My trusty DIR-655 died, and the units currently being sold now are totally different.  I switched to an Apple Time Capsule, which necessitated a new dynamic DNS provider.  I chose DynDNS.org... you get one free host name for trying their 14-day "pro" account (which you can cancel, keeping the host name, though their services are powerful and quite cost-effective for what you get).  
  4. Log into your Raspberry Pi either via its local console or via ssh.  
  5. Issue sudo apt-get install pptpd
  6. Issue sudo nano /etc/pptpd.conf --this will start a simple text editor on your Raspi.  Note that most lines are comments and are commented-out with a "#" at the beginning.  Scroll down until you find the lines which set localip and remoteip.
  7. Set localip to your Raspberry Pi's IP address.  For me, that line becomes localip
  8. Set remoteip to encompass a small block of IP addresses on your LAN that will be made available to your remote client(s).  For me, that line became localip ...there are various rules for how that block can be constructed; use the format shown here or it might not work.  
  9. Hit ctrl-X and save the file.
  10. Now issue nano /etc/resolv.conf and make a note of the nameserver identified in this file --for me, and I'd bet most other folks, it's the LAN address of my router,  Hit ctrl-X to close the editor.
  11. Issue sudo nano /etc/ppp/pptpd-options and scroll down until you find references that set ms-wins and ms-dns.  You want to set thise to the nameserver address you just noted.  For me, these lines became ms-wins and ms-dns respectively.  Hit ctrl-X and save the file.  This completes the basic IP setup for your new VPN.
  12. Issue sudo nano /etc/ppp/chap-secrets and scroll down to an empty line.  Here is where you will specify your users who can use your VPN.  For a user named Ralph with a password of SuperSecret123, the line would simply be Ralph pptpd SuperSecret123 *  --the asterisk at the end is important as it specifies that Ralph can tunnel in from any IP address.  Repeat with additional lines to specify other users you want to allow to tunnel in via your Raspberry Pi.  Then hit ctrl-X and save the file.
  13. Issue sudo nano /proc/sys/net/ipv4/ip_forward  ...see the zero?  Change it to a 1.  This tells your PPTP daemon to forward remote clients to the Internet.  Hit ctrl-X to save the file and exit the editor.
  14. Issue sudo nano /etc/sysctl.conf and scroll down until you see the commented-out line that states net.ipv4.ip_forward=1  ...uncomment this line (remove the"#").  This will tell your Raspberry Pi to always allow remote clients to access the Internet via their tunneled connection.
  15. You're done!  Reboot your Raspberry Pi.
  16. While you're waiting for it to sort itself out, you can set up a VPN connection on your traveling (client) machine.  On the Mac, go to System Preferences | Network, click on the padlock and authenticate as an administrator user, Click the "+" sign and select "VPN" from the pull-down menu.  Give this new VPN a name.  Voila a new, unconfigured VPN connection will pop into your network-connections options.  With this selected, type in your dynamic DNS address for your Raspberry Pi (e.g., YourUserName.DynDNS.org).  In the Account Name field, put the username you specified in step 12 ("Ralph").  Click the Authentication Settings and specify the password from step 12 ("SuperSecret123").  Click the Advanced button, and be sure to checkmark the option to route all your Internet traffic through the VPN.

You're done!  (Setting it up on an iPhone or iPad is even easier.)  

You should be able to connect now, and all your Internet traffic will be encrypted and funneled through your Raspberry Pi from wherever you are... or at least from wherever VPN connections are tolerated.  For other places, consider the ssh proxy tunnel I wrote about before.

26 August 2012

How to use a Raspberry Pi as a secure Web gateway from anywhere

UPDATE: The necessary modules for supporting a "real" PPTP VPN have been added to the stock kernel.  While the following methodology offers benefits in many situations, you might want to consider this new post on the topic, or set things up both ways.


Being a geek, I was the first kid on my block to sign up to purchase a Raspberry Pi Model B, a $35 computer-on-a-card that's about the size of a pack of cigarettes.  In fact, since it comes without a case, I'm tempted to buy a pack of cigarettes, toss the coffin-nails and use the wrapper as an enclosure.  Maybe someday.

Anyway, this is a fully-fledged computer centered on an ARM-based processor that's a couple notches down in capability versus the CPU found in an iPhone or Android phone.  Nevertheless it is capable of running a variety of operating systems, and it benchmarks roughly equivalent to a typical i386 or Pentium machine of a few years' vintage.  Against that metric, the power efficiencies alone are amazing.  This thing runs off a cell phone charger.

The Debian-based variant of Linux that the Raspberry Pi folks recommend as their standard OS now enables hardware acceleration which makes most operations nicely speedy.  It works quite well and, being Debian-based, has access to a huge array of free software.  I have a few projects in mind for this little pup and currently have it running the full LAMP webserver stack (Linux, Apache, MySQL, PHP) just for chuckles.  Despite all that, more than 180MB of its 256MB of RAM is unused.

There will be more to come for this device.  First up: sometimes in my overseas travels I find I can't access my US-based services like Netflix.  Connecting via a hotel WiFi network when overseas gives me a non-US IP address which Netflix detects, and since Netflix's licensing agreements with studios and TV networks don't cover overseas customers, it will refuse to serve up content even though I have an account in good standing back home in the U.S.  Blockage of other Internet-based functionalities also sometimes occurs for other reasons-- for example, VoIP traffic is sometimes blocked, either purposefully or through poorly-considered blanket policies which boil down to "We shall allow common things like web browsing and block all else."

How nice it would be, then, to run a VPN or similar private pipe through the Raspi.  The Raspi's IP address would then be the face of my connection to Netflix and everything else.  Theoretically, I could activate that whenever I needed a US connection or found my connection to some service blocked for whatever reason.

Unfortunately, the Raspi's current recommended Linux build contains a stripped-down kernel that does not support certain features needed for establishing a common encrypted PPTP VPN connection.  Specifically, the kernel lacks MPPE support, and the Raspi will spit an error in the first step of procedures like the one documented here.  Some folks have compiled custom kernels--it's not too difficult--but for various reasons I want to keep my kernel stock-standard.  Perhaps someday the stock kernel will include MPPE support-- it seems everything else needed is present in the stock build and its repositories.

But there's a simple alternative which works well and is almost as capable and easy to use, and that is to use the port-forwarding capability of the ssh server built into Linux to set up the Raspi as a proxy for remote machines.

Here's how

  • First, the ssh server must be active on your Raspberry Pi.  Most folks will have enabled this at setup time.  If not, poster "Abishur" gives the details here.
  • Set your Raspi with a static IP address on your LAN.
  • Next, if your home ISP does not give you a static IP address on the Internet, you'll need to set up an account with a dynamic DNS (DDNS) service.  This will give you a URL which will always point to your router.  My D-Link DIR-655 router (a truly excellent router, by the way) earns me a free DDNS account on D-Link's service; there are plenty of alternatives.  In D-Link's case, the url will look like [username].dlinkddns.com.  
  • You'll need to open your router's ssh port and forward it to your Raspi's IP address on your LAN.
  • On your Mac, bring up the System Preferences | Network preference pane.  Click the padlock and authenticate as an administrator if necessary.  In the Location menu at the top of the preference pane, select Edit Locations.  Highlight the connection-location you normally use for attaching to networks when you travel, click the "gear" icon, and select Duplicate Location.  Give this duplicate a name such as "Normal Connection over ssh via Raspberry Pi".  Click Done.  Now, select the duplicate location and click the Advanced button, then the Proxies tab.  Checkmark the SOCKS protocol and specify "localhost" and port 8080 ...actually, the port doesn't much matter (just be sure to specify the same port in the next step), and 8080 is innocuous.   (Click to enlarge):

Click OK and then Apply.

You'll find your Mac will update its connection to whatever WiFi or Ethernet service it was on before, but Internet traffic won't flow quite yet.  Next, open a Terminal window.  If you've been working in a non-privileged standard user account, type "login [administrator account name]" and enter the password at the prompt.  Then--and here you need to be a bit cautious since you're futzing with your Mac's system files--type "sudo nano /etc/ssh_config"

This will start the Nano text editor and load in your Mac's ssh defaults.  Scroll down to just above the "Host *" line and insert the following:

Host webproxy
  HostName [your dynamic dns url]
  User [your username on your Raspberry Pi]
  DynamicForward 8080
  Compression yes

Type ctrl-X and say yes to the prompt to overwrite the current copy of ssh_config.

Close the terminal window.  Setup is now complete.

Using your secure tunnel connection

Now you're set.  On any given day when you find an Internet service blocked:

  1. In the System Preferences | Network preference pane, select the location you created with the ssh connection proxy via your Raspberry Pi.
  2. Open a terminal window, and simply type "ssh webproxy" and provide your Raspberry Pi user account password when prompted.  

You'll now have Internet!

...But don't close that terminal window.  What's happening now is that all TCP traffic to and from your computer is being routed through your encrypted ssh connection, which will be closed if you axe that window.

When you're done: switch back to normal connectivity by selecting your usual location in the System Preferences | Network preference pane.

Note that this approach is almost but not quite as functional as a nice PPTP VPN.  It is, however, pretty much limited to providing remote access just for personal computers.  Connecting via ssh is not well-supported by mobile devices, unfortunately.  For those, a proper VPN setup would be most beneficial.  Perhaps next time.  Also, it seems that while TCP traffic is routed, some other types of traffic may not be (which would seem to be why you can type "ssh webproxy" and log onto your Raspberry Pi when Internet isn't otherwise flowing yet after selecting the ssh proxy'd location in the preference pane.)  So even though TCP traffic is encrypted, don't go trading state secrets over this connection.

In my testing, using this ssh proxy approach has shown a negligible impact on Internet throughput versus my home's normal network connection, which is admittedly fairly entry-level.  If my hotel's Internet connection is good enough to support Netflix streaming in the first place, content streams just fine.  Latency increases a little, but it's pretty terrible to begin with on my home Internet service.  Note that all your remote traffic routes through the ssh port on your router, so if your remote usage would involve time-critical applications like VoIP, it might be a good idea to add that port to the router's Quality of Service (QoS) priority list.

Demo: We're Not In Kansas Anymore, Toto

With my Mac tethered to my iPhone, the handy WhatIsMyIPAddress.com maps my IP address as in Kansas:

By selecting my new ssh proxy "location" in the System Preferences | Network preference pane and typing "ssh webproxy" in a terminal window, now it appears I'm connected via my home ISP in California, where my Raspberry Pi resides... even though I'm still tethered to the iPhone:

One wrinkle...

You should consider the possibility that in your travels, access to the ssh default port of 22 might be blocked as well.  A good plan for that case is to make use of a port unlikely to be blocked and otherwise unused in your setup.  For me, although I'm playing with my Raspi as a tiny web server, it's not serving encrypted (https) pages.  So the https port 443 is not being used and is a great candidate for our pipeline's usage.  To use this:

  • Open port 443 on your router and forward it to your Raspberry Pi.
  • If you have Apache enabled on your Raspberry Pi, comment-out the "SSLEngine on" line in /etc/Apache2/sites-available/default-ssl:

  •  Then add port 443 to the listen-list in /etc/ssh/sshd_config on your Raspberry Pi:

Reboot your Raspi ("sudo reboot") and give it a couple minutes to sort itself out.  Henceforth, on your Mac, you can type "ssh -p 443 webproxy" to route your ssh connection over port 443, which all but the most uncooperative hotspots should leave unimpeded.

Incidentally, most of the above can be useful for figuring out how to do something similar on alternate platforms: a Windows remote client instead of a Mac, for example, or a generic Linux machine or something like a Mac Mini rather than a Raspberry Pi.  Of course, if you can use a fancier machine than a Raspberry Pi (or use an alternate or custom kernel in a Raspberry Pi), you can just set up a nice PPTP VPN on it.  If the ssh proxy approach is any indication, it should work just fine.