Product Documentation

This document is a configuration guide for OpenOTP Radius Bridge (RB). The reader should notice that this document is not a guide for installing and configuring OpenOTP or WebADM. Specific application guides are available through the RCDevs documentation website.

Product Overview

OpenOTP Radius Bridge provides the RADIUS RFC-2865 (Remote Authentication Dial-in User Service) API for OpenOTP Authentication Server. Standalone, the OpenOTP server provides SOAP/XML and JSON interfaces over HTTP and HTTPS. By installing and configuring Radius Bridge, you can connect a RADIUS-compliant VPN or any other system supporting the RADIUS authentication protocol.

Radius Bridge is not included in the OpenOTP installation package but in an additional in a self-installer package or through RCDevs repository. It is implemented using the FreeRADIUS software.

FreeRADIUS is the most widely used RADIUS server implementation. More specific FreeRADIUS configurations can be found on the FreeRADIUS website. The RADIUS RFC-2865 specification provides a Challenge-Response mechanism. OpenOTP challenge authentication mode is also fully supported in the OpenOTP RADIUS API with the RADIUS Challenge-Response. Yet some VPNs do not support RADIUS Challenge-Response. RB also supports concatenated password options for these VPNs. Challenge mode is required for OpenOTP SMS and Mail authentication (in on-demand operating mode).

The Radius Bridge server supports very high loads, is multithreaded and takes advantage of multicore architectures. In clustered environments, it does not require specific RADIUS challenge session tracking as this is completely handled at the OpenOTP level.

Product Files and Folders

Find below the RB software installation directory structure and important files.

/opt/radiusd/bin/: Location for RB service binaries and setup.

radiusd: RB executable control script for starting and stopping the server process. To start RB from the command line, issue ./radiusd start. To stop RB, issue ./radiusd stop.

setup: Initial RB setup script automatically run by the self-installer. The setup can be re-run manually at any time.

radtest: Simple RADIUS client test tool. You can use it to check your RB system is working properly without needing to test from the VPN server.

backup: Script to back up your Radius Bridge configuration.

restore: Script to restore your Radius Bridge configuration.

/opt/radiusd/doc/: Location for RB documentation resources.

/opt/radiusd/conf/: Location for RB configuration files.

• radiusd.conf: Main RB configuration file. The setup script should configure this file for you. This file also contains the OpenOTP configurations. This is the most important file, and we will see the settings in details in the Configuration section.

• clients.conf: Like in any RADIUS server, you must declare your RADIUS clients (ex. VPN servers). A client consists of the VPN IP address and its RADIUS shared secret. One client must be defined per system connected to RB.

/opt/radiusd/lib/: Location for RB system libraries.

/opt/radiusd/lib/dictionaries/: Location for supported RADIUS vendor dictionaries.

/opt/radiusd/libexec/: Location for RB system executables.

/opt/radiusd/logs/: Location for log files produced by RB.

/opt/radiusd/temp/: Location for temporary files produced by RB.

RB automatically checks the configuration files for syntax errors or mistakes and displays any problem discovered at startup.

Installation

Installation with Redhat Repository

On a RPM based systems, you can use RCDevs repository.
Clear the dnf cache and install Radius Bridge package:

dnf clean all
dnf install radiusd -y

Radius Bridge is now installed.

Installation with Debian Repository

On a Debian-like system, you can use RCDevs repository.
Clear apt cache and install Radius Bridge:

apt update
apt install radiusd

Radius Bridge is now installed.

Installation Using the Self-Installer

The installation of RB is very simple and is performed in less than 5 minutes. Just download the RB self-installer package on RCDevs website and put the installer file on your server. You can use WinSCP to copy the file to your server. To install RB, login to the server with SSH and run the following commands:

gunzip radiusd-1.2.x.sh.gz
bash radiusd-1.2.x.sh

The installer will install RB in /opt/radiusd/ and will run the setup script automatically. The setup will create the UNIX system user (radiusd), set file and directory permissions, register the startup of RB at system start.

Like other RCDevs software, RB installs its files in one directory only (in /opt/radiusd/). No other is copied to your system but the startup links.

Configuration

Setup Script

A setup script is available to configure Radius Bridge.
This script can be launched with /opt/radiusd/bin/setup command.

[root@webadm1 ~]# /opt/radiusd/bin/setup
Checking system architecture...Ok
Enter the server fully qualified host name (FQDN): webadm1.rcdevsdocs.com
If WebADM is running on this server then press Enter.
Else enter one of your running WebADM server IP or hostname.
Note: You can use host:port if WebADM uses a custom HTTPS port.
Enter WebADM server IP or hostname: localhost
Found two server URLs:
> URL1: https://192.168.4.160:8443/openotp/
> URL2: https://192.168.4.161:8443/openotp/
Retrieving WebADM CA certificate... Ok
Retrieving WebADM CA trusted bundle...  Ok
The setup needs now to request a signed SSL server certificate.
This request should show up as pending in your WebADM interface and an administrator must accept it!
Waiting 5 minutes for approbation...

At this step, you have to log in on the WebADM Administration GUI to approve the SSL certificate request.

radiusbridge

Click on the red button at the end of the home page.

On the next screen, you can see the SSL certificate request is pending:

radiusbridge

Click on the Accept button and the Radius Bridge setup will continue.

radiusbridge
Waiting 5 minutes for approbation... Ok
Updating configuration file... Ok
Setting file permissions... Ok
Do you want OpenOTP RADIUS Bridge to be automatically started at boot (y/n)? y
Adding systemd service... Ok
Do you want to register OpenOTP RADIUS Bridge logrotate script (y/n)? y
Adding logrotate script... Ok
OpenOTP RADIUS Bridge has successfully been setup.

Radiusd Configuration File

In this section, we will review and explain all the available OpenOTP settings in Radius Bridge. By default, your RB should work without modifying any setting.

#
# OpenOTP RADIUS Bridge configuration
#

# Server URL(s)
# OpenOTP SOAP service URL(s). This is the only mandatory setting.
# When two servers are used, you can set server_url in the form "url1,url2" or you can preferably
# comment the server_url line and configure server_url1 and server_url2.
server_url1 = "https://192.168.4.160:8443/openotp/"
server_url2 = "https://192.168.4.161:8443/openotp/"

# Request routing policy
# Request routing policy when two server URLs are defined.
# Ordered: The first server is preferred (default). When down, the second server is used.
# Balanced: Server is chosen randomly. When down, the other is used.
# Consistent: One specific user ID is always routed to the same server (per user routing).
#server_policy = "Ordered"

# OpenOTP API key
# Wen OpenOTP is configured with 'Required Client Certificate or API Key', you need to create an
# API key in WebADM and set its value here for communicating with the OpenOTP API.
#api_key = "MY_API_KEY"

# Challenge suffix
# Suffix to be added to the challenge message.
#challenge_suffix = ": "

# Default domain (this should be set in a WebADM client policy!)
# This domain name can be used to override the default domain on the OpenOTP configuration.
#default_domain = "mydomain"

# Domain separator
# This is the separator character to be used when the domain is provided in the username.
# For example if '\' is used then username with a domain can be in the form domain\username.
# By default there is no domain separator.
domain_separator = "\\"

# Client attribute
# This is the RADIUS attribute which contains the client ID to be sent to OpenOTP.
# If this attribute is not found then the NAS IP address is sent as client ID.
# Multiple attributes can be used in the form "NAS-Identifier, NAS-IP-Address".
# By default the NAS-Identifier (first) and NAS-IP-Address (IPV4 / IPv6) attribute are used.
#client_attribute = "NAS-Identifier,NAS-IP-Address,NAS-IPv6-Address"

# Source attribute
# This is the RADIUS attribute in which the RADIUS client can pass the end user source IP address to
# OpenOTP. The attribute must be of type IPAddr.
# By default the source attribute is obtained from PaloAlto-Client-Source-IP (first), Framed-IP-Address
# and Calling-Station-Id.
#source_attribute = "PaloAlto-Client-Source-IP,Framed-IP-Address,Calling-Station-Id"

# Context attribute
# This is the RADIUS attribute in which the RADIUS client can pass the end user device ID address to
# OpenOTP. Attribute must be of type String.
# By default the context attribute is not set (ignored).
#context_attribute = "Calling-Station-Id"

# Settings attribute (deprecated in the flavor of WebADM Client Policies!)
# This is the RADIUS attribute in which the RADIUS client can pass user settings to OpenOTP.
# If the attribute is present in the RADIUS request, it will override any existing user setting
# from the user_settings setting above. The attribute must be of type String.
# By default the settings attribute is not set (ignored).
#settings_attribute = "Filter-Id"

