Managing user and group properties from command line

Introduction

When configuring OpenVPN Access Server for your needs, you can customize global properties for the entire server for all users and groups, but there are also properties you can set on specific users and groups. This document describes these properties.

In the example commands given in the documentation, <USER_OR_GROUP> indicates where you can specify either one of these:

  1. A user name
  2. A group name
  3. __DEFAULT__

How to use __DEFAULT__

You can use __DEFAULT__ (two underscores on both sides of the capitalized word, DEFAULT) as a special, reserved keyword. When you define a property for __DEFAULT__, other users and groups can inherit the defined property. Both existing and user/group accounts you haven’t created yet can then assume certain properties. An example would be the ability to use auto-login type connection profiles.

Priority of Access Control

When you define a property on multiple levels, this is the order of preference:

  1. User
  2. Group
  3. __DEFAULT__

Properties defined for a specific user take the highest priority, then group, then default.

User and Group Properties

The following commands are common tasks for managing user and group properties from the command-line interface. To run these, ensure you are signed in as root and in the directory, /usr/local/openvpn_as/scripts/.

Show the current properties for all users:

./sacli UserPropGet

Show the current properties for a specific user or group:

./sacli --pfilt <USER_OR_GROUP> UserPropGet

Enable the auto-login privilege for a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_autologin" --value "true" UserPropPut

Disable the auto-login privilege for a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_autologin" --value "false" UserPropPut

Remove the auto-login property from a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_autologin" UserPropDel

Remove all properties (this deletes the user or group):

./sacli --user <USER_OR_GROUP> UserPropDelAll

Add a new user from scratch:

./sacli --user <USER_NAME> --key "type" --value "user_connect" UserPropPut

Create a new group from scratch:

./sacli --user <GROUP_NAME> --key "type" --value "group" UserPropPut
./sacli --user <GROUP_NAME> --key "group_declare" --value "true" UserPropPut

Add a user to a group:

./sacli --user <USER_NAME> --key "conn_group" --value <GROUP_NAME> UserPropPut

Remove a user from a group:

./sacli --user <USER_NAME> --key "conn_group" UserPropDel

Set password for a user in local authentication mode:

./sacli --user <USER_NAME> --new_pass <PASSWORD> SetLocalPassword

Remove password for a user in local authentication mode:

./sacli --user <USER_NAME> RemoveLocalPassword

Change the minimum password length when password strength checking is enabled (the default is 8):

./sacli --key "auth.local.0.min_len" --value "<NEW_VALUE>" ConfigPut

Assign an authentication method to a user:

./sacli --user <USER> --key "user_auth_type" --value "<MODE>" UserPropPut

Where <MODE> can have these values:

  • local
  • pam
  • radius
  • ldap
  • saml

Note: Ensure you configure RADIUS and LDAP authentication if you assign it to a user or group. Refer to Authentication Options and Command-line Configuration for details.

Assign an authentication method to a group:

./sacli --user <GROUP_NAME> --key "user_auth_type" --value "<MODE>" UserPropPut

Where <MODE> can have these values:

  • local
  • pam
  • radius
  • ldap
  • saml

Refresh the Access Server configuration:

./sacli start

