Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Packet tracing web interface

3 views
Skip to first unread message

Brian Candler

unread,
Mar 12, 2011, 8:02:22 AM3/12/11
to
I'd like to build a "packet tracer" web interface for freeradius: that is,
somewhere where you can paste in a set of AV pairs (perhaps caught from
radsniff), and you get back the AV responses plus all the decision-making
logic that took place. Basically what freeradius -X shows.

Has anyone done this before? I have a few considerations.

(1) If I had a single persistent freeradius daemon running, and multiple
users were submitting requests to this web interface, I'd need to separate
out the debug data for each of the requests. I guess I could have a locking
system so that only one person could be using it at once.

(Alternatively I'd have to fire off a new foreground radiusd for each
request as it came in, and kill it afterwards)

(2) What's the best way to submit the request so that it looks like it's
coming from a particular IP address? The "Client-IP-Address" attribute is
internal only, not on-the-wire.

At the moment the best I've been able to do is to create loopback interfaces
on my box with examples of the source IPs I'm interested in, then use
radclient to send the packet with a Packet-Src-IP-Address of one of those
loopbacks. Is there a better way I've overlooked?

(Before you say it, I know a well-behaved radius server should be looking at
NAS-IP-Address not Client-IP-Address. Unfortunately there are some cases
where we have to make logic decisions based on the Client-IP-Address)

Thanks,

Brian.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html

Gary Gatten

unread,
Mar 12, 2011, 10:00:09 AM3/12/11
to
I don't know about all your questions, but, during my testing I found that if I start "radiusd -X > somefile.log" and then run it in the background, I can grep/tail somefile.log for stuff I need. Perhaps you could do something similar to get the results of your query? I'm sure you could find some sort of record delimiters to grab only the results of your query and not all the others. There's probably many ways to do this, including tweaking the source.

Is this for some sort of testing? What problem are you trying to solve?

Thanks,

<font size="1">
<div style='border:none;border-bottom:double windowtext 2.25pt;padding:0in 0in 1.0pt 0in'>
</div>
"This email is intended to be reviewed by only the intended recipient
and may contain information that is privileged and/or confidential.
If you are not the intended recipient, you are hereby notified that
any review, use, dissemination, disclosure or copying of this email
and its attachments, if any, is strictly prohibited. If you have
received this email in error, please immediately notify the sender by
return email and delete this email from your system."
</font>

Phil Mayers

unread,
Mar 12, 2011, 6:08:27 PM3/12/11
to
On 03/12/2011 01:02 PM, Brian Candler wrote:
> I'd like to build a "packet tracer" web interface for freeradius: that is,
> somewhere where you can paste in a set of AV pairs (perhaps caught from
> radsniff), and you get back the AV responses plus all the decision-making
> logic that took place. Basically what freeradius -X shows.
>

Have you seen

radmin
> inject file input output

?

Alan Buxey

unread,
Mar 13, 2011, 7:32:14 AM3/13/11
to
hi,

following on the info that Phil has already supplied...you can also
use radmin to run debug to a single file for special cases...so,
if you were interested in eg 'Client-IP-Address = xxx.xxx.xxx.xxx'
then you can debug just on that condition to the file.


alan

Brian Candler

unread,
Mar 14, 2011, 6:16:07 AM3/14/11
to
On Sat, Mar 12, 2011 at 11:08:27PM +0000, Phil Mayers wrote:
> On 03/12/2011 01:02 PM, Brian Candler wrote:
> >I'd like to build a "packet tracer" web interface for freeradius: that is,
> >somewhere where you can paste in a set of AV pairs (perhaps caught from
> >radsniff), and you get back the AV responses plus all the decision-making
> >logic that took place. Basically what freeradius -X shows.
> >
>
> Have you seen
>
> radmin

I can't see how radmin would help here. Is it possible to use it to inject a
test packet? I can't see how, in which case I need to use radclient anyway.

radmin can turn debugging on and off, but I'd probably run a separate
instance of radiusd for the web test interface - otherwise lots of live
debugging traffic would get intermingled with it. Hence I could leave
debugging turned on permanently.

I'm thinking about this design:

post AV pairs
browser ------------------> web app
* lock
* radclient ---- req ----> radiusd -X
<--- reply ---
* gen HTML <------------- [debug file]
HTML page * unlock
<------------------

If I run radiusd -X as a child from another process I can capture its output
without writing it to a file.

Regards,

Brian.