# User settings
# Fixed list of OpenOTP policy settings to be passed via the OpenOTP API.
#user_settings = "LoginMode=LDAPOTP,OTPType=SMS"

# Client certificate (use if OpenOTP is configured with "Require Client Certificate").
#cert_file = "/opt/radiusd/conf/radiusd.pem"
#cert_password = ""

# Trusted CA (WebADM CA certificate)
# Copy the WebADM CA file in conf/ca.crt and set the ca_file to enforce SSL server trust.
#ca_file = "/opt/radiusd/conf/ca.crt"

# SOAP timeout
# This is the SOAP request TCP timeout. Set the RADIUS timeout to a lower value on your RADIUS client.
# If you use OpenOTP Simple-Push login, then you must set the timeout to 30 secs and you must set the
# RADIUS timeout on your client (NAS) to 30 secs.
#soap_timeout = 30

# Status cache
# When two servers are configured, RadiusBridge can check the server statuses at regular intervals by# trying TCP socket connections. The status_cache is the polling interval between 10 and 600 seconds.
# By default, the server statuses are re-checked every 30 seconds. Use 0 disables the status requests.
#status_cache = 30

# RADIUS reply attributes
# This is a fixed list of attribute and values to be sent back to the RADIUS clients in Access-Accept
# packets. The syntax is the standard RADIUS value pairs (ie. attr1=value1,attr2=value2,...).
# Note: The attributes must be present in the local dictionaries (in lib/dictionaries/).
#reply_attributes = "Juniper-Allow-Commands=\"XXX\",Juniper-Deny-Commands=\"YYY\""

# No success/failure message
# If set to 'yes', then no RADIUS Reply-Message attribute is sent in the Access-Success and/or
# Access-Failure response. This is useful for some broken RADIUS clients which refuse the reply
# message attributes in the Access-Request responses.
#no_success_message = no
#no_failure_message = no

# No response delay
# You can configure RB to delay its Access-Reject responses when the OpenOTP server does not respond.
# Setting a delay allows RADIUS clients to enforce a failover policy if they do not receive a RADIUS
# response within a configured timeout. Without the no_response_delay (RB default) the client gets a
# RADIUS failure response and does also not failover to a secondary server.
#no_response_delay = 15

# Short RADIUS timeout fix
# Fix support for RADIUS servers not supporting the 30 seconds' request timeout required by
# OpenOTP Push Login. You should enable this option if you are using a Cisco ASA VPN server.
#fix_timeout = no

# MS DirectAccess Probe
# Enable this setting only if you are using Microsoft VPN with DirectAccess server.
# DirectAccess servers check the RADIUS server status via RADIUS probes requests which are sent to
# OpenOTP via Status requests.
#directaccess_probe = no
#daprobe_username = "DAProbeUser"
#daprobe_password = "DAProbePass"

# Users with OpenOTP transaction lock disabled (patterns allowed)
# Use ONLY with stress-testing usersw which require concurrent login transactions.
#nolock_usernames = "user1,user2"

# Disable the 1 sec OpenOTP response delay on request failures (patterns are allowed)
#nodelay_usernames = "*"

# Users for which LDAP credentials will be cached in OpenOTP (patterns allowed)
# Use ONLY with system polling users generating a lot of OpenOTP LDAP requests.
#cached_usernames = "user1,user2"

# Users to be rejected without sending an OpenOTP request (patterns allowed)
#denied_usernames = "root"

# OpenOTP authentication support
# You may set to 'no' if you want RadiusBridge to support EAP-TLS (ie. cert_support) only.
# OpenOTP authentication is the default RadiusBridge operating mode and is enabled by default.
#auth_support = yes

# U2F & FIDO2 support
# Enable U2F & FIDO2 over RADIUS with RCDevs vendor-specific dictionary.
# Uses dictionary attributes from /opt/radiusd/lib/dictionaries/dictionary.rcdevs.
#fido_support = yes

# EAP-TLS Wifi support
# Enable cert_support if you want to use EAP-TLS authentication for Enterprise Wifi.
# With EAP-TLS, the user authentication uses a user certificate only (no username, password or OTP).
# The user certificates are generated in WebADM or the self-services. You need to enable the OCSP
# service URL below with EAP-TLS.
#cert_support = yes

Server Endpoint URL(s) (server_url)

This is the OpenOTP SOAP endpoint URL(s). And this is the only mandatory RB setting. When WebADM and RB are installed on the same server, the server URL can be set to http://localhost:8080/openotp/. If WebADM and RB are installed on different servers it should use OpenOTP SSL port and be set to https://<WEBADM_SERVER>:8443/openotp/.

It is possible to configure two different server URLs in the form server_url1 and server_url2 defined on 2 different lines.

server_url1 = "https://192.168.4.160:8443/openotp/"
server_url2 = "https://192.168.4.161:8443/openotp/"

When two servers are configured, you may also choose a request routing policy as explained below.

Request Routing Policy (server_policy)

If two server URLs are defined in server_url, you can optionally configure a request routing policy (i.e. the server selection policy). There are three policies available:

  • Ordered: The first server is always preferred. When it does not respond, the second server is used.
  • Balanced: The server is chosen randomly for each request. When it does not respond, the other is used.
  • Consistent: The server selection depends on the user ID. A request for one specific user is also always routed to the same server. If it does not respond, the other server is used.

Status Cache Time (status_cache)

When two servers are configured, RadiusBridge can check the server statuses at regular intervals by sending OpenOTP status requests. The status_cache is the polling interval between 10 and 600 seconds. By default, the server statuses are re-checked every 60 seconds. Use the value ‘0’ disables the OpenOTP status request polling mechanism.

Challenge Suffix (challenge_suffix)

This is a suffix string to be appended to the challenge messages returned by OpenOTP. In some cases, it can be useful to add ": " for example to the user prompt, for a better display.

Domain Separator (domain_separator)

A RADIUS Access-Request does not provide a standard domain attribute. Yet, WebADM Domain names can be passed in the Radius request as part of the Radius username attribute, by using a Windows NT -like notation (i.e. domain\username or username@domain). It is also possible to configure what separator character is used when the domain name is provided in the RADIUS username with the domain_separator setting.

By default, no separator is used and RB expects only a username and no domain. When the character "@" is used as domain separator, the domain part is expected to be on the right side of the string in the form username@domain. With any other separator, the domain is expected to be on the left side in the form domain\username.

If you want to use the character "\" as a separator to provide the credential in the form domain\username, then you must configure RB with domain_separator = “\”.

Default Domain (default_domain)

It is possible to configure a default_domain in RB to allow users not to provide a domain name if they are part of your default domain.

OpenOTP is configured with a default domain in WebADM. Use this setting only if you want to use a default domain different from the OpenOTP default domain.

You can configure the default domain for a specific VPN client using a WebADM Client Policy object. This is useful when you need a different default domain depending on the RADIUS client. For example, you have two VPNs allowing access to users from two different domains.

User Settings (user_settings)

With the user_settings, you can pass a fixed list of policy settings to OpenOTP in every request. These settings will have a higher priority than any setting defined on the users, groups, client policies and OpenOTP configuration.

Only the public OpenOTP settings can be passed in the OpenOTP requests. For example, you can set user_settings = “LoginMode=OTP,OTPType=TOKEN”. To know the settings names and if they are public, just go to the OpenOTP configuration in WebADM and put the mouse over one setting name. WebADM will display the real setting name (as to be used in the RB user_settings) and its scope (public, private, etc...).

This user setting can be set in a WebADM Client Policy, WebADM User/Group objects too. This is the preferred option as you can configure it from the WebADM interface.

Settings Attribute (settings_attribute)

Deprecated in the flavor of WebADM Client Policies!

RADIUS Reply Attributes (reply_attributes)

This is a fixed list of static RADIUS attribute value-pairs to be always sent back to the RADIUS clients in the Access-Accept responses. The values will be combined with the RADIUS reply attributes which are configured in WebADM. The syntax is the standard RADIUS value pairs (i.e. attr1=value1,attr2=value2,...). Example : reply_vps = "Juniper-Allow Commands="XXX",JuniperDeny-Commands="YYY"".

The attributes must be present in the local dictionaries (in lib/dictionaries/).

Client ID Attribute (client_attribute)

RADIUS Bridge uses this attribute to send the client ID to OpenOTP. This attribute is set to NASIdentifier, NAS-IP-Address and NAS-IPv6-Address by default (attributes are tried in order). When none of the configured is found, the requestor IP address is sent as client ID.

