Contact

Subscribe via Email

Subscribe via RSS

Categories

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

OpenVPN not setting default gateway

Note to self. Using OpenVPN on Windows, if your Internet traffic still goes via the local network rather than the VPN network, check whether OpenVPN has set itself as the default gateway.

Notice the second entry with the lower metric above. That’s OpenVPN. If such an entry exists, and its metric is lower than the other entries, then it will be used as the default route. If such an entry does not exist then double check that you are running OpenVPN GUI with “Run as Administrator” rights. I wasn’t, and it took be a while to realize that was the reason why OpenVPN wasn’t setting the default route on my laptop!

Hope this helps someone.

Crazy day!

Today has been a crazy day! For one I have been up till 2 AM today and yesterday morning because I am attending the Azure Iaas sessions and they run from 21:00 to 01:00 my time! I sleep by 02:00, then wake up around 06:45, and two days of doing that has taken a toll on my I think. Today after waking up I went back to bed and tried to sleep till around 09:00 but didn’t make much progress. So my head feels a bit woozy and I have been living on loads of coffee. :)

None of that matters too much really but today has been a crazy day. There’s so many things I want to do but I seem to keep getting distracted. My laptop went a bit crazy today (my fault, updating drivers! never do that when u have other stuff to do) and I am torn between playing with Azure or continuing my AD posts. Eventually I ended up playing a bit with Azure and am now on to the AD posts. I don’t want to lose steam of writing the AD posts, but at the same time I want to explore Azure too so it make sense to me and is fresh in the moment. Yesterday’s sessions were great, for instance, and I was helped by the fact that I had spent the morning reading about storage blobs and such and created a VM on Azure just for the heck of it. So in the evening, during the sessions, it made more sense to me and I could try and do stuff in the Azure portal as the speakers were explaining. The sessions too were superb! Except the last one, which was superb of course, but I couldn’t relate much to it as it was about Disaster Recovery (DR) and I haven’t used SCVMM (System Centre Virtual Machine Manager) which is what you use for DR and Azure. Moreover that session had a lot more demo bits and my Internet link isn’t that great so I get a very fuzzy demo which means I can barely make out what’s being shown!

Anyhoo, so there’s Azure and AD on one hand. And laptop troubles on the other. Added to that Xmarks on my browsers is playing up so my bookmarks aren’t being kept in sync and I am having to spend time manually syncing them. All of this is in the context of a sleepy brain. Oh, and I tried to use VPN to Private Internet Access on my new phone (so I could listen to Songza) and that doesn’t work coz my ISP is blocking UDP access to the Private Internet Access server names. TCP is working fine and streaming isn’t affected thankfully, but now I have this itch to update my OpenVPN config files for Private Internet Access with IP address versions and import that into the phone. Gotta do that but I don’t want to go off on a tangent with that now! Ideally I should be working on the AD post – which I did for a bit – but here I am writing a post about my crazy day. See, distractions all around! :)

PowerShell: Add a line to multiple files

Trivial stuff, but I don’t get to use PowerShell as much as I would like to so I end up forgetting elementary things that should just be second nature to me. Case in hand, I wanted to a add a line to a bunch of text files. Here’s what I came up with – just posting it here as a reference to my future selef.

For the background behind this, I use Private Internet Access for my VPN needs and since last month or so my ISP’s been blocking traffic to it. Private Internet Access offers a client that lets me connects to their servers via UDP or TCP. The UDP option began failing but the TCP option surprisingly worked. Of course I don’t want to use TCP as that’s slow and so I went to Private Internet Access’s website where they give a bunch of OpenVPN config files we can use. These are cool in the sense that some of them connect via IP (instead of server name) while others connect to well-known ports or use a well-known local port and so there’s less chance of being blocked by the ISP. In my case turned out just connecting via IP was more than enough so it looks like the ISP isn’t blocking OpenVPN UDP ports, it’s just blocking UDP traffic to these server names.

