Skip to main content

Tutorial: How to Set Up Hardware Address Checking with a Post-auth Script

Abstract

Using a custom script, you can add hardware address registration as an additional authentication security check. Follow this tutorial.

Overview

The post-auth programming hook in Access Server allows you to extend the server's possibilities for authenticating against a source of credentials. This document provides examples for creating a post-auth script that includes the hardware address as part of the authentication process.

Authentication and the post-auth script role

Access Server's authentication system

Access Server supports several robust authentication systems without using a post-auth script — whether you manage it from the Admin Web UI or authenticate against a third-party system. These are the systems already supported:

  1. Local: Access Server's authentication system, which uses a SQLite3 database to store user properties and credentials with management handled in the Admin Web UI.

  2. PAM: Linux system that requires console management or an SSH session on the OS.

  3. LDAP: Once you set up the connection in the Admin Web UI, Access Server can authenticate against an LDAP server.

  4. RADIUS: Once you set up the connection in the Admin Web UI, the Access Server can authenticate against a RADIUS server.

  5. SAML: Once you set up the connection in the Admin Web UI, Access Server can use SAML single sign-on (SSO) by authenticating through an identity provider (IdP).

For more information about these authentication methods, refer to this detailed topic: Authentication System.

The post-auth script process

  1. The user signs in with a VPN client or on the Client Web UI.

  2. They successfully authenticate with their credentials.

  3. The post-auth script runs (hence, post-auth — after authentication).

The post-auth script is a text file in the programming language Python. It can do all sorts of interesting things, like automating assigning users to groups based on specific criteria, implementing a custom authentication system, adding an extra filter to the login process, or checking the user device’s hardware address.

You can create a hardware address checking script to enhance the security of your authentication by only allowing users with registered MAC addresses and UUID strings to connect to the VPN server successfully.

Our sample script automatically registers the device’s MAC address or UUID string, but you can configure it to have complete control over it as the administrator. The post-auth script can accept two hardware addresses per account but only auto-registers the first; you can manually add the optional secondary address.

Important

It depends on what the client sends: either a MAC address or a UUID string.

  • In general, OpenVPN2 clients send MAC addresses.

  • Recent OpenVPN3-based clients send UUID strings.

Both options are unique identifiers for the device, and our post-auth script accepts and stores either one. Each time the client attempts to connect, it must offer the same string to succeed. Originally, only MAC addresses were accepted, and the documentation may still reference only MAC addresses, but it also accepts UUIDs.

From a user perspective

When a new user signs in and you’re using the default settings for our post-auth script, here’s the process:

  1. A new user signs in with valid credentials.

  2. The MAC or UUID isn’t in your Access Server’s user properties database.

  3. Access Server automatically registers and stores the MAC or UUID in the user properties database.

  4. The next time the user signs in, their MAC or UUID must match the value stored in the user properties database.

Users can use most open-source clients or recent versions of OpenVPN Connect for this authentication. See below for more detailed information about client compatibility. Older clients don’t provide a MAC address or UUID string, which will lead to an error message when a user tries to connect.

Connection profile and client compatibility notes

Tip

About connection profiles: This script works with all three types of connection profiles: user-locked, server-locked, and auto-login. All adhere to the restrictions in this post-auth script. In some cases—such as with the auto-login connection profile—OpenVPN Connect may end up looping endlessly trying to connect when it‘s denied access based on MAC address or UUID string restriction, in which case you need to correct the situation by making sure the correct hardware address is registered for your device.

About client software: We recommend using OpenVPN Connect v3, however recent versions of OpenVPN Connect v2 (2.7.* and newer) are supported. This script works with OpenVPN Connect for Windows, macOS, iOS, and Android. We've also tested the following clients, but don't guarantee support by us:

  • The open-source client 'openvpn' on Linux.

  • The open-source client 'OpenVPN GUI' on Windows.

  • The open-source client 'Tunnelblick' on macOS.

  • Most open-source clients based on 'openvpn' binary version 2 or version 3 should work.

Caution