Source IP Attribute (source_attribute)

The RADIUS client can optionally forward the IP address of the end-user to RadiusBridge. This IP address is used by the OpenOTP audit and with WebADM location policies defined on Domain and Client Policy configuration objects. The user RADIUS source IP attribute is not provided by most VPN vendors. Yet, with some VPNs like Cisco ASA use the Calling-Station-Id to provide the user address. By default, the source attribute is set to Calling-Station-Id.

The attribute must be defined in the RADIUS dictionary and be of type IPAddr or String. The attribute value will be ignored if it does not contain a valid IP address.

Context ID Attribute (context_attribute)

The RADIUS client can optionally forward the device ID (i.e. the MAC address of the user’s connecting device) to RadiusBridge. The device ID is used by the OpenOTP contextual authentication feature. By default, the context attribute is not configured (ignored). With Cisco Wi-Fi, you may set it to Calling-Station-Id which may provide the MAC address of the client Wi-Fi device. The attribute must be defined in the RADIUS dictionary and be of type String.

SOAP Timeout (soap_timeout)

This is the OpenOTP SOAP requests’ timeout. It should be equal or lower than the RADIUS timeout configured on your RADIUS client(s). The minimal authorized timeout is 5 seconds. The default timeout is 30 seconds. If you use the OpenOTP Simple-Push Login method then the timeout value should be set to 30 seconds. If you don’t use Simple-Push then the timeout value should be set to 10 seconds.

CA Certificate file (ca_file)

You can copy your WebADM CA’s public certificate file, in the Radius Bridge configuration folder and point the ca_file to the certificate file, if you need to enforce OpenOTP server authentication with SSL. This configuration works only if OpenOTP is a remote service accessible via SSL.

No Success/Failure Messages (no_success_message & no_failure_message)

You can prevent RADIUS Reply-Message attributes to be sent in the Access-Success and/or Access-Failure response. This is useful for some broken RADIUS clients which refuse the reply message attributes in the Access-Request responses. It should not be used otherwise.

No OTP Response Delay (no_response_delay)

You can configure RB to delay its Access-Reject responses when the OpenOTP server does not respond. Setting a delay allows the RADIUS clients to enforce a failover policy if they do not receive a RADIUS response within a configured timeout. Without the no_response_delay (RB default) the client gets a RADIUS failure response and does also not failover to a secondary server. Use this feature only if you configure your RADIUS client(s) with several RADIUS servers.

MS DirectAccess Probe (directaccess_probe & daprobe_username & daprobe_password)

Enable DirectAccess probe ONLY if you are using Microsoft VPN with DirectAccess server! DirectAccess servers check the RADIUS server status via RADIUS probes requests which are sent to OpenOTP in Status requests. Successful DirectAccess probes return access-success responses to the Microsoft VPN server. You must also use this setting with extreme caution. You must NEVER enable probe requests for any other RADIUS client.

nolock_usernames & cached_usernames & denied_usernames

Nolock_usernames is the list of usernames for which you want OpenOTP to disable transaction locks. Cached_usernames is the list of usernames for which you want OpenOTP to cache the login results for a short amount of time. Denied_usernames is the list of usernames which are immediately denied.

FIDO Support (fido_support)

Enable U2F over RADIUS with RCDevs vendor-specific U2F dictionary (currently supported by Viscosity VPN client). Uses dictionary attributes from /opt/radiusd/lib/dictionaries/dictionary.rcdevs.

RADIUS Clients Configuration File

Your RADIUS clients (ex. VPN server) must be registered in the /opt/radiusd/conf/clients.conf file to be able to communicate with the RB server. A client configuration looks this:

client my_vpn {
    ipaddr = 192.168.0.10
    secret = testing123
}

You need to set the IP address of your RADIUS client and the shared RADIUS secret. On the VPN side, you will configure a RADIUS server with its IP address (i.e. the RB server IP address), and you will set the same secret.

Always prefer setting no RADIUS retries (retries=0) on the RADIUS configuration of your VPN when you use OpenOTP challenge mode.

Radius Bridge and WebADM Client Policies

It can be useful to create WebADM client policies for your RADIUS clients to apply set of settings to your different RADIUS client. For example, you might need to set a default domain for a specific VPN or restrict access to users who are members of a specific LDAP group. You may also need to define different access policies for your VPNs. For instance, you might want all users to use OTP Login Mode for a VPN, regardless of the Login Mode configured for the user or in OpenOTP. For these reasons, you can create WebADM Client Policy objects.

A WebADM Client Policy can be defined to assign an access control policy for a specific client application (which uses the SOAP or RADIUS APIs), or to enforce specific WebADM application settings for a client application. You can also define per-client application profiles in WebADM using Client objects.

By defining a Client Policy, you can restrict access to the client application for specific LDAP authorized groups or prevent certain groups from using the application. You can even restrict the application to work with specific WebADM domains.

Another feature of the Client is that you can define Web Application settings that will always be enforced for the client application, regardless of the settings configured for the users or their groups. For example, you might want one VPN to authenticate users through OpenOTP with OTP-only passwords and tokens, regardless of the policy defined for the user, while your internal systems authenticate users with LDAP only.

Refer to the Client Policy and Conditional Access documentation to set up your client policy.

Concatenated Password with Client Policies

When a WebADM Client policy object is configured with Challenge Support disabled and the authentication policy is set to LDAP+OTP, then OpenOTP assumes the passwords are provided in the concatenated form. OpenOTP will also de-concatenates the LDAP and OTP passwords which must be provided with the LDAP password followed by the OTP password (without any separator character).

PPTP/L2TP VPNs

RB supports PPTP and L2TP VPN servers with PAP authentication only. CHAP, MS-CHAP, TACAS and similar password protocols using hashed values are not supported. If you use PPTP with VPN clients such as Windows integrated VPN client, be sure to configure the VPN client and server with PAP authentication.

PAP uses a cleartext password transport is not recommend if you use OpenOTP with LDAP passwords. In this case, you should consider L2TP (PPP over IPSec) with PAP and not PPTP with PAP. With L2TP the VPN is established inside an IPSec channel and the PAP password is secured. A PPTP VPN with PAP remains acceptable if you use OpenOTP with OTP only since an OTP password is one-time and cannot be replayed.

Troubleshooting

Radius authentication can fail for many reasons, the following chapters describe how to troubleshoot it.

Radiusd Status Check

Check if the OpenOTP RADIUS Bridge service is running:

[root@webadm1]# /opt/radiusd/bin/radiusd status
OpenOTP RADIUS Bridge is running with PID 3525061.

or with systemctl as the service has been registered with systemctl during the setup:

[root@webadm1]# systemctl status radiusd
○ radiusd.service - OpenOTP Radius Bridge
     Loaded: loaded (/usr/lib/systemd/system/radiusd.service; enabled; preset: disabled)
     Active: inactive (dead)

Check if the OpenOTP RADIUS Bridge service rcdevs-radius is listening on right IP Address and Port. May need to install the package net-tools to run the command netstat.

[root@webadm1 ~]# dnf install net-tools
...
Installed:
  net-tools-2.0-0.51.20160912git.el8.x86_64

Complete!
[root@webadm1 ~]# netstat -tulpn | grep rcdevs-rad
tcp        0      0 0.0.0.0:1812            0.0.0.0:*               LISTEN      3525061/rcdevs-radi 
tcp        0      0 0.0.0.0:1813            0.0.0.0:*               LISTEN      3525061/rcdevs-radi 
tcp        0      0 0.0.0.0:18120           0.0.0.0:*               LISTEN      3525061/rcdevs-radi 
udp        0      0 0.0.0.0:18120           0.0.0.0:*                           3525061/rcdevs-radi 
udp        0      0 0.0.0.0:1812            0.0.0.0:*                           3525061/rcdevs-radi 
udp        0      0 0.0.0.0:1813            0.0.0.0:*                           3525061/rcdevs-radi

Connectivity Check

Please check if the ports are not blocked by a firewall with the command telnet <webadm server> <port number> and verify radiusd authentication with tcpdump -i any port 1812.