Important notes about the above commands:

  • Ensure you use single quotes (‘) around the <PASSWORD> instead of double quotes (“) if you specify passwords on the command line that have unique characters in them with special meaning on the command line—such as the $ character (variable).
  • If you set a property for a user that doesn’t exist, the result of the command is to create the user and set the property. Thus, if, for example, you set the auto-login property (prop_autologin) either false or true on a user that doesn’t exist, then the user will automatically exist from that point on. In order to authenticate, the user must also exist in the authentication system, and it depends on your chosen authentication system to set up a password and possibly an account for that user.
  • Properties work with inheritance. For example, if you enable the auto-login property on a group, users in that group inherit the privilege to download an auto-login type configuration file. Suppose you specifically deny the auto-login property on a user in that group. In that case, users in that group will be able to get an auto-login type configuration file, except for that user. If neither the user nor the group has anything specified in the auto-login property, then it will be inherited from __DEFAULT__, which by default has the value "false".
  • Groups need a subnet to work with. It can either be a global subnet you configure in the VPN Settings page or in the server's global configuration database, or it can be a subnet you define specifically for the group. Without a valid subnet to draw IP addresses from, users assigned to a group tend to end up with one of the standard addresses from the globally configured dynamic IP address pool.
  • Many commands with the sacli tool write changes to the configuration databases that store all the settings, but they may not take effect immediately. You must refresh the running servers with the sacli start command, and changes will be effective. This command only refreshes or restarts components that need it. Additionally, suppose you make changes that may require a connected user to be disconnected and reconnected. In that case, the Access Server may issue a 'kick' command to such a connected client, forcing it to disconnect and reconnect and obtain the correct settings from the server.

Assign a user a static IP address

Define a subnet

To assign a static IP address for a user, you must first configure a static IP address network. By default, Access Server uses dynamic IP addresses. Depending on your configuration, you must configure a subnet at either the global or group level.

It helps to understand the following for configuring subnets:

  1. All subnets you use must be unique, so when you configure a subnet, ensure that it’s different from anything else you have in use.
  2. For IP addresses on the subnet, it’s important to know that Access Server uses the start IP address and the end IP address for itself. For example, with the subnet 192.168.70.0/24, Access Server uses 192.168.70.1 and 192.168.70.254. You can’t use these for your user’s static IP address assignment. Valid addresses are 192.168.70.2 through 192.168.70.253.
  3. Access Server uses IP addresses more efficiently when you configure groups with subnets rather than a global static IP addressing space. This is due to how IP addressing and access control work internally, creating a certain 'waste' of IP addressing space. It’s possible that Access Server can run out of assignable addresses even though your clients haven’t used the entire subnet. However, since millions of IP addresses are in private IP address space, this should not pose any problems.
  4. In the commands below, if we assume we want to configure 192.168.70.0/24 as the subnet to use, then SUBNET is 192.168.70.0, and CIDR is 24. In the case of SUBNET/CIDR, you write it as 192.168.70.0/24.

Define a global subnet

You can define a global subnet, if none of your users are assigned to groups. You can set it from the VPN Settings page in the Admin Web UI or with the following commands.

Assign a global, default static IP addressing network:

./sacli --key "vpn.server.static.0.network" --value <SUBNET> ConfigPut
./sacli --key "vpn.server.static.o.netmask_bits" --value <CIDR> ConfigPut

You can now jump down to the instructions for assigning a user a static IP address.

Define a subnet for users not part of a group

If you have some users in groups, but the user you want to assign a static IP address to isn't part of one, the default static IP address network configured in the Admin Web UI under VPN Settings is used.

Assign a default static IP addressing network for users not part of a group:

./sacli --key "vpn.server.static.0.network" --value <SUBNET> ConfigPut
./sacli --key "vpn.server.static.o.netmask_bits" --value <CIDR> ConfigPut

You can now jump down to the instructions for assigning a user a static IP address.

Define a group subnet

If the user you want to assign a static IP address to is part of a group, the static IP address you assign to the user must fall within the subnet of the assigned group. If the group doesn't have a subnet yet, you must assign it first in order to use static IP addressing on a user in a group. For groups without defined subnets, Access Server dynamically allocates IP addresses to your users from the “Group Default IP Address Network (optional)" as configured in the Admin Web UI under VPN Settings. To switch a user over to a static IP address, you must assign a subnet to the user’s group. Such a subnet is only for static assignment and forces all users in the group to use IP addresses from the group subnet. There are two subnet fields under a group’s “More Settings” in the Admin Web UI:

  1. Subnets assigned to this group.
  2. Dynamic subnet ranges for this group.

You define the subnet for the static IP address assignment in the first field. The second field specifies a dynamic allocation range for users in a group that doesn't get a static IP address assigned.

