WPA3-Personal Wi-Fi Access Point on Linux
This document describes how to set up a WPA3-Personal Access Point using Linux, that can always have the latest security patches applied
WPA3-Personal is the only password-based Wi-Fi that as of 2020 is safe to use
WPA3-Personal published in 2018 is supported by Android 10 and macOS Catalina 10.15 or later
Why is WPA3-Personal more secure?
• sae (explained below) is a safe exchange of secrets with forward secrecy
• sae only connects Access Points and clients that prove to have the secret, thereby mitigating the evil-twin problem
WPA2-Personal does not offer any of the above characteristics, it is unsafe to use at all without vpn. The intermediate fix for WPA2 is to always use WPA2-Enterprise eap-tls, everybody else is a victim. Once an attacker is in the WPA2 network which takes only seconds, crafted packets can be sent to any authenticated node exploiting every feature of their typically low-quality software
Process
Get a Compliant Adapter
As of July 2020 the Wi-Fi Alliance only certifies WPA3-capable hardware. To run WPA3-Personal, the hardware must support sae, Simultaneous Authentication of Equals IEEE 802.11-2016
A safe way to determine that the hardware is capable of WPA3-Personal is to verify that the Wi-Fi Alliance has certified it for WPA3 using their Product Finder. At present, vendors claim WPA3 when they only support a certain feature like sae but cannot actually communicate with WPA3-Personal devices. Much hardware does work but is not directly certified
Wi-Fi under Linux generally is troublesome
A USB adapter known to work is NETGEAR A6210, other internal adapters may work if an AP-capable driver can be found
Adapter Must support pmf protected management frames
PMF (protected management frames) certification IEEE 802.11w, also called mfp management frame protection
The only way to determine whether pmf is supported is to run it. hostapd will error on start when provided the following option: ieee80211w=2
Plug the Adapter in
If it is usb, it should be recognized by lsusb
You can monitor how the command output changes in order to detect it
Most other adapters appear using lspci
In edge cases use lshw
This will give you the vendor and product id which is a two-value hexadecimal number like 846:9053
Find Network Interface
If the device has a driver, a network interface will appear with a name like wlan0. Wireless devices can be listed with iw dev
Their names ususally begin with w double-u
iw dev phy#2 Interface wlan0 ifindex 7 wdev 0x200000001 addr 00:11:22:33:44:55 type managed txpower 20.00 dBm
phy2 is the iw numbering for the device. To see everything it can do, about 200 lines: iw phy2 info
All network interfaces are listed by ip l
One can also examine which driver claims a certain vendor and product:
modprobe --showconfig | grep v0846p9053 alias usb:v0846p9053d*dc*dsc*dp*ic*isc*ip*in* mt76x2u
Here we can see that the usb product 0846:9053 is claimed by the mt76x2u driver. A driver name is a short word
If no driver claims your product, search the vendor’s web site or search generally on the Internet, many drivers are maintained by volunteers on github. Success is more likely if a tutorial is found by someone else with the same product
If a network interface appears and you want to know which driver provides it, here is for the wlp2s0b1 network interface:
ls /sys/class/net/wlp2s0b1/device/driver/.. b43
The wlp2s0b1 interface was provided by the b43 driver
If it is a usb device with a known driver name, its connected speed can be displayed:
lsusb -t | grep mt76x2u |__ Port 2: Dev 2, If 0, Class=Vendor Specific Class, Driver=mt76x2u, 5000M
The device claimed by the mt76x2u driver is connected via usb at 5 Gb/s
Disable NetworkManager
To use hostapd, the device should not be managed by NetworkManager. You have NetworkManager if the directory /etc/NetworkManager/conf.d exists There can only be one file with unmanaged-devices directive
Check for a file to append to:
grep unmanaged /etc/NetworkManager/conf.d/* /etc/NetworkManager/conf.d/00-unmanaged.conf:unmanaged-devices=interface-name:enp4s0;interface-name:enx*;interface-name:wlx08beac12be74
If /etc/NetworkManager/conf.d does not eixst, move on
If the grep command above produces output, add to the line that already exists
otherwise create a file with extension .conf like:
nano /etc/NetworkManager/conf.d/00-unmanaged.conf [keyfile] unmanaged-devices=interface-name:wlan0 systemctl restart NetworkManager.service
Verify that NetworkManager no longer manages your device:
nmcli d s DEVICE TYPE STATE CONNECTION wlan0 wifi unmanaged --
Assign IP
Pick an unused area of 256 ip addresses, like 10.0.5.0. Create a file with .network extension, here for the wlan0 interface:
nano /etc/systemd/network/10-wlan0.network [Match] Name=wlan0 [Link] RequiredForOnline=no [Network] ConfigureWithoutCarrier=true Address=10.0.5.1/24 systemctl reload systemd-networkd
ip a
should now show that the interface has an ip address
ip a s dev wlan0 7: wlan0: mtu 2312 qdisc mq state UP group default qlen 1000 link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff inet 10.0.5.1/24 brd 10.0.5.255 scope global wlan0 valid_lft forever preferred_lft forever inet6 fe80::847b:41ff:fe34:da20/64 scope link valid_lft forever preferred_lft forever
Get dhcp and dns
Install dnsmasq and hostapd: apt install --yes dnsmasq hostapd
If your interface is wlan0 and ip 10.0.5.0, create two files:
nano /etc/hostapd/wlan0-dnsmasq bind-interfaces listen-address=10.0.5.1 no-hosts dhcp-range=10.0.5.32,10.0.5.254 dhcp-option=option:router,10.0.5.1 nano /etc/systemd/system/dnsmasq@.service [Unit] Description=dhcp and dns for interface %i Requires=network.target Wants=nss-lookup.target Before=nss-lookup.target After=network.target [Service] PIDFile=/run/dnsmasq/%i.pid Restart=on-failure RestartSec=5 ExecStart=/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/hostapd/%i-dnsmasq ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target systemctl start dnsmasq@wlan0
dns and dhcp are now running:
ps -fCdnsmasq | cat UID PID PPID C STIME TTY TIME CMD nobody 45081 1 0 Dec12 ? 00:00:02 /usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/hostapd/wlan0-dnsmasq
Unblock the Transmitter
From iw dev
you have your interface’s phy number
Then verify it to be unblocked using rfkill:
rfkill ID TYPE DEVICE SOFT HARD 0 wlan phy0 unblocked unblocked 1 bluetooth hci0 unblocked unblocked 2 wlan phy1 unblocked unblocked
• For the line with the phy number, if it says blocked in the HARD column, there is a switch on the computer needing to be toggled
If the SOFT column says blocked, unblock using the number in the ID column: rfkill unblock 2
Start hostapd
Create a file named using your interface wlan0 and extension .conf: also decide on your ssid and password. The password should not be known or guessable to an attacker
nano /etc/hostapd/wlan0.conf # © 2020-present Harald Rudell (https://haraldrudell.github.io/haraldrudell) # License: ISC # 0846:9053 NetGear, Inc. A6210 WPA3-Personal 2.4 GHz 54 Mb/s: 802.11g # directive order: https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf interface=wlan0 ssid=anything logger_stdout=63 logger_stdout_level=0 country_code=US ieee80211d=1 hw_mode=g channel=9 auth_algs=1 ap_isolate=1 wpa=2 wpa_key_mgmt=SAE rsn_pairwise=CCMP ieee80211w=2 sae_password=unguessable sae_require_mfp=1
To test you access point:
hostapd -t /etc/hostapd/wlan0.conf
To run your access point:
systemctl start hostapd@wlan0
Access Points under linux are implemented using hostapd: hostapd reference
To see what hostapd is running:
ps -fChostapd | cat UID PID PPID C STIME TTY TIME CMD root 44929 1 0 Dec12 ? 00:00:18 /usr/sbin/hostapd -B -P /run/hostapd.pid -B /etc/hostapd/wlan0.conf
Provide Internet Access
The steps above allows Wi-Fi clients to access the host machine. For clients to access the Internet, ip forwarding and SNAT must be added; a template is here for wi-fi interface wlan0 and Internet interface eth0:
iptables --insert FORWARD --in-interface wlan0 --out-interface eth0 --jump ACCEPT iptables --insert FORWARD --in-interface wlan0 --out-interface eth0 --jump MARK --set-mark 0x123 iptables --insert FORWARD --in-interface eth0 --out-interface wlan0 --match state --state RELATED,ESTABLISHED --jump ACCEPT iptables --append FORWARD --jump DROP iptables --table nat --insert POSTROUTING --match mark --mark 0x123 --jump MASQUERADE echo -n 1 >/proc/sys/net/ipv4/ip_forward
To see iptable rules, which may be a lot:
iptables-save | less …
Note: as of Linux 5.4.0, bugs prevents speeds faster than 54 Mb/s 802.11g. NETGEAR A6210 can otherwise do 867 Mb/s on 5 GHz
Updated: 12/13/2020