Try  HackMD Logo HackMD

Sharing connections from an internet adapter to another

This is a fork on the gist by Konamiman. Several typos are corrected and it works on my Pop!_OS too.

Suppose you want to share the Wi-Fi interface wlx244bxx to the Ethernet interface enp0s31f6 (I know it's weird)

Following this guide, you may need to download some packages from apt.

DHCP

Configure the interface (in my case the Ethernet one) to let the device being shared internet acquire a static IP address. Here the gist proposes installing dhcpcd and edit /etc/dhcpcd.conf.

interface enp0s31f6
static ip_address=192.168.87.1/24

You may need to tick the "Automatically connect" option for the created connection in Network Manager (like via nmtui) for convenience.

Then install isc-dhcp-server, edit the config /etc/dhcp/dhcpd.conf:

authoritative;
subnet 192.168.87.0 netmask 255.255.255.0 {
 range 192.168.87.100 192.168.87.200;
 option broadcast-address 192.168.87.255;
 option routers 192.168.87.1;
 default-lease-time 600;
 max-lease-time 7200;
 option domain-name "local-network";
 option domain-name-servers 8.8.8.8, 8.8.4.4;
}

Trick: It seems that you can use the local DNS server (systemd-resolved) to serve as the DNS server for your local network with the command:

socat UDP-LISTEN:53,fork,reuseaddr,bind=192.168.87.1 UDP:127.0.0.53:53

Useful if you want to ensure the same behavior on your host machine

It's good to always assign an static address to the downstream device. Find out the device's MAC address and append:

host myrouter {
  hardware ethernet xx:xx:xx:xx:xx:xx;
  fixed-address 192.168.87.111;
}

Then the edit file /etc/default/isc-dhcp-server,

INTERFACESv4="enp0s31f6"

Now systemctl start isc-dhcp-server. Check the journal (journalctl -u ...) to see if everything goes well.

NAT

Now the iptables rules. Unfortunately it is not persistent, so the gist wraps it as a shell script and run it upon boots. You can adapt my script:

#!/bin/bash

iptables -t nat -C POSTROUTING -o wlx244bxx -j MASQUERADE
ret=$?

if [ $ret -eq 1 ]; then
  echo "Writing firewall rules..." | tee -a /tmp/wifi-nat.sh
  set -x
  iptables -t nat -A POSTROUTING -o wlx244bxx -j MASQUERADE
  iptables -A FORWARD -i wlx244bxx -o enp0s31f6 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
  iptables -A FORWARD -i enp0s31f6 -o wlx244bxx -j ACCEPT
  set +x
  echo "Success!!" | tee -a /tmp/wifi-nat.sh
elif [ $ret -eq 0 ]; then
  echo "ERROR: rule already exists" | tee -a /tmp/wifi-nat.sh
else
  echo "ERROR: unknown error (code=$ret)" | tee -a /tmp/wifi-nat.sh
fi