Assign a primary subnet for static IP addressing space to a group:

./sacli --user <GROUP_NAME> --key "group_subnets.0" --value <SUBNET/CIDR> UserPropPut

Assign a user a static IP address

Now that you have a subnet defined—either globally or at the group level—you can assign a static IP address to your user.

Assign a user a static IP address:

./sacli --user <USER_NAME> --key "conn_ip" --value <IP_ADDRESS> UserPropPut

Disconnect (kick) a user

If you need to force a user to drop its Access Server connection, you can do so using the sacli DisconnectUser function. With this function, you can:

  1. Kick a user off the server.
  2. Send a string of text to the VPN client, which displays on screen or in the log, giving a reason why the user was kicked off the server.
  3. Kick a user off the server with an invitation to reconnect again with their existing session token.

Note: If a user has multiple active OpenVPN tunnels, it impossible to specify a single VPN tunnel for that user to kick; it's all or nothing.

Disconnect all VPN connections for a given user name:

./sacli --user <USER_NAME> DisconnectUser

Disconnect all VPN connections for a given user name with a reason:

./sacli --user <USER_NAME> --client_reason <TEXT> DisconnectUser

Disconnect all VPN connections for a given user name with an invitation to auto-reconnect:

./sacli --user <USER_NAME> --restart --psid DisconnectUser

When you provide text parameters to the sacli command, such as the --client-reason, ensure you enclose it with double quotes. For example, "You have been disconnected by sysadmin". Spaces tend to upset command line programs, but it works correctly when you enclose a string of text with double quotes.

Some clients and configurations attempt to reconnect automatically no matter what method you use to kick a user off the VPN server. If you want the user to stay disconnected in such a situation, you can additionally set the prop_deny property on the user to true. This effectively bans the user from the server. See below for this.

Block (ban) a user

With the prop_deny property, you can deny access to users. You can lift this restriction at any time. You can set this property on a user name, a group name, or the pseudo name __DEFAULT__, and it can be inherited. The user still exists with Access Server with all its settings and certificates retained, but the user can’t sign in to the web services or make a VPN connection. If the user has a current VPN connection, then banning the user doesn’t disconnect them, but only prevents them from making a new connection or signing in to the web interface.

You can kick any existing connections using the sacli DisconnectUser function (above).

Deny future logins for a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_deny" --value "true" UserPropPut

Specifically allow future logins for a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_deny" --value "false" UserPropPut

Restore to default and have it adhere to any inheritance:

./sacli --user <USER_OR_GROUP --key "prop_deny" UserPropDel

Grant or revoke Admin Privileges

Admin privileges grant a user access to sign on to the Admin Web UI for Access Server. We recommend you give admin privileges only for the administration of Access Server. While you can use user accounts with admin privileges for VPN connections, they may have special access to configured subnets that can disrupt the inheritance of properties from groups like access control rules. So if you experience a problem where an admin user in a normal group doesn’t receive certain routes or access to specific subnets, that may be why.

We recommend the following due to possible issues with access control:

  • Assigning normal users in normal groups and admin users in admin groups.
  • Avoid mixing admin users in normal groups or normal users in admin groups. 

Access Server can then choose the safe path and leave out access to certain subnets rather than giving normal users access to subnets only admin users should be given access to, for example.

To grant a user or group admin privileges:

./sacli --user <USER_OR_GROUP> --key "prop_superuser" --value "true" UserPropPut

To specifically revoke admin privileges for a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_superuser" --value "false" UserPropPut

Restore to default and have it adhere to any inheritance:

./sacli --user <USER_OR_GROUP> --key "prop_superuser" UserPropDel

Auto-login profiles

Auto-login connection profiles allow automatic connection without requiring user input. This means this connection profile contains everything it needs to make a connection: user-unique, embedded client certificate and private key known at the Access Server as being allowed to make a connection in this way.

