Raspberry PI as a Router and WIFI Hotspot

Using a Raspberry PI as a Router and Wifi hotspot with a firewall for your internal LAN or household network is now possible. The Wifi hotspot can function as a hotspot for guests. This can be more secure then the cheap nasty routers supplied by your ISP with hard coded passwords.

What we are aiming at

The network we are aiming to create will be similar to this.

Raspberry Pi router Network layout

  • Internal NIC eth0
    • PPPoE connection
    • The IP address from your ISP: 1.2.3.4
  • USB2RJ45 eth1
    • IP: 10.1.200.1
    • Netmask: 255.255.255.0 (24)
    • DNS Servers: 208.67.222.222, 8.8.8.8
    • Gateway: 1.2.3.4
  • Onboard Wifi wlan0
    • IP: 10.2.200.1
    • Netmask: 255.255.255.0 (24)
    • Gateway: 1.2.3.4
  • Your existing DNS server: 3.4.5.6

You will need a static IP address from your ISP. If your ISP does not provide one, change to a different ISP. 🙂 Let’s say the IP address your ISP supplies you with is 1.2.3.4. Throughout this post you will have to exchange your real external IP with it.

The two DNS servers I have used above are one from Google 8.8.8.8 and the other is from openDNS both are free, fast and reliable.

If you have a LAN already you may or may not already have a local DNS. If you do have one change the IP address 3.4.5.6 to whatever yours is. If you do not just use the DNS servers such as 208.67.222.222, 8.8.8.8.

The network cable from the USB2RJ45, eth1, goes to the switch on your LAN.

Download The Image

To use a Raspberry PI as a Router and Wifi hotspot we will start off by installing the Raspbian Lite image to a micro SD card. We will need a way to read and write to the micro SD card on another PC. That can be done with a USB stick where a micro SD card can be plugged into it or a card reader. There are loads to choose from.

Install The Image

To restore the Ubuntu image onto the micro SD card we can use the Linux command dd. Do not just copy/paste the command below and hope it works on your system. Before running it make doubly sure of the /dev/sdX that your micro SD card appears as on your system.

The alternative is to use the disk utility gnome-disks. This is a GUI that will allow you to select the image and the device before burning the image. If it is not on your system install the package gnome-disk-utility.

sudo apt install gnome-disk-utility

Remember, both tools will overwrite anything on the drive you select once started. The old filesystem and any data will be gone when you press return or click the mouse. Gone never to return. Check it is the right device again.

sudo gnome-disks
 
      OR
 
sudo dd bs=1M if=2018-10-09-raspbian-stretch-lite.img of=/dev/sdc conv=fdatasync

Once the image has been copied over to the SSD card and before putting it into your PI we can enable SSH for your PI. We need to create an empty file called exactly ssh in the /boot directory. Since we will be looking at the filesystems on the SSD navigate to the boot partition and create an empty file ssh. If you are using Wimpdoz make sure it does not try and help by adding an extension, such as .txt.

Eject the SSD drive and wait for it to report it is safe to remove.

Put the SD card back into your PI, connect a keyboard and mouse and a HDMI cable. Boot up your PI and then login with the default user and password. If you enabled ssh you will not need the HDMI or keyboard/mouse. You will be able to use it as a headless server. wait a minute for the PI to boot and then login with:

  • Username: pi
  • Password: raspberry

Update The Software

This image may have been around for a some time so bring it up to date. It takes a minute or so to download and install. Good job it’s not like M$ where you have to wait hours to do one round of checks, downloads, configuring, updating, installing and rebooting, then more configuring and installing before running the checks all over again until all the updates are added. Once that is done the third command updates the kernel and firmware.

sudo apt update
sudo apt dist-upgrade
sudo rpi-update

Reboot just to make sure that is all working.

sudo reboot

This would be a good point to change the name of the PI to, oh let’s call it router01. Edit the usual suspects before rebooting.

sudo nano /etc/hosts

Change the line that starts 127.0.1.1, the other lines you can leave untouched. If you want to use a fully qualified domain name put the long name first as shown below.

127.0.1.1 router01.dragon.lab router01
sudo nano /etc/hostname
router01

After you reboot remember you have changed the hostname of the PI.

Change to Static IP Address

As the PI will become the network gateway for our LAN it must have a static IP address. I will be using a static IP address of 10.1.200.1 for the LAN connection on this Raspberry PI as a router and wifi hotspot. That will be the gateway for all connected systems on the LAN.

Configure eth1 for LAN

To set eth1 the USB2RJ45 network interface with a static IP address we need to update the DHCP client config. I do wish the people upstream would stop messing around unnecessarily with settings. This one seems to be utterly senseless!

