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
# source = 4.3.2.1
}
}
}
-
The
addressattribute specifies the RADIUS server’s IP address or DNS name. -
The
secretis 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_identifierwith 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 theportoption. -
The optional
sourceattribute, available since version 6.0.1, forces RADIUS messages to be sent from a specific source IP
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:
|
Default, fair selection based on server load |
|
Prefer the server, as long as it is completely unloaded |
|
Prefer the server, unless more than half of the sockets are in use |
|
Always prefer the server, unless no sockets are currently available |
|
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_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-Split-Tunneling-Policy |
55 |
Determines what kind of attributes is used for the subnets in the
|
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.
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
}
}
}
}
}
Framed-IP-Address attributeAccounting
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
Attributes sent to RADIUS Servers
| RADIUS attribute | Contents | Packet Types[1] | Comments |
|---|---|---|---|
5 (Virtual) |
✔ ✔ ✔ ✔ |
||
2 (Framed) |
✔ ✔ ✔ ✔ |
||
Unique ID of the IKE_SA |
✔ ✔ ✔ ✔ |
Changes whenever the IKE_SA is rekeyed |
|
Name of the IKE_SA |
✔ ✔ ✔ ✔ |
||
Server’s IPv4 address |
✔ ✔ ✔ ✔ |
Binary encoding of the IPv4 address |
|
Server’s IPv6 address |
✔ ✔ ✔ ✔ |
Binary encoding of the IPv6 address |
|
Server’s IP address and port |
✔ ✔ ✔ ✔ |
Text representation of the IKE server’s IP address and port e.g.
|
|
Client’s IP address and port |
✔ ✔ ✔ ✔ |
Text representation of the IKE client’s IP address and port e.g.
|
|
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 |
|
Accounting Session ID |
✔ ✔ ✔ ✔ |
Does not change over IKE_SA rekeyings |
|
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 |
|
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 attributes received in Access-Accept |
– ✔ ✔ ✔ |
Only if |
|
Sent bytes |
– – ✔ ✔ |
Total number of bytes sent over all CHILD_SAs of this IKE_SA |
|
Number of times Output-Octets overflowed 2^32 bytes |
– – ✔ ✔ |
Number of overflows over all CHILD_SAs of this IKE_SA |
|
Number of sent packets |
– – ✔ ✔ |
Total number of sent packets over all CHILD_SAs of this IKE_SA |
|
Received bytes |
– – ✔ ✔ |
Total number of bytes received over all CHILD_SAs of this IKE_SA |
|
Number of times Input-Octets overflowed 2^32 bytes |
– – ✔ ✔ |
Number of overflows over all CHILD_SAs of this IKE_SA |
|
Number of received packets |
– – ✔ ✔ |
Total number of received packets over all CHILD_SAs of this IKE_SA |
|
Number of seconds since creation of the initial IKE_SA |
– – ✔ ✔ |
||
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
# ...
}
}
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.