You can set the prop_autologin property on the __DEFAULT__ pseudo name, a group name, or a user name, and it can be inherited. Access Server doesn't have prop_autologin property defined anywhere by default, and it is then assumed to be denied.

To give a user or group auto-login privileges:

./sacli --user <USER_OR_GROUP> --key "prop_autologin" --value "true" UserPropPut

To specifically revoke auto-login privileges from a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_autologin" --value "false" UserPropPut

Allow all users in a group to use auto-login connection profiles:

./sacli --user <GROUP_NAME> --key "prop_autologin" --value "true" UserPropPut

Allow all users to use auto-login connection profiles by default:

./sacli --user "__DEFAULT__" --key "prop_autologin" --value "true" UserPropPut

Deny all users' auto-login connection profiles:

./sacli --user "__DEFAULT__" --key "prop_autologin" UserPropDel

Restore to default and have it adhere to any inheritance:

./sacli --user <USER_OR_GROUP> --key "prop_autologin" UserPropDel

Compression settings

Important note: Access Server doesn’t have compression enabled by default. For more information, refer to the security advisory about the VORACLE attack vulnerability. We recommend turning off compression for VPN connections.

In the Admin Web UI under Advanced VPN, you can enable or disable compression support. Compression support can enhance the connection speed depending on circumstances and data transferred, and in most cases, it positively impacts the transfer speed.

You can enable or disable it globally and still override it specifically for users or groups using the prop_force_lzo property shown in the examples below. This doesn’t limit Access Server to using only the LZO compression method, but the property name is just a hold-over from when LZO was the only compression method available in OpenVPN at the time. If you delete the property from the user or group, it will adhere to the global default set under Advanced VPN in the Admin Web UI.

Enable compression for a given user or group:

./sacli --user <USER_OR_GROUP> --key "prop_force_lzo" --value "true" UserPropPut

Disable compression for a given user or group:

./sacli --user <USER_OR_GROUP> --key "prop_force_lzo" --value "false" UserPropPut

Redirect-gateway and DNS settings

Redirect-gateway is the directive name in the OpenVPN protocol that instructs a VPN client to send all its traffic through the VPN tunnel to the VPN server. In the Admin Web UI under VPN Settings, you can configure connected VPN clients to send internet traffic through OpenVPN Access Server globally, and configure pushing DNS servers to the VPN clients. Usually, both are done to ensure DNS queries can be resolved, as some providers block queries to their DNS servers from non-local sources. It can be explicitly overriden for users or groups using the prop_reroute_gw_override property shown in the examples below. If you delete the property from the user or group, it adheres to the global defaults set under VPN Settings.

It's impossible to push a specific DNS server to a specific user or group. The DNS servers that are pushed are set globally, and only the act of pushing it to a user or group can be switched on or off. Additionally, suppose you want to redirect client internet traffic through Access Server without implementing DNS for a specific user or group. In that case, you can use the trick of disabling the option to redirect client internet traffic through the server in the VPN Settings page and then go to the settings for that user or group and give access via NAT method to the subnets 0.0.0.0/1 and 128.0.0.0/1.

Disable redirection of internet traffic, and don't push DNS servers:

./sacli --user <USER_OR_GROUP> --key "prop_reroute_gw_override" --value "disable" UserPropPut

Disable redirection of internet traffic, but still push DNS servers:

./sacli --user <USER_OR_GROUP> --key "prop_reroute_gw_override" --value "dns_only" UserPropPut

Use the settings as defined under VPN settings specifically:

./sacli --user <USER_OR_GROUP> --key "prop_reroute_gw_override" --value "global" UserPropPut

Restore to default and have it adhere to any inheritance:

./sacli --user <USER_OR_GROUP> --key "prop_reroute_gw_override" UserPropDel

Redirect internet traffic for a user, but don't push DNS servers:

