A problem I’ve had recently was that my WiFi adapter for my PC stopped turning on. I wasn’t able to get a new one, but I did have a Raspberry Pi collecting dust. This is when I started trying to use the Raspberry Pi 3B+ to connect to WiFi and NAT internet through the ethernet port. It was entirely possible to do and this is the walkthrough.

DHCP Server Setup

The first step is to setup a DHCP server to give an IP address to whatever you plug-in to it. In this tutorial we install isc-dhcp-server.

sudo apt update && sudo apt install isc-dhcp-server

To configure this server we need to edit two files. The first file is /etc/dhcp/dhcpd.conf. Here is my config file:

# dhcpd.conf

# option definitions common to all supported networks...
option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;

authoritative;
subnet 192.168.34.0 netmask 255.255.255.0 {
 range 192.168.34.10 192.168.34.250;
 option broadcast-address 192.168.34.255;
 option routers 192.168.34.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;
}

The next file is /etc/default/isc-dhcp-server. Here is my example:

# Defaults for isc-dhcp-server (sourced by /etc/init.d/isc-dhcp-server)

# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
#DHCPDv4_CONF=/etc/dhcp/dhcpd.conf
#DHCPDv6_CONF=/etc/dhcp/dhcpd6.conf

# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
#DHCPDv4_PID=/var/run/dhcpd.pid
#DHCPDv6_PID=/var/run/dhcpd6.pid

# Additional options to start dhcpd with.
#	Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
#OPTIONS=""

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#	Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4="eth0"
INTERFACESv6=""

Connection Forwarding

The last step is to forward connections to our device plugged in. I forward all connections through to the first device that connects to the ethernet port.

# check if rules are set
sudo iptables -F
sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT

# set up default route
DEFAULT_IFACE=`route -n | grep -E "^0.0.0.0 .+UG" | awk '{print $8}'`
if [ "$DEFAULT_IFACE" != "wlan0" ]; then
	GW=`route -n | grep -E "^0.0.0.0 .+UG .+wlan0$" | awk '{print $2}'`
	sudo route del default $DEFAULT_IFACE
	sudo route add default gw $GW wlan0
fi
sudo iptables -t nat -A PREROUTING -p tcp -i wlan0 -j DNAT --to-destination 192.168.34.10
sudo iptables -A FORWARD -p tcp -d 192.168.34.10 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

With this setup, the only way to ssh into the RPi is to ssh from the device connected to the ethernet port.

Systemd Service

The iptables setup above is not permanent afte reboot. To set this up permanently I’ve written a service file to start at boot.

[Unit]
Description=Forwards internet from wifi to ethernet on raspberry pi
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/inet_forward.sh

[Install]
WantedBy=multi-user.target

All of this can be setup using a script I wrote. See all of this code here:

https://github.com/xadlien/rpi-wifi-to-ethernet

You can run setup.sh to set this up automatically.