RADIUS update NAS-IP-Address

Problem this snippet solves:

You have a F5 device in front of a pair of Microsoft Network Policy Server (NPS) and you are load-balancing RADIUS Authentication/Accounting requests. Imagine that you want to create a specific NPS policy and NAS-IP-Address is the only RADIUS attribute that is available to catch on. But NAS-IP-Address attribute in RADIUS packet is set by the RADIUS client device. You have a simple way to use iRule to manipulate RADIUS attributes as described in F5 CloudDocs. According to F5 docs you have to use RADIUS::avp replace command to modify RADIUS attributes. This is not so easy as described. According to RFC 3579 there is a Message-Authenticator attribute which must be properly filled if used. And if you update NAS-IP-Address attribute with the new value on F5 then RADIUS server will reject this message because Message-Authenticator code will not be valid anymore

Real world example:

Cisco AnyConnect SSL VPN configuration on Cisco ASA sends Vendor-Specific attributes ASA-TunnelGroupName and ASA-ClientType to the RADIUS server. Microsoft NPS server is one of the servers that do not support policy selection based on Vendor-Specific attributes. However there is an option to create policy selection based on constant text strings from CLI (netsh), but ASA-TunnelGroupName and ASA-ClientType are not constant strings, so policy match is not possible. Special values for NAS-IP-Address attribute were selected to be used for NPS policy selection by customer

How to use this snippet:

To avoid this problem you can use this workaround:

  1. Attach radiusLB profile to your virtual server
  2. Create and attach iRule below to your virtual server


Code :

when RULE_INIT priority 500 {
    # RADIUS secret
    set static::radius_secret {supersecretcode}

    # RADIUS NAS-IP-Address values
    set static::radius_nas_old {192.0.2.1}
    set static::radius_nas_new {198.51.100.1}
}
when CLIENT_DATA priority 500 {
    if { [RADIUS::code] == 1 } {
        # Request type is Access-Request
        if { [IP::addr [RADIUS::avp NAS-IP-ADDRESS ip4] equals $static::radius_nas_old] } {
            # Request is from trusted client, update NAS-IP-Address attribute
            RADIUS::avp replace NAS-IP-ADDRESS $static::radius_nas_new ip4

            if { [string length [RADIUS::avp 80 string]] == 16 } {
                # Message-Authenticator is present and need to be recalculated
                RADIUS::avp replace 80 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" string
                RADIUS::avp replace 80 [CRYPTO::sign -alg hmac-md5 -key $static::radius_secret [UDP::payload]] string
            }
        }
    }
}

Tested this on version:

13.0
Published Aug 17, 2020
Version 1.0

Was this article helpful?

No CommentsBe the first to comment