This post will show how to share the Internet between two network adapters on Ubuntu Desktop 18.04 (any architecture) and Raspbian Buster 10 (for Raspberry Pi).

The most common situation is when your device (a laptop or Raspberry Pi) is connected to the Internet via Wifi and you want to share this connection with another device via Ethernet (port RJ45), such as a SmartTV or a Desktop that has no Integrated Wifi.

What is necessary:

  • Wifi already set up with the Internet.
  • Laptop or Raspberry Pi with Wireless Card
  • Linux Operating System (Ubuntu or Raspbian)
  • Ethernet Cable
  • The device you want to connect (TV, Computer, Printer, etc.)

What will be configured:

  • Configure the NIC (network adapter)
  • Install DHCP Server (auto-assign IPs) [learn more – CertBros]
  • Configure NAT (routing) [learn more – CertBros]
  • Install DNS Server (optional) [learn more – Techquickie]

Configuring the NIC

ip a

1: lo: <omitted unnecessary text>
inet 127.0.0.1/8 scope host lo
<omitted unnecessary text>
2: eth0: <omitted unnecessary text>
inet 172.16.1.1/24 brd 172.16.1.255 scope global noprefixroute eth0
<omitted unnecessary text>
3: wlan0: <omitted unnecessary text>
inet 192.168.2.40/24 brd 192.168.2.255 scope global dynamic noprefixroute wlan0
<omitted unnecessary text>

1: lo: It is the loopback interface. Just ignore this virtual interface.

2: eth0: This is the Ethernet adapter that will be connected to the TV, Computer, Printer…

3: wlan0: This is the Wireless adapter that has to be connected to your Wifi and have Internet connection working.

Note: The names of the interfaces may vary, in my case eth0 (LAN) and wlan0 (WAN).

In my example, my eth0 is already manually configured.

On Ubuntu, configure the eth0 using the graphical interface according to the configuration below:

On Raspbian, configure the eth0 using the terminal to edit the file /etc/dhcpcd.conf, and paste the following code inside. Go to Terminal and issue:

sudo nano /etc/dhcpcd.conf

Add this code at the end of the file.

interface eth0
static ip_address=172.16.1.1/24
nogateway

Restart the computer after changing the configuration.

Pay attention to the IPs in the new scenario:

No matter if you are doing the Laptop + TV situation or Raspberry Pi + PC or both, what you have to pay attention to is the color of the IPs. All the Orange IPs are in the same subnet and the Blue and the Green are other subnets.

The TV and the PC have to have an IP to communicate in the subnet, so or you manually configure each of them, or you dynamically configure any device that connectors the new networks.

Installing DHCP Server

sudo apt-get update
sudo apt-get install isc-dhcp-server -y
sudo nano /etc/default/isc-dhcp-server

Inform the network adapter that the DHCP will work (LAN):

INTERFACESv4="eth0"

Edit the configuration file:

sudo nano /etc/dhcp/dhcpd.conf

Clean the file content and add this code:

default-lease-time 600;
max-lease-time 7200;
option subnet-mask 255.255.255.0;
option broadcast-address 172.16.1.255;
option routers 172.16.1.1;
option domain-name-servers 8.8.8.8, 8.8.4.4;
option domain-name "host.local";
subnet 172.16.1.0 netmask 255.255.255.0 {
range 172.16.1.10 172.16.1.100;
}

Issue the commands:

sudo systemctl restart isc-dhcp-server
sudo systemctl enable isc-dhcp-server
sudo systemctl status isc-dhcp-server

The second command may fail in Raspbian, but don’t worry! Keep moving…

Check if the service is ACTIVE in green:

This is the new scenario, the devices can get IP configuration automatically:

All this configuration is customizable, take the change and make modifications and make how it works. In the example above intentionally the IPs of the Laptop and the Raspberry Pi are the same, but they are in physically different networks. Same for the TV and PC, they may get the first available IP from the DHCP Server, which is the same in both. Check if the devices got the IP correctly.

Configuring NAT (for Ubuntu):

sudo ufw enable
sudo nano /etc/ufw/sysctl.conf

Uncomment this configuration or add if you do not find it:

net/ipv4/ip_forward=1

Do the same for /etc/sysctl.conf.

Edit the startup script:

sudo nano /etc/rc.local

