Deploying a VPN Server on OSX

If you need a VPN server service, but don’t have VPN capabilities on your router, you may be able to use your Mac as a VPN server. This guide will show you how to do that.

1 Requirements

Before following this guide, you will need to be sure that your router supports forwarding for GRE (IP protocol 47). Linksys routers do not. The FiOS Quantum Gateway and Asus routers do.

2 Design

3 Set Aside Addresses for VPN

Go into your router and change the DHCP scope to exclude an IP range to be assigned by your VPN server. For example, 192.168.1.250-192.168.1.254. The address 192.168.1.250 will be reserved for the VPN server and the range 192.168.1.251-192.168.1.254 will be reserved for VPN client(s).

4 Set Up VPN on macOS

VPN management is no longer available in macOS Server in High Sierra (10.13) or Mojave (10.14). (See Changes introduced in macOS Server 5.7.1 for more information).

None of the alternative applications suggested by Apple (OpenVPN, SoftEther VPN, WireGuard) have a GUI (Graphical User Interface). They are all command line only on macOS.

The easiest and least expensive way to provide VPN functionality on macOS is to enable Apple’s own VPN from the command line. Apple is removing support for this feature, so this procedure may not work in future releases of macOS. Migration to hardware VPN as described above is recommended.

4.1 Enable Static Addressing

Configure the desktop TCP/IP with using DHCP with manual address. Configure the address 192.168.1.250. This address was excluded in the DHCP scope above.

4.2 Enable Apple VPN Server Service

Open Terminal. Run the following to create the VPN Server service startup document. When prompted for a password, enter the password for the current user.

$ cd /Library/LaunchDaemons
$ sudo nano vpn.ppp.l2tp.plist
Password:

Paste the following text into the editor. Save the document and exit the editor.

<?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>Disabled</key>
    <false/>
    <key>EnableTransactions</key>
    <true/>
    <key>Label</key>
    <string>vpn.ppp.l2tp</string>
    <key>KeepAlive</key>
    <true/>
    <key>Program</key>
    <string>/usr/sbin/vpnd</string>
    <key>ProgramArguments</key>
    <array>
      <string>vpnd</string>
      <string>-x</string>
      <string>-i</string>
      <string>com.apple.ppp.l2tp</string>
    </array>
    <key>EnableTransactions</key>
    <false/>
    <key>EnablePressuredExit</key>
    <false/>
  </dict>
</plist>

4.3 Register the VPN Service

Run the following to register the VPN service.

$ sudo launchctl load -w /Library/LaunchDaemons/vpn.ppp.l2tp.plist

4.4 Check if the VPN service is Registered

Run the following command to confirm that the VPN service is registered.

Output if the VPN service is registered:

