MAC Address Authentication
Introduction
In this guide, we will quickly explain what MAC Address Authentication is and give an example implementing it.
NOTE: Topics covered in this guide are introduced in IEEE 802.1x (Port Based Authentication)
MAC Address Authentication allows administrators to limit who can and cannot connect to a network by allowing or denying devices by their MAC address. In this guide, we will be using a RADIUS Server and an Authenticator to validate a device attempting to access a network based on their MAC Address.
Enabling MAC Address Authentication
Most NASes send the MAC address in the Calling-Station-ID attribute.
To support MAC Address Authentication, a few additions are needed:
1). Since there are several standard formats depending on the NAS, the following policy is available in FreeRADIUS version 3 and onwards at freeradius/3.0/policy.d/canonicalization
to reformat MAC Addresses under the same style. If this is not included, add the following to the defined location.
#
# Rewrite called station id attribute into a standard format.
#
rewrite_calling_station_id {
if (Calling-Station-Id =~ /([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:.]?([0-9a-f]{2})[-:]?([0-9a-f]{2})[-:.]?([0-9a-f]{2})[-:]?([0-9a-f]{2})/i) {
update request {
Calling-Station-Id := "%{tolower:%{1}-%{2}-%{3}-%{4}-%{5}-%{6}}"
}
}
else {
noop
}
}
2). Next in the freeradius/3.0/mods-available/files
create a new instance of the files module to read a new file of permitted MAC addresses as shown below:
files {
[...]
}
files authorized_macs {
# The default key attribute to use for matches. The content
# of this attribute is used to match the "name" of the
# entry.
key = "%{Calling-Station-ID}"
usersfile = ${confdir}/authorized_macs
# If you want to use the old Cistron 'users' file
# with FreeRADIUS, you should change the next line
# to 'compat = cistron'. You can copy your 'users'
# file from Cistron.
# compat = no
}
3). Finally, create a list of permitted MAC addresses titled freeradius/3.0/authorized_macs
, to be read by the new files instance. An example is shown below:
0c:2d:83:56:00:01
Reply-Message = "Device with MAC Address %{Calling-Station-Id} authorized for network access"
0d:4f:83:21:00:01
Reply-Message = "Device with MAC Address %{Calling-Station-Id} authorized for network access"
[...]
Example Configuration
Consider the following topology:
MAC Address Authentication
To check only if a device exists in the authorized MAC Address list, edit the authorize section in freeradius/3.0/sites-available/default
to call only the canonicalization policy and new files module:
authorize {
preprocess
# If cleaning up the Calling-Station-Id...
rewrite_calling_station_id
# Now check against the authorized_macs file
authorized_macs
if (!ok) {
# No match was found, so reject
reject
}
else {
# The MAC address was found, so update Auth-Type
# to accept this auth.
update control {
Auth-Type := Accept
}
}
}
Example:
After adding the MAC Address 0C:2D:83:56:00:1 to the authorized_macs list.
root@localhost:/etc/freeradius/3.0/sites-available# freeradius -X
[...]
(0) authorized_macs: EXPAND %{Calling-Station-ID}
(0) authorized_macs: --> 0C-2D-83-56-00-01
(0) authorized_macs: users: Matched entry 0C-2D-83-56-00-01 at line 1
(0) authorized_macs: EXPAND Device with MAC Address %{Calling-Station-Id} authorized for network access
(0) authorized_macs: --> Device with MAC Address 0C-2D-83-56-00-01 authorized for network access
(0) [authorized_macs] = ok
[...]
(0) Sent Access-Accept Id 26 from 192.168.1.3:1812 to 192.168.1.2:60013 length 95
(0) Reply-Message = "Device with MAC Address 0C-2D-83-56-00-01 authorized for network access"
(0) Finished request
[...]
NOTE: The above was tested on a virtual machine
MAC Address or 802.1x Authentication
The following configuration in freeradius/3.0/sites-available/default
will approve requests with either 802.1x Authentication or MAC Address Authentication.
- If 802.1x is not configured, the MAC Address of the Supplicant must be known.
- If 802.1x is configured, as long as valid credentials are presented, the Supplicants may access the network.
authorize {
preprocess
# If cleaning up the Calling-Station-Id...
rewrite_calling_station_id
# If this is NOT 802.1x, assume mac-auth. We check this by testing
# for the presence of the EAP message attribute in the request.
if (!EAP-Message) {
# Now check against the authorized_macs file
authorized_macs
if (!ok) {
reject
}
else {
# accept
update control {
Auth-Type := Accept
}
}
}
else {
# Normal FreeRADIUS virtual server config goes here e.g.
eap
}
}
Example:
After adding the MAC Address 0C:2D:83:56:00:1 to the authorized_macs list.
root@localhost:/etc/freeradius/3.0/sites-available# freeradius -X
[...]
authorized_macs: EXPAND %{Calling-Station-ID}
(2) authorized_macs: --> 0C-2D-83-56-00-01
(2) authorized_macs: users: Matched entry 0C-2D-83-56-00-01 at line 1
(2) authorized_macs: EXPAND Device with MAC Address %{Calling-Station-Id} authorized for network access
(2) authorized_macs: --> Device with MAC Address 0C-2D-83-56-00-01 authorized for network access
[...]
(11) Sent Access-Accept Id 44 from 192.168.1.3:1812 to 192.168.1.2:51656 length 177
(11) MS-MPPE-Recv-Key = 0x817d9c1889907d69989d5913864df31d3a3307813a6fd0276408523954e41b77
(11) MS-MPPE-Send-Key = 0x4ea7540a5847b49090a934053c8480587f1c07f2b24147da4d40b921f8c40269
(11) EAP-Message = 0x032d0004
(11) Message-Authenticator = 0x00000000000000000000000000000000
(11) User-Name = "anonymous"
(11) Framed-MTU += 994
(11) Finished request
[...]
NOTE: The above was tested on a virtual machine
Example:
After omitting the MAC Address 0C:2D:83:56:00:1 to the authorized_macs list and running 802.1X Authentication with EAP.
root@localhost:/etc/freeradius/3.0/sites-available# freeradius -X
[...]
(5) files: users: Matched entry Supplicant at line 3
(5) [files] = ok
(5) [expiration] = noop
(5) [logintime] = noop
(5) [pap] = updated
(5) } # authorize = updated
(5) Found Auth-Type = PAP
(5) # Executing group from file /etc/freeradius/sites-enabled/inner-tunnel
(5) Auth-Type PAP {
(5) pap: Login attempt with password
(5) pap: Comparing with "known good" Cleartext-Password
(5) pap: User authenticated successfully
(5) [pap] = ok
(5) } # Auth-Type PAP = ok
[...]
(5) Sent Access-Accept Id 39 from 192.168.1.3:1812 to 192.168.1.2:60013 length 177
(5) MS-MPPE-Recv-Key = 0x2ba733ea28be8611d63f4e05ccd677eaf5a1d693657165a54d6b4c8e462912a9
(5) MS-MPPE-Send-Key = 0xd66afec3f863ffe6c9d8ad0154f88e8130248461afa6d3a27d7d1f1c04713990
(5) EAP-Message = 0x038a0004
(5) Message-Authenticator = 0x00000000000000000000000000000000
(5) User-Name = "anonymous"
(5) Framed-MTU += 994
(5) Finished request
[...]
NOTE: The above was tested on a virtual machine
MAC Address and 802.1x Authentication
The following configuration in freeradius/3.0/sites-available/default
will combine both 802.1x Authentication and MAC Address Authentication.
- If 802.1x is not configured, the MAC Address of the Supplicant must be known.
- If 802.1x is configured, valid credentials and an accepted MAC Address must be present to access the network.
authorize {
preprocess
# If cleaning up the Calling-Station-Id...
rewrite_calling_station_id
# always check against the authorized_macs file first
authorized_macs
if (!ok) {
# Reject if the MAC address was not permitted.
reject
}
# If this is NOT 802.1x, mac-auth
if (!EAP-Message) {
# MAC address has already been checked, so accept
update control {
Auth-Type := Accept
}
}
else {
# Normal FreeRADIUS virtual server config goes here e.g.
eap
}
}
Example:
After adding the MAC address 0C:2D:83:56:00:1 to the authorized_macs list and running 802.1X Authentication with EAP.
root@localhost:/etc/freeradius/3.0/sites-available# freeradius -X
[...]
authorized_macs: EXPAND %{Calling-Station-ID}
(2) authorized_macs: --> 0C-2D-83-56-00-01
(2) authorized_macs: users: Matched entry 0C-2D-83-56-00-01 at line 1
(2) authorized_macs: EXPAND Device with MAC Address %{Calling-Station-Id} authorized for network access
(2) authorized_macs: --> Device with MAC Address 0C-2D-83-56-00-01 authorized for network access
[...]
files: users: Matched entry Supplicant at line 3
(5) [files] = ok
(5) [expiration] = noop
(5) [logintime] = noop
(5) [pap] = updated
(5) } # authorize = updated
(5) Found Auth-Type = PAP
(5) # Executing group from file /etc/freeradius/3.0/sites-enabled/inner-tunnel
(5) Auth-Type PAP {
(5) pap: Login attempt with password
(5) pap: Comparing with "known good" Cleartext-Password
(5) pap: User authenticated successfully
(5) [pap] = ok
(5) } # Auth-Type PAP = ok
[...]
(11) Sent Access-Accept Id 44 from 192.168.1.3:1812 to 192.168.1.2:51656 length 177
(11) MS-MPPE-Recv-Key = 0x817d9c1889907d69989d5913864df31d3a3307813a6fd0276408523954e41b77
(11) MS-MPPE-Send-Key = 0x4ea7540a5847b49090a934053c8480587f1c07f2b24147da4d40b921f8c40269
(11) EAP-Message = 0x032d0004
(11) Message-Authenticator = 0x00000000000000000000000000000000
(11) User-Name = "anonymous"
(11) Framed-MTU += 994
(11) Finished request
[...]
NOTE: The above was tested on a virtual machine
Example:
After omitting the authorized MAC address and running 802.1X Authentication with EAP.
root@localhost:/etc/freeradius/3.0/sites-available# freeradius -X
[...]
(0) authorized_macs: EXPAND %{Calling-Station-ID}
(0) authorized_macs: --> 0C-2D-83-56-00-01
(0) [authorized_macs] = noop
(0) if (!ok) {
(0) if (!ok) -> TRUE
(0) if (!ok) {
(0) [reject] = reject
(0) } # if (!ok) = reject
(0) } # authorize = reject
(0) Using Post-Auth-Type Reject
[...]
(0) Sent Access-Reject Id 24 from 192.168.1.3:1812 to 192.168.1.2:60013 length 44
(0) EAP-Message = 0x04990004
(0) Message-Authenticator = 0x00000000000000000000000000000000
[...]
NOTE: The above was tested on a virtual machine
For other MAC Address Authentication configurations, visit the freeRADIUS wiki: [FreeRADIUS Wiki] (https://wiki.freeradius.org/guide/mac-auth)