RADIUS Server iRule
Problem this snippet solves:
An iRule that implements a basic RADIUS service in an iRule. Users are configured statically via a data group. I wrote this iRule as an exercise to further my knowledge of both iRules and the RADIUS protocol. It is not intended for production usage, and as such has not been volume tested.
Note that the functions are all implemented using binary scans, and not the iRule RADIUS:: functions, that were not available at the time when I wrote it.
Code :
class /Common/radiusd_users { { "test@f5.com" { "LLev3ZY2n0oq6Bcst6/dljafSiroF8cg/X9iQkNVen1WohflM8QForUaayxDaA==" } # pw = password } } rule /Common/radiusd_rule { when RULE_INIT { set radius_secret "mysecret" set static::aes_key "AES 128 63544a5e7178677b45366b41405f2dab" binary scan $radius_secret H* static::hexsecret set static::hexsecretlen [string length $static::hexsecret] } when CLIENT_ACCEPTED { # request set q_payload [UDP::payload] binary scan $q_payload cH2SH32a* q_code q_id q_len q_auth q_avp set q_avplen [expr $q_len - 20] set start_index 0 set q_var2 0 while {[expr $q_avplen - $start_index] > 4} { binary scan $q_avp @${start_index}xc q_var2 set q_var4 [expr $q_var2 -2] binary scan $q_avp @${start_index}cxa${q_var4} q_var1 q_var3 if {$q_var1 eq "1"} { set q_username $q_var3 } if {$q_var1 eq "2"} { set q_userpass $q_var3 } set start_index [expr $start_index + $q_var2] #log local0. "attr_type $q_var1 attr_len $q_var2 val_len $q_var4 val $q_var3" #log local0. "q_avplen $q_avplen new_offset $start_index rem [expr $q_avplen - $start_index]" } log local0. "q_code $q_code id $q_id len $q_len auth $q_auth q_avp $q_avp q_username $q_username q_userpass $q_userpass " UDP::drop # answer set a_code 3 if { [class match $q_username contains radiusd_users] } { binary scan $q_userpass H* a_userpass binary scan [md5 [binary format H*H* $static::hexsecret $q_auth]] c* vl1 binary scan [binary format H* $a_userpass] c* vl2 set res {} foreach v1 $vl1 v2 [lrange $vl2 0 15] { append res [binary format c [expr {$v1 ^ $v2}]] } set res [string trimright $res \u0000] if { [AES::decrypt $static::aes_key [b64decode [class match -value $q_username equals radiusd_users]]] eq $res } { set a_code 2 } } set a_id $q_id set a_auth $q_auth set a_avp "" set a_len 20 set a_var1 [binary format cH2SH32H$static::hexsecretlen $a_code $a_id $a_len $a_auth $static::hexsecret ] set a_var2 [md5 $a_var1] binary scan $a_var2 H* a_auth set a_payload [binary format cH2SH32 $a_code $a_id $a_len $a_auth ] binary scan $a_payload cH2SH32 a_code a_id a_len a_auth a_avp #log local0. "a_code $a_code id $a_id len $a_len auth $a_auth " UDP::respond $a_payload } }
Published Mar 18, 2015
Version 1.0John_McInnes_44
Nimbostratus
Joined May 18, 2006
John_McInnes_44
Nimbostratus
Joined May 18, 2006
No CommentsBe the first to comment