Raspberry PI open hotspot for your company site(s) only

Raspberry HotspotThe problem is really simple, you want/need to give open Wifi to your customers (let’s say inside a shop), but to you own company website (or websites) only. And nothing else, no other resources in the (internal or external) network.

The solution is simple and it comes in a tiny format… you will just need a Raspberry PI with a Wifi USB dongle that supports AP mode. Your company website should have an exclusive IP address

Side note: as normal, I’m not liable for any kind of mess, data loss, massive meteorite smash or other apocalyptic event in your world due to this guide.

Have the PI installed with the latest Raspbian, booted and logged in as root (sudo -s or equivalent).

Update the software sources:

apt-get update

Install the required software

apt-get install hostapd dnsmasq

Configure the wireless interface with a static IP address,
edit /etc/network/interfaces

iface wlan0 inet static
address 10.0.0.1
netmask 255.255.255.0
broadcast 255.0.0.0
# pre-up iptables-restore < /etc/iptables.rules

and restart the interface

ifdown wlan0
ifup wlan0

Here I choosed the 10.0.0.1 address to isolate the Wifi guests from the 192.168.1.x internal network. You should adapt it according to your existing set-up.

edit /etc/default/hostapd

and replace
#DAEMON_CONF=””

with
DAEMON_CONF=”/etc/hostapd/hostapd.conf”

now edit (it’s a new file) /etc/hostapd/hostapd.conf

For a full list of switches and whistles please do refer to http://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf, we go with a very minimalistic (but functional) configuration

interface=wlan0
ssid=WIFI-FREE-AS-BEER
channel=0
macaddr_acl=0
auth_algs=1
wmm_enabled=0
driver=nl80211
hw_mode=g
ieee80211n=1

Here we can start the service.

service hostapd start

and I got the dreadful failed in red font… a lsusb command quickly showed the infamous RTL8188CUS chip:
Bus 001 Device 004: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter

Thanks to the good people of the Internets you get a quick fix (you are downloading an external binary… so cross your fingers before installation, and nothing bad will happen to your PI… well, it worked for me).

wget http://dl.dropbox.com/u/1663660/hostapd/hostapd
chmod 755 hostapd
mv /usr/sbin/hostapd /usr/sbin/hostapd.ori
mv hostapd /usr/sbin/

and change in /etc/hostapd/hostapd.conf
driver=nl80211
to
driver=rtl871xdrv

service hostapd start

service [….] Starting advanced IEEE 802.11 management: ok
hostapdioctl[RTL_IOCTL_HOSTAPD]: Invalid argument

Even with the warning output the service managed to start and work correctly.

By now there should be an open network called WIFI-FREE-AS-BEER available to log in, but the process will stall in the Obtaining IP Address stage. So it’s time to move to the DHCP and DNS server.

Edit /etc/dnsmasq.conf, and place at the end of the file the lines

address=/#/aaa.bbb.ccc.ddd
interface=wlan0
dhcp-range=10.0.0.10,10.0.0.250,12h015/05/raspberry-pi-open-hotspot-for-your-company-sites-only/
no-resolv
log-queries
log-dhcp

adjust the aaa.bbb.ccc.ddd to the exclusive public IP address of your company website. Basically we are configuring Dnsmasq to answer all name resolution queries to your public IP address, and setting DCHP leases to the Hostspot clients from IP 10.0.0.10 to 10.0.0.250 valid for 12h periods.

From now on it should be possible to log in to the Hotspot, but no data flow, so let’s take care of this now. First activate the kernel IP forwarding

echo 1 > /proc/sys/net/ipv4/ip_forward

and then adjust iptables rules

iptables -F
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -p tcp -d aaa.bbb.ccc.ddd --dport 80 -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -p tcp -d aaa.bbb.ccc.ddd --dport 443 -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -p udp -d 10.0.0.1 --dport 53 -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -p udp -d 10.0.0.1 --dport 67:68 -j ACCEPT
iptables -A FORWARD -i wlan0 -j DROP 

remember to replace aaa.bbb.ccc.ddd with your the exclusive public IP address like in dnsmasq. From this point there should be a fully functional system. You can login to the Hotspot, and any http/https request will be landing in your company website. All other network traffic (except for the DHCP and name resolution will be blocked).

Now, to wrap up just make all this stuff survive reboots:

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf

update-rc.d hostapd defaults
update-rc.d dnsmasq defaults

iptables-save > /etc/iptables.rules

and uncomment in /etc/network/interfaces the line
# pre-up iptables-restore < /etc/iptables.rules

There is just one thing left, avoid the captive portal detection and the respective sign in to network message. If you are using some kind of URL mapping/decoupling system (really hope you do) it’s pretty easy.

For Android, test for http://clients3.google.com/generate_204 request and send a 204 header and 0 bytes:

if (isset($script_parts) && $script_parts[0] == 'generate_204') {
    header('HTTP/1.1 204 No Content');
    header('Content-Length: 0');
    die();
}

For iOS lalaland test for the user agent ‘CaptiveNetworkSupport’ and send a 200 response:

if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/CaptiveNetworkSupport/i', $_SERVER['HTTP_USER_AGENT'])) {
    header("HTTP/1.1 200 OK");
    die();
}

That’s it folks, and I wonder what will be the next use for this tiny big computer?

UPDATE
After all been working well and good for a long time, maybe after a reboot a problem surfaced. Maybe a whim of the bits gods, the system was using the dnsmasq on internal lookups for all interfaces ignoring the interface directive.

So for example if one ssshed into the raspberry and tried to wget google.com one would get our company site…. not good.

Simple fix, manually edit /etc/resolv.conf, you can use Google public DNS (not censored) or your LAN Router IP (that normally uses the upstream DNS of your provider).

# Google IPv4 nameservers
nameserver 8.8.8.8
nameserver 8.8.4.4

and to not be automatic overwritten by dhcpclient updates set the immutable bit:

chattr +i /etc/resolv.conf

UPDATE 2
Noticed that the raspberry was missing /etc/network/interfaces (no file at all and I don’t recall to delete it). Maybe the problem was due to this and Maybe it’s time for a new SD card and fresh install.