Copy and paste this content to the file:

#!/bin/bash
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT
iptables -A INPUT -i wlan0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -d 192.168.2.40 --dport 80 -j DNAT --to-destination 172.16.1.10:80
iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -j MASQUERADE
exit 0

Note: there is one line in the middle of this code that is the template in case you want to do a Static NAT, known as Port Forwarding. The IP 192.168.2.40 shall be replaced by the public IP, and the IP 172.16.1.10 shall be replaced by the private IP, a Webserver in this case (port 80). If you are not using Port Forwarding simply delete this line, or not! See the illustration below:

Change the permission of the file to make it executable:

sudo chmod 755 /etc/rc.local

Configuring NAT (for Raspbian):

sudo nano /etc/rc.local

Add this code at the end of the file, right before the last line: exit 0

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT
iptables -A INPUT -i wlan0 -m conntrack \
--ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT
iptables -A FORWARD -i wlan0 -o eth0 -m conntrack \
--ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -j MASQUERADE
systemctl start isc-dhcp-server

Restart Ubuntu/Raspbian to take effect and test if the TV and/or PC have internet!

Installing DNS Server (optional)

Taking a look at the preview configuration, the DHCP Server auto-configure the devices (TV, PC, Printer…) to the Google Public DNS Server (no contraindication). Another alternative would be using the Wireless router DNS Server, in my case 192.168.2.1.

Here is how to create your own Private DNS Server and have full control of it. Black-list or white-list can be applied as Parental Control or Business Policy or any other application you want to perform to your network.

sudo apt install bind9 -y
sudo nano /etc/bind/named.conf.options

Replace the whole content of the file with the code below:

options{
directory "/var/cache/bind";
recursion yes;
forwarders {
8.8.8.8;
8.8.4.4;
};
forward only;
};

Note: the DNS Server works forwarding the requests that it does not know, after the first time it keeps the information in ‘cache’ for the next time, increasing the performance of the internet

Remember to restart DNS and DHCP Servers:

sudo systemctl restart bind9
sudo systemctl restart isc-dhcp-server.service

Now, restart all the devices, so they will request a new configuration from the DHCP Server and start using the local DNS Server in your gateway.

It is all set up and running!

To reserve an IP for a specific device append the following lines to the file /etc/dhcp/dhcpd.conf:

host mytv {
hardware ethernet A4:BA:DB:14:BD:4F;
fixed-address 192.168.110.10;
}

BONUS

For port forwarding in the same network or single network interface:

#!/bin/bash
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -d 192.168.1.5 --dport 443 -j DNAT --to-destination 192.168.1.50:443
iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT
iptables -t nat -A POSTROUTING -j MASQUERADE
exit 0

Or use nftables to manage the iptable rules:

sudo ufw disable
sudo systemctl disable ufw
sudo apt install nftables -y
sudo systemctl enable nftables
sudo sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
sudo sysctl -p
sudo nft list ruleset
sudo nft flush ruleset
sudo nft list ruleset
sudo nft flush ruleset
sudo nft add table nat
sudo nft 'add chain nat postrouting { type nat hook postrouting priority 100 ; }'
sudo nft 'add chain nat prerouting { type nat hook prerouting priority -100; }'
sudo nft 'add rule nat prerouting ip daddr 192.168.1.5 tcp dport { 21 } dnat 192.168.1.50:21'
sudo nft 'add rule nat prerouting ip daddr 192.168.1.5 tcp dport { 60000-65000 } dnat 192.168.1.50:60000-65000'
sudo nft add rule nat postrouting masquerade
sudo nft list ruleset | sudo tee /etc/nftables.conf

To manage the rules use the following commands:

sudo nft -a list table nat
sudo nft delete rule nat prerouting handle 7

How to do NAT with nftables:

sudo nano /etc/sysctl.conf
net.ipv4.ip_forward = 1
sudo nano /etc/nftables.conf
table inet nat {
    chain prerouting {
        type nat hook prerouting priority -100; policy accept;
    }
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname "eth0" masquerade
    }
}
table inet filter {
    chain forward {
        type filter hook forward priority 0; policy drop;
        iifname "eth1" oifname "eth0" accept
        ct state established,related accept
    }
}
sudo sysctl -p
sudo nft -f /etc/nftables.conf