7

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?

14

We are talking about an access point together with a wlan0 client connection to another wifi network (wlan repeater) or an internet router.

If you want an access point together with an ethernet port eth0 as 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
Raspbian Buster Lite 2019-07-10 updated on 2019-08-13.
Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot.

Here you will find the last tested revision for Raspbian Stretch Lite.


The Raspberry Pi is able to work as a wireless hotspot and simultanous connect to another hotspot as 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 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.

For reference I use a RPi3B+ with Raspbian Stretch Lite 2019-04-08 and upgraded by sudo bash -c 'apt update && apt full-upgrade && reboot' on 2019-05-19. I also assume that you already have a connection to the internet. All commands can simply 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 coppied to a file without the delimiter EOF.

We will first setup a wifi repeater so if anyone only need 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.


♦ Setup wifi repeater

Example for this setup:

                 wifi                        wifi            wan
mobile-phone <~.~.~.~.~> (ap0)RPi(wlan0) <.~.~.~.~.> router <───> INTERNET
            ╲             ╱          ╲
           (dhcp    192.168.4.1     (dhcp
         from RPi)               from router)


Step 1: setup systemd-networkd

For detailed information look at (1). Here only in short. Execute these commands:

# Install hostapd
rpi ~$ sudo -Es
rpi ~# apt install hostapd
rpi ~# systemctl unmask hostapd
rpi ~# systemctl enable hostapd

# disable debian networking and dhcpcd
rpi ~# systemctl mask networking.service dhcpcd.service
rpi ~# sudo mv /etc/network/interfaces /etc/network/interfaces~
rpi ~# sed -i '1i resolvconf=NO' /etc/resolvconf.conf

# enable systemd-networkd
rpi ~# systemctl enable systemd-networkd.service systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Step 2: install hostapd for the access point

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.

rpi ~# cat > /etc/hostapd/hostapd.conf <<EOF
interface=ap0
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

Set DAEMON_CONF="/etc/hostapd/hostapd.conf" in /etc/default/hostapd

rpi ~# sed -i 's/^#DAEMON_CONF=.*$/DAEMON_CONF="\/etc\/hostapd\/hostapd.conf"/' /etc/default/hostapd

Edit the hostapd.service:

rpi ~# systemctl --full edit hostapd.service

and comment the line After=network.target with # so it looks like:

#After=network.target

Save it and quit the editor. Next add interface ap0 to the hostapd.service with:

rpi ~# systemctl edit hostapd.service

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

[Unit]
Wants=wpa_supplicant@wlan0.service

[Service]
ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type __ap
ExecStopPost=-/sbin/iw dev ap0 del


Step 3: setup wpa_supplicant for client connection

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
rpi ~# systemctl enable wpa_supplicant@wlan0.service

Extend wpa_supplicant with:

rpi ~# systemctl edit wpa_supplicant@wlan0.service

In the empty editor insert these statements. Have attention to the minus sign after equal =- on some statements. Save it and quit the editor:

[Unit]
BindsTo=hostapd.service
After=hostapd.service

[Service]
ExecStartPost=/sbin/iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
ExecStopPost=-/sbin/iptables -t nat -D POSTROUTING -o wlan0 -j MASQUERADE


Step 4: setup static interfaces

Create these files:

rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
IPForward=yes
# If you need a static ip address, then toggle commenting next four lines (example)
DHCP=yes
#Address=192.168.10.60/24
#Gateway=192.168.10.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-ap0.network <<EOF
[Match]
Name=ap0
[Network]
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 bridge

Setup wifi repeater as described above.

Example for this setup:

          (dhcp
        from RPi)        bridge
           ╱    wifi    ┌──────┐
mobile-phone <~.~.~.~.> │(ap0) │              wifi            wan
                        │   br0│RPi(wlan0) <.~.~.~.~> router <───> INTERNET
      laptop <────────> |(eth0)│╲       ╲
           ╲    wired   └──────┘╱      (dhcp
         (dhcp           192.168.4.1   from router)
       from RPi)

Step 5: configure hostapd for a bridge

Add a line bridge=br0 to /etc/hostapd/hostapd.conf with:

rpi ~# echo 'bridge=br0' >> /etc/hostapd/hostapd.conf

Step 6: setup wpa_supplicant for a bridge

Extend wpa_supplicant with:

rpi ~# systemctl edit wpa_supplicant@wlan0.service

In the editor add 3 lines so it looks like following. Have attention to the minus sign after equal =- on some statements. Save it and quit the editor:

[Unit]
BindsTo=hostapd.service
After=hostapd.service
Wants=ap-bring-up.service
Before=ap-bring-up.service

[Service]
ExecStartPost=/sbin/iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
ExecStopPost=-/sbin/iptables -t nat -D POSTROUTING -o wlan0 -j MASQUERADE
ExecStopPost=-/bin/ip link set ap0 up

Please note that ExecStopPost=-/bin/ip link set ap0 up is not a typo. On stopping wpa_supplicant, interface ap must be set up again as described in section Details - wpa_supplicant for bridge (Step 6).

Step 7: bring up access point with virtual wifi interface

Create a unit with:

rpi ~# systemctl --force --full edit ap-bring-up.service

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

[Unit]
Description=Bring up wifi interface ap0
Requisite=hostapd.service

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-networkd-wait-online --interface=wlan0 --timeout=60 --quiet
ExecStartPost=/bin/ip link set ap0 up

Step 8: setup static interfaces

For a bridge ap0 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]
Address=192.168.4.1/24
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 1.1.1.1
EOF

Reboot.
That's it.


♦ Details

General

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.

  1. create a virtual interface ap0 for the access point
  2. start access point daemon hostapd using interface ap0
  3. start 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 quirks is that wpa_supplicant disables the interface ap0 when it is managed, no matter if it start or stop. So even after a start from wpa_supplicant we have to enable ap0 again.

