It is time to revisit of the simple wifi setup as much has changed since. This time, however, we will not only cover wifi, but also wired connections as well as DNS.

Wired networking

This wired setup is based on systemd-networkd, which typically comes with systemd. If you use a systemd-based Linux, you should be ready to go right away. It further assumes that acquiring an IP address via DHCP once a cable is plugged in the typical usecase.1

Create the file /etc/systemd/network/cable.network2:

[Match]
Name=<name of the wired network device> <second one if applicable> [<more ...>]

[Network]
DHCP=yes
IPv6PrivacyExtensions=true

[DHCP]
Anonymize=true

Then systemctl enable --now systemd-networkd and plug in a cable, wired networking with DHCP is up and running.

Wireless networking

The wireless setup is based on iwd, the currently vastly superior tool for wireless networking on Linux compared to existing alternatives such as wpa_supplicant (the effectively only other contender in this game) and software using it such as NetworkManager and netctl. It requires iwd as well as Linux >= 4.20 for full operation.

Create the file /etc/iwd/main.conf:

[General]
# uncomment for setting the wifi interface name yourself
# see https://iwd.wiki.kernel.org/interface_lifecycle
#UseDefaultInterface=true

# enable builtin DHCP-client within iwd for wifi
EnableNetworkConfiguration=true

# randomizes mac-address every time iwd starts or the hardware is initially detected
AddressRandomization=once

Then systemctl enable --now iwd, wireless networking with DHCP is up and running, blazingly fast and stable.

You might want to take a look at the previous post to deal with race conditions that might be introduced due to iwd being significantly faster than other wifi-solutions on Linux.

Frontends

iwd stores its known networks in /var/lib/iwd. To add, modify or delete them, several options are available:

iwctl

You can now connect to simple PSK wifi networks in the iwctl shell:

[iwctl] station <devicename> get-networks
…
[iwctl] station <devicename> connect <network-name>

iwctl will ask you for the password, iwd will memorize it for later connections and autoconnect the next time the network appears. Currently, iwctl only supports creating simple password-only network connections, for more complex network setups, instead of iwctl asking you all the nifty details of an enterprise connection, use the file-based config instead. For everything else, just type help within iwctl.

file-based config

If you have more complex wifi-setups, you can simply drop a network configuration file in /var/lib/iwd. The files must be named as networkname.protocol. You can find the protocol listed in the output of get-networks in the iwctl-shell. To fill the file, take a look to the network configuration settings in the iwd documentation or the iwd.network manpage.

For example, to use the University Heidelberg’s eduroam network, create the file /var/lib/iwd/eduroam.8021x containing

[Security]
EAP-Method=TTLS
EAP-Identity=<anonymous-identity>
EAP-TTLS-CACert=/etc/ssl/certs/T-TeleSec_GlobalRoot_Class_2.pem
EAP-TTLS-Phase2-Method=MSCHAPV2
EAP-TTLS-Phase2-Identity=<uni-id>@uni-heidelberg.de
EAP-TTLS-Phase2-Password=<your University account password>

For other institutions, the details in the method might vary, of course. See man iwd.network for details. It also includes several examples for almost all possible configurations.

Network Manager

You can also use Network Manager for a more graphical experience, you just have to enable the iwd-backend for NetworkManager to use it. In addition to that, double check if you have the right NetworkManager version for your iwd version, just as a precaution.

DNS

For modern domain name resolution, you can use systemd-resolved, which provides statistics, automated caching of DNS requests, DNSSEC validation and much more. To use it, ensure systemd-resolved is installed3 and systemctl enable --now systemd-resolved. Ensure that /etc/resolv.conf is symlinked to /run/systemd/resolve/stub-resolv.conf, if not

ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

takes care of it. Afterwards, you can change the default fallback DNS servers and other things in /etc/systemd/resolved.conf, if desired and otherwise enjoy resolvectl and resolvectl statistics.

Miscellaneous optimizations

Binding iwd to the wifi-device

To disable iwd when the wifi is not present (and iwd therefore not needed) create the file /etc/udev/rules.d/wifi.rules containing

# bind iwd to wifi
SUBSYSTEM=="rfkill", ENV{RFKILL_NAME}=="phy0", ENV{RFKILL_TYPE}=="wlan", ACTION=="change", ENV{RFKILL_STATE}=="1", RUN+="/usr/bin/systemctl --no-block start iwd.service"
SUBSYSTEM=="rfkill", ENV{RFKILL_NAME}=="phy0", ENV{RFKILL_TYPE}=="wlan", ACTION=="change", ENV{RFKILL_STATE}=="0", RUN+="/usr/bin/systemctl --no-block stop iwd.service"

If AddressRamdomization=once is set in the configuration, this udev rule has the nice side-effect that, as iwd starts nanew when the wifi is un-rfkilled, the MAC address of the interface is randomized again.

Persistent device naming

If you want to have persistent device names, for example for devices showing up in a status bar or something similar, this ist easiest achieved by creating a link-file4 /etc/systemd/network. To persistently name the wireless device wifi, create /etc/systemd/network/00-wifi.link containing

[Match]
MACAddress=ab:cd:ef:12:34:56  # wifi's original MAC address

[Link]
Name=wifi  # can be used for matching in the according *.network-file

If you do this for any device operated by iwd, ensure you have UseDefaultInterface=true set in section [General] in /etc/iwd/main.conf.

Setting specific MAC addresses for specific wifi networks and randomizing on every connect

In case you need to set a specific address for a specific wireless network, iwd>=1.6 allows using AddressOverride= inside a network configuration file. For this to take effect, however, AddressRandomization=once must be dropped from /etc/iwd/main.conf. This makes iwd generate persistent MAC addresses per network (generated from its SSID and real hardware address) by default and allows AddressOverride to take effect. Additionally, a network file can contain AlwaysRandomizeAddress=true, which randomizes the MAC address on each connect for this network (also only takes effect when AddressRandomization is not set or set do its default value in main.conf. However, due to kernel limitations, each change of a MAC address requires powercyling the card. This leads to (for iwd standards) singificantly prolonged connection times (by ≈300-400ms). Given that, as long as you do not require AddressOverride, AddressRandomization=once gives you fast connection times while still randomizing your card’s MAC address regularly enough.

Thanks to rixx for proofreading and helpful suggestions.


  1. Although this if of course an assumption, my personal statistics says that this setup has worked with 100% of all network cables I ever plugged into my laptop so far. ↩︎

  2. see man systemd.network (preferrably, as it fits your version) or https://www.freedesktop.org/software/systemd/man/systemd.network.html for the latest docs. ↩︎

  3. The simplest check is systemctl status systemd-resolved. ↩︎

  4. see man systemd.link or https://www.freedesktop.org/software/systemd/man/systemd.link.html ↩︎