[root@centos8-client ~]# telnet webadm1.rcdevsdocs.com 1812
Trying 192.168.4.160...
Connected to 192.168.4.160.
Escape character is '^]'.
Connection closed by foreign host.
[root@webadm1 ~]# tcpdump -i any port 1812 -vv
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
13:05:22.645509 IP (tos 0x10, ttl 64, id 3618, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.3.214.60210 > webadm1.rcdevsdocs.com: Flags [S], cksum 0x5db7 (correct), seq 1393734890, win 29200, options [mss 1460,sackOK,TS val 2181395168 ecr 0,nop,wscale 7], length 0
13:05:22.645988 IP (tos 0x0, ttl 64, id 44767, offset 0, flags [none], proto TCP (6), length 60)
    webadm1.rcdevsdocs.com > 192.168.3.214.60210: Flags [S.], cksum 0x893d (incorrect -> 0x4f50), seq 3386925890, ack 1393734891, win 28960, options [mss 1460,sackOK,TS val 4022334050 ecr 2181395168,nop,wscale 7], length 0
13:05:22.646205 IP (tos 0x10, ttl 64, id 3619, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.3.214.60210 > webadm1.rcdevsdocs.com: Flags [.], cksum 0xee56 (correct), seq 1, ack 1, win 229, options [nop,nop,TS val 2181395169 ecr 4022334050], length 0
13:05:22.647209 IP (tos 0x0, ttl 64, id 44768, offset 0, flags [none], proto TCP (6), length 52)
    webadm1.rcdevsdocs.com > 192.168.3.214.60210: Flags [F.], cksum 0x8935 (incorrect -> 0xee56), seq 1, ack 1, win 227, options [nop,nop,TS val 4022334051 ecr 2181395169], length 0
13:05:22.647350 IP (tos 0x10, ttl 64, id 3620, offset 0, flags [DF], proto TCP (6), length 52)
    192.168.3.214.60210 > webadm1.rcdevsdocs.com: Flags [F.], cksum 0xee52 (correct), seq 1, ack 2, win 229, options [nop,nop,TS val 2181395170 ecr 4022334051], length 0
13:05:22.647389 IP (tos 0x0, ttl 64, id 44769, offset 0, flags [none], proto TCP (6), length 52)
    webadm1.rcdevsdocs.com > 192.168.3.214.60210: Flags [.], cksum 0x8935 (incorrect -> 0xee53), seq 2, ack 2, win 227, options [nop,nop,TS val 4022334052 ecr 2181395170], length 0

Example of a successful radius authentication:

[root@webadm1]# /opt/radiusd/bin/radtest administrator localhost:1812 testing123
Enter password: ********
Result: Success
Sent Access-Request Id 37 from 0.0.0.0:45386 to 127.0.0.1:1812 length 58 User-Name: "administrator"
User-Password: "password"
NAS-Identifier: "RadTest"
Cleartext-Password: "password"
Received Access-Accept Id 37 from 127.0.0.1:1812 to 127.0.0.1:45386 length 44 Reply-Message: "Authentication success"
[root@webadm1]# tcpdump -i any port 1812 -vv
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
12:11:27.590459 IP (tos 0x0, ttl 64, id 13772, offset 0, flags [none], proto UDP (17), length 86)
    localhost.55261 > localhost.radius: [bad udp cksum 0xfe55 -> 0x9692!] RADIUS, length: 58
	Access-Request (1), id: 0xdd, Authenticator: b9cc3a8a669869cabaf009555a702080
	  User-Name Attribute (1), length: 11, Value: administrator
	    0x0000:  7465 7374 2d75 7365 72
	  User-Password Attribute (2), length: 18, Value:
	    0x0000:  79c7 cae6 2598 9c54 d83b 7c4a cfa8 3f7b
	  NAS-Identifier Attribute (32), length: 9, Value: RadTest
	    0x0000:  5261 6454 6573 74
12:11:27.631611 IP (tos 0x0, ttl 64, id 13792, offset 0, flags [none], proto UDP (17), length 72)
    localhost.radius > localhost.55261: [bad udp cksum 0xfe47 -> 0x86a7!] RADIUS, length: 44
	Access-Accept (2), id: 0xdd, Authenticator: 9901e9de1a3d690a092f860437e575ea
	  Reply-Message Attribute (18), length: 24, Value: Authentication success
	    0x0000:  4175 7468 656e 7469 6361 7469 6f6e 2073
	    0x0010:  7563 6365 7373

Debug Mode

If the RADIUS Bridge is running and reachable on the correct address and port but authentications still fail, you can run it in debug mode using the below steps. This will show the detailed RADIUS authentication flow and any errors.

Starting the OpenOTP RADIUS Bridge service in debug mode shows all passwords in clear text in the debug terminal!

[root@webadm1 ~]# /opt/radiusd/bin/radiusd stop
Stopping OpenOTP RADIUS Bridge... Ok

[root@webadm1 ~]# /opt/radiusd/bin/radiusd debug
Checking support for 32bit binaries... Ok
Checking server configuration... Ok
Starting OpenOTP RADIUS Bridge debug mode...
FreeRADIUS Version 3.2.5
Copyright (C) 1999-2023 The FreeRADIUS server project and contributors
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE
You may redistribute copies of FreeRADIUS under the terms of the
GNU General Public License
For more information about these matters, see the file named COPYRIGHT
Starting - reading configuration files ...
including dictionary file /opt/radiusd/lib/dictionaries/dictionary
including dictionary file /opt/radiusd/lib/dictionaries/dictionary.dhcp
including dictionary file /opt/radiusd/lib/dictionaries/dictionary.vqp
including configuration file /opt/radiusd/lib/radiusd.ini
including configuration file /opt/radiusd/conf/clients.conf
including configuration file /opt/radiusd/conf/radiusd.conf
main {
 security {
 	user = "radiusd"
 	group = "radiusd"
 	allow_core_dumps = no
 }
	name = "rcdevs-radiusd"
	prefix = "/opt/radiusd"
	localstatedir = "/opt/radiusd/var"
	logdir = "/opt/radiusd/logs"
	run_dir = "/opt/radiusd/temp"
}
main {
	name = "rcdevs-radiusd"
	prefix = "/opt/radiusd"
	localstatedir = "/opt/radiusd/var"
	sbindir = "/opt/radiusd/sbin"
	logdir = "/opt/radiusd/logs"
	run_dir = "/opt/radiusd/temp"
	libdir = "/opt/radiusd/lib"
	radacctdir = "/opt/radiusd/logs/radacct"
	hostname_lookups = no
	max_request_time = 30
	proxy_dedup_window = 1
	cleanup_delay = 10
	max_requests = 1024
	max_fds = 512
	postauth_client_lost = no
	pidfile = "/opt/radiusd/temp/radiusd.pid"
	checkrad = "/opt/radiusd/libexec/checkrad"
	debug_level = 0
	proxy_requests = yes
 log {
 	stripped_names = no
 	auth = yes
 	auth_badpass = no
 	auth_goodpass = no
 	colourise = no
 	msg_denied = "You are already logged in - access denied"
 }
 resources {
 }
 security {
 	max_attributes = 200
 	reject_delay = 0.000000
 	status_server = yes
 	require_message_authenticator = "auto"
 	limit_proxy_state = "auto"
 }
}
radiusd: #### Loading Realms and Home Servers ####
radiusd: #### Loading Clients ####
 client any {
 	ipaddr = *
 	secret = <<< secret >>>
  limit {
  	max_connections = 16
  	lifetime = 0
  	idle_timeout = 30
  }
 }
Debugger not attached
 # Creating Auth-Type = OTP
 # Creating Auth-Type = PAP
 # Creating Auth-Type = EAP
radiusd: #### Instantiating modules ####
 modules {
  # Loaded module rlm_pap
  # Loading module "pap" from file /opt/radiusd/lib/radiusd.ini
  pap {
  	normalise = yes
  }
  # Loaded module rlm_eap
  # Loading module "eap" from file /opt/radiusd/lib/radiusd.ini
  eap {
  	default_eap_type = "ttls"
  	timer_expire = 60
  	max_eap_type = 52
  	ignore_unknown_eap_types = yes
  	cisco_accounting_username_bug = no
  	max_sessions = 1024
  	dedup_key = ""
  }
  # Loaded module rlm_openotp
  # Loading module "openotp" from file /opt/radiusd/lib/radiusd.ini
  openotp {
  	server_url = "http://localhost:8080/openotp/"
  	server_url1 = "https://192.168.4.160:8443/openotp/"
  	server_url2 = "https://192.168.4.161:8443/openotp/"
  	password_mode = 0
  	source_attribute = "PaloAlto-Client-Source-IP,Framed-IP-Address,Calling-Station-Id"
  	client_attribute = "NAS-Identifier,NAS-IP-Address,NAS-IPv6-Address"
  	otp_length = 0
  	domain_separator = "\"
  	auth_support = yes
  	fido_support = yes
  	cert_support = yes
  	soap_timeout = 30
  	status_cache = 30
  	no_response_delay = 0
  	daprobe_username = "DAProbeUser"
  	daprobe_password = "DAProbePass"
  }
  # Loaded module rlm_detail
  # Loading module "detail" from file /opt/radiusd/lib/radiusd.ini
  detail {
  	filename = "/opt/radiusd/logs/accounting.log"
  	header = "%t"
  	permissions = 416
  	locking = no
  	dates_as_integer = no
  	escape_filenames = no
  	log_packet_header = no
  }
  instantiate {
  # Instantiating module "eap" from file /opt/radiusd/lib/radiusd.ini
   # Linked to sub-module rlm_eap_gtc
   gtc {
   	challenge = "Password: "
   	auth_type = "PAP"
   }
   # Linked to sub-module rlm_eap_tls
   tls {
   }
   tls {
   	verify_depth = 0
   	pem_file_type = yes
   	private_key_file = "/opt/radiusd/conf/radiusd.key"
   	certificate_file = "/opt/radiusd/conf/radiusd.crt"
   	ca_file = "/opt/radiusd/conf/trusted.crt"
   	fragment_size = 1024
   	include_length = yes
   	auto_chain = yes
   	check_crl = no
   	check_all_crl = no
   	ca_path_reload_interval = 0
   	reject_unknown_intermediate_ca = no
   	ecdh_curve = "prime256v1"
   	tls_max_version = "1.3"
   	tls_min_version = "1.2"
    cache {
    	enable = no
    	lifetime = 24
    	max_entries = 255
    }
    verify {
    	skip_if_ocsp_ok = no
    }
    ocsp {
    	enable = yes
    	override_cert_url = yes
    	use_nonce = yes
    	timeout = 0
    	softfail = no
    }
   }
   # Linked to sub-module rlm_eap_ttls
   ttls {
   	default_eap_type = "gtc"
   	copy_request_to_tunnel = yes
   	use_tunneled_reply = yes
   	include_length = yes
   	require_client_cert = no
   }
tls: Using cached TLS configuration from previous invocation
   # Linked to sub-module rlm_eap_peap
   peap {
   	default_eap_type = "gtc"
   	copy_request_to_tunnel = yes
   	use_tunneled_reply = yes
   	proxy_tunneled_request_as_eap = yes
   	soh = no
   	require_client_cert = no
   }
tls: Using cached TLS configuration from previous invocation
  # Instantiating module "pap" from file /opt/radiusd/lib/radiusd.ini
  # Instantiating module "openotp" from file /opt/radiusd/lib/radiusd.ini
  openotp {
  	server_url = "http://localhost:8080/openotp/"
  	server_url1 = "https://192.168.4.160:8443/openotp/"
  	server_url2 = "https://192.168.4.161:8443/openotp/"
  	password_mode = 0
  	source_attribute = "PaloAlto-Client-Source-IP,Framed-IP-Address,Calling-Station-Id"
  	client_attribute = "NAS-Identifier,NAS-IP-Address,NAS-IPv6-Address"
  	otp_length = 0
  	domain_separator = "\"
  	auth_support = yes
  	fido_support = yes
  	cert_support = yes
  	soap_timeout = 30
  	status_cache = 30
  	no_response_delay = 0
  	daprobe_username = "DAProbeUser"
  	daprobe_password = "DAProbePass"
  }
rlm_openotp: Adding attribute 'NAS-Identifier' to the client_attribute list
rlm_openotp: Adding attribute 'NAS-IP-Address' to the client_attribute list
rlm_openotp: Adding attribute 'NAS-IPv6-Address' to the client_attribute list
rlm_openotp: Adding attribute 'PaloAlto-Client-Source-IP' to the source_attribute list
rlm_openotp: Adding attribute 'Framed-IP-Address' to the source_attribute list
rlm_openotp: Adding attribute 'Calling-Station-Id' to the source_attribute list
  # Instantiating module "detail" from file /opt/radiusd/lib/radiusd.ini
  }
 } # modules
radiusd: #### Loading Virtual Servers ####
server { # from file /opt/radiusd/lib/radiusd.ini
} # server
server default { # from file /opt/radiusd/lib/radiusd.ini
 # Loading authenticate {...}
Compiling Auth-Type OTP for attr Auth-Type
Compiling Auth-Type PAP for attr Auth-Type
Compiling Auth-Type EAP for attr Auth-Type
 # Loading authorize {...}
 # Loading accounting {...}
} # server default
 thread pool {
 	start_servers = 5
 	max_servers = 32
 	min_spare_servers = 3
 	max_spare_servers = 10
 	max_requests_per_server = 1024
 	cleanup_delay = 5
 	max_queue_size = 65536
 	auto_limit_acct = no
 }
rlm_openotp: Server 192.168.4.160:8443 is available
rlm_openotp: Server 192.168.4.161:8443 is available
Thread spawned new child 1. Total threads in pool: 1
Thread 1 waiting to be assigned a request
Thread spawned new child 2. Total threads in pool: 2
Thread 2 waiting to be assigned a request
Thread spawned new child 3. Total threads in pool: 3
Thread 3 waiting to be assigned a request
Thread spawned new child 4. Total threads in pool: 4
Thread 4 waiting to be assigned a request
Thread 5 waiting to be assigned a request
Thread spawned new child 5. Total threads in pool: 5
Thread pool initialized
radiusd: #### Opening IP addresses and Ports ####
listen {
  	type = "auth"
  	ipaddr = *
  	port = 1812
  	proto = "udp"
}
listen {
  	type = "auth"
  	ipaddr = *
  	port = 1812
  	proto = "tcp"
   tls {
   	verify_depth = 0
   	pem_file_type = yes
   	private_key_file = "/opt/radiusd/conf/radiusd.key"
   	certificate_file = "/opt/radiusd/conf/radiusd.crt"
   	ca_file = "/opt/radiusd/conf/trusted.crt"
   	fragment_size = 1024
   	include_length = yes
   	auto_chain = yes
   	check_crl = no
   	check_all_crl = no
   	ca_path_reload_interval = 0
   	reject_unknown_intermediate_ca = no
   	ecdh_curve = "prime256v1"
   	tls_max_version = "1.3"
   	tls_min_version = "1.2"
    cache {
    	enable = yes
    	lifetime = 24
    	max_entries = 255
    }
    verify {
    	skip_if_ocsp_ok = no
    }
    ocsp {
    	enable = no
    	override_cert_url = no
    	use_nonce = yes
    	timeout = 0
    	softfail = no
    }
   }
  	check_client_connections = no
}
listen {
  	type = "acct"
  	ipaddr = *
  	port = 1813
}
listen {
  	type = "acct"
  	ipaddr = *
  	port = 1813
  	proto = "tcp"
   tls {
   	verify_depth = 0
   	pem_file_type = yes
   	private_key_file = "/opt/radiusd/conf/radiusd.key"
   	certificate_file = "/opt/radiusd/conf/radiusd.crt"
   	ca_file = "/opt/radiusd/conf/trusted.crt"
   	fragment_size = 1024
   	include_length = yes
   	auto_chain = yes
   	check_crl = no
   	check_all_crl = no
   	ca_path_reload_interval = 0
   	reject_unknown_intermediate_ca = no
   	ecdh_curve = "prime256v1"
   	tls_max_version = "1.3"
   	tls_min_version = "1.2"
    cache {
    	enable = yes
    	lifetime = 24
    	max_entries = 255
    }
    verify {
    	skip_if_ocsp_ok = no
    }
    ocsp {
    	enable = no
    	override_cert_url = no
    	use_nonce = yes
    	timeout = 0
    	softfail = no
    }
   }
  	check_client_connections = no
}
listen {
  	type = "status"
  	ipaddr = *
  	port = 18120
}
listen {
  	type = "status"
  	ipaddr = *
  	port = 18120
  	proto = "tcp"
   tls {
   	verify_depth = 0
   	pem_file_type = yes
   	private_key_file = "/opt/radiusd/conf/radiusd.key"
   	certificate_file = "/opt/radiusd/conf/radiusd.crt"
   	ca_file = "/opt/radiusd/conf/trusted.crt"
   	fragment_size = 1024
   	include_length = yes
   	auto_chain = yes
   	check_crl = no
   	check_all_crl = no
   	ca_path_reload_interval = 0
   	reject_unknown_intermediate_ca = no
   	ecdh_curve = "prime256v1"
   	tls_max_version = "1.3"
   	tls_min_version = "1.2"
    cache {
    	enable = yes
    	lifetime = 24
    	max_entries = 255
    }
    verify {
    	skip_if_ocsp_ok = no
    }
    ocsp {
    	enable = no
    	override_cert_url = no
    	use_nonce = yes
    	timeout = 0
    	softfail = no
    }
   }
  	check_client_connections = no
}
listen {
  	type = "control"
  listen {
  	socket = "/opt/radiusd/temp/radiusd.sock"
  	peercred = yes
  }
}
Listening on auth address * port 1812 bound to server default
Listening on auth proto tcp address * port 1812 (TLS) bound to server default
Listening on acct address * port 1813 bound to server default
Listening on acct proto tcp address * port 1813 (TLS) bound to server default
Listening on status address * port 18120 bound to server default
Listening on status proto tcp address * port 18120 (TLS) bound to server default
Listening on command file /opt/radiusd/temp/radiusd.sock
Ready to process requests

Bad format or wrong RADIUS secret / Shared secret is incorrect

Logs example

  • Radius Client (Radtest) IP is 192.168.3.54
  • Radius Bridge server IP is 192.168.4.160

Radius client output:

[root@radius_cli ~]# /opt/radiusd/bin/radtest Administrator 192.168.4.160:1812 testing1234
Enter password: ********
(0) Reply verification failed: Received Access-Reject packet from home server 192.168.4.160 port 1812 with invalid Response Authenticator!  (Shared secret is incorrect.)

Radius Bridge server debug output:

(0) Received Access-Request Id 186 from 192.168.3.54:45025 to 192.168.4.160:1812 length 62
(0)   User-Name = "Administrator"
(0)   User-Password = "T\\q\362\252ż\204\352:\177u;\241\205\243"
(0)   NAS-Identifier = "RadTest"
(0) # Executing section authorize from file /opt/radiusd/lib/radiusd.ini
(0)   authorize {
(0) eap: No EAP-Message, not doing EAP
(0)     [eap] = noop
(0) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(0) pap: WARNING: Authentication will fail unless a "known good" password is available
(0)     [pap] = noop
rlm_openotp: Invalid "User-Password" attribute (bad format or wrong RADIUS secret)
(0)     [openotp] = invalid
(0)   } # authorize = invalid
(0) Invalid user: [Administrator] (from client any port 0)
(0) Using Post-Auth-Type Reject
(0) Post-Auth-Type sub-section not found.  Ignoring.
(0) Login incorrect: [Administrator] (from client any port 0)
(0) Sent Access-Reject Id 186 from 192.168.4.160:1812 to 192.168.3.54:45025 length 0
(0) Finished request

When that kind of error happens, it comes from a wrong Radius shared secret between Radius client and Radius Bridge.

Check the secret configured for this radius client on Radius Bridge server in /opt/radiusd/conf/clients.conf:

client 192.168.3.54 {
        ipaddr = 192.168.3.54
        secret = testing123
}

I used testing1234 as secret on my radius client during the authentication. That is why it failed.

Note: If you use special characters in your Radius secret, then we advise to configure the secret in clients.conf between simple quotes like below:

client Random {
        ipaddr = 192.168.3.55
        secret = 'testing123$!'
}

To use that secret with radtest, keep quotes (else $ character will be interpreted by bash, and it will fail):

[root@radius_cli ~]# /opt/radiusd/bin/radtest Administrator 192.168.4.160:1812 'testing123$!'
Enter password: ********
(0) -: Expected Access-Accept got Access-Challenge
Result: Challenge
Session: 6a66626f47737239716371397a6e6f45
Enter your TOKEN password: 324032
Result: Success
Sent Access-Request Id 207 from 0.0.0.0:46922 to 192.168.4.160:1812 length 80 User-Name: "Administrator"
User-Password: "324032"
State: 0x6a66626f47737239716371397a6e6f45 NAS-Identifier: "RadTest"
Cleartext-Password: "324032"
Received Access-Accept Id 207 from 192.168.4.160:1812 to 192.168.3.54:46922 length 44 Reply-Message: "Authentication success"

Radius Bridge output:

(0) Received Access-Request Id 124 from 192.168.3.54:41692 to 192.168.4.160:1812 length 62
(0)   User-Name = "Administrator"
(0)   User-Password = "password"
(0)   NAS-Identifier = "RadTest"
(0) # Executing section authorize from file /opt/radiusd/lib/radiusd.ini
(0)   authorize {
(0) eap: No EAP-Message, not doing EAP
(0)     [eap] = noop
(0) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(0) pap: WARNING: Authentication will fail unless a "known good" password is available
(0)     [pap] = noop
(0)     [openotp] = ok
(0)   } # authorize = ok
(0) Found Auth-Type = OTP
(0) # Executing group from file /opt/radiusd/lib/radiusd.ini
(0)   Auth-Type OTP {
rlm_openotp: Found client ID attribute with value "RadTest"
rlm_openotp: Found source IP attribute with value ""
rlm_openotp: Found device ID attribute with value ""
rlm_openotp: Found client IP attribute with value ""
rlm_openotp: Sending openotpSimpleLogin request
rlm_openotp: OpenOTP authentication challenge
rlm_openotp: Reply message: Enter your TOKEN password
rlm_openotp: State: jfboGsr9qcq9znoE
rlm_openotp: Sending Access-Challenge
(0)     [openotp] = handled
(0)   } # Auth-Type OTP = handled
(0) Using Post-Auth-Type Challenge
(0) Post-Auth-Type sub-section not found.  Ignoring.
(0) Sent Access-Challenge Id 124 from 192.168.3.160:1812 to 192.168.4.160:41692 length 0
(0)   State := 0x6a66626f47737239716371397a6e6f45
(0)   Reply-Message := "Enter your TOKEN password"
(0)   Session-Timeout := 6908576
(0) Finished request
Waking up in 9.9 seconds.
(0) Cleaning up request packet ID 124 with timestamp +10
Ready to process requests
(1) Received Access-Request Id 207 from 192.168.3.54:46922 to 192.168.4.160:1812 length 80
(1)   User-Name = "Administrator"
(1)   User-Password = "324032"
(1)   State = 0x6a66626f47737239716371397a6e6f45
(1)   NAS-Identifier = "RadTest"
(1) session-state: No cached attributes
(1) # Executing section authorize from file /opt/radiusd/lib/radiusd.ini
(1)   authorize {
(1) eap: No EAP-Message, not doing EAP
(1)     [eap] = noop
(1) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(1) pap: WARNING: Authentication will fail unless a "known good" password is available
(1)     [pap] = noop
(1)     [openotp] = ok
(1)   } # authorize = ok
(1) Found Auth-Type = OTP
(1) # Executing group from file /opt/radiusd/lib/radiusd.ini
(1)   Auth-Type OTP {
rlm_openotp: Found client ID attribute with value "RadTest"
rlm_openotp: Found source IP attribute with value ""
rlm_openotp: Found device ID attribute with value ""
rlm_openotp: Found client IP attribute with value ""
rlm_openotp: Found state attribute "State" with value "jfboGsr9qcq9znoE" (string)
rlm_openotp: Sending openotpChallenge request
rlm_openotp: OpenOTP authentication succeeded
rlm_openotp: Reply message: Authentication success
rlm_openotp: Sending Access-Accept
(1)     [openotp] = ok
(1)   } # Auth-Type OTP = ok
(1) Login OK: [Administrator] (from client any port 0)
(1) Sent Access-Accept Id 207 from 192.168.4.160:1812 to 192.168.3.54:46922 length 0
(1)   Reply-Message := "Authentication success"
(1) Finished request

For other Radius clients like Netscaler, F5, Palo Alto... the simple quotes must not be put in the secret field of your AAA Radius Server definition.

Below, the OpenOTP logs for the previous authentication in /opt/webadm/logs/webadm.log

[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] New openotpSimpleLogin SOAP request
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] > Username: Administrator
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] > Password: xxxxxxxx
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] > Client ID: RadTest
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] > Options: RADIUS,-U2F
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Registered openotpSimpleLogin request
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Ignoring 2 memberof values for user 'CN=Administrator,CN=Users,DC=rcdevsdocs,DC=com' (out of domain group search base)
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Resolved LDAP user: CN=Administrator,CN=Users,DC=rcdevsdocs,DC=com
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Resolved LDAP groups: group policy creator owners,domain admins,enterprise admins,schema admins,denied rodc password replication group
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Using SQL server 'SQL Server'
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Using Session server 'Session Server'
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Started transaction lock for user
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Found user fullname: Administrator
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Found 1 user emails: Administrator@rcdevsdocs.com
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Found 47 user settings: LoginMode=LDAPOTP,OTPType=TOKEN,PushLogin=Yes,LockTimer=0,MaxTries=3,BlockTime=0,ChallengeMode=Yes,ChallengeTimeout=90,OTPLength=6,MobileTimeout=30,EnableLogin=Yes,SelfRegister=Yes,HOTPLookAheadWindow=25,TOTPTimeStep=30,TOTPTimeOffsetWindow=120,OCRASuite=OCRA-1:HOTP-SHA1-6:QN06-T1M,DeviceType=FIDO2,SMSType=Normal,SMSMode=Ondemand,MailMode=Ondemand,PrefetchExpire=10,LastOTPTime=300,ListChallengeMode=ShowID,ReplyData=[1 Items]
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Found 9 user data: TokenType,TokenKey,TokenState,TokenID,TokenSerial,Device1Type,Device1Name,Device1Data,Device1State
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Found 1 registered OTP token (TOTP)
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Requested login factors: LDAP & OTP
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] LDAP password Ok
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Authentication challenge required
[2020-04-17 18:24:04] [192.168.4.160] [OpenOTP:85XTWHCO] Using Push server 'Push Server'
[2020-04-17 18:24:05] [192.168.4.160] [OpenOTP:85XTWHCO] Sent push notification for token #1
[2020-04-17 18:24:05] [192.168.4.160] [OpenOTP:85XTWHCO] Waiting 27 seconds for mobile response
[2020-04-17 18:24:32] [192.168.4.160] [OpenOTP:85XTWHCO] Started OTP authentication session of ID jfboGsr9qcq9znoE valid for 90 seconds
[2020-04-17 18:24:32] [192.168.4.160] [OpenOTP:85XTWHCO] Sent login challenge response
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] New openotpChallenge SOAP request
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] > Username: Administrator
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] > Session: jfboGsr9qcq9znoE
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] > OTP Password: xxxxxx
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] Registered openotpChallenge request
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] Found authentication session started 2020-04-17 18:24:04
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] Started transaction lock for user
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] PUSH password Ok (token #1)
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] Updated user data
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] Sent terminate notification for token #1
[2020-04-17 18:24:43] [192.168.4.160] [OpenOTP:85XTWHCO] Sent login success response