Anyhow, next step was to stop the client from prompting for an username/ password. OpenVPN has an option auth-user-pass which lets you specify a file-name where the usrname and password are on separate lines. So all I had to do was create this file and add a line such as auth-user-pass pia.txt to all the configuration files. That’s what the code snippet above does.

IPv6 through OpenVPN bridging

I spent the better part of today and yesterday trying to fix something that was broken because I was typing the wrong IPv4 address! Instead of connecting to (fake) address 36.51.55.1 I was typing 36.55.51.1. And since it wasn’t working I kept thinking it was a configuration error. Grr!

Here’s what I am trying to do:

  • I have a Linux server with a /64 IPv6 block assigned to it. The server has IPv6 address 2dcc:7c4e:3651:55::1/64, IPv4 address 36.51.55.1/24. (The server is a virtual machine on my laptop so these aren’t real public IPs).
  • I want a Windows client to connect to this server via OpenVPN, get/ assign itself a public IPv6 address from the /64 block, and have IPv6 connectivity to the Internet. Easy peasy?

I could use services like SixSx or Hurricane Electric to get a tunnel, but I am curious whether it will work over OpenVPN. The idea is to do it in a test lab now and replicate in the real world later (if I feel like it). It’s been a while since I used OpenVPN so this is a good chance to play with it too.

Note

I want a single client to connect to the server so I don’t need a fancy server setup. What I am trying to achieve is a peer-to-peer setup (aka point-to-point setup). Below I refer to the client as OpenVPN client, the server as OpenVPN server, but as far as OpenVPN is concerned it’s a peer-to-peer setup.

Bridging & Routing

OpenVPN has two ways of connecting machines. One is called routing, wherein the remote machine is assigned an IP address from a different network range and so all remote machines are as though they are on a separate network. This means the OpenVPN server machine acts as a router between this network and the network the server itself is connected to. Hence the name “routing”.

The other method is called bridging, and here the OpenVPN server connects the remote machines to the same network it is on. Whereas in routing the OpenVPN server behaves like a router, in bridging the OpenVPN server behaves like a switch. All remote machines have IP addresses from the same network as the OpenVPN server. They are all on the same LAN essentially.

The advantage of bridging is that it works at the layer 2 level (because the remote machine is plugged in to the real network) and so any protocol in the upper levels can be used over it. In contrast routing works at layer 3 (because the remote machine is plugged into a separate network) and so only layer 3 protocols supported by OpenVPN can be used. Previously it was only IPv4 but now IPv6 support too exists. I could use either method in my case, but I am going ahead with bridging because 1) I want the remote machines to behave as though they are connected to the main network, and 2) I just have a /64 block and I don’t want to muck about with subnetting to create separate networks (plus blocks smaller than /64 could have other issues). Maybe I will try routing later, but for now I am going to stick with bridging.

To achieve bridging and routing OpenVPN makes use of two virtual devices – TUN (tunnel adapter) and TAP (network tap). Of these only TAP does bridging, so that’s the route I’ll take.

Before moving on I’ll point to a good explanation of Bridging vs Routing from GRC. The OpenVPN FAQ has an entry on the advantages & disadvantages of each.

OpenVPN: Quick setup on the Server side

A good intro to setting up OpenVPN can be found in the INSTALL file of OpenVPN. It’s not a comprehensive document, so it’s not for everyone, but I found it useful to get started with OpenVPN. The steps I am following are from the “Example running a point-to-point VPN” section with some inputs from the manpage. A point-to-point setup is what I want to achieve.

OpenVPN has various switches (as can be seen in the manpage). You can invoke OpenVPN with these switches, or put them in a config file and invoke the config file. For a quick and dirty testing it’s best to run OpenVPN with the switches. Here’s how I launched the server:

In practice, you shouldn’t do this as it launches the tunnel with NO encryption. You even get a warning from OpenVPN:

A better approach is to generate a shared key first and copy it to the client(s) too. A shared key can be generated with the --secret switch:

