Basic Raspberry Pi Home Wifi Router

The Goal of This Post:

This post is an extension to Jacob Salema’s Guide that was picked up by Lifehacker. My main issue with his post is that he refers to the end result as a wireless router, which is not entirely accurate. This device is not meant to be internet-facing and is really more of a wireless/ethernet bridge with the configurations provided.

My goal here was to extend what was provided in his initial post and make it suitable for placing a Raspberry Pi directly behind a cable modem and fully exposed to the internet.

raspberry_pi_pi_ap
image kindly borrowed from adafruit

Materials:

  • Raspberry Pi B (gen 2 model) any Raspberry Pi could potentially work here though
  • Edimax EW-7811Un
  • Short piece of Ethernet (to connect to cable modem)
  • Power Adapter and cord for Pi
  • SD card with Raspbian installed
  • (Optional) USB Keyboard and HDMI Monitor to access the PI. All of these steps can be performed over SSH with a little creativity however.

Performance:

The Raspberry Pi’s performance is limited by the USB throughput of the WLAN adapter; which on the Raspberry Pi is a USB2.0 hub limited to a theoretical maximum of 480mbps, so you’ll never be able to pull gigabit ethernet here but this will get the job done for small sites. However if you have really crappy broadband like I do in this location the chokepoint will be the crappy broadband and not the Raspberry Pi.

I have maxed out my crappy broadband connection with the following speedtest.net performance results:

A BLAZING — 2.78mbps download
A SIMILARLY BLAZING — 1.28mbps upload

I repeated the same speedtest.net tests using a top-notch Lenovo X1 Gen3 laptop and got the exact same results so there is no lag using the raspberry pi here (for this crappy broadband connection). Since my broadband is so crappy here I’m using 802.11G wifi which won’t choke anything.

Note: I probably wouldn’t trust this for anything over 10mbps. I think the Raspberry Pi 2 with 802.11n wifi could handle a standard 40mbps connection based on some of the numbers I’m seeing here.

1). Required Installs:

Perform these first before any of the other steps.

sudo apt-get update -y
sudo apt-get install rfkill zd1211-firmware hostapd hostap-utils iw dnsmasq bridge-utils -y

 

2). Interfaces Configuration (/etc/network/interfaces):

Modify the interfaces file (/etc/network/interfaces) as shown below.

allow-hotplug wlan0
allow-hotplug eth0

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
 
auto wlan0
iface wlan0 inet static
   address 192.168.2.1
   netmask 255.255.255.0

3). DNSmasq Configuration (/etc/dnsmasq.conf):

Modify the DNSmasq configuration file to look exactly like what you see below.

Feel free to modify your domain.

domain=example.com
bogus-priv
no-resolv
server=8.8.8.8
server=8.8.4.4
cache-size=10000
interface=wlan0
dhcp-range=192.168.2.2,192.168.2.254,12h

4). HostAPD Configuration (/etc/hostapd/hostapd.conf):

Modify the configuration file for hostapd to have the following content.

Notice we’re using the “hw_mode=g” option here this is because my limited internet connection couldn’t support max throughput of a wifi-N connection so there would be minimal benefit. If you’re interested in N and have a Raspberry Pi2 and a faster internet connection it may make sense to enable that in your scenario.

Also feel free to modify the SSID to whatever you like and modify the password too, you’ll need at least 8 characters for the password. The channel can also be set to any value between 1-14 (1,6,11,14 are common in the USA)

interface=wlan0
driver=rtl871xdrv
country_code=US
ctrl_interface=wlan0
ctrl_interface_group=0
ssid=NETWORKNAME
hw_mode=g
channel=1
wpa=3
wpa_passphrase=password
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
beacon_int=100
auth_algs=3
macaddr_acl=0
wmm_enabled=1
eap_reauth_period=360000000


5). HostAPD Default Configuration (/etc/default/hostapd):

Modify the defaults file for hostapd (/etc/default/hostapd) to have the same DAEMON_CONF line. The type of quotes used to surround the /etc/hostapd/hostapd.conf file are mission critical; if you use the wrong kind of quotes, hostapd will not start. You can debug the start of hostapd with the command “hostapd -d /etc/hostapd/hostapd.conf” which puts it into debugging mode.