Missing MFA Enrolment

In this example, the radius authentication is set to LDAP and OTP. However, the user doesn't have yet a second factor enrolled.

[root@webadm1]# /opt/radiusd/bin/radtest administrator localhost:1812 testing123
Enter password: ********
(0) -: Expected Access-Accept got Access-Reject
Result: Failed
Sent Access-Request Id 89 from 0.0.0.0:58793 to 127.0.0.1:1812 length 58 User-Name: "administrator"
User-Password: "test1234"
NAS-Identifier: "RadTest"
Cleartext-Password: "test1234"

Received Access-Reject Id 89 from 127.0.0.1:1812 to 127.0.0.1:58793 length 81 Reply-Message: "Account missing required data or MFA enrolment needed"

Error-Cause: 26985728
[root@webadm1]# /opt/radiusd/bin/radiusd debug
...
Listening on auth address * port 1812 bound to server default
Listening on auth proto tcp address * port 1812 bound to server default
Listening on auth address * port 1645 bound to server default
Listening on acct address * port 1813 bound to server default
Listening on acct address * port 1646 bound to server default
Listening on status address * port 18120 bound to server default
Listening on command file /opt/radiusd/temp/radiusd.sock
Ready to process requests
(0) Received Access-Request Id 89 from 127.0.0.1:58793 to 127.0.0.1:1812 length 58
(0)   User-Name = "administrator"
(0)   User-Password = "test1234"
(0)   NAS-Identifier = "RadTest"
(0) # Executing section authorize from file /opt/radiusd/lib/radiusd.ini
(0)   authorize {
(0) eap: No EAP-Message, not doing EAP
(0)     [eap] = noop
(0) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(0) pap: WARNING: Authentication will fail unless a "known good" password is available
(0)     [pap] = noop
(0)     [openotp] = ok
(0)   } # authorize = ok
(0) Found Auth-Type = OTP
(0) # Executing group from file /opt/radiusd/lib/radiusd.ini
(0)   Auth-Type OTP {
rlm_openotp: Found client ID attribute with value "RadTest"
rlm_openotp: Found source IP attribute with value ""
rlm_openotp: Found device ID attribute with value ""
rlm_openotp: Found client IP attribute with value ""
rlm_openotp: Sending openotpSimpleLogin request
rlm_openotp: OpenOTP authentication failed

rlm_openotp: Reply message: Account missing required data or MFA enrolment needed

rlm_openotp: Sending Access-Reject
(0)     [openotp] = reject
(0)   } # Auth-Type OTP = reject
(0) Failed to authenticate the user
(0) Using Post-Auth-Type Reject
(0) Post-Auth-Type sub-section not found.  Ignoring.
(0) Login incorrect: [administrator] (from client any port 0)
(0) Sent Access-Reject Id 89 from 127.0.0.1:1812 to 127.0.0.1:58793 length 0
(0)   Reply-Message := "Account missing required data or MFA enrolment needed"
(0)   Error-Cause := 26985728
(0) Finished request
Waking up in 9.9 seconds.
(0) Cleaning up request packet ID 89 with timestamp +8
Ready to process requests
[root@webadm1]# tail -f /opt/webadm/logs/webadm.log
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] New openotpSimpleLogin SOAP request
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] > Username: administrator
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] > Password: xxxxxxxx
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] > Client ID: RadTest
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] > Options: RADIUS,-U2F
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] Registered openotpSimpleLogin request
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] Resolved LDAP user: cn=administrator,CN=Users,DC=rcdevsdocs,DC=com
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] Started transaction lock for user
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] Found user fullname: administrator
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] Found 46 user settings: LoginMode=LDAPOTP,OTPType=TOKEN,ChallengeMode=Yes,ChallengeTimeout=90,OTPLength=6,MobileTimeout=30,EnableLogin=Yes,HOTPLookAheadWindow=25,TOTPTimeStep=30,TOTPTimeOffsetWindow=120,OCRASuite=OCRA-1:HOTP-SHA1-6:QN06-T1M,DeviceType=FIDO2,SMSType=Normal,SMSMode=Ondemand,MailMode=Ondemand,PrefetchExpire=10,LastOTPTime=300,ListChallengeMode=ShowID

