Radius Accounting Interim Update

Problem this snippet solves:

This iRule generates a Radius Accounting logging event with the status-type of Interim-Update when a user establishes a VPN Tunnel with APM.

How to use this snippet:

Apply this iRule to the HTTPS virtual that has the APM Profile applied to it that you want to generate Radius Accounting events for.

Code :

######################################################################
    ##
    ## See the RFC page for additional information on Accounting-Request
    ## http://tools.ietf.org/html/rfc2866#section-4
    ##
    ######################################################################

    when HTTP_REQUEST {
        ## Check to see if the user is currently authenticated
        ## If the HTTP path starts with /isession than most of the time 
        ## the user is trying to initiate a Network Access tunnel
        if { [ACCESS::policy result] eq "allow" && [HTTP::path] eq "/isession"} {

            ## Wait a little bit so the variable can be populated
            after 1000 -periodic {
                ## If the variable was populated than generate the Radius message
                if {[ACCESS::session data get session.assigned.clientip] ne ""}{
                    after cancel -current
                
                    ## Since the iRule doesn't have access to the AAA radius section
                    ## the variables need to be populated with the correct information
                    set __secret"123"
                    set __destination"1.1.1.1"
                    set __port"1813"
                
                    ##
                    set __code[format %02x 4]
                    set __id[format %02x [expr { int(255 * rand()) }]]
                
                    ## Accounting Session ID
                    set NA_SessionID[ACCESS::session data get session.user.sessionid]
                    binary scan $NA_SessionID H* __sid
                    set __asiLENGTH[expr {[string length $__sid] /2 + 2}]
                    set __asi[format %02x 44][format %02x $__asiLENGTH]$__sid
                
                    ## Accounting Status Type
                    set __ast[format %02x 40][format %02x 6][format %08x 3]
                
                    ## Accounting Authentication
                    set __aa[format %02x 45][format %02x 6][format %08x 1]
                
                    ## Service Type
                    set __st[format %02x 06][format %02x 6][format %08x 8]
                
                    ## NAS Port
                    set __np[format %02x 05][format %02x 6][format %08x 0]
                
                    ## Tunnel Client Endpoint
                    binary scan [IP::client_addr] H* __cip
                    set __tceLENGTH[expr {[string length $__cip] /2 + 2}]
                    set __tce[format %02x 66][format %02x $__tceLENGTH]$__cip
                
                    ## User-Name
                    set NA_UserName[ACCESS::session data get session.logon.last.username]
                    binary scan $NA_UserName H* __username
                    set __unLENGTH[expr {[string length $__username] /2 + 2}]
                    set __un[format %02x 1][format %02x $__unLENGTH]$__username
                
                    ## Framed-IP-Address
                    set NA_ClientIP[ACCESS::session data get session.assigned.clientip]
                    scan $NA_ClientIP %d.%d.%d.%d t__ip1 t__ip2 t__ip3 t__ip4
                    set __vpn[format %02x $t__ip1][format %02x $t__ip2][format %02x $t__ip3][format %02x $t__ip4]
                
                    set __fiaLENGTH[expr {[string length $__vpn] /2 + 2}]
                    set __fia[format %02x 8][format %02x $__fiaLENGTH]$__vpn
                
                    ## Combine the attributes above into a single string
                    set __attributes${__asi}${__ast}${__aa}${__st}${__np}${__tce}${__un}${__fia}
                
                    ## Calculate the lenght of the attribute string and then device by 2 to get octet count
                    set __attributesL[expr {[string length  $__attributes]/2}]
                
                    ## Combine the attributes length with the radius header length
                    set __length[expr {$__attributesL + 20}]
                
                    ## The length value needs to be stored in HEX when the MD5 attribute is calculated
                    set __length_HEX[format %04x $__length]
                
                    ## The Request Authenticator field contatins 16 zero octets
                    set __zero [format %032x 0]
                
                    ## Generate the Request Authenticator value
                    set __md5_auth [md5 [binary format H* ${__code}${__id}${__length_HEX}${__zero}${__attributes}]${__secret}]
                
                    ## Convert the MD5 value into binary
                    binary scan $__md5_auth H* __auth
                
                    ## Populate the Radius Information
                    set __radiusPayload[binary format cH2SH32H* $__code $__id $__length $__auth $__attributes] 
                
                    ## Create the sideband connection and send the data
                    set sb_conn[connect -protocol UDP -timeout 100 -idle 30 -status conn_status $__destination:$__port]
                    set sb_send[send -timeout 100 -status send_status $sb_conn $__radiusPayload]
                    set sb_recv [recv -peek -status peek_status -timeout 1000 $sb_conn]
                
                    ## After the data is sent close the connection
                    close $sb_conn
                }
            }
        }
    }
Published Oct 06, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment