Friday, November 28, 2014

Configure Radius with LDAP for network authentication

In this blog I will show you how to configure FreeRadius with OpenLDAP for network authentication schemes such as 802.1x.
In my previous article in here openldap-installation I have showed OpenLDAP installation and in this article  openldap-ssl you can find how to enable TLS for LDAP. Before going forward you have to setup LDAP and enable TLS by following above articles.

Configure FreeRADIUS with OpenLDAP

FreeRADIUS is most popular Remote Authentication Dial In User Service (RADIUS) which provides AAA (Authentication , Authorization and Accounting services). Here I am using Debian 7 as a OS, let's install RADIUS.
$ sudo apt-get install freeradius freeradius-ldap

Once its installed , lets start configuring it with LDAP server.
  1. /etc/freeradius/clients.conf

    This file is used to authenticate Radius client to Radius server, as below we can define the allowed clients for Radius access.
    client localhost {
            ipaddr = 127.0.0.1
            secret          = testing123
    }
  2. /etc/freeradius/modules/ldap
    Here we will be integrating Radius with OpenLDAP server. Below entries are modified abd rest is untouched.
    server = "ldap.example.com"
    identity = "cn=admin,ou=ldap,dc=example,dc=com"
    password = passwd
    basedn = "ou=ldap,dc=example,dc=com"
    #Changed from uid to mail as we are using mail address to lookup users on LDAP
    filter = "(mail=%{%{Stripped-User-Name}:-%{User-Name}})"
    #
    #  Group membership checking. To provide authorization based on LDAP group the user belongs to.
    #
    groupname_attribute = cn
    groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{control:Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{control:Ldap-UserDn})))"
    groupmembership_attribute = radiusGroupName
    
    
  3. /etc/freeradius/sites-available/default
    We need to enable ldap on this file as well , there are two sections you need to remove the  comments from.
    authorize {
    .
    .
    .
    ldap
    .
    .
    }
  4. /etc/freeradius/sites-available/inner-tunnel
    In here also remove the comments from below section/s.
    authorize {
    .
    .
    .
    ldap
    .
    .
    }
  5. /etc/freeradius/users

    This file is used for authorizing users based on LDAP groups they are belongs to. Also to dynamically assign VLAN ids to each user based on groups matched, which will be used for VLAN assignment by switch. For this to work you should have created a cn with object class groupOfNames and saman as a member of the created group.
    DEFAULT Ldap-Group == "cn=test1,dc=example,dc=com"
            Tunnel-Type = VLAN,
            Tunnel-Medium-Type = IEEE-802,
            Tunnel-Private-Group-Id = "17"
    
    DEFAULT Auth-Type := Reject
    Once you completed the above configurations you should be able to test the Radius using radius client as below.
    $radtest saman@example.com saman 127.0.0.1 0 testing123
    
    Sending Access-Request of id 79 to 127.0.0.1 port 1812
     User-Name = "saman@example.com"
     User-Password = "saman"
     NAS-IP-Address = 127.0.1.1
     NAS-Port = 0
     Message-Authenticator = 0x00000000000000000000000000000000
    rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=79, length=36
     Tunnel-Type:0 = VLAN
     Tunnel-Medium-Type:0 = IEEE-802
     Tunnel-Private-Group-Id:0 = "17"
    As you can see when you try to connect the Radius, first it checks the group authorization and user authorization, if it was successful then it authenticate the user with provided password and finally return the above output to Radius client.
    From the below Radius logs , you can verify the above steps. (Only parts of the logs are displayed)
    Thu Nov 27 21:02:48 2014 : Info: +- entering group authorize {...}
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] Entering ldap_groupcmp()
    Thu Nov 27 21:02:48 2014 : Info: [files]  expand: dc=example,dc=com -> dc=example,dc=com
    Thu Nov 27 21:02:48 2014 : Info: [files]  expand: %{Stripped-User-Name} -> 
    Thu Nov 27 21:02:48 2014 : Info: [files]  ... expanding second conditional
    Thu Nov 27 21:02:48 2014 : Info: [files]  expand: %{User-Name} -> saman@example.com
    Thu Nov 27 21:02:48 2014 : Info: [files]  expand: (mail=%{%{Stripped-User-Name}:-%{User-Name}}) -> (mail=saman@example.com)
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] ldap_get_conn: Checking Id: 0
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] ldap_get_conn: Got Id: 0
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] performing search in dc=example,dc=com, with filter (mail=saman@example.com)
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] ldap_release_conn: Release Id: 0
    Thu Nov 27 21:02:48 2014 : Info: [files]  expand: (|(&(objectClass=GroupOfNames)(member=%{control:Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{control:Ldap-UserDn}))) -> (|(&(objectClass=GroupOfNames)(member=uid\3dsaman\2cou\3dstaff\2cdc\3dexample\2cdc\3dcom))(&(objectClass=GroupOfUniqueNames)(uniquemember=uid\3dsaman\2cou\3dstaff\2cdc\3dexample\2cdc\3dcom)))
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] ldap_get_conn: Checking Id: 0
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] ldap_get_conn: Got Id: 0
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] performing search in cn=test1,dc=example,dc=com, with filter (|(&(objectClass=GroupOfNames)(member=uid\3dsaman\2cou\3dstaff\2cdc\3dexample\2cdc\3dcom))(&(objectClass=GroupOfUniqueNames)(uniquemember=uid\3dsaman\2cou\3dstaff\2cdc\3dexample\2cdc\3dcom)))
    Thu Nov 27 21:02:48 2014 : Debug: rlm_ldap::ldap_groupcmp: User found in group cn=test1,dc=example,dc=com
    Thu Nov 27 21:02:48 2014 : Info: ++[files] returns ok
    
    Thu Nov 27 21:02:48 2014 : Info: [ldap] performing user authorization for saman@example.com
    Thu Nov 27 21:02:48 2014 : Info: [ldap]  expand: %{Stripped-User-Name} -> 
    Thu Nov 27 21:02:48 2014 : Info: [ldap]  ... expanding second conditional
    Thu Nov 27 21:02:48 2014 : Info: [ldap]  expand: %{User-Name} -> saman@example.com
    Thu Nov 27 21:02:48 2014 : Info: [ldap]  expand: (mail=%{%{Stripped-User-Name}:-%{User-Name}}) -> (mail=saman@example.com)
    Thu Nov 27 21:02:48 2014 : Info: [ldap]  expand: dc=example,dc=com -> dc=example,dc=com
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] ldap_get_conn: Checking Id: 0
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] ldap_get_conn: Got Id: 0
    Thu Nov 27 21:02:48 2014 : Debug:   [ldap] performing search in dc=example,dc=com, with filter (mail=saman@example.com)
    Thu Nov 27 21:02:48 2014 : Info: [ldap] No default NMAS login sequence
    Thu Nov 27 21:22:54 2014 : Info: ++[ldap] returns ok
    
    
    Thu Nov 27 21:02:48 2014 : Info: +- entering group PAP {...}
    Thu Nov 27 21:02:48 2014 : Info: [pap] login attempt with password "saman"
    Thu Nov 27 21:02:48 2014 : Info: [pap] Using MD5 encryption.
    Thu Nov 27 21:02:48 2014 : Info: [pap] Normalizing MD5-Password from base64 encoding
    Thu Nov 27 21:02:48 2014 : Info: [pap] User authenticated successfully
    Thu Nov 27 21:02:48 2014 : Info: ++[pap] returns ok
    Below two configuration files are used for implementing TLS in Radius.
  6. /etc/freeradius/eap.conf
    Generate your own CA and do self sign and also create a key pair for Radius as well.
    #Create root CA
    openssl genrsa -out ca.key 2048
    openssl genrsa -out ca.key 2048 -des3
    openssl req -x509 -new -nodes -key ca.key -days 4024 -out ca.pem
    
    #Create CSR
    openssl genrsa -des3 -out server.key 2048
    openssl req -new -key server.key -out server.csr
    
    #Sign the CSR
    openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key  -CAcreateserial -out server.crt -days 500

    Now do the configuration changes in above file (/etc/freeradius/eap.conf) as below. This certificates are used for outer EAP configurations.
     tls {
    .
    .
    certdir = ${confdir}/certs
    cadir = ${confdir}/certs
    private_key_password = saman #This was generated when server keys are generated.
    private_key_file = ${certdir}/server.key
    certificate_file = ${certdir}/server.crt
    CA_file = ${cadir}/ca.pem
    dh_file = ${certdir}/dh
    random_file = /dev/urandom 
    .
    .
    . 
    } 
  7.  /etc/freeradius/modules/inner-eap
    In here generate separate  certificates and sign using the same CA certificate used earlier. This certificates are used for inner EAP configurations.

    #Create CSR
    openssl genrsa -des3 -out server-inner.pem 2048
    openssl req -new -key server-inner.pem -out server-inner.csr
    
    #Sign the CSR
    openssl x509 -req -in server-inner.csr -CA ca.pem -CAkey ca.key  -CAcreateserial -out server-inner.crt -days 500
    Now in the configuration file ( /etc/freeradius/modules/inner-eap) do below changes.
    tls {
    .
    .
    certdir = ${confdir}/certs
    cadir = ${confdir}/certs
    private_key_password = saman #This was generated when server keys are generated.
    private_key_file = ${certdir}/server-inner.key
    certificate_file = ${certdir}/server-inner.crt
    CA_file = ${cadir}/ca.pem
    dh_file = ${certdir}/dh
    random_file = /dev/urandom 
    .
    .
    . 
    } 




Wednesday, November 12, 2014

Enable SSL in OpenLDAP

In my previous article under Install OpenLDAP on Ubuntu 14.04  topic I have explained the procedure for setting up basic LDAP server. (http://mageconfig.blogspot.com/2014/10/configure-isc-dhcp-server-with-openldap.html). Now lets enable SSL which provides the secure communication channel for LDAP clients.

Since I haven't mention the client configurations for LDAP in previous article , here I will demonstrate how to configure Ubuntu server with LDAP authentication.

Configure Ubuntu Server for LDAP Authentication

On the server install following package which provides LDAP integration.
$ sudo apt-get install libnss-ldap 
At the installation time provide the information related to the LDAP server installation correctly when prompt. If you miss something you can run below command to reconfigure it  or simply change the settings on /etc/ldap.conf file.
$ sudo dpkg-reconfigure ldap-auth-config
After that update /etc/nsswitch.conf file to inform to use LDAP for authentication.
passwd:         compat ldap
group:          compat ldap
shadow:         compat ldap
Below configuration is enough for LDAP client authentication. But if you required Linux home directory to be created if not exist on initial login, you need to add below configurations at the bottom of /etc/pam.d/common-session  file.

session required    pam_mkhomedir.so skel=/etc/skel umask=0022

Enable SSL in OpenLDAP Server

Using encrypted sessions we can secure LDAP communication.  Transport Layer Security (TLS) is used for this purpose. Recent releases of  slapd  in Ubuntu is compiled with support for GnuTLS instead of OpenSSL, there for we need to install following packages now.
$sudo apt-get install gnutls-bin
After that we need to create certificate authority(CA) for this purpose.
#certtool --generate-privkey > /etc/ssl/private/cakey.pem
After that create a template file(/etc/ssl/ca.info) to assist the creation of self-sign CA.
cn = Example Company
ca
cert_signing_key
Now sign the generated CA.
#certtool --generate-self-signed \
--load-privkey /etc/ssl/private/cakey.pem \ 
--template /etc/ssl/ca.info \
--outfile /etc/ssl/certs/cacert.pem


Now create the key for slapd and sign it using generated CA.

#certtool --generate-privkey \
--outfile /etc/ssl/private/slapd01_key.pem
Create a template file.(/etc/ssl/slapd01.info)
organization = Example
cn = ldap01.example.com
tls_www_server
encryption_key
signing_key
expiration_days = 3650
Create a certificate and sign it with previously created CA.
#certtool --generate-certificate \
--load-privkey /etc/ssl/private/slapd01_key.pem \
--load-ca-certificate /etc/ssl/certs/cacert.pem \
--load-ca-privkey /etc/ssl/private/cakey.pem \
--template /etc/ssl/slapd01.info \
--outfile /etc/ssl/certs/slapd01.pem

Once the certificate is generated , now we need to tell LDAP about the created SSL certificate, for that we  need to create a LDIF file as below. (/etc/ssl/certinfo.ldif)
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/slapd01.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/slapd01_key.pem
Now add it to the LDAP.
$sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ssl/certinfo.ldif
Also make sure to grant read access to openldap user to each of below files and locations.
$chown openldap:openldap /etc/ssl/private/cakey.pem \
/etc/ssl/private/slapd01_key.pem  /etc/ssl/certs/cacert.pem   /etc/ssl/certs/slapd01.pem 
$chown -R openldap:openldap /etc/ssl/private 
Now enable SSL in /etc/default/slapd as below and restart the slapd daemon.(add ldaps:/// entry additionally.)
SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"
/etc/init.d/slapd  restart

Now lets see how to access the secured LDAP server.

Configure DHCP server to access secured LDAP

In http://mageconfig.blogspot.com/2014/10/configure-isc-dhcp-server-with-openldap.html  post I have already configured ISC DHCP to communicate with OpenLDAP server, therefor in here I will only show the extra steps required to communicate with secured OpenLDAP server.

In the DHCP server configuration file, change as below and restart the DHCP server.
/etc/dhcp/dhcpd.conf
ldap-server                 "localhost";
ldap-port 636;
ldap-ssl ldaps;
ldap-tls-reqcert never; #Telling Not to verify certificates as we have used self sign certs
ldap-base-dn                "ou=dhcp,dc=example,dc=com";
ldap-method                 static;
ldap-debug-file             "/var/log/dhcp-ldap-startup.log";
ldap-dhcp-server-cn         "server"

Configure Ubuntu Server to Authenticate with Secured LDAP

As I have explained the procedure above I will only show you the extra configurations needed. As I have used self sign certificates in here also I will disable certificate checks.

/etc/ldap.conf

.
.
uri ldaps://IpAddressOfLDAPServer:636/
.
.
ssl on
.
.
tls_checkpeer no
.
.
 
If you want to use ldapsearch  tool  for browsing , you have to follow below steps.
vim /etc/ldap/ldap.conf
TLS_REQCERT allow #Which tells not to validate self sign certs

$ldapsearch -x  -H ldaps://ldap.example.com -b dc=example,dc=com


References:
  1. https://www.digitalocean.com/community/tutorials/how-to-authenticate-client-computers-using-ldap-on-an-ubuntu-12-04-vps
  2. https://help.ubuntu.com/community/LDAPClientAuthentication
  3. https://help.ubuntu.com/community/GnuTLS