Here are mainly five components involved: virtual interface ap0, hostapd, wpa_supplicant, setup bridge and bring up access point.

hostapd (Step 2)

This is the normal setup you will find all over the web. Please set the channel to the same value than wlan0 is connected to the wifi from your router. It is the restriction from the hardware and may avoid confusion with channel setting. 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 to small and hostapd will refuse to accept connections. You will not find the access point RPiNet in your mobile phone (thanks to @Leo).

For dependencies we extend the unit from hostapd with a drop in file (overlay) (2). It always starts wpa_supplicant (Wants it) and creates interface ap0 before starting hostapd. This is respected to the starting order. Because ap0 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 ap0 its own mac address then it is not seen on the network for arp requests and the ip address for connections to ap0 is not found and get stuck. You have to set ap0 to promiscuous mode to get it to work then.

After setting up the dependencies then the hostapd.service by default will start After=network.target. The wpa_supplicant@wlan0.service must start After=hostapd.service and starts by default Before=network.target. Do you see the conflict with network.target? Systemd complains it with the error message "Found ordering cycle on wpa_supplicant@wlan0.service/start" and prevents hostapd.service to start. That's the reason why we have do comment After=network.target in the unit file of the hostapd.service.

After stopped hostapd then ap0 is also deleted so it can be created again on next start of hostapd.

wpa_supplicant (Step 3)

Setting up wpa_supplicant for wlan0 we do as usual. It's 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.

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 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.).

Setup static interfaces (Step 4)

Here we define interface wlan0 and the virtual interface ap0 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. IP forward is also enabled here that we use for routing between wlan0 and ap0.

Interface ap0 needs a static ip address because it is the access point and the source of the DHCP server for the wifi network.

hostapd for bridge (Step 5)

We have setup hostapd in Step 2. Now we only need to append bridge=br0 to its configuration so that it will dynamically manage adding ap0 to the bridge.

wpa_supplicant for bridge (Step 6)

When wpa_supplicant is started it also brings up interface wlan0. Every time it is managed, no matter if started or stopped, it will stop ap0 because it is not a real interface and depends direct on wlan0. That is also the reason why it can only brought up when wlan0 has Gained carrier. But we cannot just wait some seconds and then bring up ap0. wpa_supplicant.service must have started completely so we only can use an extra service ap-bring-up.service for doing this. The dependencies ensure this.

After stopped wpa_supplicant (bring wlan0 down) ap0 must brought up again so it can continue running for the access point.

bring up access point (Step 7)

It is not possible to just set up ap0 when needed. It can only start when wlan0 "Gained carrier" and link becomes ready (3). This will happen some or more seconds after wpa_supplicant has started. So we need ap-bring-up.service that wpa_supplicant Wants and that will check if wlan0 has "Gained carrier" and is online. There is a helper 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 ap0... and Started Bring up wifi interface ap0. covers wlan0: Gained carrier. This is very important because otherwise the bridge will not work correctly with undefined behavior. And of course this unit should only start when hostapd is running (Requisite).

define static interfaces for bridge (Step 8)

This files define the bridge. ap0 will dynamically added by hostapd. eth0 and ap0 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 on the bridge ( interfaces eth0, ap0).

Conclusion

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 an 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 ap0 with /bin/ip link set ap0 up.


refefences:
[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+

  • This looks like a good tutorial (I have not tried it, having no desire for the functionality). I have a couple of concerns - you seem to be logged as root; the Raspbian does not have root a/c and there is no explanation. Why "# cat >/etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF" when you could just list the files (and use sudo to copy)? – Milliways Oct 9 '18 at 23:06
  • @Milliways There are a couple of commands they all must be prefixed with sudo. To simplify it I like to work in a shell with user environment but with root rights. You can simply invoke this with sudo -Es. You will find it in the steps and you will find also an exit (if not rebooting). – Ingo Oct 9 '18 at 23:29
  • @Milliways I very often need the setup sequences for testing and optimizing. If I only list the files I have to invoke an editor, copy and paste it into it, save and quit the editor. With this cat >filename <<EOF thing I only select the block with my mouse and paste it with the middle button of my mouse to the prompt of my RasPi console - very quick and efficient. – Ingo Oct 9 '18 at 23:30
  • I tried it and works like a dream (No Bridge). I did it on a Rasp Zero W. Thanks! – grillp Mar 1 at 8:43
  • @Milliways: "The Raspbian does not have root a/c" It sure does: $ sudo su; # _ – Piskvor Mar 4 at 10:57
3

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 wpa_supplicant@wlan0.service
rpi ~# systemctl reboot

Checkpoint 4: After reboot and login check wifi connection with systemd-networkd:

rpi ~$ sudo systemctl start wpa_supplicant@wlan0.service
rpi ~$ systemctl status wpa_supplicant@wlan0.service
● wpa_supplicant@wlan0.service - WPA supplicant daemon (interface-specific version)
   Loaded: loaded (/lib/systemd/system/wpa_supplicant@.service; 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/wpa_supplicant@wlan0.service
           └─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='wlan@hoeft-online.de' 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 wpa_supplicant@wlan0.service

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 wpa_supplicant@wlan0.service
rpi ~$ sudo systemctl edit wpa_supplicant@wlan0.service

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 wpa_supplicant@wlan0.service

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 wpa_supplicant@wlan0.service
rpi ~$ sudo systemctl disable hostapd.service
rpi ~$ sudo systemctl reboot

This is not a working installation. You have to edit hostapd.service and wpa_supplicant@wlan0.service as shown in my other answer.

protected by Community Dec 12 '18 at 13:05

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.