You can make a difference in the Apple Support Community!

When you sign up with your Apple Account, you can provide valuable feedback to other community members by upvoting helpful replies and User Tips.

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

How to Build Secure VPN Between iOS and OS X with OpenVPN

There is currently no secure VPN option between iOS and OS X, which is a significant problem if you must access your box remotely or need a trusted connection on an untrusted network.


This post explains how to build an OpenVPN secure VPN server on OS X and connect to it from an iOS device. As far as I know, this is the only way to get a secure VPN link between your iPhone or iPad and your Mac. Until Apple replaces its VPN on OS X Server with a secure option, I intend this to replace my OS X Server VPN.


OS X Server VPN is insecure as it only uses the insecure and broken <http://arstechnica.com/security/2012/07/broken-microsoft-sheme-exposes-traffic/> PPTP and L2TP protocols with MS-CHAPv2 ("PPTP traffic should be considered unencrypted") or pre-shared keys (PSKs, "IPSEC-PSK is arguably worse than PPTP ever was for a dictionary-based attack vector") <https://www.cloudcracker.com/blog/2012/07/29/cracking-ms-chap-v2/>. The only secure options are certificate-based L2TP/IPSec or SSL-based OpenVPN. Unfortunately, there simply are no Kerberos-based certificate VPN clients for iOS, but fortunately, an excellent OpenVPN option exists on iOS. The only trick is to stand up an OpenVPN server on iOS. Running your own OpenVPN server is free, and the client app will set you back about seven dollars.


This information is scattered across the web, so I'll integrate into one place here explicitly for an OS X/iOS solution.



Step 1. Get OpenVPN on OSX and configure it.


1A. I like Macports, so assuming that you've downloaded and installed Xcode from the App Store, installed Macports, run:


sudo port selfupdate

sudo port install openvpn


2A. Create your own SSL/TLS certificates with OpenSSL (automatically installed as a OpenVPN dependent by Macports). Remember, every OpenSSL file name .key is secret and must be protected on both your OS X box and transmitted securely to iOS (as below) using either ssh or the method described at the GuizmoVPN website. You must also use a strong, secure pass phrase to protect the certificate authority you will create in this step. The integrity of your VPN relies on performing this step properly and then properly protecting your secret keys. For any security issues, such as with a lost or stolen iPhone, you must discard the compromised certificate and repeat these steps.


su root

cd /opt/local/share/doc/openvpn2/easy-rsa/2.0

# edit script defaults like KEY_CN == Common Name

vi ./vars

mkdir ./keys

touch ./keys/index.txt

echo 1 > ./keys/serial

. ./vars

./clean-all

./build-ca --pass

./build-key-server server-domainname

# choose a unique Common Name (CN) for each client

./build-key client-domainname

./build-dh

openvpn2 --genkey --secret ./keys/ta.key


# Notes:

# Use the domain name "domainname.com" for the common name

# Contact email "admin@domainname.com" must match name in CA;

# otherwise, there will be some X509 error.


# For the server-domainname cert, use the default common name

# "server-domainname".This must also match the client configuration

# setting:

# tls-remote domainname.com


# Unnecessary if you already signed with ./build-key[-server]

# ./sign-req server-domainname

# ./sign-req client-domainname


cd keys

openssl verify -CAfile ca.crt ca.crt

openssl verify -CAfile ca.crt server-domainname.crt

openssl verify -CAfile ca.crt client-domainname.crt


1C. Configure OS X to route your VPN packets correctly. See <https://forums.openvpn.net/topic11401.html>.


su

mkdir /Library/Application\ Support/vpn

vi /Library/Application\ Support/vpn/enable-vpn-forward-nat.sh


#!/bin/bash

#

# Sleep is necessary cause network has to be up at the time of following commands

# Otherwise the network will not work at all

#

sleep 15

#

sysctl -w net.inet.ip.fw.enable=1

sysctl -w net.inet.ip.forwarding=1

natd -interface en0

ipfw add divert natd ip from any to any via en0


chmod 755 /Library/Application\ Support/vpn/enable-vpn-forward-nat.sh