# Defaults for hostapd initscript
#
# See /usr/share/doc/hostapd/README.Debian for information about alternative
# methods of managing hostapd.
#
# Uncomment and set DAEMON_CONF to the absolute path of a hostapd configuration
# file and hostapd will be started during system boot. An example configuration
# file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz
#
DAEMON_CONF="/etc/hostapd/hostapd.conf"

# Additional daemon options to be appended to hostapd command:-
# -d show more debug messages (-dd for even more)
# -K include key data in debug messages
# -t include timestamps in some debug messages
#
# Note that -B (daemon mode) and -P (pidfile) options are automatically
# configured by the init.d script and must not be added to DAEMON_OPTS.
#
#DAEMON_OPTS=""

6). Reboot the Pi

Reboot the Pi to apply the interfaces config, start the hostapd daemon, start dnsmasq daemon. After the reboot you should see your new wireless SSID being broadcast and you should be able to login to it too with your provided password. At this point we need to proceed with the IP tables configuration to setup routing and PAT (port address translation).

7). Enable NAT and Routing Non-Persistently

Execute the following commands to enable NAT and routing for this particular session (we will make these settings persistent across reboots in steps 9 and 10).

#Enable Routing
sudo sysctl -w net.ipv4.ip_forward=1

#Apply the NAT/PAT config 
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Routing allows the Pi to move (or “route”) packets between the two interfaces (Wlan0 and Eth0). Making the Pi a Router allows packets which come in on the Wlan interfaces to be forwarded through the Pi and out the Eth0 port.

NAT stands for Network Address Translation. In this case we’re technically performing PAT or Port Address Translation because we are aggregating the connections and streams of multiple downstream/client IP addresses across a single public IP address using different source ports. As a result packets will be re-written as they pass through a NAT router to be sourced from the public IP address of the NAT router. This re-write hides the original source IP address of the client which generated the traffic. In order to keep track of which stream should be returned to which client, the NAT router keeps a table that maps the Egress destination port to an client IP and source port. This table is called a NAT translation table. You can view the content of the Translation table at any time with the following command:

cat /proc/net/ip_conntrack

8). IP Tables Configuration:

IPtables is a program which interacts with the networking stack in the Linux kernel and tells the kernel how to handle incoming network traffic. There are all kinds of customizations that can be made to an internet facing router. What I show below are pretty basic and generally recognized as safe defaults.

Apply the default config by pasting the following commands into the command line on your device:

#allow incoming traffic from the localhost
sudo iptables -A INPUT -i lo -j ACCEPT
#explicitly allow all icmp/ping traffic
sudo iptables -A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
#explicitly allow all traffic that is already established
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
#Allow new traffic only from the local/WLAN network
sudo iptables -A INPUT -i wlan0 -m state --state NEW -j ACCEPT
#Drop all other new traffic
sudo iptables -A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP<
#Drop all fragments
sudo iptables -A INPUT -f -j DROP 
# Drop XMAS packets
sudo iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# Drop NULL packets
sudo iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
#allow our dns traffic 
sudo iptables -A INPUT -i wlan0 -p udp -m udp --sport 53 -j ACCEPT
#log everything else that is about to get dropped. 
sudo iptables -A INPUT -j LOG --log-prefix "IPTABLES Dropped: " --log-level 7 
#drop everything else that has made it this far down and not matched. 
sudo iptables -A INPUT -j DROP

You can see the presently applied iptables rules using the “iptables-save” command with sudo.

pi@raspberrypi:~ $ sudo iptables-save
# Generated by iptables-save v1.4.21 on Thu Dec 24 17:37:34 2015
*nat
:PREROUTING ACCEPT [7039:855804]
:INPUT ACCEPT [1138:80267]
:OUTPUT ACCEPT [1167:81793]
:POSTROUTING ACCEPT [21:3945]
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
# Completed on Thu Dec 24 17:37:34 2015
# Generated by iptables-save v1.4.21 on Thu Dec 24 17:37:34 2015
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [444346:360889024]
:OUTPUT ACCEPT [4390:510099]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i wlan0 -m state --state NEW -j ACCEPT
-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
-A INPUT -f -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -i wlan0 -p udp -m udp --sport 53 -j ACCEPT
-A INPUT -j LOG --log-prefix "IPTABLES Dropped: " --log-level 7
-A INPUT -j DROP
COMMIT
# Completed on Thu Dec 24 17:37:34 2015