Edit the config file dhcpc.conf

sudo nano /etc/dhcpd.conf

Now add the following lines at the end. The first group of lines configures the interface for our LAN, the second set is for the Wifi connection using the built in controller. Note: wlan0 is commented out for the moment.

# Config for router LAN
interface eth1
static ip_address=10.1.200.1/24
static domain_name_servers=3.4.5.6
static routers=1.2.3.4
 
# Guest Wifi connection
#interface wlan0
#static ip_address=10.2.200.1/24
#static domain_name_servers=127.0.0.1
#static routers=1.2.3.4

As we have changed some config file that systemd will need we have to reload them. Another one of those half finished projects some some “special” person decided to force on the Linux users.

sudo systemctl daemon-reload
sudo systemctl restart dhcpcd.service

Enable forwarding

Since the Raspberry PI as a Router and wifi hotspot will need to talk to the outside world, and the internet, we will need to turn on port forwarding. This is done by configuring iptables and sysctl to allow port forwarding. To turn this on we have some choices, to do it until the new reboot use sysctl to perform the same function.

sudo sysctl net.ipv4.ip_forward=1

Or you can edit the .conf file as shown below which will continue to work over a reboot but does not affect the current running system.

sudo nano /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
 
####################
# If you do not use IPv6 you can disable it with the following lines
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Change default password

The default password for the user pi, is a bit of a security risk. 🙂 So now would be a good time to change it.

passwd

Create a New User

It would be even better to create a new user and delete the user pi altogether. This will not weaken security. As it adds one more step for the scumbag hackers and spammers to get past. Let’s call the new user localguy.

sudo adduser localguy

Just answer the questions as you see fit most have little use other than for admin types from Human Resources. The newly created user will only be in one group, with the same name as the new user.

Add groups

Lets see what groups thelocalguy ihas been added to already.

groups localguy

As we will be swapping out the user pi for the new localguy user find the groups that pi is in and add the same groups to localguy.

groups pi
adm dialout cdrom sudo audio video plugdev games users input netdev gpio i2c spi

That command gives you a space delimited list of groups, these need to be appended to the groups for localguy. Change the spaces to commas ‘,’. remember to tell the command it is localguy that is getting the new groups. Do not add the group pi to localguy. It is not needed. You should end up with something like this:

sudo usermod -aG adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi localguy

Before deleting the user pi we better check everything worked okay. For this login as localguy and look at the groups. Then sudo to a root shell which will check localguy has sudo access.

su - localguy
groups
sudo -i

If that all worked okay log out of all terminals that are being used by pi. Including the one use used to su to localguy with. Log back in again as localguy. For the really cautious check you can sudo -i to a root shell before continuing.

Delete The User pi

Now we can delete the unwanted pi user, doing this removes another easy way to break into our PI.

sudo deluser pi

Give your PI a reboot to get that lot into use.

sudo reboot

Install Some Software

Time to start installing some software. pppoeconf is used to configure the, well I’m sure you can work out its for the, PPPoE connection. Hostapd is for setting up the Wifi hotspot. We will of course need dnsmasq for a DNS and DHCP server. The Raspberry PI does not have a real time clock. To keep it in sync with the rest of the world and your LAN install chrony. It is a replacement for NTP. The other packages listed are not necessary but are useful for gaining information into what the network is doing. good tools to have when debugging.

sudo apt install pppoeconf hostapd dnsmasq chrony iptables-persistent ipset fireqos rng-tools

Some more packages that have useful tools to monitoring the network. It is well worth spending some time reading through their man pages to see how they can help you.

sudo apt install dnsutils bwm-ng iptraf iftop iotop whois

During the install you are asked a number of questions as iptables-persistent is configured

  • Save current IPv4 rules? Yes
  • Save current IPv6 rules? Yes

Configure Hardware Random Number Generator

This is a very abbreviated explanation of random numbers and entropy. To generate psudo-random numbers on a PI we need entropy. To build up that entropy PC’s usually use the interrupts from mouse, keyboard and spinning disks. Since this Raspberry PI as a router with most probably be headless and will not have a spinning disk that is a problem when trying to create the necessary random numbers for encrypted connections. Fortunately there is a hardware random number generator built into a PI.

sudo nano /etc/default/rng-tools

Tell rng-tools which device to use, find the line and update it as shown below

HRNGDEVICE=/dev/hwrng

We can now restart the service and check all is well by looking at the status.

sudo systemctl restart rng-tools
sudo systemctl status rng-tools

The status should show the service as enabled, and running. The log lines saying it was started, entropy feed to the kernel ready.

Configure PPPoE

We can configure the PPPoE connection.

sudo pppoeconf