And OpenVPN can be launched with this shared key thus:

Note

Remember to copy the shared key to the client. If a client connects without the shared key it will fail:

Notice I am using the --dev switch to specify that I want to use a TAP device.

TAP devices

TAP and TUN are virtual devices. TAP is a layer 2 virtual device, TUN is a layer 3 virtual device.

Each OpenVPN instance on the server creates a TAP device (if it’s configured to use TAP) – names could be tap0, tap1, and so on. It’s important to note that each OpenVPN instance on the server uses a single TAP device – you don’t create TAP devices for each client. Similarly OpenVPN on the client side creates a TAP device when it’s launched. After creating the TAP device, OpenVPN client contacts OpenVPN server and both setup a communication between their respective TAP devices. This “communication” is basically an encrypted UDP connection (by default; though you could have non-encrypted UDP or TCP connections too) from the client to the server. The client OS and applications think its TAP device is connected to the server TAP device and vice versa, while the OpenVPN programs on both ends do the actual moving around of the packets/ frames.

In my case, since I am doing a peer-to-peer connection, the TAP device created on the server will be used by a single client. If I want to add another client, I’ll have to launch a new OpenVPN instance – listening on a separate port, with a separate TAP device, preferably with a separate secret.

If multiple clients try to use the same TAP device on the server, both clients won’t work and the server generates errors like these:

This is because packets from both clients are appearing on the same TAP device and confusing the OpenVPN server.

Creating a bridge

When OpenVPN on the server creates a TAP device it is not automatically connected to the main network. That is something additional we have to do. On Linux this is done using the bridge-utils package. Since I am using CentOS, the following will install it:

A bridge is the (virtual) network switch I was talking about above. It’s a virtual device, to which you connect the machine’s network adapter as well as the TAP adapters you create above. Keep in mind a bridge is a layer 2 device. It doesn’t know about IP addresses or networks. All it knows are MAC addresses and that it has (virtual) network adapters plugged in to it.

The bridge can have any name, but let’s be boring and call it br0. I create a bridge thus:

Next I add the physical network card of my machine to the bridge. Think of it as me connecting the network card to the bridge.

Here’s a catch though. Your physical network adapter is already connected to a switch – the physical switch of your network! – so when you connect it to our virtual switch it is implicitly disconnected from the physical switch. There’s no warning given regarding this, just that you lose connectivity. As far as the machine is concerned your physical network adapter is now connected to the virtual switch (bridge), and this virtual switch is connected to the physical switch.

What this means is that all the network settings you had so far configured on the physical adapter must now be put on the bridge. Bridges are not meant to have IP addresses (remember they are layer 2 devices) but this is something we have to do here as that’s the only way to connect the bridge to the physical network.

To make this change explicit let’s zero IP the physical interface. It’s not really needed (as the interface automatically loses its settings) but I think it’s worth doing so there’s no confusion.

Next I assign the bridge interface the IP settings that were previously on the physical adapter:

Since I am on CentOS and I’d like this to be automatically done each time I start the server I must make changes to the /etc/sysconfig/network-scripts/ifcfg-eth0 and /etc/sysconfig/network-scripts/ifcfg-br0 files. I just copied over the ifcfg-eth0 file to ifcfg-br0 and renamed some of the parameters in the file (such as the interface name, MAC address, etc).

Here’s my /etc/sysconfig/network-scripts/ifcfg-eth0 file. It’s mostly the defaults except for the last two lines:

This Fedora page is a good source of information on setting up a bridge in CentOS/ RHEL/ Fedora. The PROMISC=yes line is added to set the physical adapter in promiscuous mode. This is required by OpenVPN. (By default network adapters only accept frames corresponding to their MAC address. Promiscuous mode tells the adapter to accept frames for any MAC address. Basically you are telling the adapter to be promiscuous!)

Next, here’s my /etc/sysconfig/network-scripts/ifcfg-br0 file:

The first three lines are what matter here. They give the device a name, set it as type Bridge, and tell the kernel it needn’t delay in passing frames through the bridge (by default there’s a 30s delay). The other lines are from the original eth0 configuration file, modified for br0.

Once these two files are in place, even after a reboot the bridge interface will be automatically created, assigned an IP address connecting it to the physical switch, and the physical adapter will be put in promiscuous mode and connected to this bridge.

Creating TAP devices

Back to TAP devices. Once OpenVPN creates a TAP device it must be added to the bridge previously created. This is what connects the TAP device to the main network.

Typically a shell script is used that adds the dynamically created TAP device to the bridge. For instance OpenVPN’s Ethernet Bridging page has a BASH script. Similarly the OpenVPN INSTALL document gives another BASH script (which I like more and for some reason made more sense to me).

CentOS installs an OpenVPN wrapper script in /etc/init.d/openvpn which lets you start and stop OpenVPN as a service. This wrapper script automatically starts an OpenVPN process for each config file ending with the .conf extension in the /etc/openvpn directory and if a /etc/openvpn/xxx.sh script exists for the xxx.conf file it executes this file before launching the OpenVPN process. Thus CentOS already has a place to put in the script to add TAP interfaces to the bridge.

(CentOS also looks for two files /etc/openvpn/openvpn-start and /etc/openvpn/openvpn-shutdown which are run when the wrapper script starts and shutdown – basically they are run before any of the configuration files or scripts are run. I don’t think I’ll use these two files for now but just mentioning here as a future reference to myself).

The shell script can behave in two ways – depending on how TAP devices are created. TAP devices can be created in two ways:

  1. They can be created on the fly by OpenVPN – in which case you’ll need to invoke the script via an up switch; the script will be passed a variable $dev referring to the TAP device name so it can be set in promiscuous mode and added to the bridge.

    To create TAP devices on the fly use the --dev tap switch – notice it doesn’t specify a specific TAP device such as tap0. OpenVPN will automatically create a tap0 (or whatever number is free) device.

  2. They can be pre-created as persistent TAP devices – these will stay until the machine is rebooted, and are preferred for the reason that you don’t need --up and --down switches to create them, and the devices stay on even if the connection resets. In this case the script can create TAP devices and configure and add them to the bridge – independent of OpenVPN.

    To use a specific TAP device use the --dev tap0 switch (where tap0 is the name of the device you created).

I will be using persistent TAP devices. These can be created using the --mktun switch:

Next I set them in promiscuous mode, bring up the device, zero the IP, and set it in promiscuous mode:

Lastly I add these to the bridge:

Assuming my configuration file is called /etc/openvpn/ipv6.conf I’ll create a file called /etc/openvpn/ipv6.sh and add the following:

Don’t forget to make the file executable:

Now whenever the OpenVPN service on CentOS starts, it will run the script above to create the TAP device, configure and add it to the bridge, then launch OpenVPN with a configuration file that will actually use this device. This configuration file will refer by name to the TAP device created in this script.

Firewall

The OpenVPN server listens on UDP port 1194 by default. So I added a rule to allow this port to iptables.

In CentOS I made the following change to /etc/sysconfig/iptables:

Then I reloaded the iptables service so it loads the new rule:

Forwarding

Next I enabled IPv4 & IPv6 forwarding. I added the following lines to /etc/sysctl.conf:

And got sysctl to read the file and load these settings:

IPv4 forwarding is not needed in my case, but I enabled it anyways. Also note that I am enabling IPv6 forwarding for all interfaces. That’s not necessary, the forwarding can be enabled for specific interfaces only.

In addition to enabling forwarding at the kernel level, iptables too must be configured to allow forwarding. The IPv6 firewall is called ip6tables and its configuration file is /etc/sysconfig/ip6tables. The syntax is similar to /etc/sysconfig/iptables and in CentOS forwarding is disabled by default:

I commented out the second line and reloaded the service.