./sacli --user <USER_NAME> --key "type" --value "user_compile" UserPropPut
./sacli --user <USER_NAME> --key "access_to.0" --value "+NAT:0.0.0.0/1" UserPropPut
./sacli --user <USER_NAME> --key "access_to.1" --value "+NAT:128.0.0.0/1" UserPropPut

Redirect internet traffic for a group, but don't push DNS servers:

./sacli --user <GROUP_NAME> --key "access_to.0" --value "+SUBNET:0.0.0.0/1" UserPropPut
./sacli --user <GROUP_NAME> --key "access_to.1" --value "+SUBNET:128.0.0.0/1" UserPropPut

Note: In the last two examples where we're implementing 0.0.0.0/1 and 128.0.0.0/1 routes, we're assuming that there aren’t already other access control rules present on the user or group. If there are, use the next available configuration keys (.2, .3, .4, and so on) to add these rules. It's also important to note that you can mix NAT and route rules using commands, but not in the Admin Web UI at this time. That means if you set up mixed NAT and route rules on the same user or the same group, and you next go to the Admin Web UI and change settings there, they will be reset to the settings defined in the Admin Web UI (i.e., all NAT or all route).

You may also notice the property user_compile on the user. The default for a standard user is user_connect when the user has no access control rules. In such a case, the user joins the VPN client subnet, and the server doesn’t have to set up any special rules for this user. But when you assign specific access control rules to a user, the server must be told to set up special rules the moment this user connects. For that purpose, use the property, user_compile.

Creating a bypass or exclusion route

Sometimes, people want to bypass or exclude a specific IP address or subnet. For example, you might want to redirect all VPN client internet traffic through the VPN server, except for a specific IP address or range of IP addresses that you want to remain on the client side and not be sent through the VPN tunnel. The OpenVPN protocol does this by sending a route directive with a specific route subnet, but then specifies the keyword net_gateway, translated on the client-side as the default gateway address. Such a directive is pushed from the server and looks on the client side like:

  • route 192.168.25.0 255.255.255.0 net_gateway

In the mentioned example, where all client internet traffic is being rerouted, except for the subnet just mentioned above, the routing table on the client side looks like this:

  • 0.0.0.0/0 — goes to the local default gateway on the VPN client.
  • 0.0.0.0/1 and 128.0.0.0/1 — goes to the VPN server subnet gateway address.
  • 192.168.25.0/24 — goes to the local default gateway on the VPN client side.
  • 192.168.1.0/24 — stays on the VPN client's local network; the VPN client is a part of this network.

Since with routing the smallest subnet, or better put, the most specific route, will win, the result is that internet-directed traffic goes through the 0.0.0.0/1 and 128.0.0.0/1 routes since they 'win' over the default 0.0.0.0/0 route, and 192.168.25.0/24 will go to the local default gateway on the VPN client side and not through the VPN tunnel, and 192.168.1.0/24 is the subnet that the VPN client was already on even before connecting to OpenVPN, so that traffic also remains local, unless you were to specifically override it with rules like 192.168.1.0/25 and 192.168.1.128/25 (not recommended).

Creating a bypass route:

./sacli --user <USERNAME> --key "bypass_route.N" --value <SUBNET> UserPropPut
./sacli start

The bypass_route.N is a logically numbered range starting with 0 and going up sequentially. If you leave gaps in the sequence, Access Server may not pick up all the subnets correctly, and you must ensure they're numbered right. The subnet can be a single IP such as 123.45.67.89/32 or a range such as 192.168.25.0/24. You can create the bypass route on a user, group, or global level, by using either the user name, the group name, or the __DEFAULT__ meta user name, where <USERNAME> is shown in the above example.

You can define multiple subnets by numbering bypass_route.N logically, for example:

./sacli --user <USERNAME> --key "bypass_route.0" --value "192.168.25.0/24" UserPropPut
./sacli --user <USERNAME> --key "bypass_route.1" --value "10.0.44.54/32" UserPropPut
./sacli --user <USERNAME> --key "bypass_route.2" --value "123.45.67.89/32" UserPropPut
./sacli start

