| Update - March 2010: According to a guy named Ian, these instructions still work with CentOS 5.2, FreeRADIUS 1.x, and MSSQL 2008. I put Ian's comments below. |
There aren't many start-to-finish howto's on this subject. I found some that described how to
get the SQL components working, and others that described how to get freeRADIUS to use a SQL
database (although they mostly talked about MySQL). So here I will attempt to document how
to do it from start to finish.
My requirements:
We are testing some wireless access points from a company called Extricom. We have some older,
el-cheapo Trendnet APs in some of our buildings, and with them, we've always left them wide open -
no logins required, no WEP/WPA, nothing. We are a small, private, liberal-arts school out in the
middle of nowhere, so I've never felt the least bit worried about our wireless allowing open access.
However, our department got a new boss last year, and she came from an uptight school down in Atlanta.
She isn't built to handle such open access, so she wants the Extricom stuff to at least require the
users to validate themselves before it will let them our our network. OK, that's fair enough,
she's not asking for encryption, just authorization. The Extricom gear will validate users against a
RADIUS server, so this should be pretty easy, I've just got to find a RADIUS server. And did I
mention that our primary network logins are done in Novell's eDirectory? Yes, we're also a
Netware site. That only adds more icing to the cake. :)
After looking around and asking, I found two Open Source RADIUS servers that run on Linux -
FreeRADIUS and OpenRADIUS. Of the two, FreeRADIUS is the only one that specifically mentioned
eDirectory in its docs, so that's the one I decided to learn and use. However, reading a bit further,
I found that using FreeRADIUS against eDirectory requires me to turn-on Novell's Universal Password.
Universal Password would require some changes that I don't want to make right now. So that leaves me
with three choices for where to store the usernames and passwords:
./configureHowever, if your Linux box doesn't have X Windows (mine doesn't), do a
make
make install
./configure --enable-gui=noso that it won't try to compile any GUI components.
./configureI didn't need any options for ./configure. I think at one time you had to tell it where unixODBC was, but versions since ~0.62 can find it by themselves (which is why you have to compile/install unixODBC first... )
make
make install
tsql -H blackboard -p 1433 -U tester -P letmeinIf it works, you should see this:
locale is "en_US"If you see that, you know that you can at least talk to your SQL server. That is a Good Thing (tm). If the test fails, try using the IP instead of the hostname (or edit your resolv.conf/update your DNS records/etc). If it still fails, make sure you've, umm, you know, really GOT a SQL user on your database server named "tester". If it still still fails, you've got mondo problems that I won't get into here...
locale charset is "ISO-8859-1"
1>
[mypool]
host = 127.0.0.1
port = 5000
tds version = 4.2
[blackboardhost]
host = blackboard.reinhardt.edu
port = 1433
tds version = 8.0
tsql -S blackboardhost -U tester -P letmeinYou should get the same SQL prompt as before
locale is "en_US"The -S option tells tsql to use the entry "blackboardhost" in the freetds.conf file. If that works, then your FreeTDS setup is complete.
locale charset is "ISO-8859-1"
1>
====================================Basically, it sets up a single data source (DSN) named blackboardDSN. AFAIK, you can name the DSN whatever you want, the "DSN" part is just eye-candy I put on mine to distinguish it from the server entry.
[ODBC Data Sources]
blackboardDSN = Radius on Blackboard
[blackboardDSN]
Driver = /usr/local/lib/libtdsodbc.so
Description = Radius on Blackboard
Trace = No
Servername = blackboardhost
Database = radius
[Default]
Driver = /usr/local/lib/libtdsodbc.so
====================================
isql blackboardDSN tester letmeinIf it works, you'll see this prompt:
+---------------------------------------+Woohoo! It's working. Go get yourself a candy bar and a Coke to celebrate. You can skip over the next part about troubleshooting.
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL>
[root@localhost /etc]# isql -v blackboardDSN testeeeer letmeinHere's what happens when you misspell the DSN name on the command line:
[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[28000][unixODBC][FreeTDS][SQL Server]Login incorrect.
[][unixODBC][FreeTDS][SQL Server]Login failed for user 'testeeeer'.
[ISQL]ERROR: Could not SQLConnect
[root@localhost etc]# isql -v blackbooooardDSN tester letmeinHere's what you get when odbc.ini is pointing to the wrong directory for libtdsodbc.so, or when the library name is misspelled.
[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[ISQL]ERROR: Could not SQLConnect
[root@localhost etc]# isql -v blackboardDSN tester letmeinHere's what happens when you misspell the ServerName in odbc.ini:
[01000][unixODBC][Driver Manager]Can't open lib '/usr/local/lib/freetds/libtdsodbc.so' :
/usr/local/lib/freetds/libtdsodbc.so: cannot open shared object file: No such file or directory
[ISQL]ERROR: Could not SQLConnect
[root@localhost etc]# isql -v blackboardDSN tester letmeinHere's what happens when you misspell the database name in odbc.ini:
[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[ISQL]ERROR: Could not SQLConnect
[root@localhost etc]# isql -v blackboardDSN tester letmeinLike I said, so long as the "tsql -S" test works, then the only place you have to look is in odbc.ini. Using unixODBC really IS that simple at this point of the process.
[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[28000][unixODBC][FreeTDS][SQL Server]Login incorrect.
[][unixODBC][FreeTDS][SQL Server]Login failed for user 'tester'.
[][unixODBC][FreeTDS][SQL Server]Cannot open database requested in login 'radiuuus'. Login fails.
[ISQL]ERROR: Could not SQLConnect
./configureOn my box, I used the --with-edir switch to configure, since I may later try this against our eDirectory tree, and this way I won't have to recompile. If you're not a Novell shop, you can safely ignore that last sentence...
make
make install
radiusdsimple, no?
radiusd -XYou'll see several screens of info scroll by. If you're using an xterm or a ssh term, you can scroll back through the entries to see what's going on.
radtest dave davepass localhost 1 testing123
client 172.20.254.70 {Here's the entry for my Windows workstation where I run ntradping.
secret = letmein
shortname = extricomgordy
}
client 172.20.2.22 {
secret = dave
shortname = empty2
}If you're new to radius, the "secret" may need 2 seconds of explaining. It's just what it says it is - it's a secret. You tell the server what secret goes with which client entry, then you tell the client (access point, dial-in box, etc) what the secret is and it sends the secret word anytime it makes a request. When a request comes in, the radius server checks for the secret and ignores (or returns an error) if the secret is missing or isn't what the server thinks it should be. I guess it's kinda like a password. Note that there is one secret already in the clients.con file for the localhost entry - it's "testing123". That's what we used when we ran radtest earlier.
Testing FreeRADIUS (second test):
Now that you've got some clients in the file, try testing from one of them. Kill the radiusd server you started earlier (ctrl-C), then restart it before starting the test.
Here's a quick tutorial about using ntradping:
Here's what you have to fill in on the NTRADPING screen:Then click the "Send" button.
- RADIUS Server IP
- change the Port to 1812 (1645 is the "old" port for RADIUS)
- RADIUS Secret key (the one from the clients file)
- the User-Name and Password of the unix account you're trying to test
- set the Request Type to Authentication Request.
If it works, you should get a "response: Access-Accept" line in the RADIUS Server reply box.
If you get an Access-Reject response, check your spelling of the Secret key, username and password (stupid stars, but that's another rant...), because those SHOULD be working OK since they worked when you did it on localhost.
If you get a "recvfrom() error, WSAGetLastError()=10054", check the port number.
If you get a loong pause after you click send, then you start getting noresponse and retries, check the IP address.
If it still doesn't work, check the clients.conf file on the server. Make sure you typed in the IP address and secret correctly.
You MIGHT also need to tweak any firewall/iptables/ipchains rules that are running on the radius box (if any). That might be blocking the connection down at the network level. I didn't install the firewall stuff on my RH7 box, because I didn't want any interference, so I dunno. But it's a possibility. Maybe you can just stop the firewall by running "/etc/rc3.d/Sxxx stop" if you can figure out which Sxxx file it's in. Or you might have to rename that link so it doesn't start with "S" and reboot the radius box - it could have tweaked the IP stuff at boot up, so it might be easier to reboot. Sorry, I wish I had more info on the firewall stuff, but I don't.
We're coming down the home stretch now... I promise.
Configuring the mssql.conf file:
While not too hard to configure, the mssql.conf file is really ugly. Lucky for us, we only have to make a few changes to it, and those are all at the "top" of the file. Just remember to check your double-quote marks.
1. Under Database type, make sure the driver line saysdriver = "rlm_sql_unixodbc"it already should say that, but be smart and check it.
2. Under Connect Info, set the "server" entry to be the DSN name you gave the connection in odbc.ini. Remember that far back? Yes, it was long ago. Also, the "login" and "password" are for the SQL user on the database server. I told you those were coming.
# Connect info3. The radius_db entry (under Database table configuration) should say "radius". If it doesn't, I can't help you anymore, because that means the freeRADIUS guys have changed something big... ;)
server = "blackboardDSN"
login = "tester"
password = "letmein"
# Database table configuration4.The last thing you'll want to change is
radius_db = "radius"# Print all SQL statements when in debug mode (-x)you really should set sqltrace to "yes" while you're debugging this. it will be a great help, as it will print out all of the sql stuff when you run "radiusd -X". You can reset it to "no" after you've got everything working.
sqltrace = no
sqltracefile = ${logdir}/sqltrace.sql
That's it for mssql.conf, you don't have to touch any of the other stuff in the file.
At this point, we have no way to test that mssql.conf is doing what we want, since radiusd doesn't know to use sql yet. That's why it's so handy to turn sqltrace on right now, because you're really going to need it later...
Finally, we get to the last little bit of all this. Tying it all together in FreeRADIUS. Please wake up if you've fallen asleep. My great work, umm, sorry, YOUR great work in all of this is soon to pay off and you'll want to be awake when it does.
Configuring radiusd.conf:
This is prolly a good time for a break. Go get a coke and a smoke. walk around a little. Only a few more tweaks and we're done.
radiusd.conf is a grand-pappy of a config file. In many ways, it's similar to Apache's httpd.conf file (in fact, there is a section dealing with threads that looks really similar to Apache's. wink wink)
Anyway, we don't have too much to do in this file.
Way down around line 1225 (past the "acct_unique{" section) you should see a small section on SQL stuff. Specifically, there should be a line that says:$INCLUDE ${confdir}/sql.confrem that line out and add a line that reads:$INCLUDE ${confdir}/mssql.confCongratulations, you just told radiusd to read your mssql.conf file when it starts. But, we aren't done yet. Trust me, I tried it like this the first time, and kept wondering why it wasn't working. Duh! We still have to tell radiusd to use SQL as an authorization source.
To tell radius to use SQL for authorization, scroll way, way down in the file to the "authorize {" section (the section starts at around line 1727), then scroll down another 3 or 4 pages. You shold see the following block:#uncomment the sql line. Now you've told radiusd to use sql to lookup usernames and passwords.
# Look in an SQL database. The schema of the database
# is meant to mirror the "users" file.
#
# See "Authorization Queries" in sql.conf
# sql
However, there is one last little detail that you should be aware of. At around line 103, you can set the user and password for the user that you want radiusd to run as. For now, leave them commented out, and it will run as you (you are running as root, right???). However, once you've got everything going, you should go in and set these (and turn off sqltrace, while you're at it). I think the way to do it is create a new unix user and make that user the owner of the relevant stuff in /usr/local/etc , /usr/local/etc/raddb, /usr/local/lib, and /usr/local/sbin (maybe not the stuff in sbin, I'm not sure). Or sit down and figure out how to shove all of this in a chroot jail, if you're really paranoid.
Creating tables in the radius database:
You have to create the data table structures in the radius database on the SQL server. Luckily there is a script for this. Yipee. It took me a while to find the script - I couldn't find the one for MS SQL in the source directory, although there was one for MySQL, but it wouldn't work. Finally, I found it squirrelled away in the CVS tree. I dunno why the FreeRADIUS guys aren't distributing it anymore. Maybe they got pissed off at Microsoft or something. If you read the FreeRADIUS docs, you'll see references to the MSSQL schema, but afaik, it's NOT in the source tarballs anymore, you can only get it from their CVS, or from my link below.
Fire up Enterprise Manager, browse to the radius database, and open Query Analyzer. The script is too long for me to put inline here, so
here's a link.
Paste the script into the Query Analyzer window and run it. When it finishes, you can check a few tables to make sure they have fields definied.
Next, the data.
For simple user/password authorization, you need data in three tables :-The username has to appear twice - once in usergroup, once in radcheck.
- usergroup
- radcheck
- radgroupcheck
-The password goes in the radcheck table with an "op" field of " ==" (double equals).
-radgroupcheck is the simplest of the tables - it only needs one row of data in it -Really, there's just ONE SINGLE RECORD in radgroupcheck, and it's that one. (Note: I've seen some sites - maybe the FreeRADIUS docs themselves - say that if you don't have anything in radgroupcheck, the Auth-Type will default to Local. I haven't tested this, so I can't verify it. I don't know that it makes much difference one way or the other. I would imagine that freeradius is still going to send queries for the table, it's just going to get an empty record returned.)
- the groupname you used in usergroup
- attribute = "Auth-Type"
- value = "Local"
- op = ":="
Here are my sample items:The usergroup table:
id UserName GroupName 1 spongebob static 2 patrick static 3 plankton static 4 squidward static
The radcheck table:
id UserName Attribute Value Op 1 spongebob Password softy == 2 patrick Password rockbrain == 3 plankton Password squirt == 4 squidward Password bignose ==
And the simple radgroupcheck table:
id GroupName Attribute Value Op 1 static Auth-Type Local :=
I would imagine that the usergroup and radcheck tables are linked by their "id" field, although I haven't found out for sure. I don't know if the UserName's have to be an exact match. I would GUESS that it's better if they are...
The Groupname is "static". I don't know if that's a magic value in Radius, or if it's freetext. It's what I found in one of web documents, so it's what I used here.
I didn't do anything with the radreply and radgroupreply tables on my box, they're still empty.
----------------------
Clueless NOTE: make sure you give the whichever database user you're using "select" rights to all of the rad* tables and the usergroup table. I tried using the Microsoft supplied "public" for mine, but it din't work. The user does NOT need any write access unless you plan to use sqlaccounting (which I am not doing, nor do I plan to. I don't care when or how often our little buggers log in.) ----------------------
Once you have a few test users in your database, you're ready to go to the FINAL FINAL Step.
RUN THE FINAL TEST OF FREERADIUS AND MSSQL.
Really, you're almost there. The train is either about to come roaring out of the tunnel into the daylight, or catch fire and burn down the mountain. If you've followed along, and your base distro isn't too esoteric, you should be fine.
At this point, all that's left is to kill any running radiusd servers, and restart them. Be SURE to use the -X switch. Also, you did turn sqltrace on in mssql.conf, didn't you?
For this test, it doesn't matter if you use ntradping or radtest. You should be way beyond worrying about client secrets by now. Either way, give it a whirl. Did it work? If so, wow, you got lucky. Please pick my next set of lottery numbers and email them to me. :)
For the other 99.9% of us, something didn't work. Hey, it's a kinda complex setup, and since we haven't been able to test in several steps, we've got a lot of variables that could have gone wrong. So many, in fact, that I won't go into them here. However, I will tell you some of what the radiusd screen should show you.
If you scroll back to the start of the radiusd output, you should see a line around line 7 or 8 that says:Config: including file: /usr/local/etc/raddb/mssql.confIf you don't see that, check your radiusd.conf file to make sure you didn't misspell something up around line 1225 where you told radiusd to include the mssql.conf file. Also, make sure it isn't remmed out...
Scrolling on down the output, you should eventually see the start of where the SQL module loaded.Module: Loaded SQL
sql: driver = "rlm_sql_unixodbc"
sql: server = "blackboardDSN"
sql: port = ""
sql: login = "radius"
sql: password = "br549"
Those should all look pretty familiar to you by now. You should also see several more settings that were in mssql.conf that we didn't touch. Below them, you'll see a few pages of SQL queries. After those, you'll see a few more settings. Finally you'll see the part that we're after. The Good Stuff (tm). Look for this:rlm_sql (sql): Driver rlm_sql_unixodbc (module rlm_sql_unixodbc) loaded and linkedIf you see those, your database connection (and hence your mssql.conf file) are probably OK. If you get errors, hopefully the errors are illuminating enough to show you what's wrong.
rlm_sql (sql): Attempting to connect to radius@blackboardDSN:/radius
rlm_sql (sql): starting 0
rlm_sql (sql): Attempting to connect rlm_sql_unixodbc #0
rlm_sql (sql): Connected new DB handle, #0
rlm_sql (sql): starting 1
rlm_sql (sql): Attempting to connect rlm_sql_unixodbc #1
rlm_sql (sql): Connected new DB handle, #1
If the sql module loaded OK, then maybe it's a problem with the tables in the database, or a problem with the user permissions for your sql user. Check all of them. Keep at it. This stuff really does work once you get all the little buggies out.
===================================
Once you get the bugs worked out, Congratulations!, you have a functioning RADIUS server that DIDN'T cost you $5,000. But don't think you can stop now. Start reading up on the encryption stuff, and the other authentication stuff. The FreeRADIUS guys even have a book on Amazon that goes into mind-numbing detail on those things. As well, a lot of The new wireless equipment can often times do some amazing things, if you've got time to learn how to set it all up. Now that you know how to install (and re-install) a basic RADIUS server, you can build those services on it. You've got the foundation, so now start laying the bricks.
======================================
My running config files
For the sake of completeness, here are MY files that are known to work. Only the passwords have been changed to protect the innocent (ie - me...)
(Note: these are hosted at my linuxhangout.com site.)
odbc.ini
odbcinst.ini
freetds.conf
clients.conf
mssql.conf
radiusd.conf
And last but not least, here AGAIN is the SQL script to create the tables in the database
freeradius-mssql.sql
Resources/Credits:
I pulled this howto together from several disparate sources, none of which really gave start-to-finish instructions.
http://www.slashtmp.co.uk/index.php
(find the entry for February 7, 2006 - connecting to Microsoft SQL Server on *nix)
http://www.geocities.com/satish_patel_2000_2000/doc/freeradius.html
(the top half of the article deals with setting up FreeRADIUS, the bottom half deals with the radiusd.conf tweaks for MySQL, as well as a layout of the tables and fields, and what needs to be where. This is where I swiped my pretty Spongebob tables from...) (NOTE: now that Yahoo has viciously killed Geocities, that page is no longer available. ;) )
For the rest, I primarily read the docs for each package. Of them, FreeTDS and unixODBC have some pretty decent docs. The FreeRADIUS docs just plain suck ass if you're not already a FreeRADIUS hacker...
I would also like to thank my boss, without whose paranoid delusions of invasion I would never have undertaken this little adventure.
David Doster
Network Admin
Reinhardt College
dgd at reinhardt dot edu
28 Feb. 2006
Update - March 2010 Back in November/December of 2009, a guy named Ian wrote to ask a few questions about these instructions. We emailed back and forth a few times, and eventually he got his setup working with CentOS 5.2 and MSSQL 2008. I asked him to send me any pertinent details (especially version numbers) as well as any differences he noted. From his response, it seems these instructions still work, although a few paths have changed. I have included his email below. Thanks to Ian for taking the time to let me know what is what with this.
Hi David,
I now have a NAS/Radius client -'RadiusNT' on my Win XP desktop
authenticating against MS SQL 2008 db. I pretty much used your instructions
verbatim, there were a few differences, as shown later on. I still have to
clear up a few things so there may be some changes.
This is the software used so far:
Centos 5.2
freeradius.i386 1.1.3-1.5.el5_4 installed
freeradius-mysql.i386 1.1.3-1.5.el5_4 installed
freeradius-unixODBC.i386 1.1.3-1.5.el5_4 installed
unixODBC.i386 2.2.11-7.1 installed
freetds.i386 0.64-11.el5.centos installed
Windows server 2008
Ms SQL 2008
I did try to install freeradius2 but did not see a new radiusd.conf, which
I understood was significantly different from freeradius 1.1.x
I tried to un/reinstall freeradius2, but subsequently yum refused saying the
package was not signed.
I reverted to freeradius 1.1.3 - as it is the version supported by RHEL:
These are some of the differences I found, I will try to clean it up as I
clear my understanding of how things fit together.
Differences
Referenced: The primary config file for unixODBC is /usr/local/etc/odbc.ini
Used: /etc/odbc.ini
The UnixODBC driver referenced in the document was not found, so I used the
closest by name that I found and it worked.
Referenced : Driver = /usr/local/lib/libtdsodbc.so
Used: Driver = /usr/lib/libtdsodbc.so.0
I found mssql.sql in /usr/share/doc/freeradius-1.1.3/examples/mssql.sql
Msql.sql was installed after I was prompted to install freeradius-mysql
Regards, and thanks again for your help
Ian