2023-10-31

Connect to Wi-Fi in Linux using `wpa_supplicant` and `dhclient`

If you're in a situation where you aren't using a NetworkManager of sorts, then this post will guide you how to connect to Wi-Fi using just two commands: `wpa_supplicant` and `dhclient`, okay, maybe a 3rd command called `wpa_passphrase`.
Let's get into the details.

Install Packages

If you have never connected to a Wi-Fi network in Linux on this system before, you probably have some packages to install. For at least the packages described in this post, I'll give the commands to execute:

Debian/Ubuntu

    sudo apt-get update
    sudo apt-get install -y isc-dhcp-client wpasupplicant

RHEL/RedHat/Fedora

    sudo yum install *help me in the comments section, please?*

Create Wi-Fi WPA Key

This first command using `wpa_passphrase` will allow you to create a Wi-Fi key that will be used to talk with your router. Checkout wpa_passphrase(8) when you get a chance.

    wpa_passphrase 'UVerse8654930234' 'myd0gN@m3!'

Notice how I enclosed my Wi-Fi network name and my password in quotes. If you use double-quotes, just keep in mind $ may inadvertently create a variable, so escape accordingly or use single quotes to use a literal string.

If you don't want your password on the command line, don't sweat it, just omit the password from the command and it will read from STDIN to ask you for it.

When it's all said and done, you'll end up with output like this:

$ wpa_passphrase 'My-Wi-Fi' 'mypassword'
network={
	ssid="My-Wi-Fi"
	#psk="mypassword"
	psk=6100151c208ef31a3110c38ab2b0485700005d5850600f5577a0321a1a9ced8e
}

You can take this and write it to the `NETFILE` you will create in `/etc/wifi/my-network.wifi`. At least, this is where I store my configuration for this. #YMMV

Connect to Wi-Fi Network

Now that we have our configuration file, let's run our `wpa_supplicant` command to connect us to the Wi-Fi network of our choice:

    sudo wpa_supplicant -B -s -i wlan0 -c /etc/wifi/my-network.wifi -P /run/wifi/wpa_supplicant.pid -Dwext

This will run `wpa_supplicant` in the background with the configuration specified in `/etc/wifi/my-network.wifi`, using your `wlan0` interface and creating a PID file in `/run/wifi/wpa_supplicant.pid`. The `-Dwext` says use generic Wi-Fi drivers.
For more information, you really should checkout wpa_supplicant(8).

NOTE: If you have a different interface than `wlan0`, please be sure to update your commands as necessary.

At this point, if you run `iwconfig wlan0`, you should see that you have connected over the Wi-Fi to the target network:

$ ifconfig wlan0
wlan0     IEEE 802.11  ESSID:"My-Wi-Fi"
          Mode:Managed  Frequency: 5.805 GHz  Access Point: 99:99:99:99:99:99   
          Bit Rate=780 Mb/s   Tx-Power=22 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          Link Quality=57/70  Signal level=-54 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:306   Missed beacon:0

Get IP Address

We're not out of the woods yet though, we still need to get an IP address. So far, wpa_supplicant handles the heavy lifting of decrypting and communicating with the router. We still need to get an address on the network. This is why I love Linux -- you get exposed to all the raw operations of how a computer really works.

To get an IP address, you can use the command `dhclient`. For a full breakdown of all commands and operations possible, please see dhclient(8).
Here's what I used:

    sudo dhclient -pf /run/wifi/dhclient.pid -v wlan0

This says I want the PID file to be placed in `/run/wifi/dhclient.pid`, to be verbose and to get an address we can bind to `wlan0`. The PID file option is optional. You can leave it to the defaults. I want this specifically for the script at the end of this post.

At this point, you should be connected to your Wi-Fi network and have an IP address and a default route. In theory, this is what you should have. I'll also include below situations where I don't get those expected results:

Wi-Fi Won't Connect

Troubleshooting tips

  • Make sure Wi-Fi is on. Some laptop models have a Fn-F6 or something function available somewhere to let you toggle the antenna for Wi-Fi. If it's off, you won't get a connection. I've been had by this before.
  • `iwconfig` not rendering your device? Make sure you have drivers installed and kernel modules loaded (e.g. `modprobe iwlwifi`). I have been known to have downloaded the source to my laptop's Wi-Fi drivers and custom compile them into the kernel I was using because they weren't widely accepted into the kernel just yet (Wi-Fi support needed much help).
  • Connects, but won't authenticate? Make sure there isn't a typo or trailing space in the network name and the password. The hash is a checksum of both and could be the reason it won't authenticate.
  • `dhclient` gets an IP, but doesn't set a default route? You may have a down default route that needs to be removed first and `dhclient` restarted. Seems it will only add a default route if not exist; instead of not exist and not linkup.

If this seems like a lot of work, don't worry, I got you: https://gist.github.com/markizano/
This Github Gist contains a `wifi.sh` you can place in `/etc/init.d/wifi` and a `wifi.conf` you can place in `/etc/default/wifi`. Be sure to place your Wi-Fi password configuration in `/etc/wifi`. If you want to make the service active on sysv-init setups, you can use: `sudo update-rc.d wifi defaults`

I also be sure to `sudo chmod 0700 /etc/wifi && sudo chmod 0600 /etc/wifi/*` and `sudo chown root:root /etc/wifi` to ensure restricted permissions on the configuration to secure the files.

So that's how you connect to a Wi-Fi network without a Network Manager in Linux if you ever find yourself stranded and need to pull this off, you now have this in your back pocket.