My apartment does not have hardwired ethernet, and the physical location of our incoming cable is such that it’s very difficult to position wired ethernet anywhere. I’ve considered using a powerline adapter to run ethernet over the apartment’s electric, but those adapter kits are a bit expensive. When I got my Raspberry Pi though, it occurred to me that I could use it to create an island of wired ethernet that feeds to the wifi connection we’ve got set up.

This is a depiction of the setup I was going for to turn wireless internet into wired.

I find iptables (and networking in Linux) extremely obtuse and hate having to figure this stuff out, so now that I’ve got it working I will leave the necessary configuration details below.

A much more comprehensive writeup on this concept has been developed by Robin Newman, so if this guide is unclear, I highly recommend checking out Robin’s guide.

Ben Low also pointed out a handy tutorial that gives a much more sophisticated treatment of this approach using Proxy ARP that is a good thing to check out if this configuration is not good enough.

/etc/network/interfaces should look something like this. If you couldn’t tell, this is Raspbian (a Debian-derived distribution)

# The loopback network interface
auto lo
iface lo inet loopback

# the internal (wired) network interface
allow-hotplug eth0
iface eth0 inet static
  address 192.168.2.1
  network 192.168.2.0
  netmask 255.255.255.0
  broadcast 192.168.2.255
  gateway 192.168.2.1

# the external (wifi) interface
allow-hotplug wlan0
iface wlan0 inet static
  address 192.168.1.98
  network 192.168.1.0
  netmask 255.255.255.0
  broadcast 192.168.1.255
  gateway 192.168.1.1
  wpa-ssid "homewifi"
  wpa-psk ...

pre-up iptables-restore < /etc/network/iptables

The contents of /etc/network/iptables are:

*filter
:INPUT ACCEPT [73:5085]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [72:6792]
-A FORWARD -i eth0 -j ACCEPT
-A FORWARD -i wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
*nat
:PREROUTING ACCEPT [43:2584]
:INPUT ACCEPT [2:278]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o eth0 -j MASQUERADE
-A POSTROUTING -o eth0 -j MASQUERADE
-A POSTROUTING -o wlan0 -j SNAT --to-source 192.168.1.98
COMMIT

which was generated by this script:

#!/bin/sh
IPT=/sbin/iptables
LOCAL_IFACE=eth0
INET_IFACE=wlan0
INET_ADDRESS=192.168.1.98

# Flush the tables
$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD

$IPT -t nat -P PREROUTING ACCEPT
$IPT -t nat -P POSTROUTING ACCEPT
$IPT -t nat -P OUTPUT ACCEPT

# Allow forwarding packets:
$IPT -A FORWARD -p ALL -i $LOCAL_IFACE -j ACCEPT
$IPT -A FORWARD -i $INET_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

# Packet masquerading
$IPT -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_ADDRESS

Of course, ip forwarding has to be enabled in the kernel by editing /etc/sysctl.conf and uncommenting a line:

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

and then doing sysctl –system.