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- CharlesCS_14932NimbostratusIn 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.