Raspberry Pi Mobile Internet Router
Introduction
Living alternately in an off-grid home in the woods and a campervan, a reliable Internet connection is hard to come by. For a while, my partner and I we got along by using a combination of public Wifi and the Hotspot functions of our smartphones. However, this is tedious in the long run, so I decided to turn a Raspberry Pi 2 Model B (that I already had) into a mobile router. What I like about the Pi is that it draws its power through Micro-USB, which allows us to easily run it in our off-grid home as well as the van straight from the 12 V battery system with a simple car USB adapter.
I mainly followed the Instructable tutorials by BigCowPi and Deviprasath with a few extra solutions here and there.
I purchased a USB Wifi dongle (as the Raspberry Pi 2 Model B, unlike the Pi 3, doesn’t have built-in Wifi) as well as a 3G GSM USB modem to hold a SIM card. I made sure to buy device that were recommended as Raspbian-compatible. The Wifi dongle is an Edimax EW-7811UN (“ideal for Raspberry Pi”), and the 3G modem is a Huawei E173.
SSH like MacGyver
You will probably be able to skip this step unless you’re utterly unprepared as I was. If you have either an ethernet cable (and your Pi has a working installation of Raspbian with SSH enabled) or a screen and a keyboard, you can go directly to the next section.
The first problem I ran into was that while I had previously installed the Raspbian distribution on the Raspberry Pi, I was unable to log into the device. I had a keyboard and an HDMI cable, but no screen. Neither did I have an ethernet cable or even the adapter needed for my MacBook Air. When trying to find out how to use a laptop as an external screen (impossible, apparently), I learned that fortunately, one can log into the Raspberry Pi via SSH over a USB connection from an Android phone with a terminal emulator by turning one of the Pi’s USB ports into an ethernet port and assigning a static IP to it. At least in theory – in practice, this requires editing the file /etc/network/interfaces
, which in turn requires access to the Raspberry Pi, right? So it seems I was stuck.
Then it hit me that I might be able to edit the filesystem on the Raspberry Pi directly on the laptop. Not out of the box of course, since Apple doesn’t provide drivers to access Linux filesystems, but with OSXFuse maybe? There is a fork of the Fuse-ext2 project that worked for me so I could edit /etc/network/interfaces
as follows:
allow-hotplug usb0 auto usb0 iface usb0 inet static address 192.168.42.42 netmask 255.255.255.0 network 192.168.42.0 broadcast 192.168.42.255
After rebooting the Raspberry Pi and connecting my Android phone to it through this special USB port, I was able to log in via SSH (the default password of Raspbian, in case you never changed it, is raspberry
, by the way):
$ ssh pi@192.168.42.42
Now I was able to use my phone’s Internet connection by adding a route as explained in the above link:
$ sudo route add default gw 192.168.42.129 usb0
(If needed, find the phone’s IP address using arp -a
.) From this point on, the Pi was connected to the Internet through the phone. But we wanted to have it the other way around, so keep reading.
Setting up Wifi
The next challenge was to setup the Wifi. I chose to get this running first in order to be able to log into the Pi from my laptop. The idea is to use a USB Wifi dongle in Access Point mode. It turned out that the Wifi dongle I picked worked out of the box – when used “normally”. But to get Access Point mode to work, there was a little intricacy: I had to compile patched drivers.
Fortunately, the entire procedure is rather straightforward:
$ wget https://github.com/jenssegers/RTL8188-hostapd/archive/v2.0.tar.gz tar -zxvf v2.0.tar.gz $ cd RTL8188-hostapd-2.0/hostapd $ make && sudo make install
From then on, it worked like a charm. I edited the configuration file /etc/hostapd/hostapd.conf
as follows:
# Basic configuration interface=wlan0 ssid=popcorn channel=1 #bridge=br0 # WPA and WPA2 configuration macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=3 wpa_passphrase=SUPERSECRETPASSWORD wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP # Hardware configuration driver=rtl871xdrv ieee80211n=1 hw_mode=g device_name=RTL8192CU manufacturer=Realtek
I now edited back /etc/network/interfaces
by undoing the changes made above and editing eth0
and wlan0
, as well as adding a hostapd
entry. The file now read as follows:
auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 192.168.0.1 netmask 255.255.255.0 auto wlan0 iface wlan0 inet static address 192.168.1.1 netmask 255.255.255.0 hostapd /etc/hostapd/hostapd.conf
I completed the configuration of the Wifi access point by adding DHCP, appending the following lines to /etc/dnsmasq.conf
:
# RPI ROUTER domain-needed bogus-priv interface=eth0 dhcp-range=192.168.0.1,192.168.0.100,12h interface=wlan0 dhcp-range=192.168.1.1,192.168.1.100,24h
At this point, I was able to disconnect the phone and connect to the Wifi served by the Raspbery Pi from my laptop by joining the network popcorn
and issuing:
$ ssh pi@192.168.1.1
Setting up the 3G modem
For the remaining part of this project, I needed a bunch of packages, so I went ahead and installed them right away:
$ sudo apt-get install iptables dnsmasq ppp wvdial usb-modeswitch iw
I did, as expected run into problems with the modem’s data partition which would prevent the modem from being recognized. Different devices require different values in /etc/usb_modeswitch.conf
; what worked for me was:
DefaultVendor=0x12d1 DefaultProduct=0x14d1 TargetVendor=0x12d1 TargetProductList=14c9 MessageContent="55534243123456780000000000000011062000000100000000000000000000" CheckSuccess=20
For the actual 3G connection, there are various options involving scripts to be found, but I chose a simple way using wvdial
. I edited /etc/wvdial.conf
to match my carrier’s requirements:
[Dialer Defaults] Modem = /dev/ttyUSB0 Phone = *99# Username = eplus Password = gprs Init3 = AT+CGDCONT=1,"IP","internet.eplus.de","0.0.0.0" ISDN = 0 Auto Reconnect = on Stupid Mode= 1 Idle Seconds= 0 Auto DNS = on
and added the following to /etc/network/interfaces
:
iface ppp0 inet wvdial
(Unfortunately, auto ppp0
didn’t work here because it would cause wvdial
to run on boot before the modem hardware was ready. My workaround is explained below.)
To set up NAT, I edited /etc/sysctl.conf
by uncommenting the line
net.ipv4.ip_forward=1
Then I ran
$ sudo iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE $ sudo iptables-save > /etc/iptables.ipv4.nat
and added to the file /etc/network/interfaces
the following line:
pre-up iptables-restore < /etc/iptables.ipv4.nat
Getting it ready on boot
Unfortunately, I needed to manually have the Pi establish the 3G connection, having to wait for the modem to be ready after boot. (The network devices seem to be brought up before the USB hardware is ready.) I experimented with udev
to listen for the device to show up but ultimately didn’t succeed. Instead, I wrote a simple shell script /usr/local/bin/ppp0up.sh
that just sleeps 20 seconds before bringing the device up:
#!/bin/sh -e sleep 20 /sbin/ifup ppp0
and added a line to /etc/rc.local
(run on boot):
/usr/local/bin/ppp0up.sh &
This runs my above-mentioned script in the background, so it doesn’t block the boot process. When the internet comes up, the 3G modem will signal it by lighting up its LED in green (EDGE) or bright blue (3G).
The magical memory stick
Now that the system automatically goes online on boot, there is only one problem: How can I shut the Pi down, given there is no button? I don’t want to always open an SSH connection, and I can’t afford to keep the Pi running 24/7 (even though its power consumption is little, it does strain the batteries). People have added shutdown buttons to their Pi computers via the GPIO pins, but that was a little too much for me. Instead, I repurposed an old memory stick by adding a udev
rule that would cause the Pi to shut down as soon as the stick is plugged in!
I used lsusb
to find vendor and product IDs of the memory stick and added a file /etc/udev/rules.d/11-shutdown.rules
with the following content
ACTION=="add", ATTR{idVendor}=="13fe", ATTR{idProduct}=="1f00", RUN+="/sbin/halt"
It usually only takes a few seconds for the system to come to a halt. Happy days!
Addendum: Solving the power problem
The tutorial by BigCowPi mentions the fact that the Raspberry Pi might struggle to provide the power for a 3G modem and a Wifi dongle. I did in fact experience occasional problems where the Pi would (seemingly randomly) reboot. It turned out that the devices were indeed drawing too much power. Fortunately, this is a restriction that can be lifted by changing a configuration setting. In the file /boot/config.txt
, adding the line
max_usb_current=1
will provide 1200mA to all USB ports combined, as opposed to the default 600mA. I have not experienced a power shortage since.