Creating a proper RADIUS Accounting-Response packet in iRules
If you do a lot of work with RADIUS messages being sent to
your BIGIP so that you can get some information from another network node in
the system, you are going to need to respond back to that node in a correct and
proper way, so that you don’t mess it up, or otherwise fill up its error log
with ‘improper response’ messages.
I was working on just that kind of iRule, and got it
working. Here’s the code:
2: ## RADIUS Acct-Resp packet
4: ## input variables:
5: ## $rId -> RADIUS Request ID field
6: ## $rAuth -> RADIUS Request Authorization field
7: ## $static::SHARED_SECRET -> RADIUS Shared secret of the 2 nodes.
9: UDP::drop ;## kill the incoming packet, don’t need it.
10: set RADcode 5 ;## RADIUS Accounting-Response Type code.
11: set md5hash [ format "05%02x00%02x" $rId 20 ]
12: set md5hash $md5hash$rAuth$static::SHARED_SECRET
13: set hash [ binary format H* $md5hash ]
14: set respAuth [md5 $hash]
15: set payldhdr [ binary format ccS $RADcode $rId 20 ]
16: set payload $payldhdr$respAuth
17: UDP::respond $payload
So the RADIUS Accounting-Response packet has, at a
minimum, four fields: RADIUS Type code(1 byte), ID number(1 byte),
Packet Length(2 byte Integer), and the Authenticator(16 bytes). Getting the
response authenticator correct is really the only tricky part.
Line 5: The RADIUS Request ID field comes from the incoming packet. You can retrieve this value previously in the iRule using a line of code like this: set rId [RADIUS::id]. Of course, this value can also be pulled out at the same time some other important fields are decoded using the sample code for line 6 below.
Line 6: The RADIUS Request Authorization field in the incoming packet is an MD5 hash of most if the incoming packet. To get this value, you will need to do a binary scan of the UDP packet:
set payload [UDP::payload]
binary scan $payload ccSH32a* rType rId rLen rAuth rPkt
In this example, we also pull out the Type Code (rType) and the packet ID (rId), the length of the overall packet, the Authorization field that we are looking for, and the rest of the packet, which should be all the AVP fields.
Line 9: We don’t need (and usually don’t want) the RADIUS
Request packet from going on from the BIGIP, so we just drop the packet to
Line 10: 0x05 is the
RADIUS Type Code for an Account-Response packet.
Line 11: Here’s where
we start working on our response authenticator. We are going to setup a
hexstring (which is hex characters displayed as a string; IE> “05140016” is
four bytes 0x05, 0x14, 0x00, 0x16), pack all of our values into it, convert it
to real binary hex, do the MD5 hash on the result, and use the MD5 checksum
result in the response packet. This line sets Type Code, id, and Length (hard
coded to 20 bytes).
Line 12: Using the hexstring from the last line, it adds the
Original request Authenticator, and the shared secret (which should already be
in hexstring format) to it. We now have
our complete hexstring that needs to be run through the MD5 checksum function.
Line 13: This line
simply converts the hexstring to a binary hex value.
Line 14: We get our
valid Authenticator for the response.
Line 15: Now we
create the actual response packet. This line sets the first three fields: Type
Code, id, and Length.
Line 16: We add the
header and the response Authenticator and we have our RADIUS
Line 17: Send the
The RADIUS Accounting-Response protocol is documented in RFC-2866, Section 4.2.