Block local access to client-side LAN

The server can send a directive to the OpenVPN client to instruct it to block access to the LAN network. The exception is the local internet gateway, and any more specific routes for the local network in the routing table. OpenVPN detects the local network and routes traffic for this network into the VPN tunnel. You can set this block on a user, group, or global level, by using either the user name, the group name, or the __DEFAULT__ meta username, where <USERNAME> is shown in the example below.

Turn on the local network block:

./sacli --user <USERNAME> --key "prop_block_local" --value "true" UserPropPut
./sacli start

Restore to default and have it adhere to any inheritance:

./sacli --user <USERNAME> --key "prop_block_local" UserPropDel

Specify a client-side script

In the Admin Web UI, you're limited to specifying a client-side script on a group and then assigning users to those groups. There is no more granularity than that for client-side scripting in the Admin Web UI. However, on the command line, you can set a script on a user, group, or the __DEFAULT__ special keyword from which the default properties for users and groups are inherited.

Load an on-connect client-side script for Windows:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.connect" --value_file "./windows-on-connect.txt" UserPropPut

Load an on-connect client-side script for macOS:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.connect" --value_file "./macintosh-on-connect.txt" UserPropPut

Load an on-connect client-side script for Linux:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.connect" --value_file "./linux-on-connect.txt" UserPropPut

Load an on-connect client-side script for all three platforms:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.connect" --value_file "./all-on-connect.txt" UserPropPut

Remove an on-connect client-side script of the four types shown above—note that this does not stop inheriting scripts from a higher level:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.connect" UserPropDel
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.connect" UserPropDel
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.connect" UserPropDel
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.connect" UserPropDel

Load an on-disconnect client-side script for Windows:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.disconnect" --value_file "./windows-on-disconnect.txt" UserPropPut

Load an on-disconnect client-side script for macOS:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.disconnect" --value_file "./macintosh-on-disconnect.txt" UserPropPut

Load an on-disconnect client-side script for Linux:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.disconnect" --value_file "./linux-on-disconnect.txt" UserPropPut

Load an on-disconnect client-side script for all three platforms:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.disconnect" --value_file "./all-on-disconnect.txt" UserPropPut

Remove an on-disconnect client-side script of the four types shown above—note that this does not stop inheriting scripts from a higher level:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script.win.user.disconnect" UserPropDel
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.mac.user.disconnect" UserPropDel
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.linux.user.disconnect" UserPropDel
./sacli --user <USER_OR_GROUP> --key "prop_cli.script.all.user.disconnect" UserPropDel

Setting a client-side environment variable

You can set a client-side environment variable in the Admin Web UI on a group via the Group Permissions page. But, in the command line, you can set it per group or user individually. You can push variables to the client program available to the client-side script as specified in the section above.

Example of setting variable "username" to "john" on the client:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script_env.win.username" --value "elfredy" UserPropPut

As with client-side scripting, you can adjust the "win" to "mac", "linux", or "all", to specify if this should apply to Windows, macOS, Linux, or all three of them. In the above example, the key name contains the variable's name. So if you want to specify a variable name "myvariable" then change "username" to "myvariable" in the above example.

To remove the variable setting shown above:

./sacli --user <USER_OR_GROUP> --key "prop_cli.script_env.win.username" UserPropDel

Evaluate specific directives for a user/group

This is an unsupported feature, but it can be helpful in very rare cases where you have a device that needs some particular instructions that normally should not be necessary and might actually cause problems for other devices. You don't want to affect other users and groups with such specific settings. This allows adding server-side OpenVPN directives that apply only to specific users or groups.

To set specific server-side directives for a user or group:

./sacli --user <USER_OR_GROUP> --key "prop_cc_cmds" --value 'compress lz4-v2,push "compress lz4-v2"' UserPropPut

To remove such specific directives:

./sacli --user <USER_OR_GROUP> --key "prop_cc_cmds" UserPropDel