How to Setup a L2TP VPN Server on OS X

This is a fast guide on configuring OS X to act as an L2TP VPN Server. This can be accomplished with Apple’s Server App, but if you don’t mind running a few Terminal commands and adding a couple configuration files manually, you can save yourself $20 and go out to eat instead.

This guide also includes a workaround for a known bug in the general release of OS X 10.9 Mavericks in its implementation of racoon that prevents remote clients from being able to connect to your VPN server.

Preamble

Estimated Time Required: 10-15 minutes
Tested on: OS X 10.8 Mountain Lion, OS X 10.9 Mavericks

Setup port forwarding

If your future server is behind a router, you’ll most likely need to setup port forwarding for the following ports:

  • UDP 500 for ISAKMP/IKE
  • UDP 1701 for L2TP
  • UDP 4500 for IPsec NAT Traversal
  • Optional: TCP 1723 for PPTP

Apple has more information on common ports used.

OS X 10.9 and 10.9.1 Mavericks fix

This step is only required on OS X 10.9 and 10.9.1 (Mavericks). Apple has finally fixed this bug in 10.9.2.

In OS X Mavericks, there was a change to the /usr/sbin/racoon program which breaks L2TP access from remote clients when traversing NAT. This is a known bug and I have filed a bug report with Apple. This also breaks Apple’s own Server App since it simply automates what we’re doing manually here. There are two known solutions.

Solution 1: Use a modified variation of the official fix . This modified installer does not check for the existence of the Apple Server.app. Download the modified package MavericksVPNUpdateServerAppLess.pkg.

Also checkout the official Apple KB article on this problem and their fix for users who have the Server.app installed on their systems.

Solution 2: Replace /usr/sbin/racoon with a version from Mountain Lion. If you don’t have your own backup available, you can download my backup of racoon from Mountain Lion. Simply unzip, move the executable into /usr/sbin, and reboot your Mac [or kill and restart racoon].

For example:

1
2
3
sudo mv /usr/sbin/racoon ~/Desktop/racoon.bak
sudo mv ~/Downloads/racoon /usr/sbin/racoon
sudo killall racoon

Add a shared secret to your keychain

Run the following command in Terminal after replacing SHARED-SECRET-PHRASE with your own secret phrase. When you login to your VPN server from a client, both an account password and secret phrase will be needed.

1
sudo security add-generic-password -a com.apple.ppp.l2tp -s com.apple.net.racoon -T /usr/sbin/racoon -p "SHARED-SECRET-PHRASE" /Library/Keychains/System.keychain

Configure Apple’s vpnd Service

Download Example configuration files (and racoon binary from Mountain Lion)

Modify the configuration file com.apple.RemoteAccessServers.plist below and save it to the following location. Set ownership to root:wheel and chmod 644.

1
/Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist

You need to modify the following lines with your own information:

  • Lines 19-20 under “OfferedServerAddresses”

    These two lines should be changed to the DNS domains you want your VPN clients to use. In this example, I’m providing my local router (10.0.1.1) and a Google DNS domain as a secondary (8.8.4.4).

  • Lines 29-30 under “DestAddressRanges”

    These two lines specify the start and end IP address range that will be given to clients when they login. In this example, my clients are given an IP address between 10.0.1.250 and 10.0.1.254. Ideally, you should choose a range that is outside of the range that your router will assign so that you avoid IP address conflicts. For example, my router is configured with a DHCP range of 10.0.1.2 to 10.0.249.

