6

There are several tutorials out there to setup an Ad Hoc network, for example Ad Hoc setup in RPi 3. But how can I do this using systemd-networkd? And all what I've found is using unprotected communication without encryption. Is it possible to use a setup with WPA encryption?

Ingo
  • 40,606
  • 15
  • 76
  • 189

1 Answers1

10

There are mainly three setups to have a peer to peer network:

  • unprotected ad-hoc interface by configuring the WiFi device
  • unprotected ad-hoc interface using wpa_supplicant (Recommended)
  • Only with suitable (RSN-IBSS capable) USB dongle:
    protected ad-hoc interface using wpa_supplicant and WPA encryption (best solution if possible)
  • ad-hoc interface with additional USB/WiFi dongle for uplink to internet router

Tested with
Raspberry Pi OS with desktop 2020-08-20 based on Buster updated on 2020-11-21.
For older versions look at Revision 11
Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot.


♦ Setup systemd-networkd

Just follow to Use systemd-networkd for general networking. You can use section "♦ Quick Step". Then come back here.

Configure interface wlan0:

rpi ~$ sudo -Es   # if not already done
rpi ~# rfkill unblock wlan
rpi ~# systemctl disable --now wpa_supplicant.service

Create this file:

rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wl*
[Network]
MulticastDNS=yes
LinkLocalAddressing=yes
EOF

♦ Setup unprotected ad-hoc interface by configuring WiFi device

First follow section ♦ Setup systemd-networkd.

To configure the wifi into ad-hoc mode we only have to execute two commands (don't do that now):

iw wlan0 set type ibss
iw wlan0 ibss join IBSS-RPiNet 2412 # frequency 2412 is channel 1

For a mapping of frequencies to channels look at 3. I use a systemd unit so we can also stop the service. Create a new unit file with:

rpi ~# systemctl --force --full edit ad-hoc-interface@.service

In the empty editor insert these statements, save them and quit the editor:

[Unit]
Description=Unprotected ad-hoc (IBSS) interface
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
Before=network.target

[Service]
Environment="SSID=IBSS-RPiNet" "FREQUENCY=2412"
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/iw %I set type ibss
ExecStart=/sbin/iw %I ibss join $SSID $FREQUENCY
ExecStopPost=-/sbin/iw dev %I ibss leave
ExecStopPost=-/sbin/iw %I set type managed

[Install]
WantedBy=network.target

Enable the service:

rpi ~# systemctl enable ad-hoc-interface@wlan0.service

reboot.

Check with:

rpi ~$ iw dev
rpi ~$ iw dev wlan0 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan0 scan | grep -B8 -A3 "SSID: IBSS-RPiNet"

# From another ad hoc connected device you should be able to
rpi ~$ ping -c3 raspberrypi.local


rpi ~$

You should be able to:

rpi ~$ sudo systemctl stop ad-hoc-interface@wlan0.service
rpi ~$ sudo systemctl start ad-hoc-interface@wlan0.service

To change the ssid and frequency you can edit the unit file:

rpi ~$ sudo systemctl --full edit ad-hoc-interface@wlan0.service

♦ Setup unprotected ad-hoc interface using wpa_supplicant (Recommended)

If you start from a fresh flashed Raspbian image then first follow section ♦ Setup systemd-networkd.

If you have tried unprotected ad-hoc interface by configuring the WiFi device then do sudo systemctl disable --now ad-hoc-interface@wlan0.service.

Wpa_supplicant has peer-to-peer enabled by default that is used by WiFi-Direct. This occupies the wlan0 interface so you cannot enable IBSS mode. You will get the error messages:

Nov 21 22:06:17 wpa_supplicant[262]: nl80211: Failed to set interface into IBSS mode
Nov 21 22:06:17 wpa_supplicant[262]: wlan0: Association request to the driver failed

It is important to disable p2p with option p2p_disabled=1. Setup wpa_supplicant with this file and your settings (ssid, country, maybe frequency) and enable it:

rpi ~$ sudo -Es   # if not already done
rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
update_config=1
p2p_disabled=1
country=DE

network={
    ssid="IBSS-RPiNet"
    frequency=2412   # channel 1
    mode=1           # IBSS (ad-hoc, peer-to-peer)
    key_mgmt=NONE
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl enable wpa_supplicant@wlan0.service

reboot.

Check with:

rpi ~$ iw dev
rpi ~$ iw dev wlan0 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan0 scan | grep -B8 -A3 "IBSS-RPiNet"

# From another ad hoc connected device you should be able to
rpi ~$ ping -c3 raspberrypi.local

♦ Setup protected RSN (WPA) ad-hoc interface using wpa_supplicant (best solution if possible)

First of all it must be said that Raspberry Pi does not support encrypted IBSS connections!. You have to use an additional USB WiFi dongle that usually registers an interface wlan1. My setup shows:

rpi ~$ iw list | grep -P "Wiphy|RSN-IBSS"
Wiphy phy1
        Device supports RSN-IBSS.
Wiphy phy0

You cannot find this support entry for Wiphy pyh0 that is the on-board WiFi device.

So plug in your compatible WiFi dongle and if you start from a fresh flashed Raspbian image then first follow section ♦ Setup systemd-networkd.

If you have tried unprotected ad-hoc interface by configuring the WiFi device then do sudo systemctl disable --now ad-hoc-interface@wlan0.service.

If you have tried unprotected ad-hoc interface using wpa_supplicant then do sudo systemctl disable --now wpa_supplicant@wlan0.service.

Then Setup wpa_supplicant with this file and your settings (country, ssid, psk and frequency) and enable it:

rpi ~$ sudo -Es   # if not already done
rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan1.conf <<EOF
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
update_config=1
p2p_disabled=1
country=DE

network={
    ssid="IBSS-RPiNet"
    key_mgmt=WPA-PSK
    proto=RSN
    psk="verySecretPassword"
    mode=1
    frequency=2412
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan1.conf
rpi ~# systemctl enable wpa_supplicant@wlan1.service

reboot.

Check with:

rpi ~$ iw dev
rpi ~$ iw dev wlan1 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan1 scan | grep -B8 -A3 "IBSS-RPiNet"

# From another ad hoc connected device you should be able to
rpi ~$ ping -c3 raspberrypi.local

♦ Installing additional nodes

On additional nodes setup ad-hoc mode just the same way you have done with the first one as shown above.


♦ Setup ad-hoc interface with additional USB/WiFi dongle for uplink to internet router

If you want an uplink connection to an internet router you need an additional USB/WiFi dongle. I will use the onboard WiFi device for the uplink, so you are free to use the dongle as protected RSN interface if possible.

First follow section ♦ Setup systemd-networkd if not already done. Then create these files with your settings (country, ssid, psk):

rpi ~$ sudo -Es   # if not already done
rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
update_config=1
p2p_disabled=1
country=DE

network={
    ssid="TestNet"
    psk="verySecretPassword"
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl enable wpa_supplicant@wlan0.service

rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
DHCP=ipv4
EOF

and for wlan1:

rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan1.conf <<EOF
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
update_config=1
p2p_disabled=1
country=DE

network={
    ssid="IBSS-RPiNet"
    frequency=2412   # channel 1
    mode=1           # IBSS (ad-hoc, peer-to-peer)
    key_mgmt=NONE
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan1.conf
rpi ~# systemctl enable wpa_supplicant@wlan1.service

rpi ~# cat > /etc/systemd/network/12-wlan1.network <<EOF
[Match]
Name=wlan1
[Network]
MulticastDNS=yes
LinkLocalAddressing=yes
EOF

reboot.

# you should be able to
rpi ~$ ping google.com

# From another ad hoc connected device you should be able to
rpi ~$ ping -c3 raspberrypi.local

♦ For developers and for troubleshooting

This are some things I have done to find the answer. I do not want to discard them because it has taken some effort and it may help me later and others on similar issues.

manual setup
For testing how it works you can execute these commands [2]. Be sure the interface isn't occupied by another service:

rpi ~$ sudo -Es
rpi ~# iw wlan0 set type ibss
rpi ~# ip link set wlan0 up
rpi ~# iw wlan0 ibss join RPiNet 2432
rpi ~# ip addr add 192.168.1.2/24 dev wlan0
rpi ~# ip route add 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.2
rpi ~# exit

rpi ~$ # check with:
rpi ~$ iw dev
rpi ~$ iw dev wlan0 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan0 scan | grep -B8 -A3 "SSID: RPiNet"

You can do this also on a second raspi with another ip address, e.g. 192.168.1.3. Then you can ping it.


refefences:
[1] Howto migrate from networking to systemd-networkd with dynamic failover
[2] Ad-hoc networking
[3] List of WLAN channels
[4] Raspberry Pi 2018-04-18 - Cannot put device into adhoc mode
[5] Kernel trace in brcmfmac wifi driver when joining ad-hoc network w/another brcmfmac device
[6] Linux WiFi Ad-hoc mode
[7] What is the difference between Ad-Hoc and Mesh Network? (also with p2p)
[8] Why Wi-Fi Direct can not replace Ad-hoc mode

Ingo
  • 40,606
  • 15
  • 76
  • 189