Alan Buxey

unread,
Mar 14, 2011, 6:27:00 AM3/14/11
to
Hi,

> >
> > radmin
>
> I can't see how radmin would help here. Is it possible to use it to inject a
> test packet? I can't see how, in which case I need to use radclient anyway.

you seem to have slectively edited Phils reply.

radmin can indeed inject packets and give you reply....
ie

radmin> inject ?
inject to <ipaddr> <port> - Inject packets to the destination IP and port.
inject from <ipaddr> - Inject packets as if they came from <ipaddr>
inject file <input-file> <output-file> - Inject packet from input-file>, with results sent to <output-file>


so, to revisit your flow,

> post AV pairs
> browser ------------------> web app

okay. then use radmin to take those attributes and stick em into
the running RADIUS server (dont forget that using radiusd -X
can give interesting false results (it runs in single thread...a
real server runs in multithread mode)

get the output file from radmin and then..

> * gen HTML <------------- [debug file]
> HTML page * unlock
> <------------------

done.

you could carry on ignoring initial advice sent from knowledgeable
people but we are trying to help with your quest.....

alan

Phil Mayers

unread,
Mar 14, 2011, 8:11:21 AM3/14/11
to
On 14/03/11 10:16, Brian Candler wrote:
> On Sat, Mar 12, 2011 at 11:08:27PM +0000, Phil Mayers wrote:
>> On 03/12/2011 01:02 PM, Brian Candler wrote:
>>> I'd like to build a "packet tracer" web interface for freeradius: that is,
>>> somewhere where you can paste in a set of AV pairs (perhaps caught from
>>> radsniff), and you get back the AV responses plus all the decision-making
>>> logic that took place. Basically what freeradius -X shows.
>>>
>>
>> Have you seen
>>
>> radmin
>
> I can't see how radmin would help here. Is it possible to use it to inject a
> test packet? I can't see how, in which case I need to use radclient anyway.

I'll be honest - I haven't tried it! But I quickly glanced at the source
code for the "radmin inject" command I referred to, and it certainly
seemed like it would allow injection of arbitrary packets, and capture
of the replies.

Having said that, I just segfaulted the server I tested it on, so be
careful!

Phil Mayers

unread,
Mar 14, 2011, 8:47:36 AM3/14/11
to

Ok, correct usage is:

radmin
> inject to (auth|acct) dstip dstport
> inject from srcip
> inject file input output

Failure to issue "inject to" and "inject from" first results in a segfault.

It seems to look for input & output files in "logdir" from radiusd.conf
- the code seems to in theory handy absolute file paths, but I'm having
trouble making that work.

Alan DeKok

unread,
Mar 14, 2011, 9:03:28 AM3/14/11
to
Phil Mayers wrote:
> Failure to issue "inject to" and "inject from" first results in a segfault.

<grumble> People actually want this stuff to work?

OK... I'll fix it for 2.1.11.

Alan DeKok.

Brian Candler

unread,
Mar 14, 2011, 9:07:20 AM3/14/11
to
On Mon, Mar 14, 2011 at 10:27:00AM +0000, Alan Buxey wrote:
> radmin can indeed inject packets and give you reply....
> ie
>
> radmin> inject ?
> inject to <ipaddr> <port> - Inject packets to the destination IP and port.
> inject from <ipaddr> - Inject packets as if they came from <ipaddr>
> inject file <input-file> <output-file> - Inject packet from input-file>, with results sent to <output-file>

Thank you. For what it's worth, I *did* go and read the manpage, carefully,
before replying. The 'inject' option is not mentioned there.

Have you got an example of its use? It seems rather broken to me. I do
have mode=rw set.

radmin> inject


inject to <ipaddr> <port> - Inject packets to the destination IP and port.
inject from <ipaddr> - Inject packets as if they came from <ipaddr>
inject file <input-file> <output-file> - Inject packet from input-file>, with results sent to <output-file>

radmin> inject to 127.0.0.1 1812
ERROR: Unknown socket type
radmin> inject from 127.0.0.1
ERROR: You must specify "inject to" before using "inject from"
radmin> inject file /home/brian/test.in /home/brian/test.out

$

Meanwhile, radiusd -X running in a different window shows:

radmin> inject to 127.0.0.1 1812
Ready to process requests.
radmin> inject from 127.0.0.1
Ready to process requests.
radmin> inject file /home/brian/test.in /home/brian/test.out
Segmentation fault
$

The contents of /home/brian/test.in are simply:

User-Name = "steve"
User-Password = "testing"

If I rerun radiusd -X under gdb, here's where it crashes:

Ready to process requests.
radmin> inject file /home/brian/test.in /home/brian/test.out

Program received signal SIGSEGV, Segmentation fault.
0x0000000000411b74 in command_inject_file (listener=0x7b11b0,
argc=<value optimised out>, argv=0x7fffffffdaf0)
at /usr/include/bits/string3.h:52
52 return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
(gdb) bt
#0 0x0000000000411b74 in command_inject_file (listener=0x7b11b0,
argc=<value optimised out>, argv=0x7fffffffdaf0)
at /usr/include/bits/string3.h:52
#1 0x0000000000415fc5 in command_domain_recv (listener=0x7b11b0,
pfun=<value optimised out>, prequest=<value optimised out>)
at command.c:2196
#2 0x000000000042a050 in event_socket_handler (xel=<value optimised out>,
fd=<value optimised out>, ctx=<value optimised out>) at event.c:3423
#3 0x00007ffff7bd1bdb in fr_event_loop (el=0x7a8810) at event.c:411
#4 0x000000000041c74a in main (argc=2, argv=<value optimised out>)
at radiusd.c:406
(gdb)


