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

  1. In the Google Admin Console, go to Apps > LDAP. Click on ADD LDAP CLIENT.

  2. Give the client a name and description.

  3. Set the following access permissions:

    • Verify user credentials: Entire domain

    • Read user information: Entire domain

    • Read group information: On

  4. Click on the ADD LDAP CLIENT button.

  5. At this point, you can download the certificate if desired, otherwise leave it for later and click CONTINUE TO CLIENT DETAILS.

  6. The next screen shows the settings for you new LDAP client. Click on the Authentication section.

  7. If you haven't already, download the certificate zip file. Extract the .crt and .key file and save them for later.

  8. Click on GENERATE NEW CREDENTIALS. Make note of the username and password. Be sure to copy the password now because it will no longer be available after closing the credential popup. Create new credentials if necessary.

  9. Keep the .crt and .key files, as well as the access credentials, for the Freeradius setup.

Installing Freeradius

  1. On an existing Ubuntu 18.04 installation, install Freeradius: sudo apt install freeradius freeradius-ldap

  2. Copy the .crt and .key files into the /etc/freeradius/3.0/certs folder. In this example, we'll rename the .crt and .key files to google.crt and google.key for simplicity:

    • sudo cp /path/to/.crt /etc/freeradius/3.0/certs/google.crt

    • sudo cp /path/to/.key /etc/freeradius/3.0/certs/google.key

  3. These are the freeradius files that need to be modified:

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

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

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

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

    • /etc/freeradius/3.0/clients.conf

    • Optional: /etc/freeradius/3.0/proxy.conf

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

Modifying Freeradius

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

In the ldap section, modify the following lines:

    • server 'ldaps://'

    • identity = username from access credentials

    • password = password from access credentials

    • base_dn = 'dc=domain,dc=com'

    • comment out the line description := "Authenticated as %S" in the section 'ldap -> post-auth -> update' so it appears as follows:

post-auth {

update {

#description := "Authenticated at %S"



In the tls section, modify the following lines:

    • start_tls = no

    • certificate_file = /etc/freeradius/3.0/certs/google.crt

    • private_key_file = /etc/freeradius/3.0/certs/google.key

    • require_cert = 'allow'

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

  1. First, create a certificate authority, then generate the server.key and server.crt files, as well as the ca.pem. The easiest way to get these files is to have freeradius generate the files. To do this, modify the .cnf files in /etc/freeradius/3.0/certs. Change the info for:

    • default_days

    • input_password

    • output_password

    • all the stuff in the [server] and [certificate_authority] sections of server.cnf, client.cnf and ca.cnf, respectively

    • Then issue the make command inside /etc/freeradius/3.0/certs/

    • Download ca.der (certificate authority) for installation on client devices.

  2. Change ownership of new files to freerad

    • sudo chown freerad:freerad /etc/freeradius/3.0/certs/*

  3. In the eap section, modify the following lines:

    • default_eap_type = ttls

  4. Enter the .key, .crt, and .pem in the tls-config tls-common section.

    • private_key_password = [whatever password you created]

    • private_key_file = /path/to/server.key

    • certificate_file = /path/to/server.crt

    • ca_file = /path/to/ca.pem

  5. Comment out the disable_tls lines:

    • #disable_tlsv1_2 = no

    • #disable_tlsv1_1 = yes

    • #disable_tlsv1 = yes

  6. Set tls_min_version and tls_max_version to your preferred version numbers.

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.


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




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

Auth-Type PAP {

# pap



**End unnecessary section**

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

# Auth-Type LDAP {


# }

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

  1. Perform the same steps as in /etc/freeradius/3.0/sites-available/default

  2. In the authorize section, uncomment filter_inner_identity. This will provide the ability to match outer/inner User-Name so that users can't offer anonymous names.

  3. In the post-auth section, uncomment the following lines to prevent Windows clients showing up as anonymous:

update outer.session-state {

User-Name := &User-Name


  1. In the post-auth section, find the block that starts with if (0) and change it to if (1) as shown below:

# 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 =

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 {

Auth-Type := domain


realm {

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]@[] [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 to 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: (VLAN 10), (VLAN 30), and (VLAN 50). 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 == "", 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 == "", Ldap-Group == "cn=group3,ou=Groups,dc=domain,dc=com"

Tunnel-Type = VLAN,

Tunnel-Medium-Type = IEEE-802,

Tunnel-Private-Group-Id = "50"

The realm == "" 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 with a password of "sh3k6cy" who is part of group1. Perform a radtest:

radtest 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 to length 115

User-Name = ""

User-Password = "sh3k6cy"

NAS-IP-Address =

NAS-Port = 0

Message-Authenticator = 0x00

Cleartext-Password = "sh3k6cy"

Received Access-Accept Id 214 from to length 36

Tunnel-Type:0 = VLAN

Tunnel-Medium-Type:0 = IEEE-802

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