Lastly, I added the following line to /etc/system-config/network:

This tells the initscripts bringing up the interfaces that IPv6 forwarding is to be enabled on all interfaces. Again, this can be specified on specific interfaces – in which you you’d put it in the /etc/system-config/network-scripts/ifcfg-xxx file for that interface – or enabled globally as above but disabled in the file of specific interfaces. For the curious, the initscripts-ipv6 homepage describes more options.

To summarize

To summarize what I’ve done so far:

  1. Create a bridge, add the physical adapter to the bridge, configure the bridge.
  2. Create persistent TAP devices – best to create a script like I did above so we can set it to run automatically later on.
  3. Create a secret key, copy the secret key to the client(s).
  4. Modify firewall, enable forwarding.
  5. Launch OpenVPN, telling it to use the secret key and TAP. No need to specify the TAP device name, OpenVPN will figure it out.

Mind you, this is a quick and dirty setup. Using shared keys won’t work scale, but they will do fine for me now. And rather than launch OpenVPN directly I must put it into a conf file with some logging and additional options … but that can be done later.

Troubleshooting

A very useful switch for troubleshooting purposes is --verb x where x is a number from 0 to 11. 0 means no output except fatal errors. 1 (the default) to 4 mean normal usage errors. 5 to be more verbose, and also output R and W characters to the console for each packet read and write, uppercase is used for TCP/UDP packets and lowercase is used for TUN/TAP packets. And 6-11 for debug range output.

I usually stick with --verb 3 but when troubleshooting I start with --verb 5.

Also, while UDP is a good protocol to use for VPN, during troubleshooting it’s worth enabling TCP to test connectivity. In my case, for instance, the client seemed to be connecting successfully – there were no error messages on either end at least – but I couldn’t test connectivity as I can’t simply telnet to port 1194 of the server to see if it’s reachable (since it was uses UDP). So I enabled TCP temporarily, got OpenVPN on the server to listen on TCP port 1194, then did a telnet to that port from the client … and realized I had been typing the wrong IPv4 address so far!

Here’s how you launch OpenVPN server with TCP just in case:

Be sure to open the firewall and use the corresponding switch --proto tcp-client on the client end too.

OpenVPN: Quick setup on the Client side

The server is running with the following command (remember to add --verb x if you want more verbosity):

I launch the client thus (again, remember to add --verb x if you want more verbosity):

The command is quite self-explanatory.

  1. The --remote switch specifies the address of the server.
  2. The --dev tap switch tells OpenVPN to use a TAP device. On Windows TAP devices are persistent by default so this will be a persistent TAP device.
  3. Port is 1194, the default, so I don’t need to specify explicitly. Similarly protocol is UDP, the default.
  4. The shared key is specified using the --secret switch.

And that’s it! Now my client’s connected to the server. It doesn’t have an IPv6 address yet because the server doesn’t have DHCPv6 or Router Advertisements turned on. I could turn these ON on the server, or assign the client a static IPv6 address and gateway. The address it gets will be a global IPv6 address from the /64 block so you should be able to connect to it from anywhere on the IPv6 Internet! (Of course, firewall rules on the client could still be blocking packets so be sure to check that if something doesn’t work).

Wrapping up

Here’s the final setup on the server and client. This is where I put the settings above into config files.

On the server side I created a file called /etc/openvpn/ipv6.conf:

I renamed the previously generated key to /etc/openvpn/ipv6.key.

Created /etc/openvpn/ipv6.sh:

Also created /etc/openvpn/openvpn-shutdown to remove the TAP devices when the OpenVPN service stops:

Apart from this I created /etc/sysconfig/network-scripts/ifcfg-br0 and /etc/sysconfig/network-scripts/ifcfg-eth0 as detailed earlier. And made changes to the firewall rules.

On the client side I created a file C:\Program Files\OpenVPN\config\ipv6.ovpn:

I copied the shared key to C:\Program Files\OpenVPN\config\ipv6.key. Note that it is important to escape the path name in the ovpn file on Windows.

