Setting up secure wifi
If you don’t set a password on your wifi, then not only can anyone connect, but it’s not even encrypted. This means that even when an open network gives you a captive portal, that could actually be an attacker giving you a fake portal. Even if the portal is HTTPS, because you may be connected to https://evil-fake-portal.com.
That is solved in WPA3, where even open networks become encrypted.
Of course, the attacker can just set up a fake access point, and you’ll connect, none the wiser. Even if the network has a password, the attacker only needs to know that password in order to fake it.
Before WPA3, passwords can easily be brute forced offline. A few years ago I calculated that it would cost about $70 to crack the default generated 8 character random passwords used by a popular ISP here in London, using some GPUs in Google Cloud. I’m sure it’s cheaper now.
That’s potentially years of free use of your neighbours wifi, for just the cost of a couple of months of paying for your own.
But that’s illegal, of course. This post is about protecting you against these attacks, not performing them.
If you don’t want to mandate WPA3, but still not have a password, then you can do what some hacker conferences do, and set up WPA Enterprise network with username/password, and accept any username and password provided.
And if you do want a password, WPA Enterprise can be set up to make them not vulnerable to brute force.
WPA Enterprise also makes the network authenticate to the client, so password or not, nobody can impersonate the network.
Android phones (and probably others) let you save the network’s CA (certificate authority) on first connect, so you only need that first connection to be secure. Alternatively you can download the CA and install it manually, if you can’t even trust that first connect.
Before you say that no way will you install some random CA; no this time it’s actually fine. It’ll only be used for the WPA Enterprise networks you explicitly use it for, and not for HTTPS.
But an even better solution is to not use passwords at all, but certificates.
So here’s my walkthrough about how to enable WPA Enterprise, with certificates, on a Ubiquiti network, using FreeRADIUS running on a raspberry pi.
Architecture summary
Access points themselves can’t run a user- and certificate database. For WPA Enterprise they are just dumb agents, asking a RADIUS server who should be allowed in or who should not.
EAP-TLS is the mode you want to use. It uses the RADIUS protocol as encapsulation to let the wifi client talk directly to the RADIUS server using TLS. This TLS session uses mTLS, meaning both sides provide certificates for the other side to verify.
After the wifi client and RADIUS server has had this tunneled conversation, the AP is told to let them in.
After that the RADIUS server is no longer involved.
Configure Unifi APs for RADIUS
This is the simple part, so if you have another brand of AP, then it shouldn’t be very different, assuming it supports RADIUS.
Under Settings -> Profiles, create a new RADIUS profile for authentication.
Do not check the Enable RADIUS assigned VLAN for wired/wireless
network
boxes, unless you want to do more fancy things.
Under Settings -> Wireless Networks, create a new network with WPA2 Enterprise, using this RADIUS profile.
I had trouble running with PMF turned on (optional or required), which is a requirement for WPA3, so I guess I’m not running WPA3, and disabled PMF.
That’s a shame, because WPA3 has several security improvements, including mandatory protection of management frames.
Install and configure FreeRADIUS
1. apt install freeradius
Check if this is at least 3.0.26! It needs to support TLS 1.3, or certificates won’t work on modern devices. 3.0.17 (what was packaged with my Raspian based on Debian 10 (buster)) was not enough.
Username/password worked with 3.0.17, but not certificates.
There are prebuilt packages at http://packages.networkradius.com, or you can build from source.
If you installed from source then the path may be /etc/raddb/
instead of the /etc/freeradius/3.0/
that Debian uses.
2. Create CA
Edit [certificate_authority]
section of
/etc/freeradius/3.0/certs/ca.cnf
with your details.
Bump default_days
to 3650, to be valid for 10 years.
Then run make ca.pem
in that directory.
3. Generate radius server certificate
This will prove to the wifi client that the access point is real.
Edit [server]
in /etc/freeradius/3.0/certs/server.cnf
. In
particular, set the commonName
to something like
wifi.example.com
. For example:
[server]
countryName = GB
stateOrProvinceName = Radius
localityName = Somewhere
organizationName = Example Inc.
emailAddress = admin@example.org
commonName = wifi.example.com
Under [req]
set these:
input_password = myserverkeypassword
output_password = myserverkeypassword
The default_days
doesn’t really have to be raised on the server
cert. You can always regenerate the server cert without messing with
all wifi clients. But you do have to regenerate the cert when it
expires.
Then run make server.pem
.
4. Enable clients to talk to the server
Add this to /etc/freeradius/3.0/clients.conf
:
client wifi_aps {
ipaddr = 192.168.123.0/24
secret = radiuspasswordhere
}
5. Set FreeRADIUS cert/key
Find these keys, and set them like so, in
/etc/freeradius/3.0/mods-enabled/eap
:
private_key_password = myserverkeypassword
private_key_file = ${certdir}/server.key
certificate_file = ${certdir}/server.pem
ca_file = ${certdir}/ca.pem
6. Create a test user
In /etc/freeradius/3.0/users
, create a test user:
bob Cleartext-Password := "hello"
7. Restart FreeRADIUS
systemctl restart freeradius
You should now be able to connect to the wifi using:
- EAP method:
PEAP
- Phase 2 authentication:
MSCHAPV2
- CA certificate: Either trust on first use, or import it manually.
- Domain:
wifi.example.com
, per above - Identity:
bob
- Anonymous identity:
anonymous
(default) - Password:
hello
Hopefully this worked for you. Don’t proceed until this works. But that’s not enough, we want cert based auth.
8. Generate a client cert
Edit /etc/freeradius/3.0/certs/client.cnf
, setting:
default_days
for the lifetime.[client]
->commonName
to identify the client.[req]
->input_password
andoutput_password
with a unique password.make client.pem
This also creates a client.p12
, that you can load on an android
phone by searching settings for Wi-Fi certificate
, and adding it
e.g. via Google Drive.
9. Switch to certificates
In /etc/freeradius/3.0/mods-enables/eap
:
default_eap_type = tls
private_key_password
private_key_file
certificate_file
ca_file
- Set
use_tunneled_reply = yes
everywhere the option exists in this file, and make sure it’s under thetls-config
too
User login will still work, so unless you disable the other methods,
that user you created will will work. So probably best to remove it
from the users
file.
Then restart FreeRADIUS.
10. Change wifi settings to use the cert
On Android:
- EAP method:
TLS
- CA certificate: The CA cert you imported earlier.
- Minimum TLS version:
1.3
, to avoid getting downgrade attacks. - Online certificate status: Do not verify (I’ve not enabled OCSP).
- Domain:
wifi.example.com
- Identity: Doesn’t matter, but it’ll be visible in clear text over the wire.
Your Android should now connect.
11. Connect with a Linux client
nmcli c add type wifi ifname wlan0 con-name "My-Wifi" \
802-11-wireless.ssid "WIFI-SSID" \
802-11-wireless-security.key-mgmt wpa-eap \
802-1x.eap tls \
802-1x.identity anonymous \
802-1x.ca-cert /home/pi/CA.crt \
802-1x.client-cert /home/pi/test.pem \
802-1x.private-key /home/pi/test.key \
802-1x.private-key-password testing1234
That adds a wifi with certificate auth. Then switch to this network using
nmcli c up My-Wifi
Your client is still not safe
This is all for nothing, of course, because your phone and laptop will just connect anyway to any hotel or other free wifi you’ve ever connected to in the past. An attacker can just set up a BA-Lounge wifi and wait for you to connect.
The one good thing for clients is that when they say they’re connected to “My-Wifi”, you can know that they really are connected to the real one, and not an attacker’s fake AP.
This setup does protect the network though. Users without certificates can’t connect, and can’t brute force the password.
Links
- https://www.titley.com/index.php/about-us/nigel/creating-self-signed-certificates-for-a-wpa-enterprise-wifi-using-freeradius/
- https://wiki.alpinelinux.org/wiki/FreeRadius_EAP-TLS_configuration
- https://www.tp-link.com/uk/support/faq/3456/
- https://s55ma.radioamater.si/2020/10/28/raspberry-pi-eap-tls-wi-fi-with-nmcli-network-manager/
- https://en.wikipedia.org/wiki/IEEE_802.11w-2009