On OS X Server, make sure that ipfw is running and, if blocked, that the firewall allows UDP port 443. On OS X client, I believe that the App firewall will take care of all this automatically.


sudo ipfw enable firewall

sudo ipfw add allow udp from any to any 443


Make these changes permanent on boot:


su

vi /Library/LaunchDaemons/net.openvpn.enable-vpn-forward-nat.plist


<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.openvpn.enable-vpn-forward-nat</string>

<key>ProgramArguments</key>

<array>

<string>/Library/Application Support/vpn/enable-vpn-forward-nat.sh</string>

</array>

<key>RunAtLoad</key>

<true/>

</dict>

</plist>


sudo launchctl load -w

/Library/LaunchDaemons/net.openvpn.enable-vpn-forward-nat.plist




Step 2. Get Tunnelblick on OS X and configure it.


2A. <http://code.google.com/p/tunnelblick/>


2B. Create a .tblk directory for your VPN server with all the necessary files. I'll demo a tun setup. The LAN here looks like a router on 10.0.1.1 and a OS X Server on 10.0.1.3.


mkdir ~/Desktop/Domainname_tun.tblk

cd /opt/local/share/doc/openvpn2/easy-rsa/2.0/keys

sudo cp -p ca.crt dh2048.pem server-domainname.crt server-domainname.key ta.key ~/Desktop/Domainname_tun.tblk

sudo chown -R username ~/Desktop/Domainname_tun.tblk

cd ~/Desktop/Domainname_tun.tblk

vi config.ovpn


local 10.0.1.3

port 443

proto udp


dev tun

;dev tap


ca ca.crt

cert server-domainname.crt

key server-domainname.key


tls-auth ta.key 0


dh dh2048.pem


server 10.8.0.0 255.255.255.0


;server-bridge 10.0.1.98 255.255.255.0 10.0.1.50

10.0.1.90


push "redirect-gateway def1"

push "dhcp-option DNS 8.8.8.8"

;push "dhcp-option DNS 10.0.1.3"

;push "dhcp-option DOMAIN domainname.com."


client-to-client

keepalive 10 120

;cipher BF-CBC

comp-lzo

max-clients 10


user nobody

group nobody


persist-key

persist-tun


ifconfig-pool-persist ipp.txt


verb 3



2C. Forward UDP port 443 from your router to you server at 10.0.1.3. (You may also wish to forward the default OpenVPN port 1194 as well to test other configurations.)



2D. Doubleclick on ~/Desktop/Domainname_tun.tblk within Finder, which should start Tunnelblick and import your configuration. Then,


Tunnelblick>VPN Details ... >Configuration>Settings>Set Nameserver (3.1)


You may also wish to launch this service at boot.


Hit connect and Tunnelblick should launch your OpenVPN server on UDP port 443.



Step 3. Get GuizmoVPN on iOS and configure it.


3A. <http://www.guizmovpn.com/>


3B. Create a configuration .zip file for the GuizmoVPN OpenVPN client:


mkdir ~/Desktop/tun_client-domainname

cd /opt/local/share/doc/openvpn2/easy-rsa/2.0/keys

sudo cp -p ca.crt client-domainname.crt client-domainname.key ta.key ~/Desktop/tun_client-domainname

sudo chown -R username ~/Desktop/tun_client-domainname

cd ~/Desktop/tun_client-domainname

vi tun_client-domainname.conf


####

## Domainname Mac UDP client configuration version 2.0

####

client

dev tun

proto udp

remote server.domainname.com 443

redirect-gateway def1

resolv-retry infinite

nobind

;user nobody

;group nobody

persist-key

persist-tun

ca ca.crt

cert client-domainname.crt

key client-domainname.key

ns-cert-type server

tls-auth ta.key 1

;auth-user-pass

tls-remote server-domainname

tls-cipher DHE-RSA-AES256-SHA

;cipher BF-CBC

comp-lzo

verb 3

# shaper 50000


cd ~/Desktop

zip -r tun_client-domainname.zip tun_client-domainname


3C. Securely copy the file tun_client-domainname.zip to your iOS device by either:


(1) GuizmoVPN's web server: <http://www.guizmovpn.com/index.php?option=com_content&view=article&id=3&Itemid=3>