If you connect with your client software of choice and it doesn’t report a MAC address or UUID string to Access Server, then the client is denied access. To resolve this, check that you have the latest version of that software with the most recent version of the OpenVPN binary core so that you can have a good chance of sending the required information to the server at connection time.

  1. Sign in through SSH or your Access Server server console.

  2. Obtain root privileges.

  3. Retrieve the example Python script from our website (https://swupdate.openvpn.net/scripts/post_auth_mac_address_checking.py):

    wget https://swupdate.openvpn.net/scripts/post_auth_mac_address_checking.py -O /root/mac.py1

    1

    This saves the script to the /root/directory with the name mac.py.

    Tip

    If you have problems downloading the script this way, you may need to install/update the wget and/or ca-certificates package(s) on your system.

  4. Edit the script for your specific needs:

    nano /root/mac.py
    • Make your changes to the script, then save and exit.

  5. Load the script into the Access Server configuration and reload Access Server:

    cd /usr/local/openvpn_as/scripts
    ./sacli --key "auth.module.post_auth_script" --value_file=/root/mac.py ConfigPut
    ./sacli start

Important

when you change the mac.py file, you must use the above commands to load the script again and reload Access Server.

If you want to manually register hardware addresses, you can restrict the automatic MAC/UUID registration to a specific network or turn If off and manually input them from the command-line interface.

A valid user account without a registered MAC address or UUID string—such as a new user—can connect from any device by default. After the first successful connection, Access Server stores the hardware address of that system. The server now only accepts a connection for this user account from that device.

Refer to the section below that you prefer: either restrict registration to a specific network or turn off automatic registration.

Restrict automatic registration to a specific network

If you want to restrict the automatic registration to a specific network, like a corporate network, you can use the first_login_ip_addr variable in the script.

If you set the first_login_ip_addr variable to a specific IP address, then only first-time login attempts will be accepted from that public IP address. For example, if you only want to allow hardware address registrations from one public IP, put that in the script. Let's assume the following situation:

  1. You have a private company network with an internet gateway at the public IP address 192.0.2.89.

  2. You run your Access Server on a cloud system elsewhere on the internet.

  3. Only systems connected to the internet through the company network can register a new device with your Access Server.

You must write your script to allow new device registrations only from the public IP of your company network:

  1. Open the script for editing:

    nano /root/mac.py
  2. Edit the first_login_ip_addr variable.

    first_login_ip_addr="192.0.2.89"
  3. Save and exit the script.

  4. Reload the script and restart the Access Server service:

    cd /usr/local/openvpn_as/scripts
    ./sacli --key "auth.module.post_auth_script" --value_file=/root/mac.py ConfigPut
    ./sacli start

Tip

If you leave this parameter empty, Access Server accepts first-time logins from any IP address. That is the default behavior. But if you define the item above, new registrations only succeed if their source IP matches the defined first_login_ip_addr value. This provides extra security for use cases such as denying users registering from home networks, registering only on the office network, or requiring the system administrator to register devices.

Disallow automatic registration

To turn off automatic hardware address registration:

  1. Open the script for editing:

    nano /root/mac.py
  2. Edit the first_login_ip_addr variable to NONE or DISABLED.

    first_login_ip_addr = "NONE"

    or

    first_login_ip_addr = "DISABLED"
  3. Save and exit the script.

  4. Reload the script and restart the Access Server service:

    cd /usr/local/openvpn_as/scripts
    ./sacli --key "auth.module.post_auth_script" --value_file=/root/mac.py ConfigPut
    ./sacli start
    • When users sign in, they will be denied access until you register their hardware addresses.

  5. Register a user's hardware address manually. For our command, "exampleuser" is the user account name, and the client's UUID is 6A13F222-53F2-EA22-873F-A4AE122AAB22.

    cd /usr/local/openvpn_as/scripts
    ./sacli --user "exampleuser" --key "pvt_hw_addr" --value "6A13F222-53F2-EA22-873F-A4AE122AAB22" UserPropPut
    ./sacli start

    Tip

    Depending on your authentication system, you may need to pay attention to lowercase/uppercase with the username.

If the user account is being used on another device or the hardware address has changed, you must remove the MAC address or UUID string stored and locked for that particular user. You can use the following commands to remove the saved value for the user "exampleuser" and reload the server.

  • Remove saved MAC address or UUID string for exampleuser:

    cd /usr/local/openvpn_as/scripts
    ./sacli --user "exampleuser" --key "pvt_hw_addr" UserPropDel

There are use cases requiring a secondary hardware address. For example, a laptop may report a different MAC address, whether it connects over wifi or an ethernet connection.

You can manually specify a secondary address accepted for a user account. This assumes a MAC address or UUID string is already present in the user database for a specific user. You can simply add a secondary address that’s also accepted. We don’t allow automatic registration for the secondary address for security reasons.

  • Manually register/update a secondary MAC address or UUID string for exampleuser:

    cd /usr/local/openvpn_as/scripts
    ./sacli --user "exampleuser" --key "pvt_hw_addr2" --value "ef:cd:ba:03:02:01" UserPropPut

Remove network restrictions

If you use the restriction to allow only hardware address registrations from a specific IP address, as explained above, then you should remove that restriction when troubleshooting:

  1. Undo that particular restriction in your mac.py file.

  2. Install/update the post-auth script again.

  3. Reload the settings again.

  4. Test your connections.

That way, that restriction won't be an issue in trying to debug why things aren't working.

Use the latest software versions

Ensure you use the latest software, as older software may not support the feature of reporting MAC addresses or UUID strings to the server. That goes for the client and server software, as running old server software is also not a good idea.

Check log files

On most Access Server setups, you can find any information the post_auth script outputs to the log file in the /var/log/openvpnas.log file (by default). You can also edit the mac.py file on your server and add 'print' lines to it to dump more information into the log file and see what values are in particular variables as Access Server processes the post_auth file.

  • Filter for specific messages from post-auth:

    egrep "POST_AUTH" /var/log/openvpnas.log