Setting up a Pi3B+ or Pi4 as a SeedeClip4 Wifi-Hifi Hotspot

Pi_hotspot.jpg


Note this is subject to updates as testing in various combinations occurs. The goal however is very straightforward:
  1. Give the Wifi a nice, isolated IP address range and local DNS all of it's own, regardless of whether the Pi is connected to the internet via eth0 or not.
  2. When the eth0 is attached to a LAN/broadband-adapter with internet the Wifi devices are able to access the internet too.
  3. To optionally lockout the Wifi devices from the local LAN devices via iptables.

Last updated 17 July 2019.
Instructions and files taken from a working hotspot demo on P3B+ and Pi4.

For this you will need a Pi 3B+ or Pi4 and a wired network with internet in order to configure it.
Because there is only one Wifi on the Pi you cannot use it for both a hotspot and have it use the Wifi for the internet. There is info on the internet about plugging in a USB Edimax Wifi adapter to give it a 2nd wifi but that is not covered here.
The WiFi range is pretty good with the standard Raspberry B+ Wifi.

Notes:

  • The text editors are Vi, Nano etc., I use Vi in the examples below, if you do not know 'vi' use 'nano' instead. E.g sudo nano /etc/hosts.

  • This setup uses the 192.168.1.X address range (With your Pi sitting up at 192.168.1.1), please be consistent if you choose a different range.

  • Running the Pi as a hotspot tends to disable the power management so the Pi will need a little heatsink or the Flirc case to keep it nice and cool, plus a reasonable powersupply: aim for a 2.5 Amp or upwards USB supply or a more powerful powered hub if you also want to run a USB HDD with it too.



1. Make sure your Pi 3B+ or Pi4 is up to date


Firstly make sure you are running the latest version of Raspbian Stretch, the Lite version is best for this.

sudo apt-get update
sudo apt-get upgrade

Then optionally disable Bluetooth as it may interfere, edit /boot/config.txt to add this at the end:
 # Disable internal BT
 dtoverlay=pi3-disable-bt

The uname command shows you what Linux you are running, for instance:
uname -a
Linux SeeDeclip4.home 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l GNU/Linux

You want to be on 4.19 so you'll need to upgrade, connect to the internet and then do:
sudo rpi-update

After it's all done have another look:

uname -a
Linux SeeDeclip4.home 4.19.37-v7+ #1216 SMP Thu May 2 13:32:40 BST 2019 armv7l GNU/Linux


If it's on 4.19 it should be fine.

2. Make sure the networking is as we need it

2.1 Set your new hostname and domain in /etc/hostname and /etc/hosts ..

Make sure you enter them in the format of <hostname>.<domain>, both are needed.
Do NOT set this to the same name as the SSID you choose for the WiFi network as some client devices appear to get very upset about this.

sudo vi /etc/hostname
sudo vi /etc/hosts

/etc/hostname
music.home

/etc/hosts
127.0.0.1   localhost
::1     localhost ip6-localhost ip6-loopback
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters

192.168.1.1     music.home music

Adblock at the source

Because you are routing your WiFi internet through the Pi here one can also use the hosts file as a way to block certain sites from your Wifi internet too.
Look at the contents of the dnsmasq.conf file below for instructions how to do this, else comment them out.

2.2 Edit DHCPCD to add the wlan0 interface

This type of thing doesn't go in /etc/network/interfaces anymore..

Edit the /etc/dhcpcd.conf file:
sudo vi /etc/dhcpcd.conf
and make it look like this right at the end:

/etc/dhcpcd.conf
interface wlan0
    static ip_address=192.168.1.1/24
    nohook wpa_supplicant


3. Install and configure the WiFi Hotspot software

First we need to install the software components and disable them so they don't run on their own at startup
Notice the unmask command which is vital.

sudo apt-get install hostapd dnsmasq
sudo systemctl disable hostapd
sudo systemctl unmask hostapd
sudo systemctl disable dnsmasq


3.1 Configure HOSTAPD

In the config file below you can customise these entries:

  • Set the SSID, this is the name people see when deciding to join the WiFi. Do not use your hostname (see above), use a different name.
  • Set the WiFi password people need to login to the WiFi with.
  • Set your country_code for your country so the WiFi is legal there.
  • Choose the type of Wifi, g = 2.4GHz, a = 5GHz
  • Choose the channel it will be on (choose appropriate to 2.4 or 5GHz you chose above). Use the command
    iw list
    to see available channels.

This allows you to set your own Wifi name etc.


