wpa_supplicant: Wireless Connections

Feb 10, 2021

Updated: May 2, 2024

 

It is possible, and fairly easy, to manage wireless connections on a daily basis using only wpa_supplicant. Besides, it is worthwhile to know how to use wpa_supplicant, as it is part of the base system on all Linux distributions, as well as on NetBSD and on FreeBSD, and it is usually the most reliable way of managing wireless connections on devices like the Raspberry Pi, or on certain installation media.


Usually, the network SSID and the WPA password are required to connect to a password-protected Wi-Fi network. We can either edit the /etc/wpa_supplicant/wpa_supplicant.conf file manually to provide the required information, or we can use wpa_passphrase to generate a WPA PSK from the password, and append it to the configuration file. Let's try connecting to a network called "Network" with the password "password". First, we need to make the /etc/wpa_supplicant directory, if it doesn't exist. The commands are executed as root, but doas or sudo can be used instead.

root@void ~# mkdir -p /etc/wpa_supplicant

Then, we need to save our network information to the configuration file. The wpa_passphrase program requires the ssid and the wpa password. The wpa_passphrase program writes to standard output. We can take this output, remove the line containing the actual password with sed, and write (or, in most cases, append in order to avoid overwriting the existing configuration) it to the configuration file by piping it into tee. Below is the command to do it.

root@void ~# wpa_passphrase "Network" "password" | sed '3d' | tee -a /etc/wpa_supplicant/wpa_supplicant.conf

This is actually all the configuration needed to connect to a wireless network. This process can be repeated when it is needed to connect to another network.

The configuration file looks like this right now:

network={
    ssid="Network"
    psk="..."
}
Note: wpa_cli is a text-based frontend for interacting with wpa_supplicant, which I typically do not use. In order to be able to use it when needed (presumably as a user in the "wheel" group), the following lines should be added to the beginning of the configuration file:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
update_config=1

We can now start wpa_supplicant using the command below.

root@void ~# wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf
Note: The -i option specifies the wireless interface. The interface name can be obtained using the ifconfig command. Wireless interface names on Linux typically start with "w".

Then we run a DHCP client to obtain an IP address. In this guide, dhcpcd is used.

root@void ~# dhcpcd

We can use ping to make sure that the connection is established.

root@void ~# ping google.com

We can also enable the wpa_supplicant service (and the DHCP client, if it has not already been enabled) to start wireless networking on boot. This process depends on the system, and most Linux distributions will use systemctl. Here is how to do it on Void Linux:

root@void ~# ln -s /etc/sv/wpa_supplicant /var/service/
root@void ~# ln -s /etc/sv/dhcpcd /var/service/

Eduroam Connections

Eduroam connections require additional authentication information. We can provide it by editing the configuration file manually.

Note: It is possible to provide passwords in plain text using a psk="..." entry, instead of a WPA PSK generated by wpa_passphrase.
root@void: ~# cd /etc/wpa_supplicant/
root@void: ~# vim wpa_supplicant.conf
Note: The exact configuration in this guide might not work for every institution, depending on how the network is implemented. University websites usually provide information on the authentication methods and protocols used. PEAP or TTLS (or both) may be supported as an authentication framework. For the inner authentication (phase 2), you might need to use MSCHAPv2 or PAP depending on the network. A separate guide for wpa_supplicant might not be included, but the information should still be enough for a working configuration.

We add the following network configuration to the file:

network={
    ssid="eduroam" # Eduroam network SSID
    key_mgmt=WPA-EAP # Use EAP
    eap=TTLS# Use tunneled TLS for authentication
    phase2="auth=PAP" # Use PAP for phase 2 authentication
    identity="user@mail" # University username/e-mail address
    anonymous_identity="anonymous@mail" # For phase 1 security
    password="..." # The password in plain text
}

The password is now in the configuration file. It is a good idea to make sure that the file can only be read by the root user.

root@void: ~# chmod 600 wpa_supplicant.conf

We should now be able to connect to the Eduroam network after restarting the wpa_supplicant service. Again, systemctl will be used instead on most Linux distributions.

root@void: ~# sv restart wpa_supplicant

Public Networks

It is possible to join public networks without a password. Authentication might then be handled by a captive portal. In this case, setting the key_mgmt option to NONE works.

network={
    ssid="Public_Network"
    key_mgmt=NONE
}

Finding Networks & Connecting to Hidden Networks

If the exact name of the network is not known, a scan may be performed on the wireless interface to detect available networks using the iw command on Linux.

root@server: ~# iw dev wlan0 scan | grep SSID

In some cases, the SSID of the network might be hidden. Hidden networks will obviously not appear in the scan results, but if they are known, wpa_supplicant can connect to them with the scan_ssid option.

network={
    ssid="Hidden_Network"
    scan_ssid=1
    psk="..."
}

Prioritizing Connections

For times when multiple networks are available, we can set the priority option to tell wpa_supplicant which connection to prioritize. The default priority is 0. The network with the higher priority number will be prioritized.

network={
    ssid="Home_Network"
    psk="..."
    priority=1
}
network={
    ssid="Mobile_Phone"
    psk="..."
    priority=9
}