Private PSK (PPSK) function on hostapd

  • The PPSK function in hostapd gives the user the choice of providing the PPSKs via a file or via RADIUS.
  • The option to provide the PPSKs in a text file enables fast and simplified provisioning.

  • We assume that you are familiar with the UCI system in OpenWrt.
  • Configure an SSID with WPA2 pre-shared key.
config wifi-iface 'two'
   option ifname 'two0'
   option disabled '0'
   option encryption 'psk2'
   option isolate '0'
   option key '12345678'
   option mode 'ap'
   option network 'lan'
   option device 'radio0'
   option hidden '0'
   option ssid 'RADIUSdesk'
  • Next, we will replace the key, which is a single value (12345678), with a file with multiple keys.
config wifi-iface 'two'
   option ifname 'two0'
   option disabled '0'
   option encryption 'psk2'
   option isolate '0'
   #option key '12345678'
   option wpa_psk_file /etc/psk.list
   option mode 'ap'
   option network 'lan'
   option device 'radio0'
   option hidden '0'
   option ssid 'RADIUSdesk'
  • Here is the contents of the /etc/psk.list file
# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that
# anyone can use.
00:00:00:00:00:00 highwaystar
00:00:00:00:00:00 blacknight
00:00:00:00:00:00 smokeonthewater
00:00:00:00:00:00 picturesofhome
00:00:00:00:00:00 childintime
  • Restart the WiFi network
wifi down
wifi up
  • hostapd now goes through the list in the PSK file and checks whether it finds a match when someone tries to connect to the SSID.

  • The first section dealt with a very simple PPSK implementation.
  • This section is about more advanced options, including mapping MAC and VLAN to specific keys.
  • You can also visit this forum discussion where most of the information comes from.
  • If we look at the comments of the sample psk.list file we see the following