Create the config file:
sudo vi /etc/hostapd/hostapd.conf

Make it like this with your custom changes as noted above:

/etc/hostapd/hostapd.conf (472 bytes)
# Modified from https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md
# Note: We do not use a bridge because we want a router not a hub/bridge
#
interface=wlan0
#
driver=nl80211
#
ssid=WifiHifi
wpa_passphrase=wifihifi
country_code=GB
hw_mode=g
channel=13
#
wmm_enabled=1
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
#
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
#
ieee80211n=1

Notes:

If you want to create an open hotspot with no passphrase/encryption then simply set wpa to 0, i.e.
If you do this (or set an obvious Wifi password like in the example above) people will be able to try to login to your Pi over the Wifi (as will you!), so make sure you change the default user 'pi' password and make sure any users you add also have decent passwords.

This also applies if you allow the hotspot a route to your LAN. The example /usr/local/bin/wifistart script has some example iptables rules to restrict some LAN addresses, just add/edit these as required.

wpa=0


3.1.1 Tell HOSTAPD where the config file is


.. edit the following
sudo vi /etc/default/hostapd
and put this line inside it, getting rid of any previous DAEMON_CONF entry!

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



3.2 Configure DNSMASQ

This does both the DHCP and DNS lookup stuff for the hotspot.
If it doesn't run the result is a type of zombie Wifi with limited functionality, and /etc/resolv.conf will not have a working nameserver so you may want to edit in the temporary line 8.8.8.8 there until you get DNSMASQ working.

Then it needs to be configured:
Create/edit /etc/dnsmasq.conf
sudo vi /etc/dnsmasq.conf
and make it look like this:

/etc/dnsmasq.conf (2.0kB)
#
# Cutestudio's Raspberry Pi Hotspot/Seedeclip4 dnsmasq config file:
# For option help type 'man dnsmasq', the command line option are the same as these:
#

# Listen only on this (i.e. only connected devices use dnsmasq)
interface=wlan0

# Allow DHCP serving
bind-interfaces
# DHCP assigns IP addresses with a lease time
dhcp-range=192.168.1.2,192.168.1.20,255.255.255.0,24h

# Never ask upstream about short names (without a dot or domain part)
domain-needed
# Never forward addresses in the non-routed address spaces.
bogus-priv

# Really make sure we're using this (should be used by default)
addn-hosts=/etc/hosts

# Optionally filter out adware and malware,
#  E.g to filter out facebook
   # wget -O facebook.ban https://raw.githubusercontent.com/jmdugan/blocklists/master/corporations/facebook/all
   # sudo cp facebook.ban /etc
addn-hosts=/etc/facebook.ban

# Other adware to filter
 # https://github.com/StevenBlack/hosts
 # https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts

  # wget -O final_blocklist.txt "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
  # sudo cp final_blocklist.txt /etc/final_blocklist.txt
addn-hosts=/etc/final_blocklist.txt

# Stop various silliness
filterwin2k
stop-dns-rebind

# To prevent the eth0 from giving us some dodgy domain via /etc/resolv.conf we ignore it via no-resolv.
#  This has the side effect of stopping us seeing the nameserver entry in there that we needed for 
#  the internet to work. So we specify some google nameservers which are just as good here.
# To keep the Pi still using the original DNS assigned via eth0's dhcpd we also edit resolvconf.conf
#  comment out the dnsmasq line there as we are using dnsmasq ONLY for the Wifi devices.
no-resolv

# Because we are using no-resolv...
server=8.8.4.4                  # Forward DNS requests to Google
server=8.8.8.8                  # Forward DNS requests to Google

# synth-domain=,[,]
synth-domain=home,192.168.1.0/24
# auth-zone=home,192.168.1.0/24

# auth-server=,|

Note the avoidance of resolv.conf. This keeps the Wifi domain 'home' we chose intact for Wifi users, without this everything (i.e. the Pi) gets subverted to the domain that pops up in /etc/resolv.conf, which cuts off being able to access the Pi from it's hostname from the Wifi. I.e. do this or the local Wifi DNS breaks.


3.3 Edit RESOLVCONF to isolate DNMASQ

We don't want any influence from our WiFi setup on the Pi for people logged in over ssh etc, it needs to be left as it was.
This stops the nameserver entry in /etc/resolv.conf changing.

/etc/resolvconf.conf (492 bytes)
# Configuration for resolvconf(8)
# See resolvconf.conf(5) for details

resolv_conf=/etc/resolv.conf
# If you run a local name server, you should uncomment the below line and
# configure your subscribers configuration files below.
name_servers=127.0.0.1

