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
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>
Have you seen
radmin
> inject file input output
?
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
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.
> >
> > 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
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!
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.
<grumble> People actually want this stuff to work?
OK... I'll fix it for 2.1.11.
Alan DeKok.
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.
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