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 theport
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:
|
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.