Skip to content

Instantly share code, notes, and snippets.

@lukicdarkoo
Last active November 22, 2023 04:37
Show Gist options
  • Star 59 You must be signed in to star a gist
  • Fork 24 You must be signed in to fork a gist
  • 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..."
@lukicdarkoo
Copy link
Author

lukicdarkoo commented May 21, 2018

UPDATE: Please use the following script instead
https://github.com/lukicdarkoo/rpi-wifi


The script is tested on Raspberry Pi Zero W

pi@raspberrypi:~ $ cat /sys/firmware/devicetree/base/model
Raspberry Pi Zero W Rev 1.1

with clean Raspbian Stretch

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.14.34+ #1110 Mon Apr 16 14:51:42 BST 2018 armv6l GNU/Linux

pi@raspberrypi:~ $ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.4 (stretch)
Release:	9.4
Codename:	stretch

@sebas7dk
Copy link

Awesome, works really well!

@stevenwoudstra
Copy link

this is relay awesome spent 4 days and this finally worked, thank you very much

@galaxyfreak
Copy link

galaxyfreak commented Jun 22, 2018

Hey, just tried this on Pi 3B and after I try to connect to AP, it disappears.

@ilmiont
Copy link

ilmiont commented Jul 2, 2018

Why is wpa=2PASSPHRASE in hostapd.conf? Shouldn't it be wpa=2 - is this a mistake? Or what does the PASSPHRASE do? I looked but can't see any other reference to this in hostapd docs, that I can see.

@davibe
Copy link

davibe commented Jul 19, 2018

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

is a " missing after ${MAC_ADDRESS} ?

@jakeaston
Copy link

Anyone had any joy with this on RPi 3b+? On first reboot, No AP is created, and can't SSH via ethernet...

@kevinkm
Copy link

kevinkm commented Aug 21, 2018

jakeaston, I have the same problem, these codes do not work on rpi3b+. No AP, no ethernet like you. then I plug a usb dougle as wlan1, and change some of codes, it works.

@alpgul
Copy link

alpgul commented Aug 25, 2018

is it working with rpi3?

@lukicdarkoo
Copy link
Author

is it working with rpi3?

It seems it doesn't work with Raspberry Pi 3

@marcelser
Copy link

With newest Raspbian stretch I had to disable dhcpcd as mentioned in some comments in alberts page in order to get ap0 up and working. And the script should check if 4 parameters are passed. I accidentally only passed only 2 parameters and then only the hotspot came up correctly (don't know why though as the first 2 params should be the clients ssid/pass)

@girs1982
Copy link

Great Thanks,it really worck)))

@misaalanshori
Copy link

i did the steps on the tutorial and failed (ap didnt show up and wlan0 wont work) so i erased the microsd to start new again but with the script, now the ap works but the wlan0 interface is still not working... so i can connect to it but no internet connection. what should i change?

@sbeland2
Copy link

hi,
first thanks to your script, it does the job correctly on my rpi0.
I have already a running webserver on it using nginx so i would like to modify the script in such a way that when a user connect to my AP, it brings him to my webpage (php or html).
how can i do that?

@david712
Copy link

david712 commented Mar 6, 2019

it works! really thanks. but i found some points to be modified
i fixed those points, then rpi works well(also can see rpi-ap's name on ssid list of other device)

  1. hostapd.conf : "wpa=2PASSPHRASE" should be "wpa=2"
    thanks ilmiont...
  2. start_wifi.sh : "#!/bin/bash" should be added at the top of the script
  3. crontab : didn't add "@reboot /bin/start_wifi.sh"
    i don't know why, but when i checked "crontab -e", there were nothing
    after add that manually, it works

@david712
Copy link

david712 commented Mar 6, 2019

does anyone know how to toggle ap0 without losing connection of wlan0?
i tried "ifdown --force ap0; ifup ap0" to toggle ap0, then connetion lost

@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