I’ve spent quite a bit of time over the last few days getting a VPN to work from an iPhone, so I thought I’d document the process to avoid anyone else in the same boat trying to row up the same creek.
I have a specific setup that made things more difficult:
- An iPhone as the client device
- A Mikrotik router running RouterOS
- The Mikrotik router behind an ISP-provided router
The reason for the router-behind-a-router setup is that I want to access the internet through the ‘official’ ISP-provided router – for several reasons, not least because when something goes wrong with my net connection and I’m cast into tech support Hell I don’t get immediately kicked back by “I’m sorry, we don’t support third party routers”. I also get a bit more comfort knowing that to break into my network requires two routers to be broken.
The odd setup means that the VPN server is behind NAT and reached by port forwarding. This works just fine for PPTP but unfortunately the protocol is so broken that iOS now warns about setting up a PPTP connection. That’s a no-go.
L2TP is the other VPN protocol that iOS supports natively but this is a huge pain, being a tunnelling protocol containing IPsec packets. IPsec packets are an ancient attempt to secure IP, designed back before NAT and of course NAT screws with packet headers (by definition) which causes IPsec to fail. In the era of IPv4 address scarcity NAT is going to become more and more prevalent so L2TP is also a no-go.
That kills off the iPhone native VPN support. Fortunately, there’s OpenVPN. This is supported by Mikrotik and also there’s an OpenVPN app for iOS, which accesses the VPN API of the iPhone. Unfortunately, it’s not quite as easy to set up as people say.
Instead of giving detailed step-by-step instructions, which will no doubt become invalid after some software update somewhere, I shall give a description of what’s trying to be achieved and then link to some of the more useful posts I’ve read with detailed instructions. A few small ‘gotchas’ got me, and so I’ll describe those too.
Right. First principles. OpenVPN uses Public Key Infrastructure. Which means there’s some faffing with certificates to be done (if you’ve ever tried to get a web server running HTTPS you’ll know about this). Fortunately, it’s not too difficult once you understand what’s going on.
The first step is to get a server private and public key pair, and to get a certificate with the public key signed by a certificate authority (CA). The CA basically says “yeah, we’ve checked out these people and we’ve signed this certificate that describes their server”. Your device (i.e. your iPhone) has a list of CAs that it accepts as trusted people (in the form of a collection of root certificates). So you can generate a certificate for your server then pay one of these guys to sign it for you. It’s basically money for old rope – except you don’t get any rope. And it’s difficult for a new CA to come along and bust up the cartel because the new guy has to get Apple, Google, Microsoft etc. to include them in the list of trusted CA guys. But I digress.
You can go another way, make yourself up as a CA yourself, then tell your device “hey you can trust this CA because it’s really me and I’m a good guy”. There are two ways to do this: tell your iPhone to do the trusting or tell just the OpenVPN app to do the trusting. The latter is the better way to go (because it confines the damage if the private key behind your CA certificate gets stolen).
The Mikrotik VPN server needs a CA certificate, a server certificate (signed by the CA) and the server private key. You can make these certificates by following the instructions here:
Note that if you’re using Ubuntu Linux there’s a problem, as described here:
You need to add this line:
to the last line of the vars file before running it.
Push over to the Microtik router the three generate files:
ca.crt server.crt server.key
Put them into the folder ‘pub’. Then you set up the OpenVPN server as described here:
Note that you can access the command line to the router by using ssh (with default username ‘admin’ to your router). By the way, make sure you’re running the latest RouterOS firmware: you don’t want to be hitting bugs that were fixed (I hit one that wouldn’t let me rename the certificates – which went away when I updated).
The VPN client on the iPhone needs an .ovpn file. It’s a pain to try and copy over several files, so you probably want to embed the client certificates and key directly into the .ovpn file. This is explained here:
OK, so far so good. A few more gotchas to go though.
I used the template .ovpn from the OpenVPN HOWTO page listed above. Set it to use TCP because Mikrotik’s OpenVPN implementation doesn’t support UDP:
proto tcp ;proto udp - not supported
And make sure all compression options are turned off. One more thing you need to add into the file:
This tells the client to ask for a username and password (to match what you set the PPP secret to). This is a must-do: without it the client won’t authenticate and the server will stonewall. The client app will store the username and password away in the iPhone’s keychain so it’s as secure as any other password on your iPhone.
On the Mikrotik router you’ll want to set the VPN encryption profile as follows:
- Set the Local Address to the LAN address of the router. By the way, you’ll probably want your LAN to be a random 10.x.x.x address. If you use 192.168.0.x for your LAN it’s going to go horribly wrong when you’re on holiday and the hotel’s WiFi hands out 192.168.0.x addresses – the VPN client won’t know what to do with the IP packets when the address ranges clash.
- Set the Remote Address to the DHCP pool (assuming you’re using the DHCP server in Mikrotik router to manage IP addresses on your LAN)
You’ll also need to tell the router to proxy ARP so that your client on your VPN can find the other devices on your LAN. You do this under Bridge.. then select interface ‘bridge-local’ then set ARP to ‘proxy-arp’.
OK, on to the iPhone client side now. Install the OpenVPN client from the Apple App Store. To get the .ovpn file into the app you can do what the OpenVPN guys suggest and use iTunes but I found iTunes just sat there spinning away and not listing my apps (oh I so hate iTunes!). Instead I used Dropbox, selected the .ovpn file and opened it in the OpenVPN app. I think you could use AirDrop too. Or even email it to yourself and pick it up in the Mail app (although this isn’t ideal from a security perspective..)
A couple more things are still needed before it works. Go to the iPhone Settings and scroll down to OpenVPN. Here you’ll need to change a few things. Firstly, set Compression to ‘no’. Set Protocol to ‘TCP’. Turn off ‘Force AES-CBC ciphersuites’. It will connect using AES256 anyway but trying to force it seems to cause problems with the Mikrotik implementation.
Almost there: just the port forwarding now. On your ISP-facing router forward TCP port 1194 to the Mikrotik router. And on the Mikrotik router add a firewall entry (under IP.. Firewall) to chain input on port 1194 for the TCP protocol. Make sure this rule is high enough up in the firewall list so that the default discard rules don’t get evaluated first (you do this by dragging and dropping the rule after adding it to the bottom of the list). That should be everything and you can now connect remotely. Turn off WiFi on your iPhone in order to do a proper test of remote access.
It’s possible that you’ll find a hotel WiFi that blocks port 1194 so you can move OpenVPN over to using port 443, which is where HTTPS sits and so this is unlikely to be blocked (it’s possible with advanced traffic analysis to tell the difference between HTTPS and OpenVPN but the usual rubbish hotel IT is unlikely to do anything so advanced).