Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| technical:ppsk-hostapd [2024/04/18 14:00] – [Simple as possible PPSK on OpenWrt] system | technical:ppsk-hostapd [2024/04/30 08:22] (current) – [Key specific for VLAN] system | ||
|---|---|---|---|
| Line 5: | Line 5: | ||
| ----- | ----- | ||
| - | ====== Private PSK (PPSK) | + | ====== Private PSK (PPSK) |
| ===== File or RADIUS ===== | ===== File or RADIUS ===== | ||
| - | * The PPSK feature | + | * The PPSK function |
| - | * Having the option | + | * The option |
| ------ | ------ | ||
| - | ===== Simple as possible | + | ===== FILE - Quick and dirty PPSK on OpenWrt ===== |
| - | * In this section we will look how you can activate PPSK functionality | + | * We assume that you are familiar with the UCI system |
| - | * | + | * Configure an SSID with WPA2 pre-shared key. |
| + | <code bash> | ||
| + | config wifi-iface ' | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | * Next, we will replace the key, which is a single value (12345678), with a file with multiple keys. | ||
| + | <code bash> | ||
| + | config wifi-iface ' | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | # | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | * Here is the contents of the / | ||
| + | <code bash> | ||
| + | # Special MAC address 00: | ||
| + | # anyone can use. | ||
| + | 00: | ||
| + | 00: | ||
| + | 00: | ||
| + | 00: | ||
| + | 00: | ||
| + | </ | ||
| + | * Restart the WiFi network | ||
| + | <code bash> | ||
| + | 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. | ||
| - | | + | --------- |
| - | * This is in contrast | + | |
| - | * The advantage of using different keys is the ease of management. | + | ===== FILE - Advanced PPSK on OpenWrt ===== |
| - | * Suppose | + | |
| - | * Without | + | * This section |
| - | * Change | + | * You can also visit [[https:// |
| - | * Inform all employees that the WiFi key has changed and hopefully they will be smart enough to update any devices that are configured to connect to the office WiFi network. | + | ==== Key specific for MAC ==== |
| - | * Another place where you need to update | + | * If we look at the comments of the sample psk.list file we see the following |
| - | * With PPSK support, you simply revoke the PPSK of employees. | + | <code bash> |
| - | * Also using one SSID with multiple keys improves bandwidth utilisation | + | # 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: | ||
| + | # 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: | ||
| + | </ | ||
| + | * The alternative 256-bit hex value is a hash that contains | ||
| + | * You can generate the value using this JavaScript-based online utility from WireShark.(https:// | ||
| + | * When you specify | ||
| + | * The MAC address is the MAC address | ||
| + | * 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 | ||
| + | |||
| + | ==== Key specific for VLAN ==== | ||
| + | | ||
| + | <code bash> | ||
| + | # An optional VLAN ID can be specified by prefixing the line with | ||
| + | # vlanid=< | ||
| + | vlanid=3 00: | ||
| + | vlanid=4 00: | ||
| + | </ | ||
| + | * 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 | ||
| + | * Refer to this snippet from / | ||
| + | <code bash> | ||
| + | option wpa_psk_file '/ | ||
| + | option vlan_file '/ | ||
| + | option vlan_tagged_interface ' | ||
| + | option vlan_bridge ' | ||
| + | option dynamic_vlan ' | ||
| + | </ | ||
| + | * Then here is an example of hostapd.vlan | ||
| + | <code bash> | ||
| + | # 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 | ||
| + | # (and removed) dynamically based on the use. | ||
| + | * vlan# | ||
| + | </ | ||
| + | * hostapd will create a bridge | ||
| + | <code bash> | ||
| + | root@OpenWrt: | ||
| + | bridge name | ||
| + | br-vlan3 | ||
| + | eth0.3 | ||
| + | br-lan | ||
| + | </ | ||
| ------ | ------ | ||
| + | ===== RADIUS - PPSK on OpenWrt ===== | ||
| + | * 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**. | ||
| + | <code bash> | ||
| + | # 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/ | ||
| + | # | ||
| + | # 2 = required; reject authentication if RADIUS server does not include | ||
| + | # | ||
| + | # 3 = ask RADIUS server during 4-way handshake if there is no locally | ||
| + | # | ||
| + | # | ||
| + | # 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. | ||
| + | # | ||
| + | # | ||
| + | </ | ||
| + | * Option **3** was recently added and this option is a great help. | ||
| + | * OpenWrt generates the hostapd configuration files using the / | ||
| + | * This script in turn reads and interprets the / | ||
| + | * The hostapd.sh script currently sets the **wpa_psk_radius** value to **2** if the **ppsk ' | ||
| + | * A better option would be to set it to **3**. | ||
| + | * We can search for this section in hostapd.sh | ||
| + | <code bash> | ||
| + | if [ " | ||
| + | json_get_vars auth_secret auth_port | ||
| + | set_default auth_port 1812 | ||
| + | json_for_each_item append_auth_server auth_server | ||
| + | append bss_conf " | ||
| + | append bss_conf " | ||
| + | elif [ ${#key} -eq 64 ]; then | ||
| + | |||
| + | </ | ||
| + | * And change it to: | ||
| + | <code bash> | ||
| + | if [ " | ||
| + | json_get_vars auth_secret auth_port | ||
| + | set_default auth_port 1812 | ||
| + | json_for_each_item append_auth_server auth_server | ||
| + | append bss_conf " | ||
| + | append bss_conf " | ||
| + | elif [ ${#key} -eq 64 ]; then | ||
| + | </ | ||
| + | |||
| + | * We will look at the reason for this in the next section. | ||
| + | |||
| + | ==== wpa_psk_radius=3 ==== | ||
| + | * If wpa_psk_radius=2 or wpa_psk_radius=3, | ||
| + | <code bash> | ||
| + | (9) Received Access-Request Id 48 from 44.88.212.194: | ||
| + | (9) | ||
| + | (9) | ||
| + | (9) | ||
| + | (9) | ||
| + | (9) | ||
| + | (9) | ||
| + | (9) | ||
| + | (9) | ||
| + | </ | ||
| + | * RADIUS will then typically reply with an Access Accept with the PPSK | ||
| + | <code bash> | ||
| + | (9) Sent Access-Accept Id 48 from 164.160.89.129: | ||
| + | (9) | ||
| + | </ | ||
| + | * 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, | ||
| + | * If wpa_psk_radius=3, | ||
| + | <code bash> | ||
| + | (10) Received Access-Request Id 49 from 44.88.212.194: | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | </ | ||
| + | * 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. | ||
| + | <code bash> | ||
| + | (10) Sent Access-Accept Id 49 from 164.160.89.129: | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (10) | ||
| + | (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**, | ||
| + | * If **wpa_psk_radius=3**, | ||
| + | * However, you will need to modify the / | ||
| + | |||
| + | |||
| + | <alert type=" | ||
| + | === Heads-Up === | ||
| + | |||
| + | |||
| + | * Interestingly, | ||
| + | * At some point, it stopped receiving the follow-up request no matter how many times I restarted the access points. | ||
| + | * Finally, out of desperation, | ||
| + | * Just a heads up about FreeRADIUS. | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== Reference config ==== | ||
| + | * Let us take a look at a simple reference configuration of / | ||
| + | <code bash> | ||
| + | config wifi-iface ' | ||
| + | option ifname ' | ||
| + | option encryption ' | ||
| + | option acct_interval ' | ||
| + | option mode ' | ||
| + | option nasid ' | ||
| + | option acct_server ' | ||
| + | option acct_secret ' | ||
| + | option auth_server ' | ||
| + | option auth_secret ' | ||
| + | option network ' | ||
| + | option device ' | ||
| + | option ssid ' | ||
| + | option ppsk ' | ||
| + | option vlan_naming ' | ||
| + | option vlan_tagged_interface ' | ||
| + | option vlan_bridge ' | ||
| + | option dynamic_vlan ' | ||
| + | </ | ||
| + | * 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 ' | ||
| + | option vlan_tagged_interface ' | ||
| + | option vlan_bridge ' | ||
| + | option dynamic_vlan ' | ||
| + | </ | ||
| + | * If a client establishes a connection and RADIUS specifies VLAN 100, for example, hostapd dynamically creates the following bridge: | ||
| + | <code bash> | ||
| + | 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**, | ||
| + | * Have a look at this part of the hostapd documentation | ||
| + | <code bash> | ||
| + | # When hostapd creates a VLAN interface on vlan_tagged_interfaces, | ||
| + | # to know how to name it. | ||
| + | # 0 = vlan< | ||
| + | # 1 = < | ||
| + | # | ||
| + | </ | ||
| + | * So if we change our configuration to the **vlan_naming ' | ||
| + | <code bash> | ||
| + | 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. | ||
| + | |||