Using a Pi 3 as a Ethernet to WiFi router

A Raspberry Pi 3

At Linagora I’m working on a personal assistant project called LinTo. More articles will follow about it, so I’m not going to be very long on what LinTo is, but the highlights are:

  • The software is designed to run on a Raspberry Pi
  • LinTo is connected to OpenPaaS, our awesome collaborative platform so that it can do nice things like adding events to your calendar, run video-conferences or check your emails.
  • The Pi has a microphone and a speaker, so that LinTo can receive voice commands are is able to give you answers
  • LinTo is aware of its environment, and is connected to a number of smart devices to interact with lights, printers, computer screens or TVs, cameras, etc.

While implementing support for various devices, I faced a challenge: how do you connect an Ethernet-only device, such as the Philips Hue Bridge to the Internet when you have no Ethernet sockets available (because, for instance, we’re in 2017 and you’re working for a 100% WiFi company) ?

Easy! You’d say… Use the Ethernet port on the Pi and route traffic to/from the wireless network interface. Well, you’d be right, but there’s a bit more to setup actually :) Here’s how I did it.

Setting up

First, it’s worth mentioning that the Pi is running Pixel which is based on Debian Jessie. You have some very nice low-level tools available such as systemd which makes it very easy to experiment new things.

The Pi will basically be forwarding packets between network interfaces, an operation that is disabled by default at the kernel level on most distributions. You have to enable this as a prerequisite to the other operations below:

$ sudo vi /etc/sysctl.conf

And uncomment following line in this file:

net.ipv4.ip_forward = 1

As you don’t want to reboot immediately, you can simply reload sysctl with

$ sudo sysctl -p

Serving DHCP requests from the Pi

Before even thinking at delivering IP addresses through the wired interface, you have to define your subnet and assign a static IP address to the Pi. This is required as the Pi will act as the gateway and as such, must hold a known, static IP address.

Configuration of network interfaces using the network manager, or system configuration files is out of scope of this article, but a quick one-liner can be obtained with the mighty ifconfig:

$ sudo ifconfig eth0 netmask broadcast

The above command assigns the address to the wired interface using a /24 subnet.

Now that we have our IP address setup, we can install and configure a DHCP server, so that connected devices will receive an IP address and will be able to connect to the Internet:

$ sudo apt-get install isc-dhcp-server
$ sudo service isc-dhcp-server stop
$ sudo vi /etc/default/isc-dhcp-server

And edit the INTERFACES environment variable so that the DHCP server only listens on the wired interface and don’t mess with your wireless settings (yeah, it actually CAN mess things up…):


Next, we would need to define how the DHCP server hands IP addresses to the clients on the network, this is done through the /etc/dhcp/dhcpd.conf configuration file. The configuration I’m using is as follows, simple and effective. There are some comments inline for better understanding of the various settings:

authoritative; # I will be the single DHCP server on this network, trust me authoritatively
# subnet and netmask matches what you've defined on the network interface
subnet netmask {
interface eth0; # Maybe optional, I was not sure :o

range; # Hands addresses in this range
  option broadcast-address; # Matches the broadcast address of the network interface
option routers; # The IP address of the Pi
option domain-name "local"; # You can pick what you want here
option domain-name-servers x.x.x.x, y.y.y.y; # Use your company DNS servers, or your home router, or any other DNS server
  default-lease-time 600;
max-lease-time 7200;

You’re now ready to start the DHCP server:

$ sudo service isc-dhcp-server start

If you tail your syslog, you should see some DHCPxxx log messages, meaning you’re ready to go!

Routing traffic through the wireless interface

Now that our Pi is acting as a DHCP server, the connected devices will get an IP address and will be able to talk to the Raspberry. But for now, they can’t access the “outside world” because the Pi does not know what to do with packets coming from the devices through the wired interface.

What we need is a way to make packets coming from the external device “pass through” the Pi and exit by the wireless interface. Obviously, we need the responses to go back to the device also, so that we don’t break the various network protocols in play here (mainly TCP). Technically speaking, this is NAT and we’ll use the kernel’s ability to masquerade in order to achieve this. And guess what? This is easy !

Using the powerful iptables utility, we can setup IP masquerading in a single command:

$ sudo iptables -t nat -A POSTROUTING -s -o wlan0 -j MASQUERADE

What it does is masquerade traffic coming from the subnet (the -s option) to the wlan0 network interface (the -o option). Exactly what wee need.

This change is NOT permanent, you have to persist it or restore the configuration at system startup. There are quite a lot of good iptables guides on the Web, so I’m not going to go into details about that here.

With this setup, your connected device should be connected to the Internet. Problem solved.

Interested in joining us doing awesome code? Contact us on Github, on Twitter or apply to a job offer on our website.