# List of WPA PSKs. Each line, except for empty lines and lines starting
# with #, must contain a MAC address and PSK separated with a space.
# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that
# anyone can use. PSK can be configured as an ASCII passphrase of 8..63
# characters or as a 256-bit hex PSK (64 hex digits).
00:11:22:33:44:55 paperplane
  • The alternative 256-bit hex value is a hash that contains the specific SSID to which a user connects.
  • You can generate the value using this JavaScript-based online utility from WireShark.(https://www.wireshark.org/tools/wpa-psk.html)
  • When you specify a specific MAC address for a specific device, you should keep the following in mind.
    • The MAC address is the MAC address of the WiFi radio that is trying to connect to the SSID and NOT the MAC address of the Ethernet interface of e.g. a laptop.
    • If your phone has WiFi that supports both 2.4G and 5G, the device will usually have a radio for each frequency band and then also a MAC address for each radio.
    • Also remember that there is a recent MAC randomisation feature on Android and Apple phones which can also cause the MAC address to change.
  • If we look at the comments of the sample psk.list file also we see the following
# An optional VLAN ID can be specified by prefixing the line with
# vlanid=<VLAN ID>.
vlanid=3 00:00:00:00:00:00 blueforyou
vlanid=4 00:00:00:00:00:00 piledriver
  • A few additional steps are required for the VLAN tagging function of hostapd to work as intended.
  • We need to include a few options to instruct hostapd how to handle the VLANs.
  • Refer to this snippet from /etc/config/wireless
option wpa_psk_file '/etc/hostapd.wpa_psk'
option vlan_file '/etc/hostapd.vlan'
option vlan_tagged_interface 'eth0'
option vlan_bridge 'br-vlan'
option dynamic_vlan '1'
  • Then here is an example of hostapd.vlan
# VLAN ID to network interface mapping
1	vlan1
2	vlan2
3	vlan3
4	vlan4
100	guest
# Optional wildcard entry matching all VLAN IDs. The first # in the interface
# name will be replaced with the VLAN ID. The network interfaces are created
# (and removed) dynamically based on the use.
*	vlan#
  • hostapd will create a bridge with each VLAN and automatically create tagged interfaces and make them members of this bridge:
root@OpenWrt:~# brctl show
bridge name     bridge id               STP enabled     interfaces
br-vlan3        8000.4018b1eb3c80       no              vlan3
                                                        eth0.3
br-lan          7fff.4018b1eb3c80       no              eth0

  • This section describes how to implement RADIUS-based PPSK on OpenWrt.
  • The key to enabling RADIUS-based PPSK lies in the following setting in hostapd.conf.
# Optionally, WPA passphrase can be received from RADIUS authentication server
# This requires macaddr_acl to be set to 2 (RADIUS) for wpa_psk_radius values
# 1 and 2.
# 0 = disabled (default)
# 1 = optional; use default passphrase/psk if RADIUS server does not include
#	Tunnel-Password
# 2 = required; reject authentication if RADIUS server does not include
#	Tunnel-Password
# 3 = ask RADIUS server during 4-way handshake if there is no locally
#	configured PSK/passphrase for the STA
#
# The Tunnel-Password attribute in Access-Accept can contain either the
# 8..63 character ASCII passphrase or a 64 hex character encoding of the PSK.
#
#wpa_psk_radius=0
  • Option 3 was recently added and this option is a great help.
  • OpenWrt generates the hostapd configuration files using the /lib/netifd/hostapd.sh script.
  • This script in turn reads and interprets the /etc/config/wireless file to obtain the information needed to formulate the hostapd configuration files.
  • The hostapd.sh script currently sets the wpa_psk_radius value to 2 if the ppsk '1' option is set in /etc/config/wireless.
  • A better option would be to set it to 3.
  • We can search for this section in hostapd.sh
if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then
	json_get_vars auth_secret auth_port
	set_default auth_port 1812
	json_for_each_item append_auth_server auth_server
	append bss_conf "macaddr_acl=2" "$N"
	append bss_conf "wpa_psk_radius=2" "$N"
elif [ ${#key} -eq 64 ]; then
  • And change it to:
if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then
	json_get_vars auth_secret auth_port
	set_default auth_port 1812
	json_for_each_item append_auth_server auth_server
	append bss_conf "macaddr_acl=2" "$N"
	append bss_conf "wpa_psk_radius=3" "$N"
elif [ ${#key} -eq 64 ]; then
  • We will look at the reason for this in the next section.
  • If wpa_psk_radius=2 or wpa_psk_radius=3, the first request from hostapd to the RADIUS server looks like this:
(9) Received Access-Request Id 48 from 44.88.212.194:47297 to 164.160.89.129:1812 length 160
(9)   User-Name = "ae0cd4e2c5ab"
(9)   User-Password = "ae0cd4e2c5ab"
(9)   NAS-Identifier = "m_hosta_51_74"
(9)   Called-Station-Id = "64-64-4A-D1-2D-69:PPSK-1"
(9)   NAS-Port-Type = Wireless-802.11
(9)   Calling-Station-Id = "AE-0C-D4-E2-C5-AB"
(9)   Connect-Info = "CONNECT 11Mbps 802.11b"
(9)   Message-Authenticator = 0xeefd284dc6cf79df258e03b84791c2b8
  • RADIUS will then typically reply with an Access Accept with the PPSK
(9) Sent Access-Accept Id 48 from 164.160.89.129:1812 to 44.88.212.194:47297 length 41
(9)   Tunnel-Password := "77777777"
  • The difference in behaviour between wpa_psk_radius=2 and wpa_psk_radius=3 occurs when the PPSK is not correct.
  • If wpa_psk_radius=2, hostapd does NOT make any follow-up attempts.
  • If wpa_psk_radius=3, hostapd makes a follow-up attempt with additional attributes:
(10) Received Access-Request Id 49 from 44.88.212.194:47297 to 164.160.89.129:1812 length 337
(10)   User-Name = "ae0cd4e2c5ab"
(10)   User-Password = "ae0cd4e2c5ab"
(10)   NAS-Identifier = "m_hosta_51_74"
(10)   Called-Station-Id = "64-64-4A-D1-2D-69:PPSK-1"
(10)   NAS-Port-Type = Wireless-802.11
(10)   Calling-Station-Id = "AE-0C-D4-E2-C5-AB"
(10)   Connect-Info = "CONNECT 11Mbps 802.11b"
(10)   WLAN-AKM-Suite = 1027074
(10)   Attr-245.26.11344.1 = 0xc4b0e7ca5cba50304c28e6995068b4b58dfb7d82944cf9c6caba2276018debde
(10)   Attr-245.26.11344.2 = 0x0103007502010a0000000000000000000131a6c134eadc39dd97da1e4f9c0484e8b85d127f05edf553eb063248791ab0940000000000000000000000000000000000000000000000000000000000000000aad1fa6a0274d00e683b5947b4dc5e9d001630140100000fac040100000fac040100000fac020000
(10)   Message-Authenticator = 0xd1ff97e6c9a794077c12e015e4f8e424
  • RADIUSdesk then includes advanced features in FreeRADIUS to process these additional attributes and attempt to determine the user's PPSK based on hash comparisons.
  • If a match is found, an access accept is returned with the plain text of the matching hash value.
(10) Sent Access-Accept Id 49 from 164.160.89.129:1812 to 44.88.212.194:47297 length 58
(10)   Tunnel-Medium-Type = IEEE-802
(10)   Tunnel-Type = VLAN
(10)   Tunnel-Private-Group-Id = "100"
(10)   Tunnel-Password = "11223344"
(10) Finished request
  • This behaviour enables PPSK in RADIUS, which does not require MAC address matching.
  • To summarise once again:
    • If wpa_psk_radius=2, the RADIUS implementation has to work with MAC address matching and is very cumbersome.
    • If wpa_psk_radius=3, the RADIUS implementation can work with the encrypted value of the PSK specified by the user to perform a hash comparison and is therefore much more flexible. RADIUSdesk supports this option.
    • However, you will need to modify the /lib/netifd/hostapd.sh file to create the hostapd configuration with this option.
  • Let us take a look at a simple reference configuration of /etc/config/wireless in which RADIUS-based PPSK is configured.
config wifi-iface 'zero'
        option ifname 'zero0'
        option encryption 'psk2'
        option acct_interval '300'
        option mode 'ap'
        option nasid 'a_hosta_53_97'
        option acct_server '164.160.89.129'
        option acct_secret 'testing123'
        option auth_server '164.160.89.129'
        option auth_secret 'testing123'  
        option network 'lan'
        option device 'radio0'
        option ssid 'PPSK-APdesk-1'           
        option ppsk '1'      
        option vlan_naming '0'
        option vlan_tagged_interface 'wan'
        option vlan_bridge 'br-ex_vlan'
        option dynamic_vlan '1'        
  • RADIUS-based PPSK implementations usually consist of two components:
    • The private key, which is used for authentication on the WiFi network.
    • The VLAN assignment, which is usually bound to the private key specified by the user.
  • The VLAN assignment is optional. If the RADIUS server has not specified a VLAN in the access acceptance, hostapd does not perform VLAN tagging for the connection of this client.
  • If a VLAN is specified in the RADIUS response, the following configuration options determine how hostapd handles the VLAN assignment:
option vlan_naming '0'                                                                                                                                                                                                                                                  
option vlan_tagged_interface 'wan'                                                                                                                                                                                                                                      
option vlan_bridge 'br-ex_vlan'                                                                                                                                                                                                                                         
option dynamic_vlan '1' 
  • If a client establishes a connection and RADIUS specifies VLAN 100, for example, hostapd dynamically creates the following bridge:
brctl show
bridge name	bridge id		STP enabled	interfaces
br-ex_vlan100		7fff.ae7c588014f4	no	vlan100
							zero0.100
  • The name of the bridge is formulated with the value of vlan_bridge and the appending of the VLAN number (100).
  • The members of this bridge are the tagged WiFi client connection, zero0.100 and vlan100.
  • The vlan100 interface requires a little more explanation. Depending on the value of vlan_naming, which can be 0 or 1, the name of the second interface is determined.
  • Have a look at this part of the hostapd documentation
# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs
# to know how to name it.
# 0 = vlan<XXX>, e.g., vlan1
# 1 = <vlan_tagged_interface>.<XXX>, e.g. eth0.1
#vlan_naming=0
  • So if we change our configuration to the vlan_naming '1' option, the bridge would look like this:
brctl show
bridge name	bridge id		STP enabled	interfaces
br-ex_vlan100		7fff.ae7c588014f4	no	wan.100
							zero0.100
  • Remember that for the VLAN to work correctly, you must also provide a DHCP server in the VLAN so that the client receives an IP address after it has authenticated itself in the WiFi network.
  • If you do not have such a server in your current network, you can easily do this in MESHdesk and APdesk.
  • The details are explained on the corresponding wiki pages.
  • technical/ppsk-hostapd.txt
  • Last modified: 2024/04/30 08:22
  • by system