This configuration file also enables PPTP in addition to L2TP. If you wish to enable this as well, modify lines 84-85 and 94-95.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<?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>ActiveServers</key>
  <array>
    <string>com.apple.ppp.l2tp</string>
  </array>
  <key>Servers</key>
  <dict>
    <key>com.apple.ppp.l2tp</key>
    <dict>
      <key>DNS</key>
      <dict>
        <key>OfferedSearchDomains</key>
        <array/>
        <key>OfferedServerAddresses</key>
        <array>
          <string>10.0.1.1</string>
          <string>8.8.4.4</string>
        </array>
      </dict>
      <key>IPv4</key>
      <dict>
        <key>ConfigMethod</key>
        <string>Manual</string>
        <key>DestAddressRanges</key>
        <array>
          <string>10.0.1.250</string>
          <string>10.0.1.254</string>
        </array>
      </dict>
      <key>Interface</key>
      <dict>
        <key>SubType</key>
        <string>L2TP</string>
        <key>Type</key>
        <string>PPP</string>
      </dict>
      <key>L2TP</key>
      <dict>
        <key>IPSecSharedSecret</key>
        <string>com.apple.ppp.l2tp</string>
        <key>IPSecSharedSecretEncryption</key>
        <string>Keychain</string>
        <key>Transport</key>
        <string>IPSec</string>
      </dict>
      <key>PPP</key>
      <dict>
        <key>AuthenticatorACLPlugins</key>
        <array>
            <string>DSACL</string>
        </array>
        <key>LCPEchoEnabled</key>
        <integer>1</integer>
        <key>LCPEchoFailure</key>
        <integer>5</integer>
        <key>LCPEchoInterval</key>
        <integer>60</integer>
        <key>Logfile</key>
        <string>/var/log/ppp/vpnd.log</string>
        <key>VerboseLogging</key>
        <integer>1</integer>
      </dict>
      <key>Server</key>
      <dict>
        <key>Logfile</key>
        <string>/var/log/ppp/vpnd.log</string>
        <key>MaximumSessions</key>
        <integer>128</integer>
        <key>VerboseLogging</key>
        <integer>1</integer>
      </dict>
    </dict>
    <key>com.apple.ppp.pptp</key>
    <dict>
      <key>DNS</key>
      <dict>
        <key>OfferedSearchDomains</key>
        <array/>
        <key>OfferedServerAddresses</key>
        <array>
          <string>10.0.1.1</string>
          <string>8.8.4.4</string>
        </array>
      </dict>
      <key>IPv4</key>
      <dict>
        <key>ConfigMethod</key>
        <string>Manual</string>
        <key>DestAddressRanges</key>
        <array>
          <string>10.0.1.250</string>
          <string>10.0.1.254</string>
        </array>
      </dict>
      <key>Interface</key>
      <dict>
        <key>SubType</key>
        <string>PPTP</string>
        <key>Type</key>
        <string>PPP</string>
      </dict>
      <key>PPP</key>
      <dict>
        <key>AuthenticatorACLPlugins</key>
        <array>
            <string>DSACL</string>
        </array>
        <key>CCPEnabled</key>
        <integer>1</integer>
        <key>CCPProtocols</key>
        <array>
          <string>MPPE</string>
        </array>
        <key>LCPEchoEnabled</key>
        <integer>1</integer>
        <key>LCPEchoFailure</key>
        <integer>5</integer>
        <key>LCPEchoInterval</key>
        <integer>60</integer>
        <key>Logfile</key>
        <string>/var/log/ppp/vpnd.log</string>
        <key>MPPEKeySize128</key>
        <integer>0</integer>
        <key>MPPEKeySize40</key>
        <integer>1</integer>
        <key>VerboseLogging</key>
        <integer>1</integer>
      </dict>
      <key>Server</key>
      <dict>
        <key>Logfile</key>
        <string>/var/log/ppp/vpnd.log</string>
        <key>MaximumSessions</key>
        <integer>128</integer>
        <key>VerboseLogging</key>
        <integer>1</integer>
      </dict>
    </dict>
  </dict>
</dict>
</plist>

Create a Launchd profile

Take the com.apple.ppp.l2tp.plist plist configuration file below and save it to the following location. Set ownership to root:wheel and chmod 644.

