Raspberry Pi Asked on November 28, 2021
I need a wireless access point that is bridged with the wired ethernet port and that is connected to another wifi internet router with a client connection as uplink. All devices connected to the RasPi either by wifi or by wired ethernet should have access to the internet and should be able to connect to each other.
How can I achieve this with a Raspberry Pi?
This is in addition to the Ingo’s outstanding description. Here we would like to use the default networking system of Raspbian (assuming to have previously configured it) rather than replacing it with systemd-networkd.
The standard networking mode to configure TCP/IP in Raspbian/Raspberry Pi OS is mentioned in the related documentation. At the time of writing, dhcpcd is used (dhcpcd5 package). This mode replaced the former Debian Networking (ifupdown package), where the configuration was done in /etc/network/interfaces. The documentation also describes how to setup a Wi-Fi client/Wi-Fi station via wpa_supplicant by configuring /etc/wpa_supplicant/wpa_supplicant.conf to connect the Raspberry Pi to an existing wireless LAN on its default wlan0 interface; alternatively, it describes how to set up a routed wireless access point on the same wlan0 interface (instead of the Wi-Fi station). We will use this last document as a reference, changing it in just a few points to configure the same wireless board to enable a wlan0 interface (Wi-Fi Client/Station, connected to another wifi network or internet router) as well as a Wi-Fi Access Point named uap0 (e.g., to define a wlan repeater):
As DNS forwarder and DHCP Server, we will keep dnsmasq, used in the previously mentioned Raspberry configuration. We will also keep DNS Multicast (libnss-mdns) and Zeroconf/Apple Bonjour (avahi-daemon). We will not use systemd-resolved.
Noticeably, we suppose that the older ifupdown mode is not used, meaning that /etc/network/interfaces is left to its default configuration, with no stanzas defined, apart from source-directory /etc/network/interfaces.d
, with any other note or statement commented out through an initial #
, and that /etc/network/interfaces.d directory is left empty. We also assume that sudo systemctl status dhcpcd
returns that the service is active.
Example for this setup:
(dhcp 192.168.1.3 from router) +----------------------+ (192.168.1.1
| | / +DHCP server)
wifi (eth0) wifi uplink | /
mobile-phone <~.~.~.~.~> (ap0)RPi(wlan0) <.~.~.~.~.> router <───> INTERNET
╲ ╱ ╲ wan
(dhcp 192.168.50.50 (192.168.50.1 (dhcp 192.168.1.2
from RPi) +DHCP server) from router)
Install dnsmasq and hostapd (like in Raspberry’s documentation):
sudo -Es
apt install -y dnsmasq hostapd
Configure hostapd for the Access Point:
test -f /etc/hostapd/hostapd.conf || cat > /etc/hostapd/hostapd.conf <<EOF
ctrl_interface=/var/run/hostapd
driver=nl80211
country_code=IT # Use your country code
ssid=YourSessionIdentifier
hw_mode=g
channel=7
auth_algs=1
wpa=2
wpa_passphrase=verySecretPassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
EOF
chmod 600 /etc/hostapd/hostapd.conf
# edit /etc/hostapd/hostapd.conf and verify it
Test creation and deletion of uap0 virtual device on wlan0:
/sbin/iw dev wlan0 interface add uap0 type __ap
/sbin/iw dev uap0 del
No error should be produced. If the first command fails with Device or resource busy (-16), it means that the device driver does not allow creating additional "Type AP" interfaces, which are busy for other services (e.g., an AP or a P2P-GO group is already active and has to be deleted to allow this new service to be activated).
Check this command:
iw list | grep "Supported interface modes" -A 8
It should return one line including AP. If only STA and managed are returned, the device driver of the board (or the hw itself) does not allow creating an AP interface. Output of the Raspberry Pi 4:
Supported interface modes:
* IBSS
* managed
* AP
* P2P-client
* P2P-GO
* P2P-device
Use this command to check the allowed combination options:
iw list | grep "valid interface combinations" -A 8
Every line contains alternative combinations. With the Broadcom BCM2711 SoC included in a Raspberry Pi 4 B, I get the following:
valid interface combinations:
* #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
total <= 3, #channels <= 2
* #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1,
total <= 4, #channels <= 1
Device supports scan flush.
Device supports randomizing MAC-addr in sched scans.
Supported extended features:
* [ 4WAY_HANDSHAKE_STA_PSK ]: 4-way handshake with PSK in station mode
It means that not more than one AP or P2P-GO interface can be configured at the same time.
If the test to create and delete the uap0 virtual device succeeds, you can go on, starting the uap0 AP virtual interface on wlan0:
SYSTEMD_EDITOR=tee systemctl edit --force --full [email protected] <<EOF
[Unit]
Description=IEEE 802.11 %p%i AP on wlan%i with hostapd
After=network.target
[Service]
Type=forking
PIDFile=/run/hostapd.pid
Restart=on-failure
RestartSec=2
Environment=DAEMON_CONF=/etc/hostapd/hostapd.conf
EnvironmentFile=-/etc/default/hostapd
ExecStartPre=/sbin/iw dev wlan%i interface add %p%i type __ap
ExecStart=/usr/sbin/hostapd -i %p%i -P /run/hostapd.pid -B $DAEMON_OPTS ${DAEMON_CONF}
ExecStopPost=-/sbin/iw dev %p0 del
[Install]
WantedBy=multi-user.target
EOF
systemctl stop hostapd # if the default hostapd service was active before
systemctl disable hostapd # if the default hostapd service was enabled before
systemctl enable [email protected]
rfkill unblock wlan
You might possibly want to manually edit this in the future, with:
sudo -Es
#export SYSTEMD_EDITOR=vi # uncomment this if you like "vi", otherwise "edit" will be used
export SYSTEMD_EDITOR=vi systemctl edit --full [email protected]
exit
Some configurations (especially related to the old ifupdown mode) consider adding a static rule in /etc/udev/rules.d to bring up the uap0 AP interface, like ACTION=="add", SUBSYSTEM=="ieee80211", KERNEL=="phy0", RUN+="/sbin/iw phy %k interface add uap0 type __ap"
; as we are parametrizing this with the ExecStartPre
and ExecStopPost
statements of the uap@
service definition, it is important that your configuration does not include such rule in /etc/udev/rules.d.
Now we setup wpa_supplicant for client connections.
We need to update dhcpcd (the default a DHCP client) by editing /etc/dhcpcd.conf, adding the following to the end (these settings replace the configuration suggested in Raspberry’s site, which defined a static address to wlan0 instead of a DHCP Client; ref. "Define the wireless interface IP configuration"):
interface wlan0 # these two lines are not strictly needed, as wlan0 uses the default configuration
dhcp
interface uap0 # this defines static addressing to uap0 and disables wpa_supplicant for this interface
static ip_address=192.168.50.1/24
ipv4only
nohook wpa_supplicant
Comparing with the description in Raspberry’s site, notice that, other than removing the static address, we will not use nohook wpa_supplicant
under interface wlan0, so that wpa_supplicant is activated by a default dhcpcd hook.
To verify this hook, check files included in the /lib/dhcpcd/dhcpcd-hooks directory: one of this is 10-wpa_supplicant, which is the responsible for activating wpa_supplicant on the new interface. It is automatically run when the new interface is discovered by dhcpcd.
The file used by wpa_supplicant (Wi-Fi Station agent) is the default one: /etc/wpa_supplicant/wpa_supplicant.conf. We assume that it is already configured and working; otherwise you can use a template to configure it:
test -f /etc/wpa_supplicant/wpa_supplicant.conf || cat >/etc/wpa_supplicant/wpa_supplicant.conf <<EOF
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=IT
network={
ssid="TestNet"
psk="realyNotMyPassword"
key_mgmt=WPA-PSK
}
EOF
# edit /etc/wpa_supplicant/wpa_supplicant.conf and verify it
chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf
systemctl disable wpa_supplicant.service # not used, as the agent is hooked by dhcpcd
We can then follow Raspberry’s documentation to enable routing and IP masquerading:
sudo DEBIAN_FRONTEND=noninteractive apt install -y netfilter-persistent iptables-persistent
Create a file using the following command, with the contents below:
test -f /etc/sysctl.d/routed-ap.conf || cat >/etc/sysctl.d/routed-ap.conf <<EOF
# https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md
# Enable IPv4 routing
net.ipv4.ip_forward=1
EOF
# edit /etc/sysctl.d/routed-ap.conf and verify it
Updating the firewall rules:
# Add firewall rules
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o uap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i uap0 -o wlan0 -j ACCEPT
sudo netfilter-persistent save
dnsmasq configuration follows Raspberry’s example:
cat >> /etc/dnsmasq.conf <<EOF
# disables dnsmasq reading any other files like /etc/resolv.conf for nameservers
no-resolv
interface=uap0
no-dhcp-interface=lo,wlan0
domain-needed
bogus-priv
server=8.8.8.8
dhcp-range=192.168.50.50,192.168.50.199,12h
dhcp-option=3,192.168.50.1
EOF
# edit /etc/dnsmasq.conf and verify it
The configuration is finished. You must reboot before testing.
reboot
The systemctl command on [email protected] allows disabling, enabling and monitoring the AP function; for instance, to stop AP, to remove the virtual interface and to free up device driver resources, you can issue:
sudo systemctl stop uap@0
To start again the service:
sudo systemctl stop dhcpcd && sudo systemctl start uap@0 && sudo systemctl start dhcpcd
Notice that in both cases wlan0 link goes down for some seconds and then goes up again; an active TCP connection on wlan0 is not lost anyway.
Temporarily stopping dhcpcd before starting up uap0 is needed to also stop wpa_supplicant (hooked by dhcpcd); this is in order to avoid the Broadcom driver issue "failed to enable fw supplicant" (for some weird reason the device driver attempts to reload an already loaded firmware supplicant for this interface).
If wlan1 is configured in place of the default wlan0 Wi-Fi function of the Raspberry Pi (e.g., a USB wireless dongle supporting access point mode), replace wlan0 with wlan1, uap@0 with uap@1, uap0 with uap1 every time "wlan0", "uap@0" and "uap0" are mentioned.
To use a different root name than uap for the AP interface (e.g., referring to uap0), change it with the new name every time it is mentioned.
Raspberry’s documentation describes how to set up a Raspberry Pi as a bridged wireless access point. The Ethernet interface is used to connect the Raspberry to the upstream router (e.g., provided with Internet access and featuring a DHCP server). In such configuration, the Raspberry Pi itself can be accessed by its br0 wireless interface, but not by its Ethernet interface, which participates to the bridging function and is not assigned an IP address; also, to avoid resetting active sessions, the Ethernet interface must not be disconnected from the upstream router. As described by Ingo, it is not possible to bridge the Wi-Fi client connections to the upstream router.
wpa_supplicant is interfaced to wpa_cli through UNIX sockets and when logging into the system with pi user, you should be able to successfully control wpa_supplicant and related configuration.
The following steps allow verifying wpa_supplicant permissions.
Check who starts wpa_supplicant and that you do not have more services activating this daemon. Assuming that the tested interface is wlan0, if you rely on dhcpcd you should be able to verify that wpa_supplicant does not start after temporarily adding denyinterfaces wlan0
as the first line of /etc/dhcpcd.conf (sudo systemctl restart dhcpcd
).
After restoring /etc/dhcpcd.conf and restarting the service, you shoud get something like the following with ps -ef | grep wpa_supplicant
:
root 613 1 0 Feb20 ? 01:50:03 wpa_supplicant -B -c/etc/wpa_supplicant/wpa_supplicant.conf -iwlan0 -Dnl80211,wext
Notice the root user, its dependency to the parent process id 1 and the command line arguments (-B
means daemon, -c
with the appropriate configuration file, -i
with the related interface, -D
with standard drivers).
Specifically, you need to verify the presence of -i
command-line option if wpa_supplicant.conf declares GROUP=netdev.
Check also journalctl -t dhcpcd-run-hooks
; you should get dhcpcd-run-hooks[7548]: wlan0: starting wpa_supplicant
.
If you do ls -l /etc/wpa_supplicant/wpa_supplicant.conf
you should get the following:
-rw-r--r-- 1 root root 1155 Feb 27 14:26 /etc/wpa_supplicant/wpa_supplicant.conf
Notice the permissions, the owner and the group.
If you edit /etc/wpa_supplicant/wpa_supplicant.conf, yous should verify
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
Notice /var/run/wpa_supplicant directory and netdev group.
If you do ls -ld /var/run/wpa_supplicant
, tou should get the following:
drwxr-x--- 2 root netdev 100 Feb 20 11:01 /var/run/wpa_supplicant
Notice the permissions, the owner which should be root and the group which should be netdev, thanks to GROUP=netdev in wpa_supplicant.conf.
If you do ls -l /var/run/wpa_supplicant
, you should get something like
total 0
srwxrwx--- 1 root netdev 0 Feb 20 11:00 p2p-dev-wlan0
srwxrwx--- 1 root netdev 0 Feb 20 11:00 wlan0
Notice the presence of the wlan0
Unix socket (srwxrwx---
), as well as the P2P Device (p2p-dev-wlan0).
Notice the owner, that shall be root, and the group, which is again netdev.
If you do iw dev
with wpa_supplicant active, one of the returned item should be:
Unnamed/non-netdev interface
wdev 0x2
addr ee:11:6c:59:a3:d4
type P2P-device
txpower 31.00 dBm
which refers to the P2P device (type P2P-device
).
Now edit /etc/passwd, check the presence of root users and pi users:
root:x:0:0:root:/root:/bin/bash
...
pi:x:1000:1000:,,,:/home/pi:/bin/bash
...
Edit /etc/group anch check the netdev group:
netdev:x:109:pi
User pi should be associated to a number of groups, including netdev.
Now verify that you are logged into the system with *pi user, do id
:
uid=1000(pi) gid=1000(pi) groups=1000(pi),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),105(input),109(netdev),997(gpio),998(i2c),999(spi)
One of the group shall be netdev
.
Verify that you can successfully run wpa_cli, without a need of sudo:
wpa_cli -i wlan0 ping
wpa_cli -i p2p-dev-wlan0 ping
You should get PONG twice.
Run wpa_cli -i p2p-dev-wlan0 reconfigure
; you shoud get OK.
Answered by ircama on November 28, 2021
This answer is not thought for setup. For setup look at the other answer to this question starting with Setup wifi repeater. This is mainly for troubleshooting and to show how it works with detailed commands step by step and checkpoints but without background information. I suppose you have a monitor, keyboard and mouse attached to your Raspberry Pi and have a DHCP server running on your local wireless network. Ip addresses and other settings in this check up are examples. You have to use yours. You can always look at journalctl -b -e
for logged information.
Download ZIP
image Raspbian Stretch Lite 2018-11-13 to your linux pc.
Checkpoint 1: Compare the checksum with that on the download site.
pc ~$ sha256sum 2018-11-13-raspbian-stretch-lite.zip
47ef1b2501d0e5002675a50b6868074e693f78829822eef64f3878487953234d 2018-11-13-raspbian-stretch-lite.zip
Next step: Burn the image to an attached SD Card. I assume it is attached to /dev/sdb
. Look with lsblk
to what device file your SD Card is attached.
pc ~$ unzip -p 2018-11-13-raspbian-stretch-lite.zip | sudo dd of=/dev/sdb bs=4M conv=fsync
Checkpoint 2: check partitions on the SD Card:
pc ~$ sudo parted /dev/sdb print
sudo parted /dev/sdb print
Model: Mass Storage Device (scsi)
Disk /dev/sdb: 3965MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 4194kB 50,2MB 46,0MB primary fat32 lba
2 50,3MB 1866MB 1816MB primary ext4
Next step: Mount the boot partition and create a wpa_supplicant.conf
file:
pc ~$ mkdir boot/
pc ~$ sudo mount /dev/sdb1 boot/
pc ~$ sudo editor boot/wpa_supplicant.conf
Insert this into the empty editor with your settings for country=
, ssid=
and psk=
, save it and quit the editor:
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="your wifi network"
psk="YourSecretPassword"
}
pc ~$ sudo umount boot/
Put the SD Card into your RasPi and boot.
Checkpoint 3: After login, check wifi connection and internet access. The wlan0 interface must have an ip address:
rpi ~$ ip -4 addr show dev wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.10.112/24 brd 192.168.10.255 scope global wlan0
valid_lft forever preferred_lft forever
rpi ~$ ping -I wlan0 -c3 google.com
PING google.com (216.58.210.14) from 192.168.10.112 wlan0: 56(84) bytes of data.
64 bytes from fra16s07-in-f14.1e100.net (216.58.210.14): icmp_seq=1 ttl=57 time=213 ms
64 bytes from fra16s07-in-f14.1e100.net (216.58.210.14): icmp_seq=2 ttl=57 time=14.2 ms
64 bytes from fra16s07-in-f14.1e100.net (216.58.210.14): icmp_seq=3 ttl=57 time=12.2 ms
--- google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 12.215/79.965/213.461/94.399 ms
Until now we have only done default setup. If you have some trouble then there is a general problem with your network. Check How do I set up networking/WiFi/static IP address? and fix it.
Next step: Full upgrade and reboot:
rpi ~$ sudo apt update
rpi ~$ sudo apt full-upgrade
rpi ~$ sudo systemctl reboot
After reboot and login, switch over to systemd-networkd:
rpi ~$ sudo -Es
rpi ~# systemctl mask networking.service
rpi ~# systemctl mask dhcpcd.service
rpi ~# sudo mv /etc/network/interfaces /etc/network/interfaces~
rpi ~# sed -i '1i resolvconf=NO' /etc/resolvconf.conf
rpi ~# systemctl enable systemd-networkd.service
rpi ~# systemctl enable systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
Create these files for interfaces wlan0 and ap0 with your settings:
rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
IPForward=yes
DHCP=yes
EOF
rpi ~# cat > /etc/systemd/network/12-ap0.network <<EOF
[Match]
Name=ap0
[Network]
Address=192.168.4.1/24
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 84.200.70.40
EOF
Rename /etc/wpa_supplicant/wpa_supplicant.conf so it matches the interface setting and reboot:
rpi ~# mv /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl disable [email protected]
rpi ~# systemctl reboot
Checkpoint 4: After reboot and login check wifi connection with systemd-networkd:
rpi ~$ sudo systemctl start [email protected]
rpi ~$ systemctl status [email protected]
● [email protected] - WPA supplicant daemon (interface-specific version)
Loaded: loaded (/lib/systemd/system/[email protected]; disabled; vendor preset: enabled)
Active: active (running) since Tue 2019-01-29 11:07:53 GMT; 24s ago
Main PID: 415 (wpa_supplicant)
CGroup: /system.slice/system-wpa_supplicant.slice/[email protected]
└─415 /sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-wlan0.conf -Dnl80211,wext -iwlan0
Jan 29 11:07:53 raspberrypi systemd[1]: Started WPA supplicant daemon (interface-specific version).
Jan 29 11:07:53 raspberrypi wpa_supplicant[415]: Successfully initialized wpa_supplicant
Jan 29 11:07:53 raspberrypi wpa_supplicant[415]: p2p-dev-wlan0: CTRL-EVENT-REGDOM-CHANGE init=USER type=COUNTRY alpha2=DE
Jan 29 11:07:56 raspberrypi wpa_supplicant[415]: wlan0: Trying to associate with 34:31:c4:c7:f2:74 (SSID='[email protected]' freq
Jan 29 11:07:56 raspberrypi wpa_supplicant[415]: wlan0: Associated with 34:31:c4:c7:f2:74
Jan 29 11:07:56 raspberrypi wpa_supplicant[415]: wlan0: WPA: Key negotiation completed with 34:31:c4:c7:f2:74 [PTK=CCMP GTK=CCMP]
Jan 29 11:07:56 raspberrypi wpa_supplicant[415]: wlan0: CTRL-EVENT-CONNECTED - Connection to 34:31:c4:c7:f2:74 completed [id=0 id_st
Jan 29 11:07:56 raspberrypi wpa_supplicant[415]: p2p-dev-wlan0: CTRL-EVENT-REGDOM-CHANGE init=COUNTRY_IE type=COUNTRY alpha2=DE
rpi ~$ ip -4 addr show dev wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.10.112/24 brd 192.168.10.255 scope global wlan0
valid_lft forever preferred_lft forever
rpi ~$ ping -I wlan0 -c3 google.com
PING google.com (172.217.21.238) from 192.168.10.112 wlan0: 56(84) bytes of data.
64 bytes from fra16s13-in-f238.1e100.net (172.217.21.238): icmp_seq=1 ttl=56 time=14.1 ms
64 bytes from fra16s13-in-f238.1e100.net (172.217.21.238): icmp_seq=2 ttl=56 time=13.4 ms
64 bytes from fra16s13-in-f238.1e100.net (172.217.21.238): icmp_seq=3 ttl=56 time=13.2 ms
--- google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 13.203/13.602/14.142/0.418 ms
Checkpoint 5: IMPORTANT! At this point it must be able to set and delete the virtual interface ap0 without error messages:
rpi ~$ sudo iw dev wlan0 interface add ap0 type __ap
rpi ~$ sudo iw dev ap0 info
Interface ap0
ifindex 5
wdev 0x5
addr b8:27:eb:06:e8:8b
type AP
wiphy 0
channel 1 (2412 MHz), width: 20 MHz, center1: 2412 MHz
txpower 31.00 dBm
rpi ~$ sudo iw dev ap0 del
rpi ~$
Next step: Install hostapd and helper
rpi ~$ sudo -Es
rpi ~# apt install hostapd rng-tools
rpi ~# systemctl stop hostapd.service
rpi ~# systemctl disable hostapd.service
Create this file with your settings for ssid=
and wpa_passphrase=
:
rpi ~# cat > /etc/hostapd/hostapd.conf <<EOF
interface=ap0
driver=nl80211
ssid=RPiNet
hw_mode=g
channel=1
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=verySecretPassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
EOF
rpi ~# chmod 600 /etc/hostapd/hostapd.conf
Set DAEMON_CONF="/etc/hostapd/hostapd.conf" in /etc/default/hostapd with:
rpi ~# sed -i 's/^#DAEMON_CONF=.*$/DAEMON_CONF="/etc/hostapd/hostapd.conf"/' /etc/default/hostapd
In /etc/init.d/hostapd in section INIT INFO you have to comment the line # Should-Start: $network
to ## Should-Start: $network
:
rpi ~# sed -i 's/^(# Should-Start:s*$network)$/#1/' /etc/init.d/hostapd
Edit hostapd.service with systemctl edit hostapd.service
and in the empty editor insert this, save and quit:
[Service]
ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type __ap
ExecStopPost=-/sbin/iw dev ap0 del
Reboot.
After reboot and login, check client connection together with access point. It is very important that /sbin/wpa_supplicant
starts after /sbin/hostapd
. Otherwise the wifi driver crashes and you must reboot.
Checkpoint 6: interface wlan0 must have state DOWN
and ap0 has state UP
.
rpi ~$ ip link show dev wlan0
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
link/ether b8:27:eb:06:e8:8b brd ff:ff:ff:ff:ff:ff
rpi ~$ sudo systemctl start hostapd.service
rpi ~$ ip -4 addr show dev ap0
4: ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.4.1/24 brd 192.168.4.255 scope global ap0
valid_lft forever preferred_lft forever
Checkpoint 7: Check wifi on your mobile phone. You should find RPiNet
and you can connect to it. Your mobile phone cannot get into the internet because routing isn't configured yet.
Next step: Start wpa_supplicant
after hostapd
:
rpi ~$ sudo systemctl start [email protected]
Checkpoint 8: Interfaces wlan0 and ap0 must have state UP
and you can ping google.com from the RasPi:
rpi ~$ ip -4 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.10.112/24 brd 192.168.10.255 scope global dynamic wlan0
valid_lft 25393sec preferred_lft 25393sec
4: ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.4.1/24 brd 192.168.4.255 scope global ap0
valid_lft forever preferred_lft forever
rpi ~$ ping -c3 google.com
PING google.com (172.217.21.238) 56(84) bytes of data.
64 bytes from fra16s13-in-f238.1e100.net (172.217.21.238): icmp_seq=1 ttl=56 time=13.7 ms
64 bytes from fra16s13-in-f238.1e100.net (172.217.21.238): icmp_seq=2 ttl=56 time=14.1 ms
64 bytes from fra16s13-in-f238.1e100.net (172.217.21.238): icmp_seq=3 ttl=56 time=15.9 ms
--- google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 13.775/14.608/15.908/0.936 ms
Next step: Enable Network Address Translation (NAT) so routed packages can return to devices on the access point. Extend wpa_supplicant with:
rpi ~$ sudo systemctl stop [email protected]
rpi ~$ sudo systemctl edit [email protected]
In the empty editor insert these statements. Have attention to the minus sign after equal =-
on some statements. Save it and quit the editor:
[Service]
ExecStartPost=/sbin/iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
ExecStopPost=-/sbin/iptables -t nat -D POSTROUTING -o wlan0 -j MASQUERADE
Start wpa_supplicant again:
rpi ~$ sudo systemctl daemon-reload
rpi ~$ sudo systemctl start [email protected]
Checkpoint 9: Now you should be able to get into the internet with the mobile phone.
That's it.
If you run into trouble you can try a new attempt with:
rpi ~$ sudo systemctl disable [email protected]
rpi ~$ sudo systemctl disable hostapd.service
rpi ~$ sudo systemctl reboot
This is not a working installation. You have to edit hostapd.service
and [email protected]
as shown in my other answer.
Answered by Ingo on November 28, 2021
We are talking about an access point together with a wireless client connection on interface wlan0 to another wifi network (wlan repeater) or an internet router.
If you want an access point together with an ethernet interface eth0 for a wired uplink to a switch or an internet router then look at Setting up a Raspberry Pi as an access point - the easy way.
Tested on a Raspberry Pi 4B with
Raspberry Pi OS (32-bit) with desktop 2020-08-20 updated on 2020-09-01.
Raspberry Pi OS (32-bit) with desktop 2020-05-27 updated on 2020-06-11.
Raspbian Buster Lite 2020-02-13 updated on 2020-03-03.
Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot
.
Here you will find the last tested revision for Raspbian Stretch Lite.
IMPORTANT UPDATE on 2020-09-02:
I have found that the image versions of the Raspberry Pi OS come with an unstable firmware for the built-in WiFi device. For further information look at my bug report at WiFi firmware brcmfmac crashes when using virtual AP interface. The last stable is firmware-brcm80211_20190114-1+rpt4_all.deb comming with image Raspbian Buster Lite 2020-02-13.
So we have to downgrade the WiFi firmware to this stable version as long as the bug isn't fixed. After flashing the Raspberry Pi OS image with update/full-upgrade, follow this to do downgrade:
rpi ~$ wget http://archive.raspberrypi.org/debian/pool/main/f/firmware-nonfree/firmware-brcm80211_20190114-1+rpt4_all.deb
rpi ~$ sudo dpkg --purge firmware-brcm80211
rpi ~$ sudo dpkg --install firmware-brcm80211_20190114-1+rpt4_all.deb
rpi ~$ sudo apt-mark hold firmware-brcm80211
rpi ~$ sudo systemctl reboot
The Raspberry Pi is able to work as a wireless hotspot and simultaneously connect to another hotspot as a client. But the wifi device on the RasPi has a general limitation. The client connection cannot be bridged because lack of WDS (wireless distribution system) that is needed for bridging on the wireless. For further information look at Raspberry Pi WiFi to Ethernet Bridge for a server?. So we can only use routing for the wifi client connection to the internet router. But the wifi hotspot and the wired ethernet port can be bridged so all devices on wifi and the wired port can have the same broadcast domain on its common subnet.
I assume that you already have a connection to the internet. All commands can simply be copied and pasted to the command line of the RasPi. The blocks with EOF you can select from cat
incl. the last EOF
and paste it to the RasPis command line. With Enter it will be copied to a file without the delimiter EOF.
We will first setup a wifi repeater so if anyone only needs this he can stop setup at this point and use it. For those who need a bridged ethernet port with the wifi access point can continue with setting it up.
I use systemd-networkd for reasons. For the impatient first only the Setup.
Example for this setup:
wifi wifi uplink wan
mobile-phone <~.~.~.~.~> (ap@wlan0)RPi(wlan0) <.~.~.~.~.> router <───> INTERNET
╲ ╱ ╲
(dhcp 192.168.4.1 (dhcp
from RPi) from router)
rpi ~$ sudo -Es # if not already done
rpi ~# apt install hostapd
Create this file with your settings for ssid=
, country_code=
and wpa_passphrase=
. As channel=
select the same channel wpa_supplicant with wlan0 will connect to your internet router.
ATTENTION! This is a restriction from the hardware. hostapd
will always set the channel to the same value than from the client connection, no matter what you set here. If you need different channels then you have to use an additional USB/WiFi dongle.
rpi ~# cat > /etc/hostapd/hostapd.conf <<EOF
driver=nl80211
ssid=RPiNet
country_code=DE
hw_mode=g
channel=1
auth_algs=1
wpa=2
wpa_passphrase=verySecretPassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
EOF
rpi ~# chmod 600 /etc/hostapd/hostapd.conf
Create a service for the accesspoint with hostapd:
rpi ~# systemctl edit --force --full [email protected]
In the empty editor insert these statements, save them and quit the editor:
[Unit]
Description=accesspoint with hostapd (interface-specific version)
Wants=wpa_supplicant@%i.service
[Service]
ExecStartPre=/sbin/iw dev %i interface add ap@%i type __ap
ExecStart=/usr/sbin/hostapd -i ap@%i /etc/hostapd/hostapd.conf
ExecStopPost=-/sbin/iw dev ap@%i del
[Install]
WantedBy=sys-subsystem-net-devices-%i.device
Enable the service:
rpi ~# systemctl enable [email protected]
rpi ~# rfkill unblock wlan
Create this file with your settings for country=
, ssid=
and psk=
and enable it:
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="TestNet"
psk="realyNotMyPassword"
key_mgmt=WPA-PSK # see ref (4)
}
EOF
rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl disable wpa_supplicant.service
Extend wpa_supplicant with:
rpi ~# systemctl edit [email protected]
In the empty editor insert these statements. Save it and quit the editor:
[Unit]
BindsTo=accesspoint@%i.service
After=accesspoint@%i.service
Create these files:
rpi ~# cat > /etc/systemd/network/08-wifi.network <<EOF
[Match]
Name=wl*
[Network]
LLMNR=no
MulticastDNS=yes
# If you need a static ip address, then toggle commenting next four lines (example)
DHCP=yes
#Address=192.168.50.60/24
#Gateway=192.168.50.1
#DNS=84.200.69.80 1.1.1.1
EOF
For those who want a bridge, do not need the next file and must continue with Setup bridge.
rpi ~# cat > /etc/systemd/network/12-ap.network <<EOF
[Match]
Name=ap@*
[Network]
LLMNR=no
MulticastDNS=yes
IPMasquerade=yes
Address=192.168.4.1/24
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 1.1.1.1
EOF
Setup a wifi repeater without bridge is finished. You must
Reboot.
Setup wifi repeater as described above.
Example for this setup:
(dhcp
from RPi) bridge
╱ wifi ┌──────┐
mobile-phone <~.~.~.~.> │(ap@) │ wifi uplink wan
│ br0│RPi(wlan0) <.~.~.~.~.> router <───> INTERNET
laptop <────────> |(eth0)│╲ ╲
╲ wired └──────┘╱ (dhcp
(dhcp 192.168.4.1 from router)
from RPi)
Add a line bridge=br0
to /etc/hostapd/hostapd.conf with:
rpi ~# echo 'bridge=br0' >> /etc/hostapd/hostapd.conf
Extend wpa_supplicant with:
rpi ~# systemctl edit [email protected]
In the editor append lines so it looks like the following. Have attention to the minus sign after equal =-
on some statements. Save it and quit the editor:
[Unit]
BindsTo=accesspoint@%i.service
After=accesspoint@%i.service
[Service]
ExecStartPost=/lib/systemd/systemd-networkd-wait-online --interface=%i --timeout=60 --quiet
ExecStartPost=/bin/ip link set ap@%i up
ExecStopPost=-/bin/ip link set ap@%i up
Please note that ExecStopPost=-/bin/ip link set ap@%i up
is not a typo. On stopping wpa_supplicant, interface ap@wlan0 must be set up again.
For a bridge ap@wlan is dynamically created. So create these files:
rpi ~# cat > /etc/systemd/network/02-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
EOF
rpi ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Bridge=br0
EOF
rpi ~# cat > /etc/systemd/network/16-br0_up.network <<EOF
[Match]
Name=br0
[Network]
IPMasquerade=yes
Address=192.168.4.1/24
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 1.1.1.1
EOF
Reboot.
That's it.
One problem is that we want to use the same device for a wifi client and for an access point. This must be supported by the wifi hardware. We can check this with
rpi ~$ sudo iw list | grep -A4 "valid interface combinations:"
valid interface combinations:
* #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
total <= 3, #channels <= 2
* #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1,
total <= 4, #channels <= 1
The important part is #{ managed } <= 1, #{ AP } <= 1,
but you can also see that this is only possible on one channel.
I've found that we have to setup this in sequence, otherwise, it won't work. If other applications bind to the wifi port it cannot be set.
ap@wlan0
for the access pointhostapd
using interface ap@wlan0
wpa_supplicant
for wifi client using interface wlan0
This order restricts the whole setup. It isn't possible to start hostapd when wpa_supplicant is running. You must first stop wpa_supplicant and then start hostapd and wpa_supplicant in this order. This is due to the WiFi driver brcmfmac
.
Another quirk is that wpa_supplicant disables the interface ap@wlan0 when it is managed, no matter if it starts or stops. So even after a start from wpa_supplicant, we have to enable ap@wlan0 again.
Here are mainly four components involved: virtual interface ap@wlan0, hostapd, wpa_supplicant, and setup the bridge.
This is the normal setup you will find all over the web. Please set the channel to the same value then wlan0 is connected to the wifi from your router. It is the restriction from the hardware and may avoid confusion with channel settings. hostapd will always set the channel to the same value than from the client connection, no matter what you set here.
Please use a passphrase that is long enough, I would say at least with 8 characters. It was told that 4 characters are too small and hostapd will refuse to accept connections. You will not find the access point RPiNet on your mobile phone (thanks to @Leo).
We do not need to unmask the hostapd.service as described at /usr/share/doc/hostapd/README.Debian
because we create our own [email protected]
for hostapd.
In this service the interface ap@wlan0 is created before starting hostapd. This is respected to the starting order. Because ap@wlan0 is bound to wlan0 it gets the same mac address. You may consider to give it a unique mac address but that's not a good idea. On the network is only seen the mac address from wlan0. If you give ap@wlan0 its own mac address then it is not seen on the network for arp requests and the IP address for connections to ap@wlan0 is not found and gets stuck. You have to set ap@wlan0 to promiscuous mode to get it to work then.
After stopped hostapd then ap@wlan0 is also deleted so it can be created again on the next start of hostapd.
Setting up wpa_supplicant for wlan0 we do as usual. You may consider to disable p2p with p2p_disabled=1
in /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
to avoid to get the unneeded confusing P2P-device seen with iw dev
. Don't do that in this configuration with a virtual AP interface (e.g. ap@wlan0). It confuses wpa_supplicant and it will immediately disconnect from the uplink router when it has just connected to it. It endless connect and disconnect.
Its extended unit is to strictly bind wpa_supplicant to hostapd so it will start and stop with it in the right order. We do it because running wpa_supplicant without hostapd is very complicated and may result in a total crash of the brcmfmac wifi driver, I have seen that on my tests.
Here we define interface wlan0 and the virtual interface ap@wlan0 we need for a wifi repeater. For wlan0 we get an IP address by DHCP from the internet router. Optional you can set a static IP address, but then you also have to define all other settings like gateway and DNS server because you don't get them anymore from the DHCP server.
Interface ap@wlan0 needs a static IP address because it is the access point and the source of the DHCP server for the wifi network. There is no need that clients, connected to the internet router, must also connect to clients on the access point. So we can use NAT (IPMasquerade=yes) that simplifies setup a lot. Then we don't have to configure static routes and it is not needed to configure wlan0 with static values (IP address, gateway, DNS server, etc.).
We have setup hostapd in Step 2. Now we only need to append bridge=br0
to its configuration so that it will dynamically manage to add ap@wlan0 to the bridge.
When wpa_supplicant is started it also brings up interface wlan0. Every time it is managed, no matter if it started or stopped, it will stop ap@wlan0 because it is not a real interface and depends directly on wlan0.
The ap interface can only start when wlan0 "Gained carrier" and the link becomes ready (3). This will happen some or more seconds after wpa_supplicant has started. There is a helper program systemd-networkd-wait-online that can do this synchronous. We use it with a timeout of 60 seconds. If your network connection takes longer than 60 seconds to get up, then you should increase the timeout accordingly. With journalctl -b -e
you can check if Starting Bring up wifi interface ap@wlan0...
and Started Bring up wifi interface ap@wlan0.
covers wlan0: Gained carrier
. This is very important because otherwise, the bridge will not work correctly with undefined behavior. You can check the helpers options with /lib/systemd/systemd-networkd-wait-online --help
.
After stopped wpa_supplicant (bring wlan0 down) ap@wlan0 must be brought up again so it can continue running for the access point.
These files define the bridge. ap@wlan0 will dynamically be added by hostapd. eth0 and ap@wlan0 are slaves of the bridge and don't need an IP address. The bridge br0 itself also does not need an IP address but here it has a static IP address because we need it for the DHCP server bound to br0 so the DHCP server is available on the subnet of the bridge ( interfaces eth0, ap@wlan0).
Update 2020-07-22:
Bassline Soup has made some interesting tests that may help to troubleshoot the setup.
You are now able to start, stop and restart hostapd and wpa_supplicant.
You should see the access point, here RPiNet, in your mobile phone and should get an IP address to connect to the access point. You should also get an IP address from the same subnet if you connect a laptop with a cable to the ethernet port and you can ping the mobile phone.
With this setup you have the following dependencies with starting and stopping:
hostapd │ wpa_supplicant wpa_supplicant │ hostapd
───────────┼────────────────────────────────────┼──────────
starting │ starts starting │ starts
stopping │ stops stopping │ ----
restarting │ restarts restarting │ starts
This is because of the strict order of starting (see section General). You cannot run wpa_supplicant without hostapd but you can run hostapd without wpa_supplicant by starting hostapd and then stop wpa_supplicant.
If communication stops for some reason (e.g. delay to small or something else) it is mostly enough to kick ap@wlan0 with /bin/ip link set ap@wlan0 up
.
references:
[1] Howto migrate from networking to systemd-networkd with dynamic failover
[2] man systemd.unit
[3] systemd-networkd wireless bridging - need to wait for carrier
[4] Setup WiFi on Pi 3 B+
Answered by Ingo on November 28, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP