problem with radclient

Brian Candler B.Candler at
Thu Oct 18 10:32:02 CEST 2012

On Thu, Oct 18, 2012 at 01:27:58PM +0700, Fajar A. Nugraha wrote:
> On Thu, Oct 18, 2012 at 1:18 PM, Vladimir Grujić
> <Vladimir.Grujic at> wrote:
> > The scenario is that radius is behind load balancer which advertizes it's public ip address and forward packets to another ip address on radius (which has different ip) . Advertized public ip address on radius is binded to lo:0 interface. Hence the need for udpfromto. This is a setup to have HA cluster of radius servers and only one advertized ip for the NAS.
> So ... what does that have to do with radclient, again?

FWIW, I use radclient in a similar way as part of a test suite. There are
some cases where I need to send a test packet which appears to come from a
particular IP address (so that the "preprocess" module adds a missing
NAS-IP-Address based on source address)

I create loopback interfaces bound to the appropriate source IPs, and then
invoke radclient with an additional attribute

  Packet-Src-IP-Address = x.x.x.x

This works fine, and I don't have any problem with message authenticators. 
I'm not sending CoA packets, just regular Access-Request, and I'm not behind
any sort of load balancer.  But since the authenticator is calculated
without regard to the source/destination IP addresses or ports, it should
make no difference if it is NAT'd.

To debug this problem, I suggest that the OP use tcpdump -X to capture the
packet, and calculate the message authenticator by hand to see if it's
correct.  RFC 2866 section 3 gives the algorithm (note that CoA uses the
same algorithm as Accounting-Request - see RFC 3576 section 2.3)

Using tcpdump -ieth0 -s0 -nnX udp port 1812, packet will look something like

        0x0010:  XXXX XXXX UUUU UUUU UUUU UUUU ccii llll
        0x0030:  aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa
        0x0040:  692e 636f 2e75 6b28 0600 0000 032c 1b30,.0

where XX = IP header, UU = UDP header, cc = code (should be 2b for
CoA-Request), ii = identifier, llll = length, AAAA = message authenticator,
aaaa....  = RADIUS attributes

You can verify the authenticator like this, using ruby:

$ irb
>> require 'digest/md5'
=> true
>> Digest::MD5.hexdigest(["cciillll00000000000000000000000000000000aaaa...."].pack("H*") + "secret")

Substituting the appropriate hex digits for cc, ii, llll, and aaaa.... and
the shared secret.

Here is a worked example.

echo 'Reply-Message="foo"' | radclient -x localhost coa testing123

If you run
    tcpdump -ilo -s0 -nnX
in another window at the same time you see:

09:25:44.096721 IP > UDP, length 25
	0x0000:  4500 0035 c33e 0000 4011 b977 7f00 0001  E..5.>.. at ..w....
	0x0010:  7f00 0001 87ab 0ed7 0021 fe34 2bf6 0019  .........!.4+...
	0x0020:  363e 0b98 6d1c 69c2 2981 19c6 4ad1 74c9  6>..m.i.)...J.t.
	0x0030:  1205 666f 6f                   

Now you calculate:

>> Digest::MD5.hexdigest(["2bf60019"+"00000000000000000000000000000000"+"1205666f6f"].pack("H*") + "testing123")
=> "363e0b986d1c69c2298119c64ad174c9"

and you can see this matches the authenticator in the packet at offset

If the authenticator is calculated correctly by radclient, but is being
rejected as invalid by the NAS, then either the NAS has the wrong shared
secret (most likely) or is using the wrong algorithm to calculate the
authenticator for CoA.

Note that the NAS will select the shared secret to use based on the source
IP of the packet as seen when it arrives at the NAS.



More information about the Freeradius-Devel mailing list