[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] User has no OTP token registered

[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] No usable login method found
[2020-04-03 11:54:06] [127.0.0.1] [OpenOTP:2WL6CTJJ] Sent failure response

Incorrect Protocol

Only PAP or EAP-TTLS authentication is supported for password authentication. CHAP and similar password protocols using hashed values are not supported. If your Windows clients such as Windows integrated VPN client, be sure to configure the VPN client and server with PAP authentication.

[root@webadm1]# /opt/radiusd/bin/radiusd debug
...
Listening on auth address * port 1812 bound to server default
Listening on auth proto tcp address * port 1812 bound to server default
Listening on auth address * port 1645 bound to server default
Listening on acct address * port 1813 bound to server default
Listening on acct address * port 1646 bound to server default
Listening on status address * port 18120 bound to server default
Listening on command file /opt/radiusd/temp/radiusd.sock
Ready to process requests
(0)   NAS-IP-Address = 10.10.10.10
(0)   NAS-Port = 1
(0)   User-Name = "administrator"


(0)   CHAP-Challenge = 0x111111111111111111111111
(0)   CHAP-Password = 0x222222222222222222222**


(0)   Message-Authenticator = 0x33333333333333333333333
(0) # Executing section authorize from file /opt/radiusd/lib/radiusd.ini
(0)   authorize {
(0) eap: No EAP-Message, not doing EAP
(0)     [eap] = noop
(0) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(0) pap: WARNING: Authentication will fail unless a "known good" password is available
(0)     [pap] = noop
rlm_openotp: Invalid "User-Password" attribute (bad format or wrong RADIUS secret)
...

RADIUS Attribute Value Pairs

Invalid Attribute Value Pairs

It's possible to configure RADIUS Attribute Value Pairs through the WebADM GUI for specific users, groups, or client applications. Please refer to the RADIUS Attribute Value Pairs (AVPs) documentation for instructions on how to configure them.

RADIUS return attributes must comply with the RADIUS dictionaries stored in /opt/radiusd/lib/dictionaries/. If they do not, the authentication will fail.
In the example below, RADIUS Bridge receives return attribute ASA-VLAN="string", which is not correct as the attribute is defined as integer.

[root@webadm1]# /opt/radiusd/bin/radiusd debug
...
rlm_openotp: OpenOTP authentication succeeded

rlm_openotp: Reply Data: ASA-VLAN="string"
rlm_openotp: Invalid Reply Data (invalid value-pairs format or attribute not in dictionary)
(3)     [openotp] = fail
(3)   } # Auth-Type OTP = fail
(3) Failed to authenticate the user
(3) Using Post-Auth-Type Reject
(3) Post-Auth-Type sub-section not found.  Ignoring.
(3) Login incorrect: [test] (from client any port 0)
(3) Sent Access-Reject Id 52 from 127.0.0.1:1812 to 127.0.0.1:34295 length 0
(3) Finished request

