TL;DR: A DigitalOcean droplet, strongSwan, and a custom Configuration Profile for iOS routes all the traffic from my iPhone via my droplet. Why? Just because I can.
Note: This setup does not require you to download Apple Configurator and switch your iPhone into Supervised mode (we will create a configuration profile by hand instead, and install it on the iPhone).
Configure strongSwan by following all the instructions here
- Ignore the part about configuring the firewall, we’ll do this later
- Ensure strongswan starts on boot via chkconfig
chkconfig --add strongswan chkconfig strongswan on # Verify chkconfig --list strongswan
- You don’t need to install any certificates on your iPhone/iPad/Mac as we’re using a pre-shared key (PSK) instead of a certificate based client authentication mechanism
Allow traffic to be forwarded from your server by adding the two iptables rules here
Be sure to modify the network in the two iptables commands (it should match the one specified in your strongSwan config)
Save the two rules which you’ve just added
service iptables save
Open up UDP ports 500 and 4500 for your instance if required (AWS/DigitalOcean/etc)
Adapt the following Configuration Profile for your iOS device
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
<plist version="1.0"> | |
<dict> | |
<key>PayloadContent</key> | |
<array> | |
<dict> | |
<key>UserDefinedName</key> | |
<string>MY_PROFILE_NAME</string> | |
<key>PayloadDisplayName</key> | |
<string>MY_PROFILE_NAME</string> | |
<key>PayloadIdentifier</key> | |
<string>MY_DOMAIN.vpn.always</string> | |
<key>PayloadUUID</key> | |
<string>84590314-C064-4E06-85DB-B5F6B2B7C71F</string> | |
<key>VPNType</key> | |
<string>IPSec</string> | |
<key>IPSec</key> | |
<dict> | |
<key>RemoteAddress</key> | |
<string>MY_STRONGSWAN_SERVER_IP_ADDRESS</string> | |
<key>AuthenticationMethod</key> | |
<string>SharedSecret</string> | |
<key>XAuthEnabled</key> | |
<integer>1</integer> | |
<key>XAuthName</key> | |
<string>MY_ACCOUNT_NAME</string> | |
<key>XAuthPassword</key> | |
<string>MY_ACCOUNT_PASSWORD</string> | |
<key>LocalIdentifierType</key> | |
<string>KeyID</string> | |
</dict> | |
<key>OnDemandEnabled</key> | |
<integer>1</integer> | |
<key>OnDemandRules</key> | |
<array> | |
<dict> | |
<key>Action</key> | |
<string>Connect</string> | |
</dict> | |
</array> | |
<key>OverridePrimary</key> | |
<true/> | |
<key>IPv4</key> | |
<dict> | |
<key>OverridePrimary</key> | |
<integer>1</integer> | |
</dict> | |
<key>PayloadType</key> | |
<string>com.apple.vpn.managed</string> | |
<key>PayloadVersion</key> | |
<integer>1</integer> | |
</dict> | |
</array> | |
<key>PayloadDisplayName</key> | |
<string>VPN Configuration</string> | |
<key>PayloadIdentifier</key> | |
<string>MY_INITIALS.488B9D52-412A-458B-9701-92A5DA7CDA16</string> | |
<key>PayloadRemovalDisallowed</key> | |
<false/> | |
<key>PayloadType</key> | |
<string>Configuration</string> | |
<key>PayloadUUID</key> | |
<string>CF1A90EC-2A3E-4C88-B935-045C5882621D</string> | |
<key>PayloadVersion</key> | |
<integer>1</integer> | |
</dict> | |
</plist> |
Replace the following variables with reasonable values for your setup:
MY_PROFILE_NAME - Only used for display purposes MY_DOMAIN - Just for scoping MY_STRONGSWAN_SERVER_IP_ADDRESS - Your server's IPv4 address MY_ACCOUNT_NAME - See /etc/strongswan/ipsec.secrets MY_ACCOUNT_PASSWORD - See /etc/strongswan/ipsec.secrets MY_INITIALS - Your initials (eg: JP)
Once you’ve updated the content of the XML file above, rename the file to VPNConfig.mobileconfig. Then, either AirDrop it to your iPhone/iPad, or transfer it by some other means.
Since we’re using a PSK, as soon as you install the profile, it’ll prompt you for the PSK. This can again be found in /etc/strongswan/ipsec.secrets.
All done! :)
Cheers on your newly established, always on VPN tunnel between your iOS device and your server!
The Configuration Profile was inspired from Thomas’s blog post here.