(2) SMIME encrypted email to yourself, click on the .zip file, Open In ... GuizmoVPN.


(3) A combination of ssh and iFile's web server (password enabled, running on your LAN).


3D. GuizmoVPN>Settings>DNS Configuration>DNS Push ON


3E. GuizmoVPN>General>Connect ON


Watch your log file to see the authentication, push options, and routing work. This will give you an IP of, e.g., 10.8.0.6 on your LAN, secured with TLS.



Finally, if anyone knows how to configure these additional items, please post: use of my own DNS server, and bridged connections.


(A) My LAN's DNS server is at 10.0.1.3 (same as the OpenVPN server), which serves up LAN addresses for my server and local clients. I'd like to use this DNS server as my OpenVPN client's DNS server rather than 8.8.8.8. Problem is, DNS is fail when I specify


push "dhcp-option DNS 10.0.1.3"


in the server config above. Why?! Could the client be trying to hit 10.0.1.3 on the internet, rather than my LAN? That's the only thing I can think of, but that doesn't make sense to me either because I can OpenVPN into VNC via 10.0.1.3:5900 just fine, as well http on 10.0.1.3:80 and all other services. Why would LAN DNS fail?


(B) I'd like to use bridging mode with the "dev tap" server+client settings:


dev tap

server-bridge 10.0.1.3 255.255.255.0 10.0.1.50 10.0.1.90


But that fails -- the client connects with assigned IP 10.0.1.50, but its packets don't appear to go anywhere. Pings fail in both directions, web at 10.0.1.3:80 fails, and of course DNS fails. Not sure if this is a tap issue on OS X, a Tunnelblick issue, or an ipfw issue. Any suggestions to troubleshoot or magic ipfw incantations would be greatly appreciated.

Mac mini Server (Mid 2010), Mac OS X (10.7.4), Lion Server, EyeTV HD, Turbo.264 HD

Posted on Oct 27, 2012 8:34 AM

Reply
14 replies

Nov 1, 2012 3:31 AM in response to essandess

As noted here, Tunnelblick currently has some serious local security issues (relating to local suid access, not the VPN tunnel). I hope the Tunnelblick project elliminates its reliance on suid helpers.


Here is a simplified, locally secure setup that uses a launch daemon for the OpenVPN server. It's based on this Macports post. This setup will launch an OpenVPN server at boot and launchctl will keep it alive and functional.


After using an OpenVPN server instead of OS X Server's VPN for a while now, it's clear that an OpenVPN server is preferable in many ways.Specifically, iOS clients don't drop the VPN connection when they lock, so you don't have to keep re-launching VPN, itself a security PITA.


Here's a simplified OpenVPN server setup:


su

mkdir /opt/local/etc/openvpn2

mkdir /opt/local/etc/openvpn2/domainname

rsync -va /opt/local/share/doc/openvpn2/easy-rsa/2.0/keys /opt/local/etc/openvpn2/domainname

vi /opt/local/etc/openvpn2/domainname/server.conf


local 10.0.1.3

port 443

proto udp


dev tun


ca /opt/local/etc/openvpn2/domainname/keys/ca.crt

cert /opt/local/etc/openvpn2/domainname/keys/server-domainname.crt

key /opt/local/etc/openvpn2/domainname/keys/server-domainname.key


tls-auth /opt/local/etc/openvpn2/domainname/keys/ta.key 0


dh /opt/local/etc/openvpn2/domainname/keys/dh2048.pem


server 10.8.0.0 255.255.255.0


push "redirect-gateway def1"

push "dhcp-option DNS 8.8.8.8"

;push "dhcp-option DNS 10.0.1.3"

;push "dhcp-option DOMAIN domainname.com."


client-to-client


keepalive 10 120


;cipher BF-CBC


comp-lzo


max-clients 10


user nobody

group nobody


persist-key

persist-tun


ifconfig-pool-persist /opt/local/etc/openvpn2/domainname/ipp.txt


verb 3


vi net.openvpn.server.plist


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"

"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>

<plist version="1.0">

<dict>

<key>Label</key>

<string>net.openvpn.server</string>

