본문 바로가기

Linux

iptables 를 이용한 wireless(무선) masquerade

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.

network diagram

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.

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.

/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.