Skip to main content

WiFi Setup

This guide will help you set up a WiFi Access Point on your Raspberry Pi.

Find your Raspberry's MAC address:

Enter the following command to find the MAC address of your Raspberry Pi's WiFi interface:

iw dev

You should see an output similar to this:

iw dev output:
pi@securitycam:~ $ iw dev
phy#0
Unnamed/non-netdev interface
wdev 0x2
addr ba:27:xx:xx:xx:xx
type P2P-device
txpower 31.00 dBm
Interface wlan0
ifindex 2
wdev 0x1
addr b8:27:xx:xx:xx:xx
ssid FRITZ!Box 420
type managed
channel 1 (2412 MHz), width: 20 MHz, center1: 2412 MHz
txpower 31.00 dBm

The MAC address of the wlan0 interface is b8:27:xx:xx:xx:xx in this case.

info

Remember this MAC address (write it down) and the channel number (channel 1 in this case) for later.

Allocate a device for the Access Point

Create a new interface called ap0 with the same MAC address as wlan0.
ap0 will then be the interface used for the Access Point.

sudo nano /etc/udev/rules.d/70-persistent-net.rules

Add the following lines and replace your MAC address (!) accordingly:

SUBSYSTEM=="ieee80211", ACTION=="add|change", ATTR{macaddress}=="REPLACEWITHMACADDRESS", KERNEL=="phy0", \
RUN+="/sbin/iw phy phy0 interface add ap0 type __ap", \
RUN+="/bin/ip link set ap0 address REPLACEWITHMACADDRESS"

Configure Dnsmasq

Backup the original and create a new dnsmasq configuration:

sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo sh -c 'echo "interface=lo,ap0
no-dhcp-interface=lo,wlan0
bind-interfaces
server=8.8.8.8
server=1.1.1.1
domain-needed
bogus-priv
dhcp-range=192.168.10.50,192.168.10.150,12h" > /etc/dnsmasq.conf'

Configure Hostapd

Open the configuration file:

sudo nano /etc/hostapd/hostapd.conf

Add the following content:

ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
interface=ap0
driver=nl80211
ssid=DevAccessPoint
hw_mode=g
channel=1
wmm_enabled=0
macaddr_acl=0
auth_algs=1
wpa=2
wpa_passphrase=YourPassPhraseHere
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
rsn_pairwise=CCMP
info

Before you save, make sure to do these changes to the configuration:

  1. Replace DevAccessPoint and YourPassPhraseHere with your desired values
  2. Replace the channel with the channel your wlan0 was running on (as reported by iw dev in step 1)

Now after having saved, we want to specify where hostapd should find its configuration:

sudo sed -i 's|^#DAEMON_CONF=""|DAEMON_CONF="/etc/hostapd/hostapd.conf"|' /etc/default/hostapd

Modify the wpa_supplicant configuration

Open the configuration file:

sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Add the following content if it's not already present:

country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid="YourSSID1"
psk="YourPassphrase1"
id_str="AP1"
}

network={
ssid="YourSSID2"
psk="YourPassphrase2"
id_str="AP2"
}

Customize the configuration:

  • Replace YourSSID1 and YourPassphrase1 with your Wi-Fi network’s SSID and passphrase (the network you want to connect to, not the one created in the previous step).
  • Update the country=US line to reflect your country code.
  • If you only have one Wi-Fi network, remove the second network block.
note

You can add multiple networks by duplicating the network block, incrementing the id_str for each one. Only keep the blocks for the networks you plan to connect to.

Enable support for the new AP

Modify /etc/network/interfaces to support the new AP

Open the configuration file:

sudo nano /etc/network/interfaces

Add the following content:

auto lo
auto ap0
auto wlan0
iface lo inet loopback

allow-hotplug ap0
iface ap0 inet static
address 192.168.10.1
netmask 255.255.255.0
hostapd /etc/hostapd/hostapd.conf

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface AP1 inet dhcp
iface AP2 inet dhcp
note
  • iface AP2 inet dhcp: Remove this line if you do not have a second network configured in wpa_supplicant.conf.
  • iface AP1 inet dhcp: Keep this line since it corresponds to the first network (SSID YourSSID1 in the wpa_supplicant.conf).

Start both interfaces:

