Raspberry Pi : WiFi in the CLI

This tutorial is based on a Raspberry Pi 3B running Raspbian Buster. WiFi is one of three built in network interfaces on the Pi board.

ifconfig

While ifconfig is considered deprecated, it is still included with the Buster release of Raspbian. In Debian Buster, it has been replaced by the ip command. When issued by itself, it will display information about the available network interfaces. It does not require root privileges.

pi@raspberrypi:~$ ifconfig
eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
	ether b8:27:eb:00:4a:1c txqueuelen 1000 (Ethernet)
	RX packets 0 bytes 0 (0.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 0 bytes 0 (0.0 B)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
	inet 127.0.0.1 netmask 255.0.0.0
	inet6 ::1 prefixlen 128 scopeid 0x10
	loop txqueuelen 1000 (Local Loopback)
	RX packets 0 bytes 0 (0.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 0 bytes 0 (0.0 B)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 

wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
	ether b8:27:eb:55:1f:49 txqueuelen 1000 (Ethernet)
	RX packets 0 bytes 0 (0.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 0 bytes 0 (0.0 B)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
pi@raspberrypi:~$

To view only output relating to the wireless interface we can specificy wlan0 in the command string:

pi@raspberrypi:~$ ifconfig wlan0
wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
	ether b8:27:eb:55:1f:49 txqueuelen 1000 (Ethernet)
	RX packets 0 bytes 0 (0.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 0 bytes 0 (0.0 B)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
pi@raspberrypi:~$

As you can see from the output, the wireless network interface, identified as wlan0, is up but not associated with a network. Ifconfig can also control the link state of the interface, either up or down. To bring the wlan0 interface down the following command can be issued:

pi@raspberrypi:~$ sudo ifconfig wlan0 down
pi@raspberrypi:~$ ifconfig
eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
	ether b8:27:eb:00:4a:1c txqueuelen 1000 (Ethernet)
	RX packets 0 bytes 0 (0.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 0 bytes 0 (0.0 B)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
	inet 127.0.0.1 netmask 255.0.0.0
	inet6 ::1 prefixlen 128 scopeid 0x10
	loop txqueuelen 1000 (Local Loopback)
	RX packets 0 bytes 0 (0.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 0 bytes 0 (0.0 B)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
pi@raspberrypi:~$

By executing ifconfig again, you can see that wlan0 is no longer listed in the output. To bring the interface back up, up arrow through the bash history and change the down to an up:

pi@raspberrypi:~$ sudo ifconfig wlan0 up
pi@raspberrypi:~$ ifconfig wlan0
wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
	ether b8:27:eb:55:1f:49 txqueuelen 1000 (Ethernet)
	RX packets 0 bytes 0 (0.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 0 bytes 0 (0.0 B)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
pi@raspberrypi:~$

iproute2

As ifconfig is now considered deprecated, iproute2 is the preferred tool for managing network interfaces. It is a collection of utilities that replace a number of commands of which ifconfig is one. To view information about the available network interfaces, the ip command can be used with the address modifier. In the following example the wlan0 link state is currently down.

pi@raspberrypi:~$ ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether b8:27:eb:00:4a:1c brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether b8:27:eb:55:1f:49 brd ff:ff:ff:ff:ff:ff
pi@raspberrypi:~$

To view only information about a specific interface we can utilize the show modifier:

pi@raspberrypi:~$ ip address show eth0
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether b8:27:eb:00:4a:1c brd ff:ff:ff:ff:ff:ff
pi@raspberrypi:~$

In the eth0 example, we can see that there is no network cable plugged in (no carrier), Broadcast and Multicast are enabled, and the link state is up. To bring the wireless interface up, we can use the link set modifiers with the ip command.

pi@raspberrypi:~$ sudo ip link set wlan0 up
pi@raspberrypi:~$ ip address show wlan0
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether b8:27:eb:55:1f:49 brd ff:ff:ff:ff:ff:ff

As with ifconfig, we can bring the interface back down again by specifying “down” in the command.

iwlist

To view available wireless networks use the iwlist command. The output can be rather verbose, so pipe the results through grep to clean it up:

pi@raspberrypi:~$ sudo iwlist wlan0 scan | grep ESSID
                  ESSID: "garden"
                  ESSID: "cafe"
                  ESSID: "office"
pi@raspberrypi:~$

The resulting output will contain a list of available wireless networks by SSID. For this example the network is called “garden”. If you are connecting to a network that does not broadcast its SSID, you can still connect with an additional step discussed later in this tutorial.

Raspbian uses a program called WPA_Supplicant to manage credentials for wireless network connections. To view the current configuration use the less command:

pi@raspberrypi:~$ less /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant Group=netdev
update_config=1
country=US

/etc/wpa_supplicant/wpa_supplicant.conf (END)

wpa_passphrase

To add a network configuration, use the wpa_passphrase tool. The wpa_passphrase command takes the ssid and password as its arguments, and generates a configuration entry. To add the configuration to the wpa_supplicant.conf file, use an output redirection. If you are logged in as root, you can use the following command:

pi@raspberrypi:~$ wpa_passphrase garden turnip22 >> /etc/wpa_supplicant/wpa_supplicant.conf

If you are logged in as the default user, pi, things get complicated. Because the conf file was created at the time of installation, it is owned by root. If you were to run the command using sudo, the sudo privileges would only apply to the wpa_passphrase command itself and not to the redirect.

pi@raspberrypi:~$ sudo wpa_passphrase garden turnip22 >> /etc/wpa_supplicant/wpa_supplicant.conf
bash: /etc/wpa_supplicant/wpa_supplicant.conf: Permission denied
pi@raspberrypi:~$

Because the user pi does not have write privileges for the file, you will get a permission denied error. To get around this we can pass the entire command to bash as a string. Use sudo to run bash with root privileges, and bash will execute the contents of the string:

pi@raspberrypi:~$ sudo bash -c “wpa_passphrase garden turnip22 >> /etc/wpa_supplicant/wpa_supplicant.conf”
pi@raspberrypi:~$

If you look again at the conf file, a network configuration has been added. It contains the ssid, the passkey in plain text, and it’s encrypted equivalent. The hash (#) character in front of the plain text key indicates that the line is being treated as a comment and is therefore not interpreted.

pi@raspberrypi:~$ less /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant Group=netdev
update_config=1
country=US

network={
        ssid="garden"
        #psk="turnip22"
        psk=68a1949037d37d3761579259f6665bcec21c9ac163fb8c1c91b602509b36d873039
}

/etc/wpa_supplicant/wpa_supplicant.conf (END)

To begin editing delete the plain text version of the passkey. If you are connecting to a network whose SSID is hidden, add the following line after the SSID in the network configuration:

scan_ssid=1

If you intend to connect to multiple networks, you can enforce a preferred connection order by setting a priority value. The default value is 0. The network with the highest positive integer value will connect first.

pi@raspberrypi:~$ less /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant Group=netdev
update_config=1
country=US

network={
        ssid="garden"
        scan_ssid=1
        psk=68a1949037d37d3761579259f6665bcec21c9ac163fb8c1c91b602509b36d873039
        priority=1
}

/etc/wpa_supplicant/wpa_supplicant.conf (END)

To get the Pi to connect to the network without rebooting, run daemon-reload and then restart the dhcpcd service.

pi@raspberrypi:~$ sudo systemctl daemon-reload
pi@raspberrypi:~$ sudo systemctl restart dhcpcd

To verify connectivity use the ifconfig command again:

pi@raspberrypi:~$ ifconfig wlan0
wlan0: flags=4163<UP,BROADCAST,MULTICAST> mtu 1500
        inet 10.10.1.2 netmask 255.255.255.0 broadcast 10.10.1.255
        inet6 fe80::7c1a:d5f5:de23:3a3 prefixlen 64 scopeid 0x20<link>
	ether b8:27:eb:55:1f:49 txqueuelen 1000 (Ethernet)
	RX packets 1 bytes 576 (576.0 B)
	RX errors 0 dropped 0 overruns 0 frame 0
	TX packets 24 bytes 3876 (3.7 KiB)
	TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
pi@raspberrypi:~$
Posted in Bash, Learn, Linux, Raspberry Pi, Raspbian