1
/Library/LaunchDaemons/com.apple.ppp.l2tp.plist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 <?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>Label</key>
        <string>com.apple.ppp.l2tp</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/sbin/vpnd</string>
            <string>-x</string>
            <string>-i</string>
            <string>com.apple.ppp.l2tp</string>
        </array>
        <key>OnDemand</key>
        <false/>
    </dict>
</plist>

Launchd Loading and Unloading

This command will load the launchd configuration and start the vpnd service. The VPN service will automatically start when you reboot your computer.

1
sudo launchctl load -w /Library/LaunchDaemons/com.apple.ppp.l2tp.plist

This command will unload the launchd configuration and stop the vpnd service. This will also stop VPN services from starting when you reboot.

1
sudo launchctl unload -w /Library/LaunchDaemons/com.apple.ppp.l2tp.plist

Troubleshooting

If things just aren’t working, take a look in Console to see what errors vpnd is reporting.

59 comments… add one

  • Terri Phenn Oct 9, 2014

    I have the results. But, if I try to post the entire plist, it won’t accept the CAPTCHA.

  • MacDevGuy Oct 8, 2014

    Hey sorry to be a noodge but I have 10.9.5 which I assume means I don’t need any replacement config files. So what are the steps to get this going? I have been away from the command line for a bit and want to get going again.

    • Jon Stacey Oct 9, 2014

      MacDevGuy, you won’t need to replace replace racoon because Apple finally fixed the problem in 10.9.2, but you will still need to edit and add the plist configuration files to enable the service.

  • Adam Sep 30, 2014

    Just trying to implement this on 10.9.3 but I don’t have a file at this location:

    /Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist

    Any thoughts?

    • Jon Stacey Sep 30, 2014

      Adam, you may have to create the file using the sample provided above. Don’t forget to make your customizations to OfferedServerAddresses and DestAddressRanges.

  • Terri Phenn Sep 13, 2014

    Offer– I have a copy of 10.6.8 server. I could configure the VPN through Apple’s Server Admin utility GUI, then send you a copy of the config files. Would that be helpful?

    How would you like it configured. And what files should I post here?

    • Matt Sep 16, 2014

      Thanks for the offer – that’s great. I’m not sure what the configuration options are in Server but I just want to have the L2TP server only configured. Internal IP address range would be 192.168.1.150 – 192.168.1.151 (2 addresses).

      DNS would be 192.168.1.1.

      For the config file, not sure if there are more than what’s referenced above in the original post. At least this one:

      /Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist

      I appreciate the help.

  • Matt Sep 1, 2014

    I set everything up and it worked. The issue I have (Snow Leopard – I know – untested) is that I can log in with any account and password, even an account that doesn’t exist on the Mac. Any ideas?

    • Jon Stacey Sep 2, 2014

      Huh, that’s a new one. I assume l2tp, and it doesn’t ask for a shared secret? You might try man vpnd to see if there are any differences in the configuration parameters between 10.6 and 10.8+ around the authentication mechanism. Some digging would be needed. Why not upgrade?

      • Matt Sep 3, 2014

        Yes – l2tp. The shared secret does work. When I take that out of the connecting client I get denied access. But as long as the shared secret is in the connecting client, the server lets me in regardless of what I put as the username and password.

        I ran a man vpnd on both my Snow Leopard box and my Mavericks box. Exact same output (except Mavericks adds “vpnd(5)” to the SEE ALSO section). Both are dated 21 August 2003.

        The reason I’m not upgrading is just because the Snow Leopard machine is an old Mac mini. Would love to figure out how to make it work.

    • Morten Pedersen Sep 25, 2014

      I have the same issue with Lion (10.7.3) only the shared secret is checked before succesful login :-/
      Also thank you so much for a great article… spent last night down the winding openVPN-road without satisfacotry results… this really was only 15 minutes thanks! :)

  • Spike Lightfoot Aug 27, 2014

    Thanks for doing this!!

Leave a Comment


4 × three =