sudo ifdown --force wlan0
sudo ifdown --force ap0
sudo ifup ap0
sudo ifup wlan0
danger

It's crucial to copy and paste the entire block of commands above all at once.
Executing them one by one will disconnect you from the Pi after disabling the interfaces, preventing you from re-enabling them immediately.
If your Raspberry Pi Zero 2 W does not reconnect to your WiFi network at this point wait a few more seconds, unplug the power and plug it back in.

Check the interfaces

You should be able to see the DevAccessPoint network on your device.

SSH into the Pi again (either you connect to the DevAccessPoint and ssh with ssh pi@192.168.10.1 as configured in here or find the Raspberry Pi's new IP address in your router and ssh into it).

Now check the interfaces:

pi@securitycam:~$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether b8:27:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.178.102/24 brd 192.168.178.255 scope global dynamic noprefixroute wlan0
valid_lft 863907sec preferred_lft 755907sec
inet6 2a02:4500:4507:8d04:e2455:6452:6e45:2f66/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 7102sec preferred_lft 2496sec
inet6 fe45::4455:a1e3:45c9:5451/64 scope link
valid_lft forever preferred_lft forever
3: ap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether b8:27:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.10.1/24 brd 192.168.10.255 scope global ap0
valid_lft forever preferred_lft forever
inet 169.254.165.183/16 brd 169.254.255.255 scope global noprefixroute ap0
valid_lft forever preferred_lft forever
inet6 fe45::7d45:45b8:b45:2f45/64 scope link
valid_lft forever preferred_lft forever
inet6 fe45::ba27:eb45:fe7c:3cea/64 scope link
valid_lft forever preferred_lft forever

You should see both wlan0 and ap0 interfaces with their respective IP addresses.

Bridge traffic between AP and Client side

Enbale ip-forwarding:

sudo sysctl -w net.ipv4.ip_forward=1

Create an nftables rule to handle NAT (Masquerading):

sudo sh -c 'echo "
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 192.168.10.0/24 oifname != \"ap0\" masquerade
}
}" >> /etc/nftables.conf && sudo nft -f /etc/nftables.conf'

Restart dnsmasq:

sudo systemctl restart dnsmasq

Now you should be able to connect to the AP and use its internet connection to access the internet. (If you have a working internet connection on its client side)

Automate the workaround

Create a new file:

sudo sh -c 'cat <<EOF > /opt/start-ap-managed-wifi.sh
#!/bin/bash
LOGFILE="/var/log/pi_startup.log"
echo "[$(date)] Starting script. Sleeping 15 sec..." >> \$LOGFILE
sleep 15
echo "[$(date)] Starting execution" >> \$LOGFILE
sudo sysctl -w net.ipv4.ip_forward=1
echo "[$(date)] Enabled IP forwarding" >> \$LOGFILE
sudo sh -c "echo \"
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
ip saddr 192.168.10.0/24 oifname != 'ap0' masquerade
}
}\" >> /etc/nftables.conf && sudo nft -f /etc/nftables.conf"
echo "[$(date)] Applied nftables rules for NAT" >> \$LOGFILE
sudo systemctl restart dnsmasq
echo "[$(date)] Restarted dnsmasq" >> \$LOGFILE
echo " " >> \$LOGFILE
EOF

sudo chmod +x /opt/start-ap-managed-wifi.sh'

Add a cronjob to run the script on boot:

sudo bash -c 'echo "@reboot /opt/start-ap-managed-wifi.sh" >> /var/spool/cron/crontabs/root'

Continue to bluetooth.mdx to set up bluetooth.

note

These instructions are tested on Raspbian Bookworm with a Raspberry Pi Zero 2 W.

info

Shoutout to TheWalrus for the original instructions. A comment under the post pointed out that the instructions depend upon if-up and if-down system which is no longer used as of Raspian Buster. You might want to visit the original post for more information.

These instructions depend upon if-up and if-down system used by Raspbian Stretch version.

But as of 2020, you would be using Raspbian Buster, which uses a different system, based on dhcpcd daemon. While it is technically possible to still get it working (because the ifup/ifdown system are still there), it is recommended to use systemd-networkd approach, which doesn't depend upon having to introduce udev hook.

The instructions are here: https://raspberrypi.stackex...