Skip to content

Instantly share code, notes, and snippets.

@lukicdarkoo
Last active November 22, 2023 04:37
Show Gist options
  • Save lukicdarkoo/6b92d182d37d0a10400060d8344f86e4 to your computer and use it in GitHub Desktop.
Save lukicdarkoo/6b92d182d37d0a10400060d8344f86e4 to your computer and use it in GitHub Desktop.
Raspberry Pi: AP + client mode
#!/bin/sh
# The script configures simultaneous AP and Managed Mode Wifi on Raspberry Pi Zero W (should also work on Raspberry Pi 3)
# Usage: curl https://gist.githubusercontent.com/lukicdarkoo/6b92d182d37d0a10400060d8344f86e4/raw | sh -s WifiSSID WifiPass APSSID APPass
# Licence: GPLv3
# Author: Darko Lukic <lukicdarkoo@gmail.com>
# Special thanks to: https://albeec13.github.io/2017/09/26/raspberry-pi-zero-w-simultaneous-ap-and-managed-mode-wifi/
MAC_ADDRESS="$(cat /sys/class/net/wlan0/address)"
CLIENT_SSID="${1}"
CLIENT_PASSPHRASE="${2}"
AP_SSID="${3}"
AP_PASSPHRASE="${4}"
# Install dependencies
sudo apt -y update
sudo apt -y upgrade
sudo apt -y install dnsmasq dhcpcd hostapd
# Populate `/etc/udev/rules.d/70-persistent-net.rules`
sudo bash -c 'cat > /etc/udev/rules.d/70-persistent-net.rules' << EOF
SUBSYSTEM=="ieee80211", ACTION=="add|change", ATTR{macaddress}=="${MAC_ADDRESS}", KERNEL=="phy0", \
RUN+="/sbin/iw phy phy0 interface add ap0 type __ap", \
RUN+="/bin/ip link set ap0 address ${MAC_ADDRESS}
EOF
# Populate `/etc/dnsmasq.conf`
sudo bash -c 'cat > /etc/dnsmasq.conf' << EOF
interface=lo,ap0
no-dhcp-interface=lo,wlan0
bind-interfaces
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=192.168.10.50,192.168.10.150,12h
EOF
# Populate `/etc/hostapd/hostapd.conf`
sudo bash -c 'cat > /etc/hostapd/hostapd.conf' << EOF
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
interface=ap0
driver=nl80211
ssid=${AP_SSID}
hw_mode=g
channel=11
wmm_enabled=0
macaddr_acl=0
auth_algs=1
wpa=2PASSPHRASE
wpa_passphrase=${AP_PASSPHRASE}
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
rsn_pairwise=CCMP
EOF
# Populate `/etc/default/hostapd`
sudo bash -c 'cat > /etc/default/hostapd' << EOF
DAEMON_CONF="/etc/hostapd/hostapd.conf"
EOF
# Populate `/etc/wpa_supplicant/wpa_supplicant.conf`
sudo bash -c 'cat > /etc/wpa_supplicant/wpa_supplicant.conf' << EOF
country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="${CLIENT_SSID}"
psk="${CLIENT_PASSPHRASE}"
id_str="AP1"
}
EOF
# Populate `/etc/network/interfaces`
sudo bash -c 'cat > /etc/network/interfaces' << EOF
source-directory /etc/network/interfaces.d
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
EOF
# Populate `/bin/start_wifi.sh`
sudo bash -c 'cat > /bin/start_wifi.sh' << EOF
echo 'Starting Wifi AP and client...'
sleep 30
sudo ifdown --force wlan0
sudo ifdown --force ap0
sudo ifup ap0
sudo ifup wlan0
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 ! -d 192.168.10.0/24 -j MASQUERADE
sudo systemctl restart dnsmasq
EOF
sudo chmod +x /bin/start_wifi.sh
crontab -l | { cat; echo "@reboot /bin/start_wifi.sh"; } | crontab -
echo "Wifi configuration is finished! Please reboot your Raspberry Pi to apply changes..."
@opcodex64
Copy link

Hello Lukic,

thank you very much for this ! It worked perfectly for me using only your script on a RPi4. It worked directly on first attempt !
uname -r -> 5.10.17-v7l+

This saved many hours for me..

Best regards,
Tugrul

@Simo182
Copy link

Simo182 commented Jul 11, 2021

Has anyone got this working with alternative hostapd seetings of "hw_mode=n" or "ieee80211n=1" .. if I use either of these, the SSID is hidden and cant connect to it

@igrowing
Copy link

igrowing commented Dec 18, 2021

Thanks for the base.

  1. In line 23 missing double quote by the end of line. Should be:
    RUN+="/bin/ip link set ap0 address ${MAC_ADDRESS}"

  2. It's better to set network config in /etc/wpa_supplicant/wpa_supplicant.conf

network={
        ssid="${CLIENT_SSID}"
        psk="${CLIENT_PASSPHRASE}"
        id_str="AP1"
        scan_ssid=1
        key_mgmt=WPA-PSK
        priority=100
}

This way RPi can connect to hidden network too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment