Sunday, May 11, 2014

Raspberry Pi 3G-Ethernet Router

In this post, I'm going to explain a DIY 3G-ethernet router based on Raspberry Pi. The configuration of this DIY "router" is simple:

Internet <--> USB 3G modem <-->powered USB hub <--> Raspberry Pi <--> Ethernet <--> user machine (PC/Laptop)

The purpose of this kind of router varied, depending on your needs. However, I have a very specific need in one of my setup where providing Internet connection directly from the 3G modem is not possible and only Ethernet interface can be used by the user (physical/virtual) machine.

These are what you need:
  1. A Raspberry Pi (I'm using the B revision), with Raspbian distro.
  2. A powered USB hub. This is required because most USB 3G modems are power hungry and cannot be operated reliably only via the USB connector on the Pi.
  3. A USB 3G modem. Use whatever you have, hopefully Raspbian kernel already support it. I'm using Huawei E153 USB modem which is rather not so friendly in terms of operation in Raspbian, but it works reliably nonetheless, once you know how to "switch" it into modem "mode".
  4. Ethernet cable.
  5. A user machine to test the interconnection.
  6. Internet/data plan subscription to your mobile operator or whatever works for you.
Let's start with installing the software needed for the USB 3G modem to work on Raspbian. I'm basically using the steps mentioned at The Fan Club, but modify them a bit because I'm not using wvdial. These are my modified steps:
  1. Update your Raspbian with "sudo apt-get update"
  2. Install the needed packages with "sudo apt-get install ppp usb-modeswitch"
  3. Configure the pppd configuration file according to your needs.
Now, the software installation steps to setup the DHCP server and Network Address Translation (NAT) are mostly similar to the one at Adafruit: https://learn.adafruit.com/setting-up-a-raspberry-pi-as-a-wifi-access-point/install-software, except that you should remember that the "outgoing" interface in our case is eth0, instead of wlan0 and the "incoming" interface is ppp0 instead of eth0. Therefore, I believe you can adjust the steps accordingly. Also, I found that Adafruit step to make the NAT setting permanent is not working for me. I have to modify the configuration line in /etc/network/interfaces to:

pre-up iptables-restore < /etc/iptables.ipv4.nat

instead of the one explained by Adafruit to make the NAT work permanently across reboots and shutdowns.

The next step is to connect to the Internet. These are my steps:
  1. Power on the Raspberry Pi.
  2. Unplug the 3G USB modem from the USB hub, and then plug it back again if it's previously plugged in before Raspberry Pi finished booting. This is a compatibility hack because sometimes it is required, and sometimes not.
  3. Wait until the 3G USB modem is recognized (watch syslog, i.e. tail -f /var/log/messages)
  4. Run usb_modeswitch on the modem
  5. Run pppd
  6. Watch syslog to find out whether the data connection succeeded or not, i.e. tail -f /var/log/messages 
  7. Test the connection with your user machine connected through Raspberry Pi Ethernet.
Note that step 1 to 5 must be carried out exactly as mentioned above, otherwise pppd will always fail to initialize data connection with pppd. I'm not so sure what causes it, but it seems that the modem cannot respond to the AT command(s) sent by pppd correctly, at least the command to establish data connection. I saw that through syslog.

I also run a DHCP server in my Raspberry Pi, the isc-dhcp server. The configuration files for isc-dhcp are /etc/init.d/isc-dhcp-server, /etc/default/isc-dhcp-server and /etc/dhcp/dhcpd.conf. You only need to deal with the last two config files. /etc/default/isc-dhcp-server determines which network interface(s) used to listen for DHCP client requests. /etc/dhcp/dhcpd.conf determines the network configuration, such as the IP addresses to assign to the client, DNS servers, gateway, etc. Let's have a look at my configuration files.
This is how my /etc/default/isc-dhcp-server looks like.

# Defaults for isc-dhcp-server initscript
# sourced by /etc/init.d/isc-dhcp-server
# installed at /etc/default/isc-dhcp-server by the maintainer scripts

#
# This is a POSIX shell fragment
#

# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
DHCPD_CONF=/etc/dhcp/dhcpd.conf

# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
#DHCPD_PID=/var/run/dhcpd.pid

# Additional options to start dhcpd with.
#       Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
#OPTIONS=""

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="eth0"
As you can see, isc-dhcp listens to client on the ethernet interface and the dhcpd configuration file to use is set to /etc/dhcp/dhcpd.conf. Now, let's have a look at /etc/dhcp/dhcpd.conf.
#
# Sample configuration file for ISC dhcpd for Debian
#
#

# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;

# option definitions common to all supported networks...
#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

default-lease-time 7200;
max-lease-time 86400;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;

# .. irrelevant commented config omitted for brevity ..

# Raspberry Pi subnet - note: this is the subnet of M$ Internet Connection Sharing
# TODO: Make sure the router configuration is correct
subnet 192.168.137.0 netmask 255.255.255.0 {
  range 192.168.137.3 192.168.137.21;
  option broadcast-address 192.168.137.255;
  option routers 192.168.137.2;
  default-lease-time 7200;
  max-lease-time 86400;
  option domain-name "local";
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}
As you can see, the lease time and maximum lease time configuration are consistent. I found that inconsistencies in these parameters sometimes causes isc-dhcp fails to provide valid IP addresses to the DHCP clients. So, watch-out to those parameters values.

Well, there are some more details regarding pppd, usb_modeswitch and iptables which are missing. This post is still considered beta and I'm going to update it in the not so distant future..

Post a Comment

No comments: