A while ago I was working on a project to decommission the old TACACS server and we chose to replace it with Radius for Cisco router authentication.
After trying a few different radius packages (on Linux) one of our engineers said that he had luck in the past with Radiator – a closed source radius package for Linux. The Radiator software http://open.com.au/radiator/index.html is probably under-utilised for basic authentication, but has been rock solid in our production environment for 6 months+.
What we now have is a radius server that accepts authentication requests from our Cisco devices, checks whether the username or Calling-Station-Id is in a blacklist, authenticates them against LDAP to our Domain Controller and then checks the users group membership to allow them to authenticate. All failed and accepted attempts are also logged.
Whilst the documentation is huge and detailed (376 pages) I couldn’t find any specific examples on the net to tie everything we wanted together. So below is a sample configuration for what we are running as detailed above. Essentially we make a Radius user on the domain who can read LDAP (because we don’t allow anon ldap queries right?). We also make a RadiusSG security group which will contain the users that we want to allow login to our devices (because we don’t want to allow a terminal login for all our other AD users).
Note, I have also included a clients-group1.cfg file to specify each NAS into nice groups. I use this option to create multiple includes to split devices by region/country.
file: /etc/radiator/radius.cfg
#Foreground
LogStdout
LogDir /var/log/radius
DbDir /etc/radiator
# Use a low trace level in production systems. Increase
# it to 4 or 5 for debugging, or use the -trace flag to radiusd
Trace 3
# You will probably want to add other Clients to suit your site,
# one for each NAS you want to work with
# INCLUDE OUR REGION SETTINGS
include %D/clients-group1.cfg
<Realm DEFAULT>
# LOG ALL FAILED REQUESTS TO /var/log/radius/<YEAR>-<MONTH>-attempts-failed.log
<AuthLog FILE>
Filename %L/%Y-%m-attempts-failed.log
LogFailure 1
LogSuccess 0
FailureFormat %d/%m/%Y %H:%M:%S FAIL Username: %U Password: %P from %{Calling-Station-Id} on %{NAS-IP-Address}
</AuthLog>
# LOG ALL ACCEPTED REQUESTS TO /var/log/radius/<YEAR>-<MONTH>-attempts-ok.log
<AuthLog FILE>
Filename %L/%Y-%m-attempts-ok.log
LogSuccess 1
LogFailure 0
SuccessFormat %d/%m/%Y %H:%M:%S OK Username: %U Password: <hidden> from %{Calling-Station-Id} on %{NAS-IP-Address}
</AuthLog>
# CHECK BAD USERNAMES THEN BAD IP’S THEN LDAP FOR AUTHENTICATION
<AuthBy GROUP>
# FLOW THROUGH OUR BLACKLIST MODULES
AuthByPolicy ContinueUntilReject
#CHECK FOR BAD USERNAMES
<AuthBy FILE>
Blacklist
Filename %D/reject-usernames
</AuthBy>
#CHECK FOR BAD IP’S
<AuthBy FILE>
Blacklist
AuthenticateAttribute Calling-Station-Id
Filename %D/reject-ip
</AuthBy>
#CHECK AGAINST OUR AD VIA LDAP
<AuthBy LDAP2>
# SPECIFY THE DOMAIN CONTROLLER ADDRESS AND LDAP PARAMS
Host <INTERNALIPOFDOMAINCONTROLLER>
SSLVerify none
UseTLS
Port 3268
# OUR DC WONT ALLOW ANON READING SO WE HAVE TO AUTH AS A VALID USER
AuthDN cn=Radius, OU=Service Accounts, DC=<DOMAINHERE>, DC=prd
AuthPassword <RadiusUSERPASSWORDHERE>
# USE THE CACHE FOR MULTIPLE ATTEMPTS WHICH SAVES LDAP QUERIES
CachePasswords
# START SEARCHING LDAP FROM THIS DN FORWARDS
BaseDN DC=<DOMAINHERE>, DC=prd
UsernameAttr sAMAccountName
ServerChecksPassword
# REQUIRE GROUP MEMBERSHIP
SearchFilter (&(%0=%1)(memberOf=CN=RadiusGroup SG, OU=Security Groups, DC=<DOMAINHERE>, DC=prd))
</AuthBy>
</AuthBy GROUP>
</Realm>
I have also created some scripts to poll for top IP offenders (bruteforce attempts etc) so I will most likely post these details soon.