# Mirror the Debian package defaults for the below resolvers
# so that resolvconf integrates seemlessly.
pdnsd_conf=/etc/pdnsd.conf
unbound_conf=/var/cache/unbound/resolvconf_resolvers.conf
# dnsmasq_resolv=/var/run/dnsmasq/resolv.conf

Note the last line is now commented out so data from dnsmasq is not used here.


4. Automating the hotspot software startup

Img_Pi_Hotspot.jpg


So everything is ready to run, to automate the orderly update we create this script:

sudo vi /usr/local/bin/wifistart

/usr/local/bin/wifistart (1.9kB)
#!/bin/bash

function daemon_stop()
{
    echo "Stopping all wlan services (if running)..."
    systemctl daemon-reload
    systemctl stop hostapd
    systemctl stop dnsmasq
    ifconfig wlan0 down
}

function daemon_start()
{
    echo "Bring the WiFi up"
    ifconfig wlan0 up
    systemctl start hostapd

    echo "Waiting for wlan0 to be setup before trying to run DNSMasq"
    sleep 15
    echo "Start DNSMasq"
    systemctl start dnsmasq
}

function forwarding()
{
    echo "Enable IPV4 forwarding"
    sysctl net.ipv4.ip_forward=1
}

function iptables_clear()
{
    echo "Clear iptables (in case we play with this script from the command line)"
    iptables -F
    iptables -t nat -F
}

function iptables_router()
{
    # Allow just your own LAN
    iptables -P FORWARD DROP
    iptables -A FORWARD -i eth0 -j ACCEPT

    # Cut off your own LAN from the wifi.
    iptables -A FORWARD -i wlan0 -d 192.168.0.0/16 -j REJECT
    iptables -A FORWARD -i wlan0 -d 10.0.0.0/24    -j REJECT

    # Route as required
    iptables -A FORWARD -i wlan0 -m state --state ESTABLISHED,RELATED -j ACCEPT
    iptables -A FORWARD -i wlan0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

    echo "Add NAT routing as we'll need this for routing between our subnets and the internet"
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
}

function iptables_redirect()
{
    IPS=`ip -4 addr show | grep inet | grep -v 127.0 | sed "s@/@ @" | awk '{print $2}'`
    for IP in $IPS
    do
        echo "Allow people to use port 80 to get SeeDeclip4 at port 8000 ($IP)"
        iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT -d $IP --to-ports 8000
    done
}

function iptables_list()
{
    # List the iptables
    echo "Filter"
    iptables -L -v
    echo "NAT"
    iptables -t nat -L -v
}

function iptables_config()
{
    iptables_clear
    iptables_router
    iptables_redirect
    iptables_list
}

# Tidy up in case we are playing with this script
daemon_stop

# Setup the hotspot
forwarding
daemon_start
iptables_config

# Clean exit
exit 0

And make it executable
sudo chmod a+rx /usr/local/bin/wifistart

Notes about iptables

The key to understanding iptables is this diagram:


iptables.png


By default all routes are open.



5. Make it all happen on startup

Once you are happy it works add the hotspot startup lines it to rc.local so it's there on every startup:

sudo vi /etc/rc.local

/etc/rc.local (877 bytes)
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

# Run USB Automounting - get this in first!!
printf "Starting udisks-glue as user 'pi'"
sudo -u pi /usr/bin/udisks-glue
sleep 1

# Hotspot setup starts now
printf "Starting Wifi Hotspot"
/bin/bash /usr/local/bin/wifistart &

# Run seedeclip4 - use wildcard in case we reinstall it later with a newer version..
printf "Starting SeeDeClip4 as user 'pi' (after 10s to allow disks to mount)"
(sleep 10 && sudo -u pi /home/pi/ARM32_SeeDeClipV4.*/seedeclip4 ) &

exit 0


Reboot safely by typing:
sync
sudo reboot

The sync command makes sure everything is written to disk/SDcard safely. The reboot command also ensures this but using 'sync' can be a useful habit to get into.

Reverting to a Wifi Client

These are the steps to undo or comment out to revert back to the previous out-of-box behaviour"

  • Comment out the new wlan0 section at the bottom of dhcpcd.conf
  • Comment out the line in /etc/rc.local that calls the wifistart script.
  • Revert the /etc/hostname and /etc/hosts entries
  • Reboot.




Copyright © 2007-2023, CuteStudio
Page generated in 0.141s, Powered by Silk V1.3-0 from Cutestudio