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







Tuesday, October 21, 2014

Configure ISC DHCP Server with OpenLDAP


Configure ISC DHCP Server with OpenLDAP

This is my experience of configuring ISC (Internet System Consortium) DHCP  (Dynamic Host Configuration Protocol) with OpenLDAP. First lets go through each components which will be used here.

ISC DHCP Server

ISC DHCP Server is an open source software that implements the Dynamic Host Configuration Protocol in order to provide IPs and other configuration information (DNS Server , Gateway Address...) to the devices such as servers,desktops. Earlier BOOTP (Bootstrap Protocol) was  used to provide IP addresses to devices. BOOTP required manual  steps for adding configuration information on each client and also it does not have mechanisim to reclaim unused IP addresses.

Components of ISC DHCP server can be listed down as below.

  1.     DHCP Server :- server which handles the client request for configuration.
  2.     DHCP Client :- A agent which request configuration information from the DHCP server.
  3.     DHCP relay agent :- This component passes the DHCP request from one network to another which eliminate the need of having separate DHCP server per LAN.


OpenLDAP Server

OpenLDAP is a open source implementation of Lightweight Directory Access Protocol. Directory is a specialized database optimized for read access. In OpenLDAP informations are stored as entries, entries contains attributes. Attributes are consist of  type and value, typically types are uid(User ID) , mail (mail address). Values are depend on types, such as for uid: foo , for mail : foo@example.com.
Each entry is uniquely identified by using DN (Distinguished Name), as a example DN for foo  is dn: uid=foo,dc=example,dc=com. Information in OpenLDAP is arranged in tree-like hierarchical structure, this structure usually represent  organizational structures.

Further Readings

Install OpenLDAP on Ubuntu 14.04

For OpenLDAP  server and management utilities , respectively you need to install slapd and ldap-utils packages.
  $sudo apt-get install slapd ldap-utils  

During slapd installation you will be prompted for Administrator password , at this point provide some password because we will be configuring the slapd again. Onward OpenLDAP 2.3,  for the purpose of storing configuration  there is entry in the DIT (Directory Information Tree) known as cn=config. When you use this method you no need to restart the slapd server once you change the configurations, this method is also known as OLC (Online Configuration)

Futher Readings

Once installtion is finish , lets configure slapd.
  $sudo dpkg-reconfigure slapd  

When prompted provide answers as follows.

  1.     Omit OpenLDAP Server configuration :- no
  2.     DNS Doman name (this will be used to create base DN),if you provide example.com , base DN would be dc=example,dc=com , so provide this appropriately.
  3.     Organization name :- Example
  4.     Administrator password , this password will be used for the admin entry of the base  DN defined above.
  5.     Database Back-end :- HDB

For the remaining  questions go with defaults.

Verify the openLDAP installation by querying the DIT.
  $ldapsearch -x -H ldap://127.0.0.1 -b dc=example,dc=com  

Above command should show you entries in BaseDN.

 -x :-  Ignore SASL and use simple authentication
-H :- LDAP URI
-b :- base DN (search base)

Also you can check the LDAP server configurations in the DIT as below.
  $ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config"

Once OpenLDAP server is working , now we need to add groups for storing people related information. (uid,name,email...etc.). We are performing the data adding and modification using LDIF (Ldap Data Interchange Format). Now lets add groups called People and Groups.  When you are adding data , you need to provide the  Administrator password defined earlier.

addPeople.ldif

 dn: ou=People,dc=example,dc=com  
 objectClass: organizationalUnit  
 ou: People  

Add  above data to the Ldap server.

 $ ldapadd -x -H ldap://127.0.0.1 -D cn=admin,dc=example,dc=com -W -f addPeople.ldif  

-D :-  Use the given bindDN value to bind the Ldap directory.
-W :- prompt for password.
-f :- Read data from the file.

Again as above, add group called Groups  for storing groups.

addGroups.ldif

 dn: ou=Groups,dc=example,dc=com  
 objectClass: organizationalUnit  
 ou: Groups  

Once DIT is defined for storing users and groups ,lets start adding group first.

addGroupData.ldif
 dn: cn=dev,ou=Groups,dc=example,dc=com  
 objectClass: posixGroup  
 cn: dev  
 gidNumber: 5000  

  ldapadd -x -H ldap://127.0.0.1 -D cn=admin,dc=example,dc=com -W -f addGroupData.ldif  


Now lets add a user.
addUserData.ldif

 dn: uid=saman,ou=People,dc=example,dc=com  
 objectClass: inetOrgPerson  
 objectClass: posixAccount  
 objectClass: shadowAccount  
 uid: saman  
 sn: Perera  
 givenName: Saman  
 cn: Saman Perera  
 displayName: Saman Perera  
 uidNumber: 10000  
 gidNumber: 5000  
 userPassword: saman  
 gecos: Saman Perera  
 loginShell: /bin/bash  
 homeDirectory: /home/saman  

  ldapadd -x -H ldap://127.0.0.1 -D cn=admin,dc=example,dc=com -W -f addUserData.ldif   

Now you have OpenLDAP server with basic DIT which is having one group for storing groups and another is for storing users. OpenLDAP is having features for providing SSL , Replication and many other. Now lets start integrating the ISC DHCP server with OpenLDAP server.

Install ISC DHCP Server

Now let's install ISC DHCP server which can be used it's backend as LDAP.

 sudo apt-get install dhcp3-server-ldap
After DHCP package is installed , let's setup LDAP for storing DHCP configurations. First copy the LDAP schema for DHCP as below.
cd /usr/share/doc/isc-dhcp-server-ldap/;
gunzip dhcp.schema.gz
cp dhcp.schema  /etc/ldap/schema/ 
Now we need to add the above schema to the DIT, before that we need to convert it to LDIF format. For old LDAP versions which used slapd.conf instead of dynamic configuration (cn=config) copying schema file and restarting the slapd server is enough, But for newer versions (which I am using here) , we need to add the configurations to the DIT through the LDIF.

Using slaptest utility we can convert the schema file to LDIF format. First create a file called dhcp.conf  which contains following.
include /etc/ldap/schema/dhcp.schema
There after execute below commands.
mkdir /tmp/dhcp
slaptest  -f /tmp/dhcp.conf  -F /tmp/dhcp
Once LDIF file is created at /tmp/dhcp/cn\=config/cn\=schema/cn\=\{0\}dhcp.ldif , remove below unwanted lines at the bottom.
structuralObjectClass: olcSchemaConfig
entryUUID: 9bcf5d1c-ee67-1033-8cfe-8d23f897bb77
creatorsName: cn=config
createTimestamp: 20141022184725Z
entryCSN: 20141022184725.031859Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20141022184725Z
Also change below configuration at the top of LDIF
dn: cn={0}dhcp
objectClass: olcSchemaConfig
cn: {0}dhcp
To
dn: cn=dhcp,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: dhcp

Now add the LDIF to DIT.

ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /tmp/dhcp/cn\=config/cn\=schema/cn\=\{0\}dhcp.ldif
Once LDIF for DHCP is added , now we need to add data to DIT. There are 4 main components we should add to LDAP in order to have working DHCP server.
  1. DHCP Server itself need to define in top level, below the base DN (dc=example,d=com).
  2. DHCP Service
  3. DHCP Subnet definition.
  4. DHCP Host definition
Before adding  DHCP server  entries to the DIT, let's create separate tree for storing DHCP configuration as below under the baseDN.

dhcp.ldif

dn: ou=dhcp,dc=example,dc=com
ou: dhcp
objectClass: top
objectClass: organizationalUnit
description: DHCP Servers

ldapadd  -x -H ldap://localhost/ -D cn=admin,dc=example,dc=com -W -f dhcp.ldif 
Now let's add DHCP server entries.

dhcpserver.ldif
dn: cn=server,ou=dhcp,dc=example,dc=com
cn: server
objectClass: top
objectClass: dhcpServer
dhcpServiceDN: cn=config,ou=dhcp,dc=example,dc=com

ldapadd  -x -H ldap://localhost/ -D cn=admin,dc=example,dc=com -W -f dhcpserver.ldif

Now  Lets add DHCP service entries.

dhcpservice.ldif
dn: cn=config, ou=dhcp,dc=example,dc=com
cn: config
objectClass: top
objectClass: dhcpService
dhcpPrimaryDN:  cn=server,ou=dhcp,dc=example,dc=com
dhcpStatements: ddns-update-style none
dhcpStatements: get-lease-hostnames true
dhcpStatements: use-host-decl-names true

 ldapadd  -x -H ldap://localhost/ -D cn=admin,dc=example,dc=com -W -f dhcpservice.ldif 
Let's add DHCP subnet information now.

dhcpsubnet.ldif
dn: cn=192.168.1.0, cn=config, ou=dhcp,dc=example,dc=com
cn: 192.168.1.0
objectClass: top
objectClass: dhcpSubnet
objectClass: dhcpOptions
dhcpNetMask: 24
dhcpRange: 192.168.1.150 192.168.1.200
dhcpStatements: default-lease-time 600
dhcpStatements: max-lease-time 7200
dhcpOption: netbios-name-servers 192.168.1.16
dhcpOption: subnet-mask 255.255.255.0
dhcpOption: routers 192.168.1.1
dhcpOption: domain-name-servers 192.168.1.11
dhcpOption: domain-name "example.com"

 ldapadd  -x -H ldap://localhost/ -D cn=admin,dc=example,dc=com -W -f dhcpsubnet.ldif
Now lets add a Host entry which bind Mac to Ip.

host.ldif
dn: cn=client01, cn=config, ou=dhcp,dc=example,dc=com
cn: client01
objectClass: top
objectClass: dhcpHost
dhcpHWAddress: ethernet 00:16:3e:3d:eb:87
dhcpStatements: fixed-address 192.168.1.111

ldapadd  -x -H ldap://localhost/ -D cn=admin,dc=example,dc=com -W -f host.ldif



Finally you need to configure DHCP server to communicate OpenLDAP for getting configuration
/etc/dhcp/dhcpd.conf
ldap-server                 "localhost";
ldap-port                   389;
# We do an anonymous bind
# ldap-username             "cn=directorymanagerloginname";
# ldap-password             "mypassword";
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"

Before starting DHCP server follow below steps too. Make sure to shut down slapd daemon.
/etc/init.d/slapd stop

vim /etc/ldap/slapd.d/cn\=config/olcDatabase\=\{1\}hdb.ldif , add below lines after the line with "olcDbIndex: objectClass eq"  for missing indexes. After that run the "slapindex" for reindexing and start the slapd daemon.
(http://muzso.hu/2010/04/26/fixing-bdb_equality_candidates-errors-on-your-openldap-server)

olcDbIndex: cn eq
olcDbIndex: gidNumber eq
olcDbIndex: memberUid eq
olcDbIndex: uid eq
olcDbIndex: uidNumber eq
olcDbIndex: uniqueMember eq
sudo -u openldap slapindex -F /etc/ldap/slapd.d/
etc/init.d/slapd start
Finally restart the DHCP server and now it should be ready to server with basic configurations.
 /etc/init.d/isc-dhcp-server restart

Current dynamic leases are stored in below file.
 /var/lib/dhcp/dhcpd.leases
Steps need to follow in order to configure ISC DHCP server with secured OpenLDAP can be find at http://mageconfig.blogspot.com/2014/11/enable-ssl-in-openldap.html


References 

  • https://tools.ietf.org/html/draft-ietf-dhc-ldap-schema-00
  • http://wiki.herzbube.ch/index.php/ISCDHCP#Converting_dhcpd.conf_to_LDIF









Saturday, June 7, 2014

Configure GIT/GERRIT with OPEN LDAP for Code Review Process

This post is about setting up and configuring GIT/Gerrit  which is authenticated by LDAP backend for code review process.

GIT

Git is a distributed version control system which is open source. And this is based on many branches and merges.

Gerrit

Gerrit is a another open source product which can manage Git repositories. This provides authentication,  authorization management for Git projects and most importantly code review facility.

LDAP

For the purpose of authenticating users for the Gerrit, OpenLdap is used. This provides means for  centrally managing all developers and reviwers.

Setting Up Gerrit.

As for the  server environment , Ubuntu 12.04 is used and for the JRE , version  1.7_10 is used.



  1. Create gerrit user and group. 

    # adduser git (This will add both user/group)
  2. Install Git

    # apt-get install git-core
  3. Get the Gerrit and configure as gerrit user.

    # su - gerrit (Switch to the user gerrit)

    $ wget http://gerrit-releases.storage.googleapis.com/gerrit-2.8.5.war (Stable by this time)


    Create required Mysql database and grant the privileges. At the installation provide the correct DB and User/Password information.


    mysql>create database reviewdb;
    mysql> grant all privileges on reviewdb.* to 'gerrit'@'localhost' identified by 'gerrit';

    Database -> reviewdb
    User -> gerrit
    Password -> gerrit

    $java -jar gerrit*.war init -d review_site (Install Gerrit , and it will ask questions o the process such as DB to use , SMTP server ...etc)

     After the installation is over you can find Gerrit configuration file at "/home/gerrit/review_site/etc/gerrit.config"

    Following is My content. (/home/gerrit/review_site/etc/gerrit.config).

     [gerrit]  
         basePath = git  
         canonicalWebUrl = http://gitserver:8080/  
     [database]  
         type = mysql  
         hostname = localhost  
         database = reviewdb  
         username = gerrit  
     [auth]  
         type = ldap  
     [ldap]  
       server = ldap://ldapserverr  
       accountBase = ou=people,dc=domain,dc=com  
       groupBase = ou=groups,dc=domain,dc=com  
       referral = follow  
       accountPattern = (uid=${username})  
       groupPattern = (cn=${groupname})  
       accountFullName = cn  
       accountMemberField = memberOf  
       accountEmailAddress = mail  
     [sendemail]  
         smtpServer = SMTP server  
         smtpUser = gerrit  
     [container]  
         user = gerrit  
         javaHome = /opt/java/jdk  
     [sshd]  
         listenAddress = *:29418  
     [httpd]  
         listenUrl = http://*:8080/  
     [cache]  
         directory = cache  
  4. Once the configurations are correctly configured you can start the Gerrit  and access (http://gitserver:8080/) to it for further  configurations such ah creating projects,groups and to setup ACLs.

    $cd /home/gerrit/review_site/bin/;./gerrit.sh  start (As gerrit user)

    First Login, just after the installation  to the Gerrit system, will get the Admin rights.

    Once you logged in you can create groups for developers and for reviewers, In my set up I have restricted direct  code push to the GIT for developers , instead they have to go through code review process. In Gerrt there is a reference mapping called ref/for/BRANCH NAME , which is used as staging area for code review and push to this mapping will not causes to code to get merge with the branch. Once developer push the commit , reviewer must review and push the commit to the branch. Below diagram shows the Gerrit code review process.



    (REF - https://review.openstack.org/Documentation/intro-quick.html#_creating_the_review)

    Following is the ACL I have used  for the created  Git project and from the All-Projects ACL I have removed all privileges except Administrator privileges  globally  to  create fine grained access control per project.


    On above ACL I have restricted Push rights only on  reference map refs/for/* for developer group which forces developers to perform the code review. Also review group members must add the required project to the watched project list to receive emails on review request as below.


  5. On client machine you need to install following packages and setup remote branch for gerrit review process.

    $apt-get install git-core git-review

    After package installation completed , login to the Gerrit server to add SSH public key for accessing the repository.

    Generate the keys if not available

    $ssh-keygen -C  user@example.com

    (This email address should match with the email address on Gerrit account., in this scenario this email address should be set to the users's LDAP account). After that get the key and add it as below. On Gerrit below the user name (right side upper corner) click and go to the Settings section, there go to the SSH Public Key section.




    Once key is added  clone of the repository first , you can find the clone URL from the Gerrit server once you logged in.




    $git clone ssh://username@gitserver:29418/testProject

    Get the remote repository URLs.

    $git remote -v
    origin ssh://username@gitserver:29418/testProject (fetch)
    origin ssh://username@gitserver:29418/testProject (push)

    Add the gerrit alias to the remote repository which return from the above command. (This alias is used by the git review command to create review request)

    $git  remote  add gerrit ssh://username@gitserver:29418/testProject

    Now client environment is ready for code review process. Following is the list of command.

    Add file a file to the repository.

    $git add

    Commit the file to the local branch.

    $git commit -m "Commit message"

    Request a code review before the merge happen.

    $git review

    Once client execute this command , reviewer get the review request and after the approval , code will get merged with the branch.





Sunday, February 3, 2013

Convert tcpflow out put to syslog format for analysis

Convert tcpflow out put to syslog format for analysis


Following is the set of script i used to convert tcpflow out put in to syslog format

#Main script

------------------------------------------------------------------------------------------------------------

#monitor.sh

#!/bin/bash

#
#This script will start tcpflow and construct syslog like log from the out put of tcpflow for analysis
#

RUN_CMD=/usr/local/bin/tcpflow
OUTPUT_DIR=raw_data
LOG_DIR=logs
INTERFACE=eth0

${RUN_CMD} -i ${INTERFACE}  dst port 80 -p -o ${OUTPUT_DIR} > /dev/null 2>&1 &


#Start watch log in background

cd bin;./watch_logs.sh ${OUTPUT_DIR} > /dev/null 2>&1 &

#start raw data delete process

./delete_raw_data.sh > /dev/null 2>&1 &


------------------------------------------------------------------------------------------------------------
#watch_logs.sh
#For this i have use i  apt-get install inotify-tools  to monitor new file creation

#!/bin/sh

RAW_DATA_PATH="../$1"
       while inotifywait --exclude ~*.xml  --format %f   -e create ${RAW_DATA_PATH} | xargs perl create_log.pl ; do
         #if tail -n1 /var/log/messages | grep httpd; then
         #  kdialog --msgbox "Apache needs love!"
         #fi
echo "Log file created" > /dev/null
       done
-----------------------------------------------------------------------------------------------------------
#create_log.pl
#Log path is /tmp/tcpflow.log

#!/usr/bin/perl -w

use POSIX qw/strftime/;

$TCPFLOWFILE_NAME=$ARGV[0];
$TCPFLOWFILE_DIR="../raw_data";
$TCPFLOWFILE_PATH="$TCPFLOWFILE_DIR/$TCPFLOWFILE_NAME";
#Time format Jan  4 12:39:01
$TIME = strftime('%b %d %T',localtime);
$SERVER="titan580";
$PROGRAM="tcpflow";
$LOGFILE="/tmp/cpflow.log";
#-------------------------------------------------
#Get ip address(src and dst)
$TCPFLOWFILE_NAME =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.\d{0,}-(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/;


sub trim_zeros {

$ip_seg = $_[0];
#print "$ip_seg \n";

if ( $ip_seg =~ /0{3}/ ){
$ip_seg = 0;
return $ip_seg;
}else{
$ip_seg =~ s/^0+//;
return $ip_seg;

}

}


#Construct ip address
$srcip1 = trim_zeros $1;
$srcip2 = trim_zeros $2;
$srcip3 = trim_zeros $3;
$srcip4 = trim_zeros $4;
$dstip1 = trim_zeros $5;
$dstip2 = trim_zeros $6;
$dstip3 = trim_zeros $7;
$dstip4 = trim_zeros $8;


$srcip="$srcip1.$srcip2.$srcip3.$srcip4";
$dstip="$dstip1.$dstip2.$dstip3.$dstip4";




#print $TCPFLOWFILE_PATH;

open(TCPFLOWFILE_PATH) or die("Could not open tcpflow  file.");
foreach $line () {

open  LOGFILE_FH, ">>/tmp/tcpflow.log";

    # do line-by-line processing.
if ($line =~ /^\s*$/) {
#open(LOGFILE_FH,'>>LOGFILE') || die("Cannot Open Log File");
print LOGFILE_FH "\n";

}else{
$line =~ s/\n//;
$TCPFLOW="$TIME $SERVER $PROGRAM: $srcip->$dstip:$line";
#print $TCPFLOW;
#open(LOGAPPEND,">>LOGFILE") || die("Cannot Open Log File");
print LOGFILE_FH "$TCPFLOW";

}
close(LOGFILE_FH);

}
close(TCPFLOWFILE_PATH);
#Remove log file
#unlink $TCPFLOWFILE_PATH;


---------------------------------------------------------------------------------------------------
#Log deleting process
#delete_raw_data.sh

#!/bin/bash


#
#This script will  delete created tcp data file which are older than given time
#


EXPIRE_TIME=3 #Time in minutes which log file expire
ROTATION_TIME=3  #Time in minutes wait before next check
FIND=/usr/bin/find
RM=/bin/rm
RAW_DATA_DIR="../raw_data"



while [ 1 -ne 0 ]
do
${FIND} ${RAW_DATA_DIR}  -mmin +${EXPIRE_TIME} -exec ${RM} -rf {} \;

sleep ${ROTATION_TIME}
done



--------------------------------------------------------------------------------------------------


Detect malicious PHP shells and quarantine them on Shared Server


Detect malicious PHP shells and quarantine them on Shared Server

Here i have use perl code from  http://ketan.lithiumfox.com/doku.php/phpshell_scanner  to detect malicious php shells and i have written shell script to do further processing after the bad shell is found.

-----------------------------------------------------------------------------------------------------------
# ./execute_findshell.sh

#!/bin/bash

ECHO=/bin/echo
TIME=`/bin/date`
MAIL=/usr/bin/mail
MV=/bin/mv
Quarantine_Dir=/tmp #Directory where quarantine file goes to
WEB_ROOT=/var/www #Web root to watch for changes
LOG=badshell.log
FIND=/usr/bin/find
GREP=/bin/grep
AWK=/usr/bin/awk
LS=/bin/ls
CAT=/bin/cat
SORT=/usr/bin/sort
FILE_INDEX=file_index
TMP_FILE_INDEX=tmp_file_index
CHANGES_IN_INDEX=changes_in_index
MD5_SUM=/usr/bin/md5sum
WC=/usr/bin/wc
DIFF=/usr/bin/diff
TR=/usr/bin/tr

#Execute file checker on shared hosting server on file changes using their checksum values
#*/1 * * * * cd /home/user/scripts; ./execute_findshell.sh > /dev/null 2>&1 

#
#Php shell finder-----
#

check_for_php_shells(){

FILE_NAME=$1
FINDSHELL_OUTPUT=`perl findshell.pl  10 ${FILE_NAME}`

#echo "${FILE_NAME}"

if [ "${FINDSHELL_OUTPUT}" ];then
echo "bad shell found\n"
echo "${FINDSHELL_OUTPUT}" 
${MV} ${FILE_NAME} ${Quarantine_Dir}
${ECHO} "Possible Backdoor Found,and Quarantined. Please Verify...${FINDSHELL_OUTPUT} -  ${TIME} " | ${MAIL} -s 'Possible Back door Found On  Server'  email@address.com
else
echo "bad shell not found \n"
fi


}


#----------------------

#Build file index
NO_OF_FILES=`${FIND} ${WEB_ROOT}  -type f  |${WC} -l`
if [ -f "${FILE_INDEX}" ];then
#if File exist, check for new entrie
#Create tmp file index and compare
${FIND}  ${WEB_ROOT} -type f -exec ${MD5_SUM} {} \; > ${TMP_FILE_INDEX}

${DIFF} ${TMP_FILE_INDEX} ${FILE_INDEX} > ${CHANGES_IN_INDEX}
if [ -s "${CHANGES_IN_INDEX}" ];then
echo "integrity changed \n"
CHANGES_IN_INDEX_ARRAY=(`${CAT} ${CHANGES_IN_INDEX} |${AWK} {'print $3'}| ${GREP} -P '(\/\w+\/.*)' | ${SORT} -u | ${TR} '\n' ' '`)

#Going through changes files
for i in "${CHANGES_IN_INDEX_ARRAY[@]}"
do
check_for_php_shells $i
done
else
echo "no changes found\n"
fi

else
#create file index
${FIND}  ${WEB_ROOT} -type f -exec ${MD5_SUM} {} \; > ${FILE_INDEX}
fi

-----------------------------------------------------------------------------------------------------------
#Perl code
#findshell.pl  

http://ketan.lithiumfox.com/doku.php/phpshell_scanner

------------------------------------------------------------------------------------------------------------

How to use Portsentry with notifications and Iptable firewall rule expiraton

How to use Portsentry with notifications and Iptable  firewall rule expiration


Following is the how i use Portsentry  to block port scan activities.

By default Portsentry detect and block given ip/ports, but it will not expire the Iptable rules after given time,here i have a script written to do that job as well.


#Port Sentry On ubuntu 12.04
apt-get install portsentry


#I use the following config entries for my setup

#######################Start of Config file  entries################################
#######################
# Port Configurations #
#######################
#Under the Port Configurations first set is enabled.[comprehensive set]
TCP_PORTS="1,7,9,11,15,70,79,80,109,110,111,119,138,139,143,512,513,514,515,540,635,1080,1524,2000,2001,4000,4001,5742,6000,6001,6667,12345,12346,20034,27665,30303,32771,32772,32773,32774,31337,40421,40425,49724,54320"
UDP_PORTS="1,7,9,66,67,68,69,111,137,138,161,162,474,513,517,518,635,640,641,666,700,2049,31335,27444,34555,32770,32771,32772,32773,32774,31337,54321"

##################
# Ignore Options #
##################

BLOCK_UDP="1"
BLOCK_TCP="1"



###################
# Dropping Routes:#
###################

KILL_ROUTE="/sbin/iptables -I INPUT -s $TARGET$ -j DROP"



###################
# External Command#
###################
KILL_RUN_CMD_FIRST = "0"
#
#
KILL_RUN_CMD="/etc/portsentry/scripts/notify.sh $TARGET$ $PORT$ $MODE$"

#This script will notify when port scan trigger



#####################
# Scan trigger value#
#####################

SCAN_TRIGGER="2"

#######################End of Config file entries ################################


Below are the scripts used for Portsentry



#----------------------------------Notification script-----------------------------------------------------
##/etc/portsentry/scripts/notify.sh


#!/bin/bash


TARGET=$1
PORT=$2
MODE=$3


echo "Attack reported-${TARGET}- ${PORT} - ${MODE}" | mail -s 'Unauthorized Port scan  Alert'  email@address.com



------------------------------------------------------------------------------------------------------------


-----------Firewall rules expiration script------------------------------------------------------------------
#delete_fw_entries.sh
#This script is running as cronjob every 5 minutes



#!/bin/bash


BLOCKED_LIST_TCP="/var/lib/portsentry/portsentry.blocked.tcp"
BLOCKED_LIST_UDP="/var/lib/portsentry/portsentry.blocked.udp"
ECHO=/bin/echo
TOUCH=/usr/bin/touch
CAT=/bin/cat
AWK=/usr/bin/awk
DATE=/bin/date
EXPR=/usr/bin/expr
FW_EXPIRE_TIME=10 #Iptable rule expiration time in minutes
TR=/usr/bin/tr
CUT=/usr/bin/cut
IPTABLE=/sbin/iptables
SED=/bin/sed
#
#DO NOT CHANGE BELOW THIS LINE--------------------------------------------
#

get_time_diff() {

BLOCKED_TIME=$1

CURRENT_TIME=`${DATE} +%s`
TIME_DIFF_IN_SEC=`${EXPR} ${CURRENT_TIME} - ${BLOCKED_TIME}`
TIME_DIFF_IN_MIN=`${EXPR} ${TIME_DIFF_IN_SEC} / 60`


}



#Get the blocked list entries for processing



BLOCKED_LIST_TCP_ARRAY=(`${CAT} ${BLOCKED_LIST_TCP} | ${TR} -d " " |${TR} '\n' ' '  `)
BLOCKED_LIST_UDP_ARRAY=(`${CAT} ${BLOCKED_LIST_UDP} | ${TR} -d " " | ${TR} '\n' ' ' `)

#TCP

for i in "${BLOCKED_LIST_TCP_ARRAY[@]}"
do
BLOCKED_IP=`${ECHO} $i |${CUT} -d ":" -f4|${CUT} -d "/" -f1`
BLOCKED_TIME=`${ECHO} $i | ${CUT} -d "-" -f1`

get_time_diff ${BLOCKED_TIME}
echo "time$TIME_DIFF_IN_MIN"

echo "ip - ${BLOCKED_IP}"
if [ "${TIME_DIFF_IN_MIN}" -ge ${FW_EXPIRE_TIME} ];then
        echo "need to flush"
${IPTABLE} -D INPUT -s ${BLOCKED_IP} -j DROP
#remove entry from block lidt file
${SED} -i "/${BLOCKED_TIME}/d" ${BLOCKED_LIST_TCP}
else

        echo "wait and see"
fi




done

#UDP

for i in "${BLOCKED_LIST_UDP_ARRAY[@]}"
do    
BLOCKED_IP=`${ECHO} $i |${CUT} -d ":" -f4|${CUT} -d "/" -f1`
BLOCKED_TIME=`${ECHO} $i | ${CUT} -d "-" -f1`

get_time_diff ${BLOCKED_TIME}
echo "time$TIME_DIFF_IN_MIN"

        echo "ip - ${BLOCKED_IP}"
if [ "${TIME_DIFF_IN_MIN}" -ge ${FW_EXPIRE_TIME} ];then
        echo "need to flush"
${IPTABLE} -D INPUT -s ${BLOCKED_IP} -j DROP
#remove entry from block lidt file
                ${SED} -i "/${BLOCKED_TIME}/d" ${BLOCKED_LIST_UDP}


else

        echo "wait and see"
fi


done






------------------------------------------------------------------------------------------------------------


REF:-http://www.symantec.com/connect/articles/portsentry-attack-detection-part-one
REF:-http://www.symantec.com/connect/articles/portsentry-attack-detection-part-two