In this post I present VPNStatus, an application that replicates some functionalities of macOS built-in VPN status menu:

  • list the VPN services and their status
  • connect to a VPN service
  • disconnect from a VPN service
  • possibility to auto connect to a VPN service if the application is running

This application also allows to auto connect to an IKEv2 VPN service, something that is currently not possible on macOS. For Apple employees reading this blog post, you can find my bug report 41950946: scutil doesn't support IKEv2 VPN services here: rdar://41950946.

The precompiled binaries as well as the complete source code is available at the end of this post.

Auto connecting to a L2TP service

With macOS 10.13, it is simple to auto connect to a L2TP service, either using the built-in scutil tool or an AppleScript. scutil lets you for example list your L2TP services with scutil --nc list:

Timac:~ timac$ scutil --nc list
Available network connection services in the current set (*=enabled):
* (Disconnected)   940C2D07-8CF4-492C-A7DE-DD50C337149F PPP --> L2TP       "My_L2TP_VPN" [PPP:L2TP]

It also lets you start the VPN connection:

scutil --nc start My_L2TP_VPN

As previously mentioned, it is also possible to use an AppleScript to start the connection:

set MyVPNName to "My_L2TP_VPN"

tell application "System Events"
	tell current location of network preferences
		set myConnection to the service MyVPNName
		if myConnection is not null then
			if current configuration of myConnection is not connected then
				connect myConnection
			end if
		end if
	end tell
end tell

What about IKEv2 services?

If you use IKEv2, you will notice that scutil doesn’t list your VPN service:

Timac:~ timac$ scutil --nc list
Available network connection services in the current set (*=enabled):

Neither will it let you start or stop the service:

Timac:~ timac$ scutil --nc start My_IKEv2_VPN
No service

Similarly the AppleScript will fail to find the IKEv2 service:

AppleScript fails for IKEv2 services

If you search online, you will find multiple complains about this issue. The only workaround I could find was provided by Matt Coneybeare who used AppleScript’s UI scripting. While UI scripting works, it has several caveats. So I decided to find a better solution.

Summary of macOS VPN architecture

In a previous blog post, I explained some internal details about the macOS VPN architecture. You can find the article here: macOS VPN architecture from System Preferences down to nesessionmanager. Here is a summary of the VPN architecture from the System Preferences application down to the nesessionmanager daemon:

macOS VPN architecture

Building our own VPN app

With this knowledge, it is easy to build a replacement for macOS built-in VPN Status menu. This application can use the NEConfigurationManager class from the private part of the NetworkExtension.framework in order to retrieve the NEConfiguration configurations. It can contain classes similar to ANPNEServicesManager and ANPNEService (respectively called ACNEServicesManager and ACNEService) which can use the ne_session_* APIs to talk to the nesessionmanager daemon.

The architecture of such an application would look like:

VPNStatus architecture

VPNStatus: a replacement for macOS built-in VPN Status menu

VPNStatus is a NSStatusItem application that lives in the menubar. It can:

  • list the VPN services and their status
  • connect to a VPN service
  • disconnect from a VPN service

It can also let you auto connect to a VPN service when the application is running and pause/resume the auto connection:

The icon in the menubar has 3 different states:

  • green: VPN is connected
  • yellow: VPN is not connected but should automatically reconnect (the user paused the auto connect for a determined duration)
  • red: VPN is not connected and auto connect is disabled

Bonus: vpnutil and VPNApp

vpnutil is a command line tool similar to scutil and can start and stop a VPN service from the Terminal. It also works with IKEv2 VPN services, something not supported by the built-in scutil.

Usage: vpnutil [start|stop] [VPN name]

Examples:
	To start the VPN called 'MyVPN':
	vpnutil start MyVPN

	To stop the VPN called 'MyVPN':
	vpnutil stop MyVPN

VPNApp is an application rather than a NSStatusItem. It has no real advantages except for debugging purposes:

All these applications are open source under the MIT license. The precompiled binaries can be downloaded below.

Some important points

  • if you add, remove, rename or change some parameters of the VPN service in the System Preferences, VPNStatus won’t be notified. In these rare cases, you should relaunch the VPNStatus app.

  • The precompiled binaries are not code signed. If you download the precompiled binaries, you will need to do the following once to pass the GateKeeper protection:

    1. Right-click the app in the Finder
    2. Select Open
    3. Click on the Open button

Alternatively you can sign the precompiled binaries or recompile the application yourself.

  • These applications have only been tested on macOS 10.13. The precompiled binaries are targeting macOS 10.13 and later.

Downloads

References