<key>ServiceDescription</key>

<string>Starts an OpenVPN Server.</string>

<key>WorkingDirectory</key>

<string>/opt/local/etc/openvpn2/domainname</string>

<key>Program</key>

<string>/opt/local/sbin/openvpn2</string>

<key>ProgramArguments</key>

<array>

<string>openvpn2</string>

<string>--config</string>

<string>server.conf</string>

<string>--log-append</string>

<string>/opt/local/var/log/openvpn2/server.log</string>

<string>--status</string>

<string>/opt/local/var/log/openvpn2/status.log</string>

<string>3600</string>

<string>--mute</string>

<string>10</string>


</array>

<key>RunAtLoad</key>

<true/>

<key>KeepAlive</key>

<dict>

<key>NetworkState</key>

<true/>

</dict>

<key>TimeOut</key>

<integer>90</integer>

</dict>

</plist>


cp net.openvpn.server.plist /Library/LaunchDaemons

launchctl load -w /Library/LaunchDaemons/net.openvpn.server.plist

Jan 31, 2013 3:56 PM in response to YoQuieroTacoBell

At long last! This is a great app. It works with the OpenVPN server setup described above and the following client configuration file:


client.ovpn:


####

## Domain Mac UDP client configuration version 2.0

####

client

dev tun

proto udp

remote server.domainname.com 443

redirect-gateway def1

resolv-retry infinite

nobind

;user nobody

;group nobody

persist-key

persist-tun

;ca ca.crt

;cert sts-iPad-domainname.crt

;key sts-iPad-domainname.key

<ca>

-----BEGIN CERTIFICATE-----

MY CERT from ca.crt

-----END CERTIFICATE-----

</ca>

ns-cert-type server

;tls-auth ta.key 1

key-direction 1

<tls-auth>

#

# 2048 bit OpenVPN static key

#

-----BEGIN OpenVPN Static key V1-----

MY CERT from ta.key

-----END OpenVPN Static key V1-----

</tls-auth>

;auth-user-pass

;tls-remote server-domainname

tls-cipher DHE-RSA-AES256-SHA

;cipher BF-CBC

;client-http-proxy 10.0.1.3 3128

comp-lzo

verb 3


Compared to Guizmo VPN, there are some trade-offs: The OpenVPN lets you use certs stored in your iOS keychain, which offers greater security, but GuizmoVPN uses the client-http-proxy directive, allowing proxies even over udp tunnels. This appears not to work for me using the OpenVPN app. I'll ping them and request this feature.


Also, when creating multiple client certificates using easy-rsa, be sure not to use the same common name as the server's for your client certs.

Feb 9, 2013 11:16 AM in response to essandess

Apple's own VPN server is using the open-source Racoon software. I have discovered this can be configured to use Cisco IPSec rather than L2TP or PPTP. See http://blog.dest-unreach.be/2011/03/03/iphone-compatible-ipsec-vpn-on-an-ubuntu- server-with-ldap-authentication


It appears that Racoon can also be configured to use certificate based authentication rather than MS-CHAP see http://bsdsupport.org/configuring-racoonipsec-tools-to-use-x509-certificates/


Therefore by (manually) configuring Racoon to use Cisco IPSec and certificate authentication it should be possible to achieve the same goals as the above mentioned OpenVPN solution but to do so without the need to use an additional thirdparty VPN client. Furthermore this should work for both iOS and OS X clients.


If I am right and please correct me if I am not, then this would seem a preferable solution to OpenVPN. Would anyone be able to write up detailed instructions for implementing this on a Mountain Lion Mac?


PS. Clearly the best option would be for Apple to build into Server.app this as an option.

May 30, 2013 12:40 AM in response to essandess

Hello,


First of all, your article helped me greatly in setting up my openVPN server. Thanks!


I'm currently using pfctl instead of ipfw, and running into issues configuring the NAT configurations to correctly forward packets from the VPN to the local network and the internet.


Ive attempted to mimic what

natd -interface en0

ipfw add divert natd ip from any to any via en0