Once you’ve setup the rules you’d like, and you’ve tested that they behave as expected, proceed to step 8 to save the IP tables rules.

9). Make the IPtables Settings Persistent

During the installation of the iptables-persistent program it will ask you if you want to save the presently applied rules, select YES.

sudo apt-get install iptables-persistent -y

Once the rules are saved, they can be edited at the /etc/iptables/rules.v4 (for normal IPv4 traffic). If you’re testing your iptables changes by applying the rules directly using the iptables syntax in step 7 then as you make changes, they can be made persistent by writing the output of the “iptables-save” command directly to the rules.v4 file like so.

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

10). Enable Routing Persistently

The following change allows the Raspi Router to move packets from one interface (wlan0) to another (eth0) by making the device a router.

sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
Advertisements

Raspberry Pi WeMo Home Automation Control Center

WeMo PlugFor the last year I’ve had a Raspberry Pi that is always on mounted underneath my house. I power this device using PoE (Power over Ethernet) so there is literally a single ethernet cable that provides it with the ability to run for simplicity’s sake. This unit was the first Pi I had ever purchased so I’m a little nostalgic about it until you consider that I make it live in a crawlspace under my home.

While it is sitting under the house it’s performing a few vital services for me.

Service 1: Property Temperature Monitoring — Perhaps someday I’ll do a write up on this aspect.

Service 2: Amazon Dash Button Receiver

Service 3: Home Automation Control Center 

I have been meaning to write an article on Service 3 for some time. Of course I didn’t actually get around to doing it until there was a contest involved because it is a well known fact that I will do unspeakable things for free t-shirts. The write up on my Raspberry Pi Home Automation Control Center can be found on Instructables.com

http://www.instructables.com/id/Raspberry-Pi-WEMO-Control-Center/?ALLSTEPS

Raspberry Pi Nursery Cam

One of my most recent projects has centered on the new IMG_20150104_005102addition in my family. With the baby on the way I started looking at baby monitors and realizing that a simple little video-enabled baby monitor was around $300. I figured I could do much better than a tiny 2″ screen and integrate some useful features along the way.

Goal: Sub $300 Baby Monitor Camera

Result: $100 Nightvision Camera /w FM Audio Broadcast

Capabilities:

  • Full 1080p Streaming (cropped image) over Ethernet (Full Frame Image /w 1296×972 resolution)
  • Internet Streaming capabilities to broadcast video to Computers, Phones and HTPCs.
  • Selectable FM Frequency for Audio Transmission – any radio in the house is now a baby monitor including bedside clock radios.
  • Separate Audio and Video Transmission for all different kinds of endpoints
  • Full Nightvision capabilities with the PiNoir Camera Module and IR LED module (can be used in total darkness and picture is excellent)
  • IR LED module shuts itself off when not needed due to a built-in photoresistor
  • Authentic Camera look salvaging a dummy enclosure
  • Stream plays easily in XBMC making any HTPC double as a video receiving endpoint.

Parts list:

Dummy Camera Shell from Monoprice — $7.94
IR LED Light Array from Amazon — $5.90
Slice of Pi Breakout Board — $8.25
Cheap USB Microphone from Amazon — $7.95
Raspberry Pi Model B — ~$40
Raspberry PiNoir Camera Module — $25
Nylon Washers and Tiny Nuts/Bolts — $1.50

Misc Parts (freebies):

SD Card
Piece of Wire
Ethernet Cable
MIcro USB Cable
USB Power Brick
12vdc Power Adapter for LED’s

Project Details:

Gut The Dummy Camera Enclosure

The first order of business was to gut the innards of the dummy camera case to make room for the Pi. In my case I took my dremel cut off wheel and hollowed-out the back of the case to make room for all the wires and SD card which hangs out the back a bit. Removing all the Battery, LED components, and fake LED array left plenty of room for our frankencamera. The IR LED array is pretty much a direct fit for the fake one that was removed. I discarded the black plastic backer behind the fake LED array too. By countersinking the holes that hold the fake LED array in place I was able to reuse the mounting bracket to tighten down the new LED array as a direct replacement for the fake one.

You can see the LED array has mounting holes that line up almost perfectly with one of the pairs from the PiNoir module.
You can see the LED array has mounting holes that line up almost perfectly with one of the pairs from the PiNoir module. I used nylon washers and a pair of nylon spacers between the two boards to keep them from touching each other or anything conductive.
IMG_20141213_124430
You could even dremel-out the battery compartment and stick a little thumb drive here for local storage of video/audio content. Since my device is a network streamer I left this compartment alone after removing all the metallic components.
IMG_20141213_124446
Dremel out the back of the enclosure. This was only necessary for me because of my cheap USB microphone which could not bend very well in the case.
My pet black widow I caught in my workshop as I was working.
My pet black widow I caught in my workshop as I was working.

Install Software

For this project I just used the basic Raspbian image on the SD card. From there I enabled turbo-mode for on demand overclocking up to 1ghz. This project uses PiFM to broadcast audio on the FM bands. PiFM is a quick and dirty solution to acheive my goals. Be aware that PiFM is a pretty noisy transmission that has strong harmonics in bands you should not be transmitting on — that being said, your range is very small (about 30-300ft depending on the length of your antenna) and will probably not hurt anyone (use your judgement and check your local laws to make sure you’re in the clear here). Install PiFM and test that your broadcasting works. Once you’ve confirmed you’re broadcasting as expected you can use Radio Locator to determine which FM frequencies are vacant in your area. Broadcasting on a vacant frequency will give you the best performance and range. I ended up trying a few of the frequencies in the “BEST” category before I found one that was pretty much perfect for me and gave crystal clear audio. For a more permanent antenna attachment, I soldered my antenna wire to the “Slice of Pi” breakout board. I may also add a toggle switch for the FM transmission at some point so it’s nice to have the breakout board ready to go.

Configure Camera

The PiNoir camera module is actually a really capable camera and using the included raspivid software can be configured to behave however you could want it. It’s worth reading about the different modes the camera supports and making a decision as to what is most important for your application. For me I did not need a high quality 1080p stream so much as I did a wide field of view since the camera is close to the subject being filmed. For this reason I selected the 1296×972 resolution which uses the entire sensor for the widest possible field of view.

After selecting the resolution it’s time to tweak your raspivid settings to give you the best results. I after reading through all of the settings and doing a good bit of experimentation I settled on the string below:

#1296×972 1-42fps, 4:3 aspect binned full FOV.
raspivid -h 972 -w 1296 -br 46 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

You’ll notice in my code above I’m using the color effects feature to skew all the colors to a nightvision color palette. I did this because occasionally due to power fluctuations on the camera module the image would shift a bit back and forth from green to red, the effect was significant enough for my wife to notice it which means I wanted to fix it. By specifying the color effects I was able to work around the color-shifting artifacts. FYI the color shift is due to the poor design of the Raspberry Pi power supply circuitry; I believe this may no longer be an issue with the enhancements made to the newest B+ model but since I don’t own one, I can’t say.

Create a Streaming File for XBMC/Kodi

If you want to play your stream on an XBMC/Kodi machine you can put the details of your stream into a simple text file and Kodi will play your stream when you play the file. Here’s my example file that I used.

Filename: Baby.strm

rtsp://[IP Address of PI]:8554

Startup Scripts

A bit of scripting will allow the video and audio to start when the machine boots. My startup scripts are provided below.

/etc/init.d/SCREEN_STARTUP — quick script that starts both Audio and Video streaming at boot time. Don’t forget to add it to your startup with “sudo update-rc.d SCREEN_STARTUP defaults”.

#!/bin/bash

#Raspberry Pi actually doesn't actually support MTU over 1500
#   but does not bark when you set it. See Link below:
#http://www.raspberrypi.org/forums/viewtopic.php?t=52807&p=405135
#ifconfig eth0 mtu 9198

/usr/bin/screen -d -m -S "RASPIVID SESSION" /home/pi/raspivid_abstraction &

sleep 2 

/usr/bin/screen -d -m -S "PIFM SESSION" /home/pi/pifm_stream_command &

echo "Script has attempted to start both screens"

sleep 1
echo "List of available screens is:"

screen -list

/home/pi/screen_watcher.sh &

exit

/home/pi/raspivid_abstraction — necessary to run VLC under the Pi user, VLC will not run as root without modification.

#!/bin/bash

su - pi -c "/home/pi/raspivid_stream_command"

/home/pi/raspivid_stream_command — starts the video stream (just uncomment whatever mode you want to use)

#!/bin/bash
#1296×972 1-42fps, video mode, 4:3 aspect binned full FOV.
raspivid -h 972 -w 1296 -br 46 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

#Experimental adding sound -- does not work! Raspivid sends raw H264 Stream, would need to have an intermediary step with Gstreamer adding the timing information to the video stream in order to layer the audio on top of it.
#raspivid -h 972 -w 1296 -br 46 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --input-slave=alsa://plughw:1,0 --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264


#1296×730 1-49fps, video mode, 16:9 aspect , binned, full FOV (width), used for 720p
#raspivid -h 730 -w 1296 -br 40 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

#1920×1080 1-30fps, video mode, 1080p30 cropped
#raspivid -h 1080 -w 1920 -br 40 --colfx 120:120 -o - -t 0 -vf -hf | cvlc -v stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

/home/pi/pifm_stream_command — Starts PiFM

#!/bin/bash
arecord -fS16_LE -r 22050 -Dplughw:1,0 - |  /home/pi/software/pifm - 106.7 22050

/home/pi/screen_watcher.sh — Makes sure that both commands are still running, I’ve found PiFM occasionally dies out, so this script restarts it.

#!/bin/bash

while true; do
    sleep 30
    PIFM=$(screen -list | grep PIFM | wc -l)
    RASPIVID=$(screen -list | grep RASPIVID | wc -l)
    if [ "$PIFM" -ne "1" ]
    then
        /usr/bin/screen -d -m -S "PIFM SESSION" /home/pi/pifm_stream_command &
        echo " $(date) -- PIFM restarted." >> /var/log/screen_watcher.log
    #else
    #    echo "PIFM still running"
    fi

    if [ "$RASPIVID" -ne "1" ]
    then
        /usr/bin/screen -d -m -S "RASPIVID SESSION" /home/pi/raspivid_abstraction &
        echo " $(date) -- RASPIVID restarted." >> /var/log/screen_watcher.log
    #else
    #    echo "RASPIVID still running"
    fi
done

Ideas for Future Enhancements

  • A button to toggle the FM transmission on/off
  • Eventually I’ll do a similar build (minus the audio) for an exterior surveillance system. Monoprice sells actual camera enclosures for this purpose

Final Tests

Two sided tape was applied to the bottom of the microphone to stick it to the wall. I used the included hardware to mount the bracket as well.
Two sided tape was applied to the bottom of the microphone to stick it to the wall. I used the included hardware to mount the bracket as well.
The baby actually looks a bit creepy here but the picture quality is awesome on this old 25" monitor I had laying around. I purchased a flat screen TV wall mount for my Bedroom Media Center project.
The baby actually looks a bit creepy here; I think he is hypnotized by the faint red glow of the IR LEDs but the picture quality is awesome on this old 25″ monitor I had laying around. I purchased a flat screen TV wall mount for my Bedroom Media Center project which is what I’m using to view the video stream here.
The XBMC Bedroom Media Center playing the stream.
The XBMC Bedroom Media Center playing the stream.

Everything works like a charm. There is about a 6 second delay for both the audio and video transmission which does not really bother me for my application. In my brief research on the subject I think I read it was due to the buffering. One of the things I really like about this project is the separation of the audio and video transmission so you don’t have to have the whole media center on to listen to the audio. You can just use a bedside clock radio (not pictured) to listen to the stream.