Skip to content

Instantly share code, notes, and snippets.

@lukicdarkoo
Last active June 6, 2024 16:05
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 <[email protected]>
# 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..."
@mahesh2000
Copy link

mahesh2000 commented Dec 28, 2019

Thanks, @lukicdarkoo & @david712! The newer script at https://github.com/lukicdarkoo/rpi-wifi works perfectly with Rasbpian Buster (Dec 2019) with minor mods.


Change

wpa=2PASSPHRASE
to
wpa=2

Next, insert #!/bin/bash as below

# Populate `/bin/start_wifi.sh
sudo bash -c 'cat > /bin/rpi-wifi.sh' << EOF
#!/bin/bash
echo 'Starting Wifi AP and client...'

@xthursdayx
Copy link

I tried using new script with the updates @mahesh2000 mentions, however I'm unable to get wlan0 to connect to the broader internet. My AP ssid works and I'm able to connect to my RPi W Zero via ssh, however not able to ping any external website (or run any apt commands). If I run ip addr both wlan0 and ap0 seem to be up and have correct IP addresses. Any ideas?

@oxxopro
Copy link

oxxopro commented Jul 8, 2020

Hello, thank you so much for this tutorial. This worked well for me in a Raspberry pi zero W.

Do you how will be the right process for after editing wpa_suplicant.conf file, to re-connect (toggle WiFi wlan0 connection) from my command line the wlan0 interface without dropping/affecting the ap0 interface connection?

Thanks in advance

@mahesh2000
Copy link

in the end, the raspi0 w spent so much time switching between the two modes (i could see it connect-pause-disconnect-pause-connect-... to the router) that it wasn't very practical. i'm now using ESP8266 or ESP32 as a repeater. it's about $5 total, way faster (way) and no messy config. in retrospect, trying the raspi0w in this config was a poor use of several days of my life :-).

@ChulHOKang
Copy link

고맙습니다. 실행이 잘 됩니다.
웹에서 사용된 html 페이지는 어떻게 구성하는지 소스를 오픈 해주시겠습니까?
궁금합니다.
curl과 bash를 공부 중입니다.
감사합니다.

@ChulHOKang
Copy link

thank you. It runs fine.
Could you open the source for how to organize the html page used on the web?
I wonder.
I'm studying curl and bash.
Thank you.

@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