━━━ Setting up an access point ━━━
We are talking about an access point together with an ethernet port eth0.
If you want an access point together with a wlan0 client connection to another wifi network (wlan repeater) then look at Access point as WiFi router/repeater, optional with bridge.
It is possible to configure Raspbian Stretch as a wifi access point without installing additional software. All needed components are available: networking, DHCP server and bridging comes with systemd-networkd and wifi can be setup with wpa_supplicant. Connecting two interfaces eth0 and wlan0 can be done by routing or by bridging. Below first the setup for quick installation and then the details. First we have to switch over to systemd-networkd.
Tested with
Raspbian Buster Lite 2020-02-13 on a Raspberry Pi 4B updated at 2020-05-12.
Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot
.
Here you can find the last tested revision for previous Raspbian versions.
♦ General setup
Switch over to systemd-networkd
Just follow to Use systemd-networkd for general networking. You can use section "♦ Quick Step". Then come back here.
Configure wpa_supplicant as access point
To configure wpa_supplicant as access point create this file with your settings for country=
, ssid=
, psk=
and maybe frequency=
. You can just copy and paste this in one block to your command line beginning with cat
and including both EOF (delimiter EOF will not get part of the file):
rpi ~$ sudo -Es # if not already done
rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="RPiNet"
mode=2
frequency=2437
#key_mgmt=NONE # uncomment this for an open hotspot
# delete next 3 lines if key_mgmt=NONE
key_mgmt=WPA-PSK
proto=RSN WPA
psk="password"
}
EOF
rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl disable wpa_supplicant.service
rpi ~# systemctl enable wpa_supplicant@wlan0.service
rpi ~# rfkill unblock wlan
Finished General setup. Go back.
♦ Setting up a stand alone access point
Example for this setup:
wifi
mobile-phone <~.~.~.~.~> (wlan0)RPi(eth0)
\ /
(dhcp) 192.168.4.1
Do "General setup" then create the following file to configure wlan0. We only have the access point. There is no ethernet device configured.
rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
Address=192.168.4.1/24
MulticastDNS=yes
DHCPServer=yes
EOF
If you want this then reboot.
That's it.
Otherwise go on, no need to reboot at this time.
♦ Setting up an access point and with eth0, without routing
Example for this setup:
|
wifi | wired wan
mobile-phone <~.~.~.~.~> (wlan0)RPi(eth0) <---------> router <---> INTERNET
\ / | \ /
(dhcp) 192.168.4.1 | (dhcp) 192.168.50.1
Setup
Do "Setting up a stand alone access point" then create the following file to configure eth0.
rpi ~$ sudo -Es # if not already executed before
rpi ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
DHCP=yes
EOF
Reboot.
That's it.
Details
Interface eth0 is connected with an ethernet cable to the internet router and gets it configuration by DHCP from the internet router. It is no problem to give it a static ip address with e.g. Address=192.168.50.2
instead of DHCP=yes
.
Without routing you cannot get into the internet with the mobile-phone. You can only get into it from the RPi itself to get updates or something like.
♦ Setting up an access point and with eth0, with NAT (recommended)
Example for this setup:
wifi wired wan
mobile-phone <~.~.~.~.~> (wlan0)RPi(eth0) <---------> router <---> INTERNET
\ / \
(dhcp) 192.168.4.1 (dhcp)
Setup
Do "General setup" then create the following files to configure wlan0 and eth0. If you have tried one of the previous setups then you can just overwrite the two files. Be sure that you use a different subnet for the access point than that from the router. The router in this example does not use subnet 192.168.4.0/24. If you need another subnet then just change the Address line, e.g. Address=192.168.5.1/24
.
rpi ~$ sudo -Es # if not already executed before
rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
Address=192.168.4.1/24
MulticastDNS=yes
# IPMasquerade is doing NAT
IPMasquerade=yes
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 1.1.1.1
EOF
rpi ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
DHCP=yes
EOF
Reboot.
That's it.
Details
If you have no access to the internet router you can fake it with NAT (network address translation) to tell it a lie that all packages are coming from your RasPi AP. But this is not clean routing and has limitations. Clients on the subnet of the router cannot connect to clients on the wifi. But in most cases this is not needed so this setup is recommended because it simplifies the setup. If you need to connect to the wifi clients from the router network then you have to use full routing as desribed in the next section.
♦ Setting up an access point and with eth0, with routing
Example for this setup:
wifi wired wan
mobile-phone <~.~.~.~.~> (wlan0)RPi(eth0) <---------> router <---> INTERNET
\ / \ /
(dhcp) 192.168.4.1 192.168.50.2 192.168.50.1
Setup
Do "General setup" then create the following files to configure wlan0 and eth0. If you have tried one of the previous setups then you can just overwrite the two files. Be sure that you use different subnets for the access point and the router network. We have to use static ip addresses because we must use them as gateways.
rpi ~$ sudo -Es # if not already executed before
rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
Address=192.168.4.1/24
MulticastDNS=yes
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 1.1.1.1
EOF
rpi ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Address=192.168.50.2/24
Gateway=192.168.50.1
DNS=84.200.69.80 1.1.1.1
IPForward=yes
EOF
Reboot.
To get routing complete working you have to set a static route in your internet router so it can find the route for back coming packages over the RasPi to the clients connected by wifi to the access point. On most internet router you can set a static route but how to do that varies from model to model. It's up to you to find it out. For example your RasPi eth0 interface has the static ip address 192.168.50.2. Then on your router the gateway (next hop) is 192.168.50.2, destination network is 192.168.4.0/24 (or 192.168.4.0 netmask 255.255.255.0).
That means for the internet router: "send all packages belonging to subnet 192.168.4.0/24
(destination network from AP) to the next router on my subnet, the RasPi AP 192.168.50.2
(gateway). It knows where to go on."
That's it.
♦ Setting up an access point with a bridge
Example for this setup:
RPi
wifi ┌──────bridge──────┐ wired wan
mobile-phone <.~.~.~> │(wlan0) br0 (eth0)│ <-------> router <-----> INTERNET
\ | / DHCP-server
(dhcp (dhcp 192.168.50.1
from router) from router)
If you have already an ethernet network with DHCP server and internet router and you want to expand it with a wifi access point but with the same ip addresses then you use a bridge. This is often used as an uplink to a router.
Setup
Do "General setup" then create the following three files to configure the network interfaces. If you have tried one of the previous setups then you can just delete all files in /etc/systemd/network/
except 99-default.link
if present. The ip addresses are examples. You have to use your own.
rpi ~$ sudo -Es # if not already executed before
rpi ~# cat > /etc/systemd/network/02-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
EOF
rpi ~# cat > /etc/systemd/network/04-br0_add-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Bridge=br0
EOF
rpi ~# cat > /etc/systemd/network/12-br0_up.network <<EOF
[Match]
Name=br0
[Network]
MulticastDNS=yes
DHCP=yes
to use static IP uncomment these and comment DHCP=yes
#Address=192.168.50.60/24
#Gateway=192.168.50.1
#DNS=84.200.69.80 1.1.1.1
EOF
Now we have to tell wpa_supplicant to use a bridge. We do it by modifying its service with:
rpi ~# systemctl edit wpa_supplicant@wlan0.service
In the empty editor insert these statements, save them and quit the editor:
[Service]
ExecStartPre=/sbin/iw dev %i set type __ap
ExecStartPre=/bin/ip link set %i master br0
ExecStart=
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dnl80211,wext -i%I -bbr0
ExecStopPost=-/bin/ip link set %i nomaster
ExecStopPost=-/sbin/iw dev %i set type managed
Reboot.
That's it.
Details
We have to tell wpa_supplicant that its interface wlan0 is slave of a bridge. Otherwise it will reject client connects with "wrong password" means the key negotiation does not work. When we tell /sbin/wpa_supplicant with option -dbr0
to use a bridge for wlan0 then the interface must already be a member of the bridge. That's what we do with the drop in file (overlay) for the wpa_supplicant service. The empty statement ExecStart=
deletes the old entry. Otherwise you have two lines ExecStart=
and wpa_supplicant will start two times. The original ExecStart=
you can view with systemctl cat wpa_supplicant@wlan0.service
.
Normally the router you are connected to with the ethernet cable has a DHCP server enabled. The bridge is also transparent for DHCP requests from the stations (devices connected to the access point) so you don't have to worry about configuration of its interfaces with ip addresses and options. The router will serve it.
excursus:
But if the router doesn't have a DHCP server, you can setup one on the RasPi. systemd-networkd has options to configure its built-in DHCP server but the problem is that systemd-networkd assumes it is running on the router itself and that's not true in this case. It will serve wrong options to the stations, in particular the router option. There is no way to configure it. So we have to install dnsmasq
in this case that can be configured as needed. Install and configure it with (example, use your own ip addresses):
rpi ~$ sudo -Es
rpi ~# apt install dnsmasq
rpi ~# systemctl stop dnsmasq
rpi ~# mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
rpi ~# cat > /etc/dnsmasq.conf <<EOF
interface=br0
dhcp-range=192.168.50.128,192.168.50.164,255.255.255.0,24h
dhcp-option=option:router,192.168.50.1
dhcp-option=option:dns-server,8.8.8.8,1.1.1.1
EOF
rpi ~# systemctl start dnsmasq
rpi ~# exit
rpi ~$
In this example are ip addresses 192.168.50.128 to 192.168.50.164 reserved to give to stations. For other static ip addresses use one outside this pool, also the ip address for the bridge itself.
♦ Optimizing
When starting wpa_supplicant you mostly get this messages in the journal:
wpa_supplicant[427]: random: Cannot read from /dev/random: Resource temporarily unavailable
wpa_supplicant[427]: random: Only 12/20 bytes of strong random data available from /dev/random
wpa_supplicant[427]: random: Not enough entropy pool available for secure operations
wpa_supplicant[427]: WPA: Not enough entropy in random pool for secure operations - update keys later when the first station connects
It is not a big issue. wpa_supplicant needs random numbers to generate encrpyting keys. This is done a little bit slow so it has to wait. Fortunately the RasPi has a build in True Random Number Generator (TRNG). We can use it and speed up getting random numbers by installing a piece of software (3) with:
rpi ~$ sudo apt install rng-tools
Update:
Since Raspbian Stretch 2019-04-08 there is no need to install rng-tools
. They are installed by default.
♦ Troubleshooting
systemd-networkd
Look at the status of a service:
rpi ~$ systemctl status systemd-networkd.service
rpi ~$ systemctl status wpa_supplicant@wlan0.service
Or even a bit more:
rpi ~$ journalctl --boot --pager-end
I found it helpful to follow the ongoing logging:
rpi ~$ journalctl --boot --follow
If you have made a drop in file you can look at the result:
rpi ~$ systemctl cat wpa_supplicant@wlan0.service
To check the runtime environment of a unit you can show it and for example look if there are two ExecStart=
lines:
rpi ~$ systemctl show wpa_supplicant@wlan0.service
And if nothing others help you can enable the debug option from /sbin/wpa_supplicant
with -d
in a drop in file:
rpi ~$ sudo systemctl edit wpa_supplicant@wlan0.service
ExecStart=
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dnl80211,wext -i%I -bbr0 -d
The output is in the journal. This way I have found the issue with the wrong key negotiation.
wifi
If you have setup the access point you should find it with a mobile phone. Showing the available networks, it is presented with name RPiNet and you can connect to it. On the RasPi you can also use the command:
rpi ~$ sudo iw dev wlan0 info
phy#0
Interface wlan0
ifindex 3
wdev 0x2
addr b8:27:eb:06:e8:8b
ssid RPiNet
type AP
channel 1 (2412 MHz), width: 20 MHz, center1: 2412 MHz
As you can see it is type AP (access point) and it will also show you what channel it is using. A problem may be to translate a channel into frequency. The frequency must match a channel. You can look at (2) for a list of WLAN channels. For example to use channel 36 on the 5.1 GHz band you have to set frequency=5180
in /etc/wpa_supplicant\wpa_supplicant.conf
. But you must be sure that your wifi supports the 5.1 GHz band. You can check with sudo iw phy
. This will give you a bunch of information. It must also contain supported frequencies above 5000 MHz. If you only see frequencies of 24xx MHz then of course you can only use this.
Another point could be random numbers. For encrypting keys for secured connections wpa_supplicant needs random numbers. Generating this is very slow on a Raspberry Pi. If it does not have enough entropy to generate encrypting keys wpa_supplicant will reject the authentication. You can look with cat /proc/sys/kernel/random/entropy_avail
how many entropy is available. It should be >1000 to work quick enough. To speed up this, the rng-tools
are installed by default. Look at the section Optimizing for further information.
references:
[1] Howto migrate from networking to systemd-networkd with dynamic failover
[2] List of WLAN channels
[3] Rng-tools
ls /var/log/journal/
. You will see a directory that looks likefa9462093e8d419cb646d0a0c44771c2
. This is the storage for the journal you access withjournalctl
. I will update my answer. – Ingo Aug 18 '18 at 06:59proto=WPA2
in the AP configuration. My phone, at least, complains about "weak security" without it. – Robin Dinse Mar 31 '19 at 00:21proto=RSN
. That's what the docu prefers (namingproto=WPA2
an alias). – Ingo Mar 31 '19 at 00:53