eap-radius Plugin

Purpose

The eap-radius plugin for libcharon does not implement an EAP method directly, but it redirects the EAP conversation with a client to a RADIUS backend server. On the gateway, the EAP packets get extracted from the IKE messages and encapsulated into the RADIUS protocol, and vice versa. The gateway itself does not need special support for a specific EAP method, as it handles the EAP conversation between the client and the RADIUS backend more or less transparently.

The plugin is disabled by default and can be enabled with the ./configure option

--enable-eap-radius

RADIUS Servers

The plugin should work with any RADIUS server. It has been tested successfully with FreeRADIUS and the NPS Server included with Windows Server 2008 R2.

For EAP methods providing an MSK (Master Session Key) the RADIUS server must include the MSK in the MS-MPPE-Send-Key/MS-MPPE-Receive-Key attributes. Unfortunately, FreeRADIUS before version 2.1.10 did not include these attributes when used with EAP-MSCHAPv2.

Configuration

To let a connetion in swanctl.conf use a RADIUS backend server, define

connections.<conn>.remote.auth = eap-radius

Configuration for the eap-radius plugin is done in the following section of strongswan.conf

charon {
  plugins {
    eap-radius {
      # ...
    }
  }

Basic Configuration

The plugin supports multiple RADIUS servers. To define a RADIUS backend server, add a new section to the servers subsection with a name of your choice

    eap-radius {
      servers {
        server-a {
          address = 1.2.3.4
          secret = R4diu5-shared-$ecreŧ
          # nas_identifier = ipsec-gateway
        }
      }
    }
  • The address attribute specifies the RADIUS server’s IP address or DNS name.

  • The secret is used to authenticate the packets exchanged with the RADIUS server. In untrusted networks make sure to use a strong secret with enough entropy because the secret might be subject to dictionary attacks.

  • The nas_identifier with default [strongSwan] identifies the gateway against the RADIUS server and allows it to enforce a policy, for example. If you need an UDP port different from the RADIUS default [1812] use the port option.

Parallel RADIUS Sessions

The EAP exchange over RADIUS might need several packets and depending on the RTT (Round-Trip-Time) will take several fractions of a second to complete. As a single RADIUS client port can handle only one concurrent authentication session, multiple client ports can be used to do parallelize authentication for high load scenarios.

The per-server sockets option with default [1] defines the number of pre-allocated sockets to use. A value of 5 allows the gateway to authenticate 5 clients simultaneously over RADIUS.

Multiple RADIUS Servers

Multiple RADIUS servers can be defined for high availability or load sharing purposes. Use additional sections in the servers subsection and configure the individual servers accordingly.

The server used for an authentication session is selected randomly. If a server is under load (i.e. one or more of the defined sockets are in use), the server is degraded in the election process. If a server is unreachable it is further degraded. From time to time a previously non-responsive server is reused to automatically reintegrate it when it becomes available again.

RADIUS Server Preference

With the preference parameter of a server, priorities for specific servers can be defined. This allows to use a secondary RADIUS server only if the first gets unresponsive or overloaded.

A reachable server gets a priority value between 110 and 210, proportionally to the current use of its sockets (higher is better). Previously unavailable servers get a value of 0-100, only. The defined preference value is added to the calculated priority. Servers with the same calculated value will be elected randomly. The following preference values result in:

0

Default, fair selection based on server load

1

Prefer the server, as long as it is completely unloaded

50

Prefer the server, unless more than half of the sockets are in use

99

Always prefer the server, unless no sockets are currently available

101

Always prefer the server, unless it gets unreachable

Defining a preference of 110 and more is not a good idea, as such a server may always win the election process even if it is not available.

Session-Timeout and Dynamic Authorization Extension

A received Session-Timeout from the RADIUS backend is enforced using Repeated Authentication.

The Dynamic Authorization Extension allows a RADIUS backend to actively terminate a session using a Disconnect-Request or change the timeout of a session using a Session-Timeout attribute in a CoA-Request. The extension is enabled using a dae subsection in the eap-radius configuration:

    eap-radius {
      dae {
        enable = yes      # enable DAE extension
        listen = 0.0.0.0  # listen address, default to all
        port = 3799       # port to listen for requests, default
        secret = xxx      # shared secret to verify/sign DAE messages
      }
    }

RADIUS Attribute Forwarding

The following RADIUS attributes are forwarded to clients in corresponding IKE configuration attributes (more details about the attributes can be found in the docs on the attr plugin):

RADIUS attribute Code Configuration Attribute Code Description

Framed-IP-Address

8

INTERNAL_IP4_ADDRESS

1

Virtual IPv4 address

Framed-IP-Netmask

9

INTERNAL_IP4_NETMASK

2

Netmask of the internal network

Framed-IPv6-Address

168

INTERNAL_IP6_ADDRESS

8

Virtual IPv6 address

DNS-Server-IPv6-Address

169

INTERNAL_IP6_DNS

10

DNS server

Microsoft DNS/NBNS Servers (defined in the Microsoft namespace 0x000137)

RADIUS attribute Code Configuration Attribute Code Description

MS-Primary-DNS-Server

28

INTERNAL_IP4_DNS

3

DNS server

MS-Secondary-DNS-Server

29

INTERNAL_IP4_DNS

3

DNS server

MS-Primary-NBNS-Server

30

INTERNAL_IP4_NBNS

4

NBNS server

MS-Secondary-NBNS-Server

31

INTERNAL_IP4_NBNS

4

NBNS server

Cisco DNS/NBNS Servers (defined in the Altiga namespace 0x000c04)

RADIUS attribute Code Configuration Attribute Code Description

CVPN3000-Primary-DNS

5

INTERNAL_IP4_DNS

3

DNS server

CVPN3000-Secondary-DNS

6

INTERNAL_IP4_DNS

3

DNS server

CVPN3000-Primary-WINS

7

INTERNAL_IP4_NBNS

4

NBNS server

CVPN3000-Secondary-WINS

8

INTERNAL_IP4_NBNS

4

NBNS server

Cisco Unity Extensions for IKEv1 (defined in the Altiga namespace 0x000c04)

RADIUS attribute Code Configuration Attribute Code Description

CVPN3000-IPSec-Banner1

15

UNITY_BANNER

28672

Message displayed on certain clients after login

CVPN3000-IPSec-Split-Tunnel-List

27

UNITY_SPLIT_INCLUDE

28676

The attribute contains a comma-separated list of subnets that are either included in a UNITY_SPLIT_INCLUDE or a UNITY_LOCAL_LAN attribute, depending on the value of the CVPN3000-IPSec-Split-Tunneling-Policy attribute

UNITY_LOCAL_LAN

28678

CVPN3000-IPSec-Default-Domain

28

UNITY_DEF_DOMAIN

28674

Default search domain

CVPN3000-IPSec-Split-DNS-Names

29

UNITY_SPLITDNS_NAME

28674

Space-separated list of domain names

CVPN3000-IPSec-Banner2

36

UNITY_BANNER

28672

Same as CVPN3000-IPSec-Banner1

CVPN3000-IPSec-Split-Tunneling-Policy

55

Determines what kind of attributes is used for the subnets in the CVPN3000-IPSec-Split-Tunnel-List attribute:

1: UNITY_SPLIT_INCLUDE

2: UNITY_LOCAL_LAN

Arbitrary RADIUS Attribute Forwarding

Arbitrary RADIUS attributes can be forwarded from/to the IKE peer using custom IKEv2 notify payloads. The notify uses the strongSwan specific private notify 40969. Forwarding is configured in a eap-radius subsection called forward:

    eap-radius {
      forward {
        ike_to_radius = Reply-Message, 11
        radius_to_ike = 36906:12
      }
    }

Both options define a comma separated list of RADIUS attributes to forward in the corresponding direction (ike_to_radius or radius_to_ike, respectively). Attributes can be defined by name or attribute number. The number in front of a colon defines the namespace or Private Enterprise Number (PEN) of a vendor-specific attribute to forward.

An IKE client can use the radattr plugin to provide or print such attributes.

Identity Exchange

The eap-radius plugin starts the conversation with the RADIUS server directly with an EAP-Identity response using the IKEv2 identity of the peer. To enforce a different identity in this exchange, set

connections.<conn>.remote.eap_id = test@example.com

in swanctl.conf. To trigger an EAP-Identity exchange with the VPN client and ask for an EAP identity, set

connections.<conn>.remote.eap_id = %any

Another option is to let the RADIUS server itself initiate the EAP conversation by sending an EAP-Start message. Set

eap_start = yes

in the eap-radius section of strongswan.conf to initiate the conversation with EAP-Start. This kind of operation is not supported by all RADIUS servers. Don’t forget --enable-eap-identity if you use EAP-Identity exchanges initiated by the VPN gateway.

The id_prefix option in the eap-radius section of strongswan.conf prepends a prefix to the negotiated identity. This is useful, as some RADIUS servers interpret such a prefix as a request for a specific EAP method (e.g. 0 as EAP-SIM, 1 as EAP-AKA).

Identity Matching

The client’s IKE or EAP identity might be completely unauthenticated when the authentication is delegated to a RADIUS server. So switching connections or basing other policy decisions on that identity is potentially unsafe. Consider using group selection instead.

The plugin sends the IKE identity (or EAP identity if the IKE daemon is instructed to do an EAP-Identity exchange) as User-Name attribute to the RADIUS server. As described in the previous section, that same identity is also sent as EAP-Identity response in the first Access-Request message if eap_start=no is configured (the default).

However, whether that identity is validated in any way depends on the RADIUS server’s behavior and configuration. For instance, whether it enforces a match against the client certificate if EAP-TLS is used, or whether it uses it as a lookup key to find a password in case of EAP-MD5/MSCHAPv2. If it doesn’t, the IKE daemon can’t trust that identity.

Moreover, with eap_start=yes, the RADIUS server may perform its own EAP-Identity exchange. This identity can be completely unrelated to the IKE identity that’s passed in the User-Name attribute (e.g. with Windows clients that send their IP as IKE identity). And the IKE daemon won’t know about this even if the RADIUS server changes the User-Name attribute in the Access-Accept reply as the plugin currently doesn’t process this attribute.

Therefore, switching connections or basing other policy decisions on the IKE/EAP identity (e.g. in a script or plugin like ext-auth or whitelist) is potentially unsafe when RADIUS servers are involved. Instead, consider using group selection based on attributes provided by the RADIUS server in the Access-Accept message. However, unless validated, the RADIUS server shouldn’t base this attribute assignment on the User-Name attribute either, but instead use e.g. information extracted from the verified client certificate.

When using EAP-TLS with FreeRADIUS, it’s easily possible to match the IKE/EAP identity passed in the User-Name attribute against the Common Name (CN) RDN in the client certificate’s subject distinguished name (DN) by setting:

check_cert_cn = %{User-Name}

Even more flexibility is offered by the virtual_server offered by the rlm_eap_tls module, which can also match against other and even multiple attributes extracted from the client certificate such as CN (TLS-Client-Cert-Common-Name attribute) and SANs (e.g. TLS-Client-Cert-Subject-Alt-Name-Email or TLS-Client-Cert-Subject-Alt-Name-Dns).

However, if the IKE/EAP identity is the certificate’s subject DN, matching TLS-Client-Cert-Subject generally won’t work because the string value it contains does not match the binary ASN.1-encoded value that’s sent in the User-Name attribute.

Group Selection

The plugin optionally interprets the class attribute sent in the Access-Accept message as group membership information. A swanctl.conf configuration with

connections.<conn>.remote.groups = sales, finance

is acceptable only if the RADIUS server includes one of the two groups in the class attribute. As this behavior is not standardized, the boolean flag

class_group = yes

in the eap-radius plugin subsection must be set.

Alternatively, the Filter-Id and Tunnel-Type attributes may be used for group selection. If the option

filter_id = yes

is enabled in the eap-radius plugin subsection and the Tunnel-Type attribute contains an arbitrary one-byte tag, followed by the value 9 in the remaining three bytes in network order which signifies IPsec with ESP in tunnel mode, the value of the Filter-Id attribute will be applied as group name to the IKE_SA.

Examples

Here is an example configuration with two RADIUS servers defined in the eap-radius section of strongswan

charon {
  plugins {
    eap-radius {
      class_group = yes
      eap_start = no
      servers {
        primary {
          address = radius1.strongswan.org
          secret = $ecreŧxyz
          nas_identifier = ipsec-gateway
          sockets = 20
          # use secondary only if overloaded/non-responsive
          preference = 99
        }
        secondary {
          address = radius2.strongswan.org
          secret = $ecreŧabc
          nas_identifier = ipsec-gateway
          sockets = 5
          # uses custom RADIUS authentication port
          port = 12345
        }
      }
    }
  }
}
topology
Figure 1. strongSwan example using the Framed-IP-Address attribute
topology
Figure 2. strongSwan example using the Class attribute

Accounting

strongSwan supports RADIUS accounting but it is disabled by default and can be enabled using the accounting option. A non-standard port can be specified using the acct_port option in the server section. The new auth_port option is an alias for the port option.

    eap-radius {
      accounting = yes
      servers {
        server-a {
          address = 1.2.3.4
          auth_port = 1812   # default
          acct_port = 1813   # default
        }
      }
    }

When the IKE SA has been established the strongSwan VPN gateway sends an Accounting-Start request to the RADIUS server with the attributes as shown in the example below:

Thu Nov 11 19:54:01 2021
        Acct-Status-Type = Start
        Acct-Session-Id = "1634624945-573"
        NAS-Port-Type = Virtual
        Service-Type = Framed-User
        NAS-Port = 573
        NAS-Port-Id = "rw"
        NAS-IP-Address = 10.10.0.150
        Called-Station-Id = "10.10.0.150[4500]"
        Calling-Station-Id = "90.166.19.115[62472]"
        User-Name = "koala.strongsec.com"
        Framed-IP-Address = 10.10.1.65
        NAS-Identifier = "strongSwan"
        Event-Timestamp = "Nov 11 2021 19:54:01 CET"
        Tmp-String-9 = "ai:"
        Acct-Unique-Session-Id = "fa1f75166d50a9845e97ad0b86d01f52"
        Timestamp = 1636656841

When the IKE SA is terminated or reauthenticated the strongSwan VPN gateway sends an Accounting-Stop request to the RADIUS server with the attributes as shown in the example below:

Thu Nov 11 22:12:31 2021
        Acct-Status-Type = Stop
        Acct-Session-Id = "1634624945-573"
        NAS-Port-Type = Virtual
        Service-Type = Framed-User
        NAS-Port = 573
        NAS-Port-Id = "rw"
        NAS-IP-Address = 10.10.0.150
        Called-Station-Id = "10.10.0.150[4500]"
        Calling-Station-Id = "90.166.19.115[62472]"
        User-Name = "koala.strongsec.com"
        Framed-IP-Address = 10.10.1.65
        Acct-Output-Octets = 4074254197
        Acct-Output-Packets = 2865171
        Acct-Input-Octets = 84667320
        Acct-Input-Packets = 1257964
        Acct-Session-Time = 8310
        Acct-Terminate-Cause = User-Request
        NAS-Identifier = "strongSwan"
        Event-Timestamp = "Nov 11 2021 22:12:31 CET"
        Tmp-String-9 = "ai:"
        Acct-Unique-Session-Id = "fa1f75166d50a9845e97ad0b86d01f52"
        Timestamp = 1636665151

The Accounting-Stop message additionally adds Acct-Session-Time, Acct-Input-Octets, Acct-Output-Octets, Acct-Input-Packets and Acct-Output-Packets. The plugin optionally adds Class attributes received in Access-Accept messages to RADIUS accounting messages.

Example

topology
Figure 3. strongSwan example showing the use of RADIUS accounting

Attributes sent to RADIUS Servers

RADIUS attribute Contents Packet Types[1] Comments

NAS-Port-Type

5 (Virtual)

✔ ✔ ✔ ✔

Service-Type

2 (Framed)

✔ ✔ ✔ ✔

NAS-Port

Unique ID of the IKE_SA

✔ ✔ ✔ ✔

Changes whenever the IKE_SA is rekeyed

NAS-Port-Id

Name of the IKE_SA

✔ ✔ ✔ ✔

NAS-IP-Address

Server’s IPv4 address

✔ ✔ ✔ ✔

Binary encoding of the IPv4 address

NAS-IPv6-Address

Server’s IPv6 address

✔ ✔ ✔ ✔

Binary encoding of the IPv6 address

Called-Station-Id

Server’s IP address and port

✔ ✔ ✔ ✔

Text representation of the IKE server’s IP address and port e.g. 10.10.0.150[4500]. To omit the port station_id_with_port may be disabled

Calling-Station-Id

Client’s IP address and port

✔ ✔ ✔ ✔

Text representation of the IKE client’s IP address and port e.g. 90.166.19.115[62472]. To omit the port station_id_with_port may be disabled

User-Name

Client’s IKE identity

✔ ✔ ✔ ✔

If the daemon did an EAP-Identity exchange already, this contains the EAP identity instead. It is optionally prefixed, with id_prefix, refer to section above

Acct-Session-Id

Accounting Session ID

✔ ✔ ✔ ✔

Does not change over IKE_SA rekeyings

Framed-IP-Address

Client’s virtual IPv4 address(es)

– ✔ ✔ ✔

Only actually assigned addresses (not necessarily via RADIUS) are sent, except for Accounting-Stop, which also includes any unclaimed addresses assigned by the RADIUS server in Access-Accept

Framed-IPv6-Address

Client’s virtual IPv6 address(es)

– ✔ ✔ ✔

Only actually assigned addresses (not necessarily via RADIUS) are sent, except for Accounting-Stop, which also includes any unclaimed addresses assigned by the RADIUS server in Access-Accept

Class

Class attributes received in Access-Accept

– ✔ ✔ ✔

Only if accounting_send_class is set in the eap-radius section of strongswan.conf

Acct-Output-Octets

Sent bytes

– – ✔ ✔

Total number of bytes sent over all CHILD_SAs of this IKE_SA

Acct-Output-Gigawords

Number of times Output-Octets overflowed 2^32 bytes

– – ✔ ✔

Number of overflows over all CHILD_SAs of this IKE_SA

Acct-Output-Packets

Number of sent packets

– – ✔ ✔

Total number of sent packets over all CHILD_SAs of this IKE_SA

Acct-Input-Octets

Received bytes

– – ✔ ✔

Total number of bytes received over all CHILD_SAs of this IKE_SA

Acct-Input-Gigawords

Number of times Input-Octets overflowed 2^32 bytes

– – ✔ ✔

Number of overflows over all CHILD_SAs of this IKE_SA

Acct-Input-Packets

Number of received packets

– – ✔ ✔

Total number of received packets over all CHILD_SAs of this IKE_SA

Acct-Session-Time

Number of seconds since creation of the initial IKE_SA

– – ✔ ✔

Acct-Terminate-Cause

Termination cause

– – – ✔

This is either 3 (Lost Service), if the client was not rechable after several retransmits, or 5 (Session Timeout) if the IKE_SA expired without being rekeyed by either peer or 1 (User Request) for any other reason, including explicit deletion by the client

Arbitrary attributes

✔ – – –

Refer to the section above

For a full list of RADIUS attributes, please refer to the IANA registry of RADIUS types.

XAuth via RADIUS

An XAuth backend in the eap-radius plugin can directly verify XAuth credentials using RADIUS User-Name and User-Password attributes. The same set of servers is used for both EAP and XAuth authentication and Accounting and other RADIUS functionality can be used with XAuth as well.

To configure an IKEv1 connection on VPN gateway to verify XAuth credentials with RADIUS, set 'auth = xauth-radius' in a remote section:

connections {
  <conn>: {
    remote-rsa {
      auth = pubkey
    }
    remote-xauth {
      auth = xauth-radius
    }
    version = 1
    # ...
  }
}

Example

topology
Figure 4. strongSwan example showing the use of XAuth with the eap-radius plugin

Multiple Rounds

The eap-radius backend supports multiple XAuth rounds. It initiates multiple XAuth exchanges and for each one the client shows a dialog with an appropriate message. All replies get concatenated to the User-Password attribute, which gets verified over RADIUS.

The number and kind of rounds is configured by so called authentication profiles. You can have multiple profiles defined, each in its own subsection of the eap-radius.xauth section:

    eap-radius {
      # ...
      xauth {
        pinprofile {
          nextpin = Please enter the next Code from your scratch list:
        }
        passandcode {
          password = Please enter your Password:
          passcode = Please enter current authenticator token code:
        }
        passandcodegerman {
          password = Bitte Passwort eingeben:
          passcode = Bitte aktuellen Code des Tokens eingeben:
        }
      }
    }

This example defines three XAuth profiles, the pinprofile just asking for a PIN, the passandcode profile asking for both a password and a passcode, and the passandcodegerman doing the same in German language. In the latter two, the two answers get concatenated and it is up to the AAA server to correctly verify this answer.

Valid XAuth types to request are: password, passcode, nextpin and answer. For the strongSwan VPN gateway or the AAA server these types are not relevant but the client may show different dialog types (along with the configured message).

To use the configured profiles, you’ll have to refer to them in the connection definitions of swanctl.conf. To do so, append the profile name, separated by a colon, to the xauth-radius method in the remote auth configuration:

connections {

  finance {
    # Certificate authentication + PIN:
    remote-pubkey {
      auth = pubkey
    }
    remote-xauth {
      auth = xauth-radius:pinprofile
    }
    version = 1
    # ...
  }

  sales {
    # Hybrid authentication with password+passcode
    remote-xauth {
      id = sales@example.com
      auth = xauth-radius:passandcode
    }
    version = 1
    # ...
  }

  sales-german {
    # Hybrid authentication with German password+passcode
    remote-xauth {
      id = sales.german@example.com
      auth = xauth-radius:passandcodegerman
    }
    version = 1
    # ...
  }
}

The native iOS and macOS clients are known to work fine with multiple authentication rounds.


1. Use in packet types: Access-Request, Accounting-Start, Accounting-Interim-Update, and Accounting-Stop