$ launchctl print system/vpn.ppp.l2tp
vpn.ppp.l2tp = {
active count = 1
path = /Library/LaunchDaemons/vpn.ppp.l2tp.plist
state = running
program = /usr/sbin/vpnd
…

Output if the VPN service is not registered:

$ launchctl print system/vpn.ppp.l2tp
Could not find service "vpn.ppp.l2tp" in domain for system

4.5 Setup the VPN Service

Run this to set up the VPN.

$ cd /Library/Preferences/SystemConfiguration
$ sudo nano com.apple.RemoteAccessServers.plist

Paste the following text into the editor. Change the the IP addresses as needed. For example, you can set the DNS IP address(es) and the first and last IP address that that the VPN server will assign to VPN clients. Save the document and exit the editor.

<?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>192.168.1.1</string>
				</array>
			</dict>
			<key>IPv4</key>
			<dict>
				<key>ConfigMethod</key>
				<string>Manual</string>
				<key>DestAddressRanges</key>
				<array>
					<string>192.168.1.251</string>
					<string>192.168.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>
	</dict>
</dict>
</plist>

4.6 Add the security key

Run the following to add the security key SHARED_SECRET to the system keychain. Replace SHARED_SECRET with your actual key name. This is the key that will be used to encrypt data transmitted over the VPN tunnel.

$ sudo security add-generic-password -a com.apple.ppp.l2tp -s com.apple.net.racoon \
-T /usr/sbin/racoon -p "SHARED_SECRET" /Library/Keychains/System.keychain

4.7 Restart the VPN to Load the Configuration

Run the following to restart the VPN service and load the configuration changes.

$ sudo killall -HUP vpnd

4.8 Add VPN users

Any active user on the macOS server can authenticate with the VPN server. Add additional users as necessary.

4.9 Follow the Log

Run the following to follow the log output. Do this while you connect the VPN client to the VPN server the first time.

$ tail -f /var/log/ppp/vpnd.log

5 Set Up Port Forwarding on the Router

Connect to your router and set the following port-forwarding rules (PAT). The target host is 192.168.1.250 for all of the rules.

  • ISAKMP/IKE: UDP/500
  • L2TP: UDP/1701
  • IPsec NAT Traversal: UDP/4500
  • IP Protocols: GRE

6 Configure VPN Client

Now you are ready to configure a VPN client.

6.1 Configure macOS Mojave

Open System Preferences.

Open Network.

Click + (plus) to create a new service.

Specify the following interface settings and click Create.

  • Interface: VPN
  • VPN Type: L2TP over IPSec
  • Service Name: VPN

Configure the interface as follows.

  • Configuration: Default
  • Server Address: <MY OUTSIDE IP>>
  • Account Name: <OSX ACCOUNT>

Note: The server address may shift if the Internet provider is assigning a Dynamic IP. Get the current address by connecting to https://www.whatsmyip.org/ from the VPN server’s network. This step can be eliminated by getting your Internet provider to assign a static address or by enabling dynamic DNS on the router and connecting by name.

Click Authentication Settings…

Set the following authentication settings and click OK.

Note: Leave the password blank to be prompted at each login. This is more secure. You must use the share secret that was assigned on the VPN server.

  • User Authentication: Password
  • Password: <BLANK>
  • Shared Secret: <SHARED_SECRET>

Click Apply to save the interface settings.

6.2 Connect VPN

  1. Click Connect.

Enter your password.

You should see the following if you are connected.

6.3 Review the VPN Connection Log

Return to the VPN server, you should see something like this

Sat Apr 13 12:31:12 2019 : Directory Services Authorization plugin initialized
Sat Apr 13 12:31:12 2019 : publish_entry SCDSet() failed: Success!
Sat Apr 13 12:31:12 2019 : publish_entry SCDSet() failed: Success!
Sat Apr 13 12:31:12 2019 : publish_entry SCDSet() failed: Success!
Sat Apr 13 12:31:12 2019 : L2TP incoming call in progress from '40.30.20.10'...
Sat Apr 13 12:31:12 2019 : L2TP received SCCRQ
Sat Apr 13 12:31:12 2019 : L2TP sent SCCRP
Sat Apr 13 12:31:12 2019 : L2TP received SCCCN
Sat Apr 13 12:31:12 2019 : L2TP received ICRQ
Sat Apr 13 12:31:12 2019 : L2TP sent ICRP
Sat Apr 13 12:31:12 2019 : L2TP received ICCN
Sat Apr 13 12:31:12 2019 : L2TP connection established.
Sat Apr 13 12:31:12 2019 : using link 0
Sat Apr 13 12:31:12 2019 : Using interface ppp0
Sat Apr 13 12:31:12 2019 : Connect: ppp0 <--> socket[34:18]
Sat Apr 13 12:31:12 2019 : sent [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x2e5e139e> <pcomp> <accomp>]
Sat Apr 13 12:31:12 2019 : rcvd [LCP ConfReq id=0x1 <asyncmap 0x0> <magic 0x3bd6dfd6> <pcomp> <accomp>]
Sat Apr 13 12:31:12 2019 : lcp_reqci: returning CONFACK.
Sat Apr 13 12:31:12 2019 : sent [LCP ConfAck id=0x1 <asyncmap 0x0> <magic 0x3bd6dfd6> <pcomp> <accomp>]
Sat Apr 13 12:31:12 2019 : rcvd [LCP ConfAck id=0x1 <asyncmap 0x0> <magic 0x2e5e139e> <pcomp> <accomp>]
Sat Apr 13 12:31:12 2019 : sent [LCP EchoReq id=0x0 magic=0x2e5e139e]
Sat Apr 13 12:31:12 2019 : sent [IPCP ConfReq id=0x1 <compress VJ 0f 01> <addr 192.168.1.250>]
Sat Apr 13 12:31:12 2019 : rcvd [LCP EchoReq id=0x0 magic=0x3bd6dfd6]
Sat Apr 13 12:31:12 2019 : sent [LCP EchoRep id=0x0 magic=0x2e5e139e]
Sat Apr 13 12:31:12 2019 : rcvd [LCP EchoRep id=0x0 magic=0x3bd6dfd6]
Sat Apr 13 12:31:12 2019 : rcvd [IPCP ConfReq id=0x1 <addr 0.0.0.0> <ms-dns1 0.0.0.0> <ms-dns3 0.0.0.0>]
Sat Apr 13 12:31:12 2019 : ipcp: returning Configure-NAK
Sat Apr 13 12:31:12 2019 : sent [IPCP ConfNak id=0x1 <addr 192.168.1.251> <ms-dns1 192.168.1.1> <ms-dns3 192.168.1.1>]
Sat Apr 13 12:31:12 2019 : rcvd [IPV6CP ConfReq id=0x1 <addr fe80::9a01:a7ff:fe8d:f457>]
Sat Apr 13 12:31:12 2019 : Unsupported protocol 0x8057 received
Sat Apr 13 12:31:12 2019 : sent [LCP ProtRej id=0x2 80 57 01 01 00 0e 01 0a 9a 01 a7 ff fe 8d f4 57]
Sat Apr 13 12:31:12 2019 : rcvd [ACSCP ConfReq id=0x1 <route vers 16777216> <domain vers 16777216>]
Sat Apr 13 12:31:12 2019 : Unsupported protocol 'Apple Client Server Control Protocol' (0x8235) received
Sat Apr 13 12:31:12 2019 : sent [LCP ProtRej id=0x3 82 35 01 01 00 10 01 06 00 00 00 01 02 06 00 00 00 01]
Sat Apr 13 12:31:12 2019 : rcvd [IPCP ConfRej id=0x1 <compress VJ 0f 01>]
Sat Apr 13 12:31:12 2019 : sent [IPCP ConfReq id=0x2 <addr 192.168.1.250>]
Sat Apr 13 12:31:12 2019 : rcvd [IPCP ConfReq id=0x2 <addr 192.168.1.251> <ms-dns1 192.168.1.1> <ms-dns3 192.168.1.1>]
Sat Apr 13 12:31:12 2019 : ipcp: returning Configure-ACK
Sat Apr 13 12:31:12 2019 : sent [IPCP ConfAck id=0x2 <addr 192.168.1.251> <ms-dns1 192.168.1.1> <ms-dns3 192.168.1.1>]
Sat Apr 13 12:31:12 2019 : rcvd [IPCP ConfAck id=0x2 <addr 192.168.1.250>]
Sat Apr 13 12:31:12 2019 : ipcp: up
Sat Apr 13 12:31:12 2019 : found interface en0 for proxy arp
Sat Apr 13 12:31:12 2019 : local  IP address 192.168.1.250
Sat Apr 13 12:31:12 2019 : remote IP address 192.168.1.251
Sat Apr 13 12:31:12 2019 : Received protocol dictionaries
Sat Apr 13 12:31:12 2019 : Committed PPP store
Sat Apr 13 12:31:12 2019 : Received acsp/dhcp dictionaries
Sat Apr 13 12:31:12 2019 : Committed PPP store
Sat Apr 13 12:31:12 2019 : Received acsp/dhcp dictionaries
Sat Apr 13 12:31:12 2019 : Committed PPP store
Sat Apr 13 12:31:12 2019 : l2tp_wait_input: Address added. previous interface setting (name: en0, address: 192.168.1.250), current interface setting (name: ppp0, family: PPP, address: 192.168.1.250, subnet: 255.255.255.0, destination: 192.168.1.251).
Sat Apr 13 12:31:12 2019 : rcvd [IP data <src addr 192.168.1.251> <dst addr 255.255.255.255> <BOOTP Request> <type INFORM> <client id 0x08000000010000> <parameters = 0x6 0x2c 0x2b 0x1 0xf9 0xf>]
Sat Apr 13 12:31:15 2019 : rcvd [IP data <src addr 192.168.1.251> <dst addr 255.255.255.255> <BOOTP Request> <type INFORM> <client id 0x08000000010000> <parameters = 0x6 0x2c 0x2b 0x1 0xf9 0xf>]
Sat Apr 13 12:31:18 2019 : rcvd [IP data <src addr 192.168.1.251> <dst addr 255.255.255.255> <BOOTP Request> <type INFORM> <client id 0x08000000010000> <parameters = 0x6 0x2c 0x2b 0x1 0xf9 0xf>]
…

7 Troubleshooting and Maintenance

7.1 VPN won’t connect

If you are unable to connect, open the VPN server log as above and review the connection request in the log. If your connection never transitions from Listening for connections… to Incoming Call…

  • Confirm that the VPN server service is running.
    • If it isn’t, enable it. (See below.)
    • If it is, restart it. (See below.)
  • Confirm that the macOS firewall is disabled on the VPN server.
  • Confirm that the VPN server IP address is assigned manually. (See above.)
  • Confirm that NAT is configured correctly on the router. (See above.)
  • Confirm that the VPN client is configured correctly. (See above.)

7.2 Update the Security Key

If you wish to update the security key, use the following procedure:

Open Keychain. Search and delete the key named “com.apple.net.racoon”

Generate a new key with the following command. Change SHARED_SECRET to the key you want to use

$ sudo security add-generic-password -a com.apple.ppp.l2tp -s com.apple.net.racoon \
-T /usr/sbin/racoon -p "SHARED_SECRET" /Library/Keychains/System.keychain

7.3 Check if the VPN service is running

Check that the VPN server service is running:

 $ ps -aef |grep vpnd

7.4 Register the VPN service

The VPN server service can be disabled with the following command:

$ sudo launchctl unload -w /Library/LaunchDaemons/vpn.ppp.l2tp.plist

$ sudo launchctl unload -w /Library/LaunchDaemons/vpn.ppp.l2tp.plist

7.5 De-Register the VPN Service

The VPN server service can be enabled with the following command:

$ sudo launchctl load -w /Library/LaunchDaemons/vpn.ppp.l2tp.plist

7.6 Check if the VPN service is Registered

Run the following command to confirm that the VPN service is registered.

Output if the VPN service is registered.

$ launchctl print system/vpn.ppp.l2tp
vpn.ppp.l2tp = {
	active count = 1
	path = /Library/LaunchDaemons/vpn.ppp.l2tp.plist
	state = running

	program = /usr/sbin/vpnd
…

Output if the VPN service is not registered.

$ launchctl print system/vpn.ppp.l2tp
Could not find service "vpn.ppp.l2tp" in domain for system

7.7 Check if the VPN is Running

You can tell if the VPN service is running with the following command:

This is the output when the VPN server running:

$ ps -aef |grep vpnd
    0   596     1   0 11:48AM ??         0:00.02 vpnd -x -i com.apple.ppp.l2tp
  501   599   356   0 11:48AM ttys000    0:00.00 grep vpnd

This is the output when the VPN server not running:

$ ps -aef |grep vpnd
  501   585   356   0 11:45AM ttys000    0:00.00 grep vpnd

7.8 Restart VPN

The VPN server service can be restarted with the following command:

$ sudo killall -HUP vpnd

8 Make a Connection over VPN

Connect to an application via VPN, or just ping something on the remote side of the VPN.

$ ping -c 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: icmp_seq=0 ttl=64 time=1.319 ms

--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.319/1.319/1.319/0.000 ms
$ 

9 Known Issues

The VPN service may not come up properly after reboot. Restart the service with the following command after a reboot.

$ sudo killall -HUP vpnd

References

Changes introduced in macOS Server 5.7.1

https://support.apple.com/en-us/HT208312

macOS Server Server Migration Guide v1.2

https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf

How to Setup a L2TP VPN Server on OS X

https://jonsview.com/how-to-setup-os-x-10-9-as-a-l2tp-vpn-server-without-apples-server-app/comment-page-2

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.