Check Radius AVP returned

For this test, I configured Citrix-User-Groups as Radius returned attribute with a mapping to memberof attribute of my Administrator account.

radius

Radius Client output :

[root@radius_cli ~]# /opt/radiusd/bin/radtest Administrator 192.168.4.160:1812 'testing123$!'
Enter password: ********
Result: Success
Sent Access-Request Id 55 from 0.0.0.0:60026 to 192.168.4.160:1812 length 62 User-Name: "Administrator"
User-Password: "password"
NAS-Identifier: "RadTest"
Cleartext-Password: "password"
Received Access-Accept Id 55 from 192.168.4.160:1812 to 192.168.3.54:60026 length 410 Citrix-User-Groups: "CN=Organization Management,OU=Microsoft Exchange Security Groups,DC=rcdevsdocs,DC=com"
Citrix-User-Groups: "CN=Group Policy Creator Owners,CN=Users,DC=rcdevsdocs,DC=com"
Citrix-User-Groups: "CN=Domain Admins,CN=Users,DC=rcdevsdocs,DC=com"
Citrix-User-Groups: "CN=Enterprise Admins,CN=Users,DC=rcdevsdocs,DC=com"
Citrix-User-Groups: "CN=Schema Admins,CN=Users,DC=rcdevsdocs,DC=com"
Citrix-User-Groups: "CN=Administrators,CN=Builtin,DC=rcdevsdocs,DC=com"
Reply-Message: "Authentication success"

