Linux internet sharing (I) - Wifi to LAN (NAT)

Scenario:
There is a WifiAP which has internet access.
There is a computer which runs linux (PC1) and is connected to this WifiAP.
There is a second computer (PC2) which has LAN connection to the PC1 but not Wifi antenna.
Both run linux Debian based distro (e.g: Debian, Raspbian, Ubuntu, Backtrack, Kali...).
We want to access internet from PC2 (eth0) through PC1 (eth0) through the WifiAP (wlan0).
We assume that the PC2 has no fixed IP, so PC1 needs to provide a DHCP service in order to automate the connection of PC2.
I have chosen this setup as I don't like remembering IP addresses for the different machines.
I'll lease IP addresses from my IP range 192.168.42.10-50 for PC2 and similar clients. My local PC1 IP address will be 192.168.42.1 for eth0.

A script will be attached to this post at the end, which takes care of the routing after this setup has finished without the boot time configurations, so anytime you can make this work by running the script.

Configure interfaces

First of all we need to make sure that the client network settings are appropriate in PC2.

nano /etc/network/interfaces

make sure this is in it:

auto eth0
allow-hotplug eth0
iface eth0 inet dhcp

Install and configure necessary services

On PC1 we need to install DHCP service:

apt-get install isc-dhcp-server

Edit the DHCP configuration file

nano /etc/dhcp/dhcpd.conf

Find the lines that say

option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

and comment them out with a # in the beginning so they say

#option domain-name "example.org";
#option domain-name-servers ns1.example.org, ns2.example.org;

Find the lines that say

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

and uncomment them by removing the # so it says

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

Then scroll down to the bottom and add the following lines

subnet 192.168.42.0 netmask 255.255.255.0 {
 range 192.168.42.10 192.168.42.50;
 option broadcast-address 192.168.42.255;
 option routers 192.168.42.1;
 default-lease-time 600;
 max-lease-time 7200;
 option domain-name "local";
 option domain-name-servers 8.8.8.8, 8.8.4.4;
}

Configure the DHCP service

nano /etc/default/isc-dhcp-server

scroll down to INTERFACES="" and modify it to say INTERFACES="eth0"

Modify the network interface configuration of PC1 to have the fixed IP and to automatically set up the IP when connected.

nano /etc/network/interfaces

Make sure that the followings exist

auto eth0
allow-hotplug eth0
iface eth0 inet static
 address 192.168.42.1
 netmask 255.255.255.0

Set up IP forwarding by editing syscontrol:

nano /etc/sysctl.conf

Configure forwarding (NAT)

Find and uncomment, or add to the bottom as a new line:

net.ipv4.ip_forward=1

Save the file. This will start IP forwarding on boot up.

To set up the IP forward immediately, run:

echo 1 > /proc/sys/net/ipv4/ip_forward

To set up the firewall to forward traffic from the wlan0 internet capable interface to the eth0 lan interface:

iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT

You can check to see how the firewall rules look like

iptables -t nat -S
iptables -S

To make this happen at every boot (so you don't have to type it every time) run

iptables-save > /etc/iptables.ipv4.nat
nano /etc/network/interfaces

Add this line:

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

Start services

After plugging in both ends of the network cable you can set up the PC1 network manually without reboot:

ifconfig eth0 192.168.42.1 netmask 255.255.255.0

Then start the services and check their status:

service isc-dhcp-server start
service isc-dhcp-server status

If you want to do this at every boot time, execute this:

update-rc.d isc-dhcp-server enable

Routing in the router PC1 should look like this:

root@computer:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.20.1.1 0.0.0.0 UG 0 0 0 wlan0
172.20.0.0 0.0.0.0 255.255.240.0 U 0 0 0 wlan0
192.168.42.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

where 172.20.1.1 is Internet gateway on the Wifi AP

172.20.0.0 is the Wifi network
192.168.42.0 is the LAN network

Nameserver on the PC1 is the Wifi AP provided DNS (xxx.xxx.xxx.xxx) and Internet DNS like 8.8.8.8. You can define this in the /etc/resolv.conf.

Routing in the PC2 should look like this:

root@home1:/home/pi# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.42.1 0.0.0.0 UG 0 0 0 eth0
192.168.42.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

Nameserver on the PC2 is the Internet DNS provided by WifiAP (xxx.xxx.xxx.xxx).

If the above routes are not look like this, you can modify them using the follwoing commands:

e.g: on PC1

route add default gw 172.20.1.1 wlan0

e.g: on PC2

ip route add default gw 192.168.42.1

Test the connections by pinging 8.8.8.8 and "wget google.com".

Script to automate the startup of the NAT

The script to run after the initial setup has been performed

#!/bin/bash
echo "### Wifi to LAN nat script ###"
echo "### developed by itfanatic ###"
 
echo "If you need to reset firewall rules, run these!"
echo "iptables -F"
echo "iptables -t nat -F"
echo "iptables -X"
echo "iptables -t nat -X"
 
echo "Make sure that on the client system the followings are set:"
echo "    auto eth0"
echo "    allow-hotplug eth0"
echo "    iface eth0 inet dhcp"
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
 
ifconfig eth0 192.168.42.1 netmask 255.255.255.0 up
 
service isc-dhcp-server start
service isc-dhcp-server status
 
echo "Started, start browsing from remote computer"