is doing by adding the following in pf.conf below "nat-anchor "com.apple/*"


nat on tun0 from any to any -> en0

Is there something I'm missing or doing wrong? Any help would be appreciated.

Oct 27, 2013 9:17 AM in response to Kakky07

My OpenVPN ipfw setup no longer works with Mavericks 10.9, though it worked fine on Mountain Lion. I used ipfw to divert all natd packets, allowing VPN LAN IPs on, say 10.2.1.0/24 to 10.0.1.0/24. Now VPN no longer works, and if I run this ipfw script, it breaks my servers internet and LAN access as well!


It looks like ipfw and natd are obsolete on OS X, and it's finally time to learn how to implement divert using pfctl.


Has anyone used pfctl with tunnelblick? What are the command to obtain a divert, as done below with natd/ipfw?


#!/bin/bash

#

# Reference: https://forums.openvpn.net/topic11401.html

#

# Sleep is necessary cause network has to be up at the time of following commands

# Otherwise the network will not work at all

#

sleep 15

#

/usr/sbin/sysctl -w net.inet.ip.fw.enable=1

/usr/sbin/sysctl -w net.inet.ip.forwarding=1

/usr/sbin/natd -interface en0

/sbin/ipfw add divert natd ip from any to any via en0


The natd command throws the error on Mavericks:


natd: Unable to bind divert socket.: Address already in use

Mar 21, 2014 4:09 PM in response to zMakUzr

For what it's worth since my previous reply on 9th Feb 2013 I have now got a fully working and deployed solution running.


I was able to get Racoon working with certificates for iOS clients but when I extended this to include VPN on Demand I discovered that Apple would not let you save the password. I therefore switched to using StrongSwan5 and Xauth-noauth to disable the username/password authentication leaving just the certificate authentication. It was then possible to use the built-in IPSec client, a certificate, VPN on Demand and not get nagged each time for a password.


My own write up is here http://jelockwood.blogspot.co.uk/2014/03/how-to-do-vpn-on-demand-for-ios-at-zero .html

Mar 24, 2014 4:37 PM in response to John Lockwood

Actually, the instructions I've put up tell you how to have IPSec running, including "on-demand" without the user having to enter a password every time the VPN connects -- see and search the page for "having to enter" and you'll find the detail -- and you can "track back" from there, depending upon what you're using.


BTW, your requirement point 3 is not true. I also was under the impression that a device had to be "managed" before you could use the VPN on-demand capabilities. However, it seems that's not true. My instructions omit the step of making a device managed (though it's a nice capability, for a small number of units, it's a serious "pain" and a huge amount of overhead -- but a boon for enterprise-level use, I'm sure).


I agree that Apple could do better at making VPN on-demand work more easily, especially in the case of an all-Apple environment (which we try to be).


In the end, what I found is that OpenVPN works far better than IPSec, at least for mobile (we continue to use IPSec for an always-on inter-office VPN). One of the things I liked about OpenVPN is that you can have a series of servers on different ports in case the network the mobile is on is blocking ports. The clients will then try all servers in round-robin sequence. In our case I set up 4 UDP servers (best for performance) with a final one being TCP:443. Since that looks like HTTPS (unless you start seriously inspecting traffic/patterns), it's unlikely to be blocked -- and if it is, maybe you don't want to be on that network. #;-)


It's interesting how close your solution appears to be to the one which I also developed. A case of "great minds think alike" ... or just "idiots seldom differ?" BTW, if you're interested in adding an "Alternative Solutions" heading I'd be interested in adding the same and we could cross-link our articles. After all, it's all about being connected! <sic>


<Link Edited By Host>

Mar 23, 2014 1:37 PM in response to zMakUzr

It is true you don't have to enrol a device to an MDM but you do need to use a profile which could in theory either be totally written by hand or more likely initially produced by something like iPhone Configuration Utiltiy. This produces a mobileconfig file which is basically an XML plist file containing the settings for in this case -


  • Certificate to use for the VPN connection
  • VPN configuration
  • VPN on Demand settings


I see you are using Apple Configurator


I have seen of course your article suggesting using OpenVPN and a couple of others but I have been somewhat puzzles by this as it is not one of the VPN types listed by Apple as being supported. The ones listed by Apple are the built-in Cisco IPSec client which I used, or Cisco AnyConnect, and several SSL solutions including Cisco, Juniper, SonicWall, F5.


Are you using OpenVPN as a Cisco IPSec compatible VPN server? If so I don't know how it can use multiple ports. Is it instead acting as a Cisco AnyConnect compatible system? (Which uses SSL.)


I see you are getting round the Cisco IPSec password issue in a different way but actually hand editing it in to the XML plist like the following.


add the following entry to the IPSec dict(tionary) section:

<key>XAuthPassword</key>
  <string>myVPNuserPassword</string>


I had not seen this documented elsewhere, it is not in the official Apple document. This is a different approach to what I used and has the advantage of keeping two levels of authentication i.e. certificate and password, but requires either you not to change the password, or to have to regularly install a new mobileconfig file. My approach has the advantage of not needing to be updated for password changes. Personally I think what Apple should do is not require the username and password to be in the mobileconfig, to allow these to be entered and saved by the user, and when the password is changed and therefore no longer valid to re-ask and re-save the new password - just like a normal setup works.

Mar 24, 2014 4:39 PM in response to John Lockwood

Re: ... but I have been somewhat puzzles by this as it is not one of the VPN types listed by Apple as being supported.

---

Well, the free OpenVPN Connect app is supported -- it's just not documented by Apple (at least in any technical documentation I've seen from Apple). [getting on the soapbox] While Apple tends to be exemplary at developing good software architectures, they're absolutely terrible at producing good (i.e., complete) release notes and some kinds of technical documentation. [stepping off the soapbox] According to some posts on the OpenVPN forums, a part of the OpenVPN team is working closely with Apple (non-disclosure close), so that's good.


Though it won't be complete for another couple of days, if you look there's already enough there to see how to support the OpenVPN Connect VPN type. All the hardware, software and documentation I've used is documented on

http://www.derman.com/blogs/VPN-Hardware-and-Software-Used


Hey, I know there's a lot of stuff there, but I'm trying to be complete and rigorous (e.g., the graphics and examples should be consistent across the collection, etc.).


Yeah, I don't even remember how I came to the

XAuthPassword
parameter -- it was either mentioned by someone else or (what I think I remember is that) I saw it in a PPTP or L2TP config I gen'd to have a "look see." Again, this is only one example of why I say that the technical documentation on the configuration profiles stuff is incomplete.


Re: Personally I think what Apple should do is not require the username and password to be in the mobileconfig ...

---

I'm guessing this is due to conforming with the "Cisco way."


FYI, with OpenVPN you can have only account (username/password -- without on-demand, of course), only certificate (with on-demand) or both account and certificate (with on-demand) for authentication. You can also force a check to ensure that the user certificate is the same as the one associated with the user's account and that the root certificate is validated within a certain number of levels. As I said, OpenVPN seems to excel in almost all aspects.


Re: ... allow these to be entered and saved by the user, ...

---

Yeah ... it seems like of those "du-oh" things. Can't imagine what the reasoning is, but having to manually enter a password for every on-demand connection in many usage scenarios would only encourage the user to either turn off the VPN or get frustrated enough to destroy the phone. $;-) However, having said that, I've been a software developer for over 35 years and learned a long time ago that there are often very valid reasons for things where those reasons are not obvious until you get down to the details. When confronting such things with the people responsible, I generally use the "Can you help me understand why ... is so?" approach, as opposed to the "Well that's stupid!" approach. Of course, I'd have to admit to dining on some foot and some crow before I got to that approach. #:-)

Re: I may receive some form of compensation, financial or otherwise, from my recommendation or link. <Edited by Host>

---

Yes, we do run some (non-animated) ads on some parts of our sites to help defray the costs. However, that's not the reason for putting up the information -- if it was, I'd be working for fractions of a cent per hour. Spending the dozens of hours it's taken to put together and put up the information is really just trying to help others avoid having to spend so much time. I appreciate it when others "share" and, as I have time, try to do the same in return. Thanks for considering the value of the links and not just deleting the comments outright.


<Link Edited By Host>

How to Build Secure VPN Between iOS and OS X with OpenVPN

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.