Regards,

Brian.

Brian Candler

unread,
Mar 14, 2011, 9:37:42 AM3/14/11
to
On Mon, Mar 14, 2011 at 12:47:36PM +0000, Phil Mayers wrote:
> Ok, correct usage is:
>
> radmin
> > inject to (auth|acct) dstip dstport

Aha. The 'help' message is decidedly unhelpful there (so is the error
"Unknown socket type"). It works when I add 'auth', thank you.

> > inject from srcip
> > inject file input output

And it turns out radiusd forces a prepend onto the output path, but not the
input path:

++[exec] returns noop
Failed to send injected file to /v/build/fr/var/log/radius//home/brian/test.out: No such file or directory

It would be nice to allow '-' for input and output, so you didn't have to
mess with temporary files, but that would involve sending the request and
response across the socket.

I'll probably stick to radclient + loopbacks for now, although the ability
to set an arbitrary source IP using radmin inject is nice.

Simple GUI app attached. It's quite neat what you can do in 70 lines of ruby
:-)

Regards,

Brian.

---------------------------------------------------------------------------
require 'rubygems'
require 'sinatra'
require 'haml'

RADCLIENT = "/usr/bin/radclient"
RADIUSD = "/usr/sbin/freeradius"

# List available loopback interfaces [Label, IP address, secret]
SOURCES = [
['Default', '127.0.0.1', 'testing123'],
['Test LAC', '192.0.2.1', 'anothersecret'],
]

$radiusd = IO.popen("#{RADIUSD} -X -i 127.0.0.1 -p 18123","w+")
begin
exit unless (line = $radiusd.gets)
print line
end until line =~ /Ready to process requests/

set :lock, true # prevent concurrent requests

get '/' do
haml :root
end

post '/' do
# Flush any remaining debug info
$radiusd.gets while select([$radiusd], nil, nil, 0)
@radclient = ""
@radiusd = ""
source = SOURCES.find { |src| src[1] == params[:source] } || SOURCES.first
IO.popen("#{RADCLIENT} -x 127.0.0.1:18123 auth '#{source[2]}' 2>&1","w+") do |io|
io.puts "Packet-Src-IP-Address = #{source[1]}"
io.puts params[:avp]
io.close_write
loop do
ready, _ = select([io, $radiusd], nil, nil, 10)
unless ready
@radiusd << "** TIMEOUT **"
break
end
if ready.include?(io)
break unless (line = io.gets)
@radclient << line
end
if ready.include?($radiusd)
exit unless (line = $radiusd.gets)
@radiusd << line
end
end
end
haml :root
end

__END__

@@ root
%html
%head
%title radtest GUI
%body
%form{:action=>'/',:method=>'post'}
%ul
- SOURCES.each do |label, ip, secret|
%li
%input{:type=>'radio',:name=>'source',:value=>ip,:checked=>params[:source]==ip}&= label
%textarea{:name=>'avp',:rows=>12, :cols=>60}&= params[:avp]
%input{:type=>'submit'}
- if @radclient
%h1 radclient response
%pre&= @radclient
- if @radiusd
%h1 radiusd debug output
%pre&= @radiusd

0 new messages