Use a Raspberry Pi 3 as an access point

 

raspberry-pi-logo

 

Raspberry Pis are awesome [citation needed].

This post is about how to setup a WiFi with a Raspberry Pi 3. It describes what packages you have to install and one example is shown how to configure them. In the end you will have an Raspberry Pi 3, which is connected through ethernet to the internet. The Pi provides an SSID and takes care that the traffic between WiFi and Ethernet is forwarded.

This tutorial basically follows the instructions on http://elinux.org/RPI-Wireless-Hotspot, except that it uses dnsmasq instead of udhcpd.

Steps

Operating system

Download and install an operating system for the Raspberry Pi. I used “Raspbian” and followed this description.

https://www.raspberrypi.org/documentation/installation/installing-images/mac.md

Before you unmount the flashed card, create a file named ssh in the boot segment on the disk. Otherwise you won’t be able to SSH into the Raspberry Pi.

Installations

Connect the Pi to your local network (through ethernet), search for the little rascal (i.e. using nmap) and connect to it via ssh.

When logged in, you will have to install at least 2 packages: dnsmasq and hostapd. I always love to have vim, so here’s what I did:

sudo apt-get update
sudo apt-get install vim
sudo apt-get install dnsmasq
sudo apt-get install hostapd

Configure the wlan interface

Now, let’s edit the iface wlan0 part in /etc/network/interfaces, make sure it is static and has following properties:

allow-hotplug wlan0
iface wlan0 inet static
address 10.0.0.1
netmask 255.255.255.0
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Behold, that I used the address 10.0.0.1 as static IP. We will have to use the same IP for the DHCP configuration.

At this point you should quickly restart the networking service.

sudo service networking restart

ifconfig wlan0 should then show the applied changes on in the wlan0 interface.

Configure DNSmasq

The Pi will have to manage the clients IP address (DHCP) on the wlan0 interface. I used DNSmasq for the DHCP server, but it should work fine with any other DHCP servers.

However, let’s edit /etc/dnsmasq.con

domain-needed
bogus-priv
interface=wlan0
listen-address=10.0.0.1
dhcp-range=10.0.0.2,10.0.0.254,12h
dhcp-option=option:router,10.0.0.1
dhcp-authoritative

Note that the Pi’s static IP address is used for listen-address and dhcp-option=option:router. For more information about that, consider reading http://www.thekelleys.org.uk/dnsmasq/doc.html. ;-)

Portforwarding (route wlan0 to eth0)

The next step affects iptables. I am no expert in this, so I basically just copy pasted that stuff and ensured that the in -i and out -o parameters made sense.

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

In a nutshell, it allows that general traffic/communication is allowed between the interfaces wlan0 (wireless) and eth0 (ethernet).
In order that the iptable rules apply immediately, you’ll have to do this:

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

In order that the iptable rules are considered after reboot, edit /etc/sysctl.conf, and uncomment this line:

net.ipv4.ip_forward=1

Finally persist the iptable rules, otherwise they get truncated after reboot. I used a package iptables-persistent which persists the rules right during installation which is pretty convenient.

sudo apt-get install iptables-persistent

Configure the access point

Now it get’s interesting. We can create our own SSID and define a password.
Therefore create /etc/hostapd/hostapd.conf and paste and save this:

interface=wlan0
driver=nl80211
ssid=SIMPLIFICATOR-WIFI
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=YOUR-INCREDIBLY-SECURE-PASSWORD
wpa_key_mgmt=WPA-PSK
#wpa_pairwise=TKIP  # You better do not use this weak encryption (only used by old client devices)
rsn_pairwise=CCMP
ieee80211n=1          # 802.11n support
wmm_enabled=1         # QoS support
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]

Let’s connect the above config to the default hostapd config, edit /etc/default/hostapd and make sure DAEMON_CONF is uncommented and points to the config file.

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

Services (hostapd & dnsmasq)

Lastly, let’s restart the services and enable them, so that the start automatically on boot.

sudo service hostapd restart
sudo service dnsmasq restart
sudo update-rc.d hostapd enable
sudo update-rc.d dnsmasq enable

That’s it

You should now see a WiFi named SIMPLIFICATOR-WIFI and connect to it using the passphrase YOUR-INCREDIBLY-SECURE-PASSWORD, or whatever values you have given it.

Insights

While writing the blog post I had several insights:

  • Raspberry Pi 3 comes with an 2.4 GHz 802.11n (150 Mbit/s) WiFi. It’s always good to know the limits of the bandwidth.
  • Even if you used a WiFi USB adapater with 1000 Mbit/s, the maximum speed would be 480 Mbit/s because of the USB 2 interface (!)
  • I wasn’t able to configure the Pi, so that two WiFi dongles run simultaneously, so that you could extend the range of an existing WiFi without having the Pi connected to an ethernet cable.

Vaults with Ansible

When it comes to software versioning, you normally do not want to upload passwords or secrets into shared repositories. Too many people might have access to the code, and it’s irresponsible to have secrets there without protection.

On the other hand, you actually do want to share such secrets among certain co-workers (the “circle of trust”, implying that all other co-workers are not trustworthy 😉).

So, what we want are “protected” secrets in our versioning control system, that only the circle of trust has access to.

We are going to identify our files to be protect and encrypt them with Ansible. The encryption bases on a password, that we share with the people who may know our secrets. So, this password is chosen once and used for the same file “forever”.

Encrypt 🔐

Let’s say we store our secrets in a file named secrets.yml, and the content looks like this

favorite_artists:
- Lady Gaga
- Justin Bieber
- Kanye West

Obviusly no one should ever know that we like those artists, but the circle of trust may know, if necessary.

Now we can use ansible-vault encrypt to encrypt our secrets.

pi@raspberrypi:~ $ cat ./secrets.yml
favorite_artists:
- Lady Gaga
- Justin Bieber
- Kanye West

pi@raspberrypi:~ $ ansible-vault encrypt ./secrets.yml
Vault password:   # enter a vault password here
Encryption successful

pi@raspberrypi:~ $ cat ./secrets.yml
$ANSIBLE_VAULT;1.1;AES256
38373634613533646632343139633431313465386136613231316163633965623832313832623830
6537656536393339626161616632633062656161346630360a653833373033643565313632386338
34623537393861623236666132356231656165393033633035333338306436376563383234383030
3330346664326339300a313565313933333464643436353130363539666534323634346439636433
33396636353461653436613764373861396133623833386436303536636363333737653136656165
31643164303564373861343239643038656161346562343236323761663335363465633833363436
61373966343633663531653932326239346438626330653265343739646561346431323966313132
64626134356535366562

Behold where it asks to enter a vault password (# enter a vault password here). We’ve chosen a wise, complicated password (= foo), and can now share this with the people in the circle of trust.

Further, we can check in secrets.yml and upload it to our versioning control system.

Decrypt

Of course, at some point we will have to decrypt secrets.yml, we do this:

pi@raspberrypi:~ $ ansible-vault decrypt ./secrets.yml
Vault password:    # enter the vault password here
Decryption successful

pi@raspberrypi:~ $ cat ./secrets.yml
favorite_artists:
- Lady Gaga
- Justin Bieber
- Kanye West

That’s the whole magic.

One more thing

Don’t be confused that you’ll get different contents of encrypted files, without changing the original content (and same vault password).

Eencrypt the file with foo twice, save the corresponding outputs to ./secrets1.yml and ./secrets\2.yml

pi@raspberrypi:~ $ cat ./secrets.yml
favorite_artists:
- Lady Gaga
- Justin Bieber
- Kanye West

pi@raspberrypi:~ $ ansible-vault encrypt ./secrets.yml --output=./secrets1.yml
Vault password:  # "foo" goes here
Encryption successful

pi@raspberrypi:~ $ ansible-vault encrypt ./secrets.yml --output=./secrets2.yml
Vault password:  # "foo" goes here too
Encryption successful

Compare the files: secrets1.yml and secrets2.yml

pi@raspberrypi:~ $ cat ./secrets1.yml
$ANSIBLE_VAULT;1.1;AES256
39356232653735336132323762643366336530666334333039373265336334373635336665643965
3230336463613962363730393530316566313432613761650a636666623132323462323466613164
62316434663763613637666133626536633639616362313236383964363331616436353331363631
3336343339363733390a343034616365323163346231303065393065313039373837393264363361
35343961623165383037626231333061316263626431623361323164333235393835363262363438
61626433323032323261376261303536313534663861623638383235343566353532393736396464
65326337346562633330366134633731643930323364333730316533383432643266373464633863
30356437636633363465

pi@raspberrypi:~ $ cat ./secrets2.yml
$ANSIBLE_VAULT;1.1;AES256
65323662356530333862393965386137666539636262656332323535363934343033363633353831
3738666430363738386465306134316333383734633762350a616433656465343866613766643237
33636537303962366131363965326637333633333161616562346334663134343666666266646264
6166366564313431370a353630363635643865346138613634633833653863376561336638386138
32616536646165313034303938343863316630373731353730326330306231653532306363366634
31376437643539646464636635306365653962666262623637303335613230383133326363383432
65626162303735303863373031396537363837626461613363336537323362653163663735303931
37633961326136663162

Encrypted, they are not identical, but still they can both be decrypted with foo, eventually with the same result.

pi@raspberrypi:~ $  ansible-vault decrypt ./secrets1.yml
Vault password:
Decryption successful

pi@raspberrypi:~ $  ansible-vault decrypt ./secrets2.yml
Vault password:
Decryption successful

pi@raspberrypi:~ $  cat ./secrets1.yml
favorite_artists:
- Lady Gaga
- Justin Bieber
- Kanye West

pi@raspberrypi:~ $  cat ./secrets2.yml
favorite_artists:
- Lady Gaga
- Justin Bieber
- Kanye West