I created two command files to be run when the client connects and disconnects. These are specified by the --up and --down switches.

Here’s ipv6-up.cmd:

And here’s ipv6-down.cmd:

I should add code to set the DNS servers too, will do that later.

FYI

There’s a reason why I use the short name format to specify the path for these files. Initially I was using the full name escaped but the client refused to launch with the following error:

I noticed that it was trying to run the ipv6-up.cmd file without escaping the space between “Program Files”. Must be an OpenVPN bug, so to work around that I used the short name path.

To connect to the server I launch OpenVPN thus:

OpenVPN for Windows also installs a GUI system tray icon (called OpenVPN GUI). If your config files end with the ovpn extension and are in the C:\Program Files\OpenVPN\config\ folder you can right click this tray icon and connect. Very handy!

Note

This post was updated to include the wrapping up section above. And some errors in my understanding of TAP devices were corrected.

This post was further updated to add the netsh files for the client and also to clarify that this is a peer-to-peer setup. It will only work with one client at a time. Multiple clients will fail unless you create separate OpenVPN instances (on different ports and TAP adapters) to service them.

OpenVPN “pausing” bug in iOS 7

20140108-105419.jpg

If you are using iOS 7 and the OpenVPN app you might notice it “pauses” when on 3G and the phone goes to sleep.

This only happens on 3G and when you switch from Wi-Fi to 3G and is a known bug.

Private Internet Access OpenVPN on iOS

I use Private Internet Access for my VPN needs. They have servers in many countries and provide OpenVPN, L2TP, and PPTP access. Been using them for a year now and no complaints so far. For Android and Windows they provide apps that use OpenVPN, but for iDevices you are stuck with L2TP and PPTP and while that’s fine I prefer OpenVPN (see here and here; also worth reading this on why TCP isn’t a good idea for tunneling). Thankfully iOS has an OpenVPN client so this is something one can setup manually.

Private Internet Access provides a zip file containing all the certificates and config files for OpenVPN. You can’t use these config files directly in the client though. Will have to use iTunes and copy over the files to the OpenVPN app (with a modification to the config files which I’ll come to in a minute). Or you can make two changes to these config files (one of which you have to make even in the iTunes case) and skip iTunes. That’s what I am going to do here. I avoid iTunes if I can (not coz I hate it but generally, I don’t like to be tied to it).

The zip file provided by Private Internet Access contain files with an ovpn extension – which are the configuration files for their server at each location – as well as a ca.crt file which is the certificate for the Private Internet Access servers. The first thing we have to do is combine this ca.crt file into each of the ovpn files. This way we don’t have to worry about how to have both files in the same location as the contents are now merged into one.

The second thing we have to do is added a line like this to each of the ovpn files:

This line tells the OpenVPN client there is no client certificate. By default the iOS OpenVPN client expects a client certificate so unless make this change to the config files the client will not let us connect.

To combine the ca.crt file into each of the config files copy paste the contents of file into each of the config files, surrounding the contents with <ca> and </ca> tags. Alternatively, you could be a geek and use something like PowerShell to automate the process. Copy paste the snippet below and run it in the folder where you extracted the zip file from Private Internet Access.

Pretty straightforward. Replace the line with the contents of the file, add an extra line.

I did this for the files from Private Internet Access and uploaded the resulting files to a zip file you can download from here.

You can download the zip file on your computer, extract the contents, and email the config files you want to an email account you have on the iDevice. Opening the config file from the email will launch OpenVPN and let you add the profile to it.

Alternatively you could visit the above link in a browser such as iCab Mobile on your iDevice. Or even in a browser such as Safari, but download and open with an app like File Explorer (or any other app really which lets you open a zip file and pass the contents to another app).

IMG_6919IMG_6920IMG_6922IMG_6923IMG_6924IMG_6925
IMG_6926
IMG_6927

 

 

 

 

 

IMG_6928