For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

RADIUS Load Balancing

Problem this snippet solves:

An iRule to load balance RADIUS requests.

Code :

when RULE_INIT {
  array set ::msg_types {
    1 "Access-Request"
    2 "Access-Accept"
    3 "Access-Reject"
    4 "Accounting-Request"
    5 "Accounting-Response"
    11 "Access-Challenge"
    12 "Status-Server"
    13 "Status-Client"
    255 "Reserved"
  }

  array set ::attr_types {
    1 "RADIUS_ATTR_USER_NAME"
    2 "RADIUS_ATTR_USER_PASSWORD"
    4 "RADIUS_ATTR_NAS_IP_ADDRESS"
    5 "RADIUS_ATTR_NAS_PORT"
    6 "Service-Type"
    7 "Framed-Protocol"
    8 "Framed-IP-Address"
    9 "Framed-IP-Netmask"
    10 "Framed-Routing"
    11 "Filter-Id"
    12 "RADIUS_ATTR_FRAMED_MTU"
    13 "Framed-Compression"
    14 "Login-IP-Host"
    15 "Login-Service"
    16 "Login-TCP-Port"
    24 "RADIUS_ATTR_STATE"
    25 "RADIUS_ATTR_CLASS"
    26 "RADIUS_ATTR_VENDOR_SPECIFIC"
    27 "RADIUS_ATTR_SESSION_TIMEOUT"
    28 "RADIUS_ATTR_IDLE_TIMEOUT"
    29 "RADIUS_ATTR_TERMINATION_ACTION"
    30 "RADIUS_ATTR_CALLED_STATION_ID"
    31 "RADIUS_ATTR_CALLING_STATION_ID"
    32 "RADIUS_ATTR_NAS_IDENTIFIER"
    40 "RADIUS_ATTR_ACCT_STATUS_TYPE"
    41 "RADIUS_ATTR_ACCT_DELAY_TIME"
    42 "RADIUS_ATTR_ACCT_INPUT_OCTETS"
    43 "RADIUS_ATTR_ACCT_OUTPUT_OCTETS"
    44 "RADIUS_ATTR_ACCT_SESSION_ID"
    45 "RADIUS_ATTR_ACCT_AUTHENTIC"
    46 "RADIUS_ATTR_ACCT_SESSION_TIME"
    47 "RADIUS_ATTR_ACCT_INPUT_PACKETS"
    48 "RADIUS_ATTR_ACCT_OUTPUT_PACKETS"
    49 "RADIUS_ATTR_ACCT_TERMINATE_CAUSE"
    50 "RADIUS_ATTR_ACCT_MULTI_SESSION_ID"
    51 "RADIUS_ATTR_ACCT_LINK_COUNT"
    52 "RADIUS_ATTR_ACCT_INPUT_GIGAWORDS"
    53 "RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS"
    55 "RADIUS_ATTR_EVENT_TIMESTAMP"
    61 "RADIUS_ATTR_NAS_PORT_TYPE"
    64 "RADIUS_ATTR_TUNNEL_TYPE"
    65 "RADIUS_ATTR_TUNNEL_MEDIUM_TYPE"
    77 "RADIUS_ATTR_CONNECT_INFO"
    79 "RADIUS_ATTR_EAP_MESSAGE"
    80 "RADIUS_ATTR_MESSAGE_AUTHENTICATOR"
    81 "RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID"
    85 "RADIUS_ATTR_ACCT_INTERIM_INTERVAL"
    95 "RADIUS_ATTR_NAS_IPV6_ADDRESS"
  }
}

when CLIENT_DATA {
  if { [UDP::payload length] > 4 } {
    #log "UDP::payload length [UDP::payload length]"
    binary scan [UDP::payload] c hdr_code
    log "radius type  $::msg_types($hdr_code)"
    binary scan [UDP::payload] @20a* rest_string
    while { [string length $rest_string] >4} {
      binary scan $rest_string cca* attr_id attr_length rest_string
      scan $attr_length  %i length
      set ff [format "a%da*" [expr {$length} - 2]]
      switch $attr_id {
1 { #if the type of attrbuite is RADIUS_ATTR_USER_NAME
  binary scan $rest_string $ff attr_value rest_string
          log "attribute id:  $::attr_types($attr_id); attribute length: $length; value: $attr_value"
  persist uie $attr_value
}
4 { #if the type of attrbuite is RADIUS_ATTR_NAS_IP_ADDRESS
  binary scan $rest_string c4a* IPtmp rest_string
  set IP {}
  foreach num $IPtmp {
    lappend IP [expr ($num + 0x100) % 0x100]
  }
  set attr_value [join $IP .]
  log "$::attr_types($attr_id) value $attr_value"
}
default {
  binary scan $rest_string $ff attr_value rest_string
                 #log "attribute id:  $::attr_types($attr_id); attribute length: $length; filed value: $attr_value"
}
            }   
}
    } 
}

when SERVER_DATA {
  if { [UDP::payload length] > 4 } {
    #log "UDP::payload length [UDP::payload length]"
    binary scan [UDP::payload] c hdr_code
    log "radius type  $::msg_types($hdr_code)"
    binary scan [UDP::payload] @20a* rest_string
    while { [string length $rest_string] >4} {
      binary scan $rest_string cca* attr_id attr_length rest_string
      scan $attr_length  %i length
      set ff [format "a%da*" [expr {$length} - 2]]
  switch $attr_id {
1 { #if the type of attrbuite is RADIUS_ATTR_USER_NAME
  binary scan $rest_string $ff attr_value rest_string
                  log "attribute id:  $::attr_types($attr_id); attribute length: $length; value: $attr_value"
}
4 - 
8 - 
9 { # 4 "RADIUS_ATTR_NAS_IP_ADDRESS" 8 "Framed-IP-Address"  9 "Framed-IP-Netmask"
  binary scan $rest_string c4a* IPtmp rest_string
  set IP {}
  foreach num $IPtmp {
     lappend IP [expr ($num + 0x100) % 0x100]
  }
  set attr_value [join $IP .]
  log "$::attr_types($attr_id) value $attr_value"
}
default {
  binary scan $rest_string $ff attr_value rest_string
                 #log "attribute id:  $::attr_types($attr_id); attribute length: $length; filed value: $attr_value"
}
            }   
}
    } 
}
Published Mar 18, 2015
Version 1.0

1 Comment

  • In version 10.x and later, the global array variables (::msg_types and ::attr_types) should instead be defined in the static:: namespace (static::msg_types and static::attr_types, respectively). This will allow CMP compatibility.