Raspberry Pi Internet in a box

From Wiki
Jump to: navigation, search

I have a lot of wireless devices I like to use when I'm out and about. In the past, I've relied on public hotspots or sharing the internet connection of friends. However, it struck me that I could pay for a single 3G connection and use a Linux box to share that with all my wireless devices. I could simply use a smartphone and suitable 'portable hotspot' app to do this, but firstly I don't own one and secondly I thought there might be some fun possibilities in creating my own device.

Hardware

The basis of the project is a Raspberry Pi model B, which surely by now everyone must have heard of. The RPi is an ideal candidate because of its low cost, and low power consumption. The addition of a USB 3G dongle and USB hostapd compatible WiFi card completes the setup. The integrated 10/100Mb LAN interface is a useful addition, since it allows the box to connect to my firewall and act as a backup internet link at home when I'm not using the box out in the real world.

I chose a 3G dongle from T-Mobile, which is a Huawei E1750. Impressively, the young lady at the T-Mobile shop knew that this was supported with a recent Linux kernel, and right she was. At £5 plus a £10 top-up, it was pretty affordable too. For WiFi, I wanted an adapter that would work with hostapd so that the box will act as an access point (master mode). I selected a TP-Link WN822N, because it has a couple of dipole antennae, is surprisingly powerful, supported by hostapd, and above all was £20 from Argos.

The Basics

The 'official' operating system for use with a Raspberry Pi is Raspbian Linux, a Debian-based distribution. That will do for me, I like Debian, and Raspbian is available as a handy image file which can be dded straight to a SD card – no installation routine needed.

$ unzip *raspbian.zip
# dd if=raspbian/raspbian.img of=/dev/rdisksomething bs=1024

With the basic setup out of the way, I started with the 3G dongle. Because it caters mainly to Microsoft Windows users, the device initially mounts as a filesystem with the driver software ready to load. Very clever, but not what we want. It's necessary to use usb-modeswitch in order to have the card present as a network interface:

# apt-get install usb-modeswitch

Then, simply remove/reinsert the dongle and use

# dhclient eth1

to bring up the interface. Don't forget to add it to the network configuration:

# vi /etc/network/interfaces

allow-hotplug eth1
iface eth1 inet dhcp

Since the box is now on the Internet, a simple iptables ruleset would be a good idea, too. I'll take the opportunity to set up NAT at the same time:

# vi /etc/iptables-rules

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# NAT anything leaving eth1 (the 3G dongle)
-A POSTROUTING -o eth1 -j MASQUERADE
COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# We'll be managing the device from the LAN (eth0) initially
-A INPUT -i eth0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3/4 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
# Deny connections from anywhere else
-A INPUT -j DROP
COMMIT
# iptables-restore < /etc/iptables-rules
# vi /etc/network/interfaces

auto eth0
iface eth0 inet static
 address 192.0.2.10
 netmask 255.255.255.0
 pre-up iptables-restore < /etc/iptables-rules

Allow connections to traverse the box by uncommenting this line:

# vi /etc/sysctl.conf

net.ipv4.ip_forward=1

and apply the change:

# sysctl -p

Now it's time to tackle WiFi. Plug in the WiFi adapter and create an interface configuration for it. This is the IP address range in which your end hosts will live:

# vi /etc/network/interfaces

allow-hotplug wlan0
iface wlan0 inet static
 address 172.16.20.1
 netmask 255.255.255.0

A DHCP server will be very useful, install one:

# apt-get install isc-dhcp-server

Edit /etc/default/isc-dhcp-server and make sure DHCP listens only where it is needed (rogue DHCP servers on your LAN are bad!):

# vi /etc/default/isc-dhcp-server

INTERFACES="wlan0"

Create a scope for your end hosts:

# vi /etc/dhcp3/dhcpd.conf

subnet 172.16.20.0 netmask 255.255.255.0 {
        range 172.16.20.100 172.16.20.125;
        option domain-name-servers 8.8.8.8, 4.2.2.4;
        option routers 172.16.20.1;
}

Start DHCP:

# service isc-dhcp-server start

Install hostapd

# apt-get install hostapd

Create a configuration file for it. More complicated setups are possible, but these are the basics for testing:

interface=wlan0
driver=nl80211
ssid=raspitest
channel=1

Uncomment this line:

# vi /etc/default/hostapd

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

and start hostapd:

# service hostapd start

At this point, your end hosts will be able to associate with the SSID raspitest, acquire an IP address and browse the Internet. Of course, long term, it would be advisable to protect your SSID with WPA2 or another secure authentication and encryption mechanism.

Fine Tuning

Frequency Scaling

With firmware versions later than September 2012, it's possible to alter the clock speed of the Broadcom SoC (CPU/GPU). The latest version of Raspbian includes the necessary firmware in /boot. Whilst it is possible to set clock speeds up to 1Ghz, I am more interested in scaling the clock speed down when the RPi is idle in order to reduce heat output and power consumption. To do so, I set the following values in /boot/config.txt

# vi /boot/config.txt

# Badly named option, means 'enable frequency scaling':
force_turbo=0
# The lowest frequency we will allow the RPi to run at:
arm_freq_min=100
# for more options see http://elinux.org/RPi_config.txt

A reboot is necessary for this to take effect:

# shutdown -r now

Install the cpufreq utilities:

# apt-get install cpufrequtils

See what the CPU is doing right now:

# cpufreq-info

...

analyzing CPU 0:
... 
  hardware limits: 100.0 MHz - 700 MHz
  available cpufreq governors: conservative, ondemand, userspace, powersave, performance
  current policy: frequency should be within 100.0 MHz and 700 MHz.
                  The governor "ondemand" may decide which speed to use
                  within this range.
  current CPU frequency is 100.0 MHz (asserted by call to hardware).

In particular, we're interested that the frequency range is 100-700MHz, the CPU is presently idling at 100MHz and 'ondemand' governor is being used, which will ramp up the CPU speed as needed. I'm fairly sure that 'ondemand' is the default governor, but if not it can be set using:

# cpufreq-set -g ondemand

You can see this in action. In one shell, run this:

# watch -n 1 'cpufreq-info | grep "current CPU frequency is"'

and in another shell, do something processor intensive. apt-get update, or even just sshing to the box is enough to see the CPU speed spike and then drop back down to 100MHz. Nice.

The Voltage Regulators

The Raspberry Pi includes two voltage regulators, whose job is to reduce the ~5V USB-supplied power to 3.3V and 1.8V to power various components. These regulators is not terribly efficient and wastes (some say about 30%) of the power by turning it into heat. I haven't modded my RPi yet, but I intend to replace regulators RG1 and RG2 at some point.

USB Power

On my RPi, which is a revision 1, the two usb ports can supply around 100mA between them. This is due to polyfuses which protect the RPi from drawing too much current from its power supply (which might be another computer). Unfortunately, 100mA is nowhere near enough for the 3G and WiFi dongles. This problem might or might not exist on later revisions, since I understand the polyfuses have been removed. In any case, I needed a solution, and the simplest way seems to be to solder a couple of wires between the input of components F3 and D17 to the power pins of the USB ports, like so:

Rpi-solder-usb-power.jpg