Skip to content

Instantly share code, notes, and snippets.

@kdmukai
Last active September 29, 2024 12:28
Show Gist options
  • Save kdmukai/ab7b2b1de898c6c3e64ffbe1e0316bbe to your computer and use it in GitHub Desktop.
Save kdmukai/ab7b2b1de898c6c3e64ffbe1e0316bbe to your computer and use it in GitHub Desktop.
Configuring a Raspberry Pi to relay an ethernet-connected device over wifi to a Tailscale exit node

The problem

You want a device, let's call it a BRoku, to route its traffic through your home IP even though it's actually physically located in someone else's house on their wifi network.

The solution

  • BRoku connects over wired ethernet directly to a Raspberry Pi (3B+ or 4).
  • Raspi connects to local wifi.
  • Raspi's traffic is routed to a Tailscale exit node (potentially another Raspi) in your home LAN.

Steps

The majority of this is taken from: https://www.instructables.com/Share-WiFi-With-Ethernet-Port-on-a-Raspberry-Pi/

Many of the early steps can be done directly in the Raspberry Pi Imager; enabling ssh, setting login, configuring wifi, configuring locale.

In the Raspberry Pi Imager, navigate the OS selection options to install the 64-bit version (with or without the desktop UI).

The "Set your ethernet adapter to a static IP address" section lacks detail. The missing necessary steps are taken from here and are copied below:

sudo nano /etc/dhcpcd.conf

At the end of the file add:

denyinterfaces eth0

CTRL-X, y to save

Next:

sudo nano /etc/network/interfaces

We're going to configure the Raspi to use a static IP addr on its ethernet port that will be the beginning of its own mini-LAN for anything connecting to it over ethernet:

source /etc/network/interfaces.d/*

auto eth0
allow-hotplug eth0
iface eth0 inet static
    address 192.168.2.1
    netmask 255.255.255.0
    network 192.168.2.0
    broadcast 192.168.2.255

auto wlan0
allow-hotplug wlan0
iface wlan0 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

CTRL-x, y to save.

After dnsmasq is installed, configure it with:

sudo nano /etc/dnsmasq.conf

The Raspi's ethernet connection will have its own local dns server to create its own mini-LAN. Configure it to assign IP addrs in the 192.168.2.x range:

interface=eth0
dhcp-range=192.168.2.50,192.168.2.100,12h
server=8.8.8.8
bind-interfaces
domain-needed
bogus-priv

CTRL-x, y to save.

Now we enable internet sharing:

sudo nano /etc/sysctl.conf

Find this line and enable it by removing the "#":

net.ipv4.ip_forward=1

CTRL-x, y to save.

And activate ip forwarding:

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

Install & configure Tailscale

Follow the steps here for Debian Bullseye to install Tailscale on the Raspi: https://tailscale.com/kb/1038/install-debian-bullseye/

We assume that you're already running your own Tailscale network in your home LAN. Configure one of your always-on devices to be an exit node.

Configure the Raspi's Tailscale defaults:

sudo tailscale set --exit-node=EXIT_NODE_TAILSCALE_IP --exit-node-allow-lan-access

EXIT_NODE_TAILSCALE_IP should be that IP provided in the Tailscale dashboard for your exit node.

Final steps

Copy the wifi-to-eth-route.sh script included in this gist. It sets up the necessary iptables routing, etc.

nano wifi-to-eth-route.sh

Paste in the raw contents of the script. CTRL-x, y to save.

Now configure the Raspi to run that script whenever it boots:

sudo nano /etc/rc.local

Instruct it to run the .sh file before the exit 0 line:

sudo bash /home/pi/wifi-to-eth-route.sh

CTRL-x, y to save

Alice's BRoku
    |
    |
(ethernet)
    |
    |
    v
Alice's Raspi
    |
    |
 (wifi)
    |
    |
    v
Alice's wifi
    |
    |
(Tailscale)
    |
    |
    v
Your Tailscale network
    |
    |
    v
Your Tailscale exit node
    |
    |
    v
Internet from your IP addr
#!/bin/bash
# Share Wifi with Eth device
#
#
# This script is created to work with Raspbian Stretch
# but it can be used with most of the distributions
# by making few changes.
#
# Make sure you have already installed `dnsmasq`
# Please modify the variables according to your need
# Don't forget to change the name of network interface
# Check them with `ifconfig`
ip_address="192.168.2.1"
netmask="255.255.255.0"
dhcp_range_start="192.168.2.2"
dhcp_range_end="192.168.2.100"
dhcp_time="12h"
dns_server="1.1.1.1"
eth="eth0"
wlan="wlan0"
sudo systemctl start network-online.target &> /dev/null
sudo iptables -F
sudo iptables -t nat -F
sudo iptables -t nat -A POSTROUTING -o tailscale0 -j MASQUERADE
sudo iptables -A FORWARD -i $wlan -o $eth -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i $eth -o $wlan -j ACCEPT
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
sudo ifconfig $eth down
sudo ifconfig $eth up
sudo ifconfig $eth $ip_address netmask $netmask
# Remove default route created by dhcpcd
sudo ip route del 0/0 dev $eth &> /dev/null
sudo systemctl stop dnsmasq
sudo rm -rf /etc/dnsmasq.d/* &> /dev/null
echo -e "interface=$eth
bind-interfaces
server=$dns_server
domain-needed
bogus-priv
dhcp-range=$dhcp_range_start,$dhcp_range_end,$dhcp_time" > /tmp/custom-dnsmasq.conf
sudo cp /tmp/custom-dnsmasq.conf /etc/dnsmasq.d/custom-dnsmasq.conf
sudo systemctl start dnsmasq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment