Freeradius, Dynamic VLANs, and Google LDAP

This tutorial is based on Ubuntu 18.04. Here, we will install FreeRadius and connect it to Google Workspace Secure LDAP. Then, we will assign VLANs to users based on their groupings in Google Workspace.

Google Workspace Secure LDAP Setup

 Installing Freeradius

Modifying Freeradius

Editing /etc/freeradius/3.0/mods-available/ldap

In the ldap section, modify the following lines:

post-auth {

    update {

       #description := "Authenticated at %S"

    }

}

In the tls section, modify the following lines:

Save and exit the file. Next, symlink the file to mods-enabled:

sudo ln -s /etc/freeradius/3.0/mods-available/ldap /etc/freeradius/3.0/mods-enabled/ldap

Editing /etc/freeradius/3.0/mods-available/eap

Editing /etc/freeradius/3.0/sites-available/default

In the authorize section, enable LDAP by removing the "-" sign before it so it looks like:

#

# The ldap module reads passwords from the LDAP database.

ldap

In the authorize section, before the password authentication protocol (PAP) statement, add an if statement so it looks like:

#  This module should be listed last, so that the other modules

#  get a chance to set Auth-Type for themselves.

#


if (User-Password ) {

update control {

Auth-Type := ldap

}

}


pap

**This section is no longer necessary.** In the authenticate section, modify the Auth-Type PAP block as follows:

Auth-Type PAP {

#  pap

   ldap

}

**End unnecessary section**

In the authenticate section, modify the Auth-Type LDAP block as follows:

# Auth-Type LDAP {

    ldap

# }

Editing /etc/freeradius/3.0/sites-available/inner-tunnel

update outer.session-state {

       User-Name := &User-Name

}

 #  Instead of "use_tunneled_reply", change this "if (0)" to an

 #  "if (1)".

 #

 if (1) {

  #

  #  These attributes are for the inner-tunnel only,

  #  and MUST NOT be copied to the outer reply.

  #

  update reply {

   User-Name !* ANY

   Message-Authenticator !* ANY

   EAP-Message !* ANY

   Proxy-State !* ANY

   MS-MPPE-Encryption-Types !* ANY

   MS-MPPE-Encryption-Policy !* ANY

   MS-MPPE-Send-Key !* ANY

   MS-MPPE-Recv-Key !* ANY

  }


  #

  #  Copy the inner reply attributes to the outer

  #  session-state list.  The post-auth policy will take

  #  care of copying the outer session-state list to the

  #  outer reply.

  #

  update {

   &outer.session-state: += &reply:

  }

 }

Editing /etc/freeradius/3.0/clients.conf

Add the following block to have the freeradius server accept requests from your lan. Modify the client name, IP block, and secret.

client mylan {

  ipaddr  = 192.168.0.0/24

  secret  = [your radius secret]

}

Editing /etc/freeradius/3.0/proxy.conf

Optional: This is a useful setting if you want your RADIUS server to serve multiple domains or subdomains. Create a realm, then point it at the specific Auth-Type which controls that realm. Alternatively, this can use used to require users to type in their full email address as their username. An example is shown below.

realm domain.com {

     Auth-Type := domain

}


realm subdomain.domain.com {

     Auth-Type := subdomain

}

At this point, we have made the necessary modifications to use Freeradius with Google Workspace Secure LDAP. Restart Freeradius:

sudo systemctl restart freeradius

Test a user:

radtest [username]@[domain.com] [userpassword] localhost 0 testing 123

If everything is set up correctly, you should receive the following response from freeradius:

Received Access-Accept Id 68 from 127.0.0.1:1812 to 0.0.0.0:0 length 20

Editing /etc/freeradius/3.0/mods-config/files/authorize

This file is used to attach VLAN information to the user account based on certain criteria. This first example will assign a specific VLAN ID to all users who have an organizational account. This is useful if you don't need to separate users from each other based on user type:

DEFAULT Ldap-UserDN := "uid=%{User-Name},ou=Users,dc=domain,dc=com"

        Tunnel-Type = VLAN,

        Tunnel-Medium-Type = IEEE-802,

        Tunnel-Private-Group-Id = "100"

The following set of modifications makes the assumption that you have groups created in Google Workspace and the users are in the group individually, not using shortcut entries such as "All users in the organization". In the following example, there are 3 groups with their respective group email addresses: group1@domain.com (VLAN 10), group2@domain.com (VLAN 30),  and group3@domain.com (VLAN 50). A catch-all entry is shown at the end to place users that are not otherwise assigned to a group. Place this block of code at the top of /etc/freeradius/3.0/mods-config/files/authorize.

DEFAULT Ldap-Group == "cn=group1,ou=Groups,dc=domain,dc=com"

        Tunnel-Type = VLAN,

        Tunnel-Medium-Type = IEEE-802,

        Tunnel-Private-Group-Id = "10"


DEFAULT realm == "domain.com", Ldap-Group == "cn=group2,ou=Groups,dc=domain,dc=com"

        Tunnel-Type = VLAN,

        Tunnel-Medium-Type = IEEE-802,

        Tunnel-Private-Group-Id = "30"


DEFAULT realm == "domain.com", Ldap-Group == "cn=group3,ou=Groups,dc=domain,dc=com"

        Tunnel-Type = VLAN,

        Tunnel-Medium-Type = IEEE-802,

        Tunnel-Private-Group-Id = "50"


DEFAULT Ldap-UserDN := "uid=%{User-Name},ou=Users,dc=domain,dc=com"

        Tunnel-Type = VLAN,

        Tunnel-Medium-Type = IEEE-802,

        Tunnel-Private-Group-Id = "50"

The realm == "domain.com" portion above is optional and is useful for multiple domains or for requiring users to type their entire email address as their username. If you modified proxy.conf, you should consider matching the realms here.

Save the file, then restart freeradius:

sudo systemctl restart freeradius

Let's assume we have an account of testuser@domain.com with a password of "sh3k6cy" who is part of group1. Perform a radtest:

radtest testuser@domain.com sh3k6cy localhost 0 testing123

The radtest should produce the following result showing Access-Accept and the Tunnel-Private-Group-ID, which is the VLAN assignment for the user:

Sent Access-Request Id 214 from 0.0.0.0:40001 to 127.0.0.1:1812 length 115

  User-Name = "testuser@domain.com"

  User-Password = "sh3k6cy"

  NAS-IP-Address = 127.0.1.1

  NAS-Port = 0

  Message-Authenticator = 0x00

  Cleartext-Password = "sh3k6cy"

Received Access-Accept Id 214 from 127.0.0.1:1812 to 0.0.0.0:0 length 36

  Tunnel-Type:0 = VLAN

  Tunnel-Medium-Type:0 = IEEE-802

  Tunnel-Private-Group-Id:0 = "10"