Intro
You guessed correctly. This is yet another article on how to setup FreeRADIUS to do 802.1x authentication. Why am I doing another when there are a plethora of other such guides out there? Well, the others I found lacking. When I set this up a few years ago, I remember having at least 10 different HowTo's/Guides/FAQs open.
Recently in my studies I needed to debug something with FreeRADIUS (was not working with Dynamic VLAN assignment), and I got thinking: Where exactly does FreeRADIUS kick over authentication to LDAP? Since I couldn't recall, I figured I would make up a guide, and redo the configuration to better understand it.
This was also expedited by user in the #freeradius FreeNode channel looking to do the same, but as I as posting configs, it wasn't helping.
This will get you to a place where you can do User and MAC address authentication, and Dynamic VLAN Assignment (or 802.1x VLAN assignment) So, without further ado, I give you my guide on setting up FreeRADIUS, pulling authentication information from an LDAP backend.
What does this page assume?
- You have a working OpenLDAP setup.
- The FreeRADIUS machine does need /etc/openldap/ldap.conf configured correctly, at least if you are doing TLS for LDAP.
- There's a few good guides out there, and this isn't terribly difficult. I may come up with something later, in which case I'll link to it at that time.
- Passwords are stored in plain text
- My LDAP tree is setup as such:
- ou=Wireless,ou=Services,dc=domain,dc=com -- Where the RADIUS settings are stored (I originally set this up for Wireless, hence the name)
- ou=Machines,ou=Wireless -- Where Machine MAC addresses are stored, with uid=001122334455, and password of the same
- ou=Users,ou=Wireless -- Where users are stored. Note, the passwords here are in plain-text, so it needs protected via LDAP ACLs
- ou=Wireless,ou=Services,dc=domain,dc=com -- Where the RADIUS settings are stored (I originally set this up for Wireless, hence the name)
- I highly suggest Apache Directory Studio to manage the LDAP Database, if you don't already have something graphical.
- You have configured your end devices (or will once FreeRADIUS is setup).
- In my case, my wireless AP is a Cisco AP-1242AG, and the LAN switches I have tested this on are: 2950-24T, 2950G-48, 3750-48PS, 3550-24-PWR. The configuration for these devices is fairly simple and well documented on Cisco's website. Using another manufacture shouldn't be much different, as RADIUS/EAP is standards based.
- You have Server SSL Certs. I won't go in to this much, as SSL is it's own beast, but I got my wildcard certs from CACert. I do recommend them, especially if you can get assured. You can also setup your own CA for SSL Certs ( I think this is recommended by FreeRADIUS).
My testing environment
- Linux, Distro: Gentoo Hardened, AMD64 Stable (Note: SELinux was disabled on this machine)
- While some stuff may be Gentoo specific, the basics of the files in the /etc/raddb (FreeRADIUS's config directory on Gentoo) should be the same across the board
- freeradius-2.1.11-r1 was emerged with the following USE line:
- USE="ldap mysql pam snmp ssl threads udpfromto -bindist -debug -edirectory (-firebird) -frascend -frxp -kerberos -postgres" Adjust as needed, but you will need at least 'ldap' and 'ssl'.
- You can do this with: echo "net-dialup/freeradius ldap mysql pam snmp ssl threads udpfromt" >> /etc/portage/package.use/freeradius
- I'm doing this as I write this, so if you find this in the middle of editing, sorry. Otherwise, you'll know it's complete and working for me.
- SSL Cert from CACert (needs to be known who the CA is when configuring it). This is needed for the EAP stuff, not just TLS to LDAP (it's actually not used there).
The Files
- All files are referenced from /etc/raddb/
clients.conf
- Only modification here was adding the client stanza at the bottom. In my case, I did one stanza to cover most of my devices. If you want more fine-grain control, you can specify each one as a /32.
client 10.0.3.64/28 {
secret = testing1234
}
eap.conf
- Under EAP {}:
- default_eap_type = peap
- Under TLS {}:
- This section says not to use a known CA, but this is where I use my cert from CACert, so known or not is up for debate.
- pem_file_type = yes -- This is an addition
- certdir = /etc/ssl/<domain>_wildcard -- This is where I store the wildcard cert mentioned above
- cadir = /etc/ssl/certs -- since CACert is included in the system CAs
- #private_key_password = whatever -- Commented this out, as my privkey has no password (a pain with Apache)
- private_key_file = ${certdir}/<domain>_wildcard.key
- certificate_file = ${certdir}/<domain>_wildcard.crt
- CA_file = ${cadir}/cacert.org.pem
- #CA_path = ${cadir} -- Commented out, maybe this is fine?
- Under peap {}:
- use_tunneled_reply = yes -- This is only needed for Dynamic VLAN Assignment. For straight Auth, you don't need to change this
ldap.attrmap
- Added: checkItem Cleartext-Password userPassword
- I haven't tried to modify this to include the normal hashed password used for system authentication, which requires bouncing through something like ntlm_auth. So, for now, as explained above, I store the password in plaintest, in a ACL protected OU.
modules/ldap
- Under ldap {}:
- server = "server.domain.com" -- set to your LDAP Server
- identity = "cn=radius,ou=virtual,ou=users,dc=domain,dc=com" -- Set to your RADIUS LDAP user, or some other user that can access the stuff in your OU below
- password = "MyradiusUserPassword"
- basedn = "ou=Wireless,ou=Services,dc=domain,dc=com" -- The OU where your RADIUS stuff is stored. I explained this above for my layout.
- #filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})" -- Commented, as everything under the DN above is RADIUS, so I don't need to filter.
- Under tls {}:
- start_tls = yes -- My LDAP Server is setup for TLS, and I prefer to use it in all instances connecting to it.
- cacertdir = /etc/ssl/certs -- Uncomment, letting it use the system root CAs.
- require_cert = "demand" -- Uncomment
- access_attr_used_for_allow = yes -- Uncomment
- set_auth_type = no -- Uncommented and changed
modules/mschap
- Under mschap {}:
- authtype = MS-CHAP -- Addition
- use_mppe = yes -- Uncommented and changed
- require_encryption = yes -- Uncommented
- require_strong = yes -- Uncommented
- with_ntdomain_hack = yes -- Uncommented and changed
- Note: sites-enabled only had the default files symlinked inside (control-socket, default, inner-tunnel)
sites-enabled/default
- Under authorize {}:
- #chap -- Commented
- #digest -- Commented
- #suffix -- Commented
- ntdomain -- Uncommented
- ldap -- Uncommented
- #pap -- Commented
- Under authenticate {}:
- #Auth-Type CHAP {} -- Section commented
- #digest -- Commented
- #unix -- Commented
sites-enabled/inner-tunnel
- Under server inner-tunnel {}:
- #listen {} -- Commented listen block
- Under authorize {}:
- unix -- Uncommented - Old?
- #suffix -- Commented
- ntdomain -- Uncommented
- ldap -- Uncommented
Caveats
- Passwords need to be stored in plain text in the LDAP DB. You can limit in OpenLDAP who can do what with ACLs, and I did it in this case. I may write up about this later, but it isn't fully applicable here, as it's more of an OpenLDAP configuration then a FreeRADIUS configuration.