As you can see, groups of Administrator account are well returned.

Radius Bridge output :

(2) Received Access-Request Id 55 from 192.168.3.54:60026 to 192.168.4.160:1812 length 62
(2)   User-Name = "Administrator"
(2)   User-Password = "password"
(2)   NAS-Identifier = "RadTest"
(2) # Executing section authorize from file /opt/radiusd/lib/radiusd.ini
(2)   authorize {
(2) eap: No EAP-Message, not doing EAP
(2)     [eap] = noop
(2) pap: WARNING: No "known good" password found for the user.  Not setting Auth-Type
(2) pap: WARNING: Authentication will fail unless a "known good" password is available
(2)     [pap] = noop
(2)     [openotp] = ok
(2)   } # authorize = ok
(2) Found Auth-Type = OTP
(2) # Executing group from file /opt/radiusd/lib/radiusd.ini
(2)   Auth-Type OTP {
rlm_openotp: Found client ID attribute with value "RadTest"
rlm_openotp: Found source IP attribute with value ""
rlm_openotp: Found device ID attribute with value ""
rlm_openotp: Found client IP attribute with value ""
rlm_openotp: Sending openotpSimpleLogin request
rlm_openotp: OpenOTP authentication succeeded
rlm_openotp: Reply Data: Citrix-User-Groups="CN=Organization Management,OU=Microsoft Exchange Security Groups,DC=rcdevsdocs,DC=com",Citrix-User-Groups="CN=Group Policy Creator Owners,CN=Users,DC=rcdevsdocs,DC=com",Citrix-User-Groups="CN=Domain Admins,CN=Users,DC=rcdevsdocs,DC=com",Citrix-User-Groups="CN=Enterprise Admins,CN=Users,DC=rcdevsdocs,DC=com",Citrix-User-Groups="CN=Schema Admins,CN=Users,DC=rcdevsdocs,DC=com",Citrix-User-Groups="CN=Administrators,CN=Builtin,DC=rcdevsdocs,DC=com"
rlm_openotp: Reply message: Authentication success
rlm_openotp: Sending Access-Accept
(2)     [openotp] = ok
(2)   } # Auth-Type OTP = ok
(2) Login OK: [Administrator] (from client any port 0)
(2) Sent Access-Accept Id 55 from 192.168.4.160:1812 to 192.168.3.54:60026 length 0
(2)   Citrix-User-Groups = "CN=Organization Management,OU=Microsoft Exchange Security Groups,DC=rcdevsdocs,DC=com"
(2)   Citrix-User-Groups = "CN=Group Policy Creator Owners,CN=Users,DC=rcdevsdocs,DC=com"
(2)   Citrix-User-Groups = "CN=Domain Admins,CN=Users,DC=rcdevsdocs,DC=com"
(2)   Citrix-User-Groups = "CN=Enterprise Admins,CN=Users,DC=rcdevsdocs,DC=com"
(2)   Citrix-User-Groups = "CN=Schema Admins,CN=Users,DC=rcdevsdocs,DC=com"
(2)   Citrix-User-Groups = "CN=Administrators,CN=Builtin,DC=rcdevsdocs,DC=com"
(2)   Reply-Message := "Authentication success"
(2) Finished request

Below, the OpenOTP logs for the previous authentication. You can see them once the authentication has been successfully validated by OpenOTP. OpenOTP return the attribute configured on my Administrator account and then the log regarding radius returned attribute appears : Returning 6 RADIUS reply attributes.

[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] New openotpSimpleLogin SOAP request
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] > Username: Administrator
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] > Password: xxxxxxxx
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] > Client ID: RadTest
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] > Options: RADIUS,-U2F
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Registered openotpSimpleLogin request
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Ignoring 2 memberof values for user 'CN=Administrator,CN=Users,DC=rcdevsdocs,DC=com' (out of domain group search base)
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Resolved LDAP user: CN=Administrator,CN=Users,DC=rcdevsdocs,DC=com
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Resolved LDAP groups: group policy creator owners,domain admins,enterprise admins,schema admins,denied rodc password replication group
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Started transaction lock for user
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Found user fullname: Administrator
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Found 1 user emails: Administrator@rcdevsdocs.com
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Found 47 user settings: LoginMode=LDAPOTP,OTPType=TOKEN,PushLogin=Yes,LockTimer=0,MaxTries=3,BlockTime=0,ChallengeMode=Yes,ChallengeTimeout=90,OTPLength=6,MobileTimeout=30,EnableLogin=Yes,SelfRegister=Yes,HOTPLookAheadWindow=25,TOTPTimeStep=30,TOTPTimeOffsetWindow=120,OCRASuite=OCRA-1:HOTP-SHA1-6:QN06-T1M,DeviceType=FIDO2,SMSType=Normal,SMSMode=Ondemand,MailMode=Ondemand,PrefetchExpire=10,LastOTPTime=300,ListChallengeMode=ShowID,ReplyData=[1 Items]
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Found 10 user data: LastOTP,TokenType,TokenKey,TokenState,TokenID,TokenSerial,Device1Type,Device1Name,Device1Data,Device1State
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Last OTP expired 2020-04-17 18:29:43
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Found 1 registered OTP token (TOTP)
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Requested login factors: LDAP & OTP
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] LDAP password Ok
[2020-04-17 18:50:45] [192.168.4.160] [OpenOTP:4JKBFJ4C] Authentication challenge required
[2020-04-17 18:50:46] [192.168.4.160] [OpenOTP:4JKBFJ4C] Sent push notification for token #1
[2020-04-17 18:50:46] [192.168.4.160] [OpenOTP:4JKBFJ4C] Waiting 27 seconds for mobile response
[2020-04-17 18:50:56] [192.168.4.160] [OpenOTP:4JKBFJ4C] Received mobile authentication response from 192.168.4.189
[2020-04-17 18:50:56] [192.168.4.160] [OpenOTP:4JKBFJ4C] > Session: cupcbM2KWdmcAxjF
[2020-04-17 18:50:56] [192.168.4.160] [OpenOTP:4JKBFJ4C] > Password: 16 Bytes
[2020-04-17 18:50:56] [192.168.4.160] [OpenOTP:4JKBFJ4C] Found authentication session started 2020-04-17 18:50:45
[2020-04-17 18:50:56] [192.168.4.160] [OpenOTP:4JKBFJ4C] PUSH password Ok (token #1)
[2020-04-17 18:50:56] [192.168.4.160] [OpenOTP:4JKBFJ4C] Returning 6 RADIUS reply attributes
[2020-04-17 18:50:56] [192.168.4.160 [OpenOTP:4JKBFJ4C] Updated user data
[2020-04-17 18:50:56] [192.168.4.160] [OpenOTP:4JKBFJ4C] Sent login success response