While that is running it will ask a number of questions most are self explanatory this is what I used.

  • Most people using popular dialup providers…: yes
  • Please enter the username: username from ISP
  • Password: password from ISP
  • DNS added to resolve.conf yes
  • Should pppoe clamp MSS at 1452 bytes?: yes
  • Restart at boot: yes
  • Restart now: yes

If you are unsure about why you need to say yes to the question “Should pppoe clamp MSS at 1452 bytes?”, do a google search for “why PPoE has MTU 1492” There are loads of pages that can explain if better than me. It is all to do with the maximum size of a packet you can send over TCP or UDP with out fragmentation.

Let’s take a look at the expected output from one of the suggested commands.

ip addr show ppp0
5: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1492 qdisc pfifo_fast state UNKNOWN group default qlen 3
    link/ppp 
    inet 1.2.3.4 peer 2.3.4.5/32 scope global ppp0
       valid_lft forever preferred_lft forever

Note that inet has returned 1.2.3.4 your external IP from your ISP and peer 2.3.4.5 is the IP address at your ISP you are connecting into, this is point-to-point after all.

You should at this point be able to ping some external hosts from the router. You will not be able to access the internet from another machine on your LAN. For that you need to add a firewall to forward packets in and out and to do some network address translation (NAT) from the private address space you are using as your LAN. Three common private address spaces are 192.168.0.0/16, 172.16.0.0/12 and 10.0.0.0/8.

Configure iptables

As a minimum we will need something like the following, for your iptable rules. I put them into a bash file so I can rerun the rules and order them correctly. we shall call this script iptables1.sh. Put it into the bin directory in the home directory for root. I find the most productive way to play around with iptables, firewalls and routing is to use my Test Networking Lab Ubuntu On 18.04. It is using Ubuntu that is a derivative distribution of Debian which is where Raspbrian Lite also comes from. Therefore what works on one should work on the other. There are a few exceptions 🙂 just to make it interesting.

sudo mkdir /root/bin
sudo nano /root/bin/iptables1.sh

The new file should have the following contents to get the initial setup working.

#!/bin/bash
 
/root/bin/fw.stop
 
echo "Recreating the firewall rules"
 
# Set default policy for chains. 
# DROP everything coming in and forward. Allow everything going out
iptables -P INPUT   DROP
iptables -P FORWARD DROP
iptables -P OUTPUT  ACCEPT
 
# Allow everything on the loopback interface
iptables -A INPUT -i lo -j ACCEPT
 
# Allow everything on LAN
iptables -A INPUT -i eth1 -j ACCEPT
 
# Allow replies to outgoing packages from WAN
iptables -A INPUT -i ppp0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 
# NAT from LAN to WAN
iptables -t nat -A POSTROUTING -o ppp0 -s 10.1.200.0/24 -j SNAT --to-source 1.2.3.4
 
# Allow routing from LAN to WAN
iptables -A FORWARD -i eth1 -o ppp0 -j ACCEPT
 
# Allow replies from existing connections. i.e. HTTP requests, DNS, ssh
iptables -A FORWARD -i ppp0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

You will have noticed that the script above calls another script called fw.stop. This is shown below. It resets the default policies for the INPUT, OUTPUT and FORWARD chains to allow everything from everywhere. It removes the fire wall and all its rules. The two commands at the end flush and then delete all ipset lists, when they are not commented.

#!/bin/bash
 
echo "Stopping firewall and allowing everyone..."
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t raw -F
iptables -t nat -F
iptables -t filter -F
iptables -t mangle -F
iptables -F
iptables -X
 
#ipset -F
#ipset -X

Make the two scripts read, write and executable for root and nothing for the world.

sudo chmod 750 /root/bin/{fw.stop,iptables1.sh}

To setup the iptable rules run the script iptables1.sh. After that you will be able to connect to the internet from the LAN not just your PI. This very basic firewall router setup will not allow any new connections from the outside. It will allow outgoing connections, for example browsing the web and the data that will be returned when you request data by clicking on a link.

iptables-persistent

This tool will allow you to make your iptable rules persistent that is they will survive a reboot. Once you have the iptable rules as you want them just run the command below. The same rules will be reloaded on a reboot. Each time you change the rules run the command again.

sudo iptables-save > /etc/iptables/rules.v4

Configure hostapd

We have already installed the software to make the built in Wifi work as an access point or hotspot. There are two config files for hostapd. There is an example hostapd.conf file in /usr/share/doc/hostapd/examples/hostapd.conf.gz. Copy that over to /etc/hostapd and gunzip it.

sudo cp /usr/share/doc/hostapd/examples/hostapd.conf.gz /etc/hostapd
sudo gunzip /etc/hostapd/hostapd.conf.gz
sudo nano /etc/default/hostapd
sudo nano /etc/hostapd/hostapd.conf

These are the options that I changed:

interface=wlan0
driver=nl80211
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=Raspberry Pi hotspot
country_code=GB
hw_mode=g
channel=8
auth_algs=1
own_ip_addr=127.0.0.1
wpa=2
wpa_passphrase=hotraspberries
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP

If you read the comments in the example config file there are some good explanations for the options.

Configure Wifi interface

We can now uncomment the lines we added to dhcpcd.conf.

sudo nano /etc/dhcpcd.conf

Now uncomment the lines at the end of the file.

# Guest Wifi connection
interface wlan0
static ip_address=10.1.200.1/24
static domain_name_servers=127.0.0.1
static routers=1.2.3.4

As we have changed some config files that systemd will need we have to reload them. Another one of those half finished projects some some “special” person decided to force own the users.

sudo systemctl daemon-reload
sudo systemctl restart dhcpcd.service

Dnsmasq setting for Wifi DNS and DHCP

sudo nano /etc/dnsmasq.conf

These are the options I changes or are left uncommented in the Dnsmasq config file.

port=0
domain-needed
bogus-priv
no-resolv
no-poll
server=208.67.222.222
server=8.8.8.8
interface=wlan0
no-hosts
dhcp-range=set:wifi,10.3.141.50,10.3.141.69,255.255.255.0,6h
dhcp-option=tag:wifi,option:router,10.3.141.1
dhcp-option=tag:wifi,option:dns-server,208.67.222.222,8.8.8.8
log-queries
log-dhcp
dhcp-mac=set:client_is_a_pi,B8:27:EB:*:*:*
dhcp-reply-delay=tag:client_is_a_pi,2

There are comments in the config file that explain these settings. The option port=0 turns off DNS from Dnsmasq.

The option dhcp-range sets the range of IP addresses given out by the DHCP server. This is limited to 19 connections 69 – 50 = 19. The lease is for 6 hours. The two options towards the end for logging are useful for testing and debugging. They can be turned off once everything is working.

Restart the DNS service check the status to make sure all is well and no syntax errors were added to the config file.

sudo systemctl restart dnsmasq.service 
sudo systemctl status dnsmasq.service

iptables for Wifi

This is a guest Wifi and paranoia says the traffic on this wifi should not interact with your LAN. Do you trust everyone has fully patched their devices and and not infected with malware or botnets? To get the Wifi traffic routed out to the internet and back in again without touching your LAN. We need to update iptables1.sh lets call this one iptables2.sh. I am so adventurous with names 🙂

sudo cp /root/biniptables1.sh /root/bin/iptables.sh
sudo nano /root/bin/iptables2.sh

The new file should have the following contents to get the initial setup working.

#!/bin/bash
 
/root/bin/fw.stop
 
echo "Recreating the firewall rules"
 
# Set default policy for chains. 
# DROP everything coming in and forward. Allow everything going out
iptables -P INPUT   DROP
iptables -P FORWARD DROP
iptables -P OUTPUT  ACCEPT
 
# Allow everything on the loopback interface
iptables -A INPUT -i lo -j ACCEPT
 
# Allow everything on LAN
iptables -A INPUT -i eth1 -j ACCEPT
 
# Allow Wifi connections access to DHCP only. 
iptables -A INPUT -i ppp0 -p udp --dport 67 -j ACCEPT
 
# Allow replies to outgoing packages from WAN
iptables -A INPUT -i ppp0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 
# NAT from LAN to WAN
iptables -t nat -A POSTROUTING -o ppp0 -s 10.1.200.0/24 -j SNAT --to-source 1.2.3.4
#NAT from Wifi to WAN
iptables -t nat -A POSTROUTING -o ppp0 -s 10.3.141.0/24 -j SNAT --to-source 1.2.3.4
 
# Allow routing from LAN to WAN
iptables -A FORWARD -i eth1 -o ppp0 -j ACCEPT
 
# Allow replies from existing connections. i.e. HTTP requests, DNS, ssh
iptables -A FORWARD -i ppp0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 
# Allow routing from Guest WIFI <=> WAN
iptables -A FORWARD -i wlan0 -o ppp0  -j ACCEPT
iptables -A FORWARD -i pppo  -o wlan0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Reboot to get that lot taken into use. You should now be able to

  • connect to the Wifi hotspot Raspberry Pi hotspot with the password hotraspberries.
  • pick up an IP address in the range 10.3.141.50 – 69.
  • be able to browse the internet.
  • connect from the LAN to the internet

Leave a Reply

Your email address will not be published. Required fields are marked *