Bridge your ZeroTier and local network with a RaspberryPi

Do you have devices at home can’t run ZeroTier? Do you want access them remotely? Do you already use ZeroTier? You can use a small linux PC as a bridge between ZeroTier and physical networks.

 

Assumptions/Requirements

  • You’re doing this on your home network and can log in to your router and find the DHCP settings.

  • You have a keyboard, monitor, and ethernet cable plugged into your Pi. Chances are high we’ll break networking and lose access to the Pi.

  • You’re somewhat familiar with the command line, ssh.

  • We’re going to use systemd networking for this. You could probably adapt the concepts to a different linux network configuration system if you have opinions about systemd.

  • We used a raspberry Pi 2 while writing this, but a Pi 3 or 4 should work fine. Anything running a Debian 10 based distro should be fine. It doesn’t have a be a raspberrypi, but some of these instructions might be raspbian specific.

 

Prepare this information:

  • Physical LAN Subnet

  • Physical LAN DHCP Range

  • ZeroTier Auto-Assign Range

  • Default Gateway IP Address (the router)

  • Bridge IP Address (will be statically assigned)

  • Create a new ZeroTier network and get the ID. Keep an old network around for secondary way to connect any devices already using ZeroTier.

The DHCP range and ZeroTier Auto-Assign range should be in the same subnet, but not overlap. You’d probably base this off what is already configured on your router.

An example plan:

Name

Value

Referred to below as

Name

Value

Referred to below as

Physical LAN Subnet

192.168.192.0/24

 

Physical LAN DHCP RANGE

192.168.192.65 through 192.168.192.126

 

ZeroTier Auto-Assign Range

192.168.192.129 through 192.168.192.190

$ZT_POOL

ZeroTier Managed Route

192.168.192.0/23

$ZT_ROUTE

Default Gateway IP Address

192.168.192.1

$GW_ADDR

Bridge IP Address

192.168.192.2/24 (or use DHCP)

$BR_ADDR

ZeroTier Network ID

d5e04297a19bbd70

$NETWORK_ID

ZeroTier Network Interface Name

zt3jnwghuq

$ZT_IF

 

Get your bridge device up and running.

 

Follow the Raspberry Pi install instructions

This is the version we used: https://www.raspberrypi.org/downloads/raspbian/

Raspbian Buster Lite Minimal image based on Debian Buster Version: February 2020 Release date: 2020-02-13 Kernel version: 4.19 Size: 434 MB

 

Initial Setup

 

Enable SSH

https://www.raspberrypi.org/documentation/remote-access/ssh/

 

SSH into the Pi

It’s easier to login via ssh now and copy/paste commands from the comfort of your own PC.

The DNS name might just work for you:

ssh pi@raspberrypi.local ssh pi@<ip-address-of-pi>

 

Update the Operating System

sudo apt update && sudo apt -y full-upgrade && sudo reboot

Log back in after it’s done

 

Install ZeroTier

Follow linux instructions here: https://www.ZeroTier.com/download/

Basically:

Let’s set some shell variables now

 

Join ZeroTier Network

We don’t want ZeroTier to manage addresses or routes on $ZT_IF. We’re doing it statically below, on the bridge interface.

 

Set one more variable

ZT_IF=<your-zt-interface-name>

Copy the `dev` name from the `listnetworks` output for $ZT_IF. It will be something like: zt3jvirser

 

Configure the device at my.zerotier.com

  • Go to the Members section of the Network

  • Open the Wrench Icon for advanced settings and check

    • [ ] Check Allow Bridging

    • [ ] Check Do Not Auto Assign

  • [ ] Authorize the member

 

Switch to systemd networking

Remove existing network stuff

Enable systemd-networkd

  1. Configure interfaces

    Write Network Configuration files. Puts ethernet and zerotier into the bridge, configures the bridge with a static IP. See below for DHCP configuration on the bridge.

    Review configuration

    If needed, edit the files with the editor of your preference.

    If it looks good:

    You should be able to, from the physical LAN, connect to the Pi via $BR_ADDR

If it takes a long time waiting for the network during boot.

Sometimes the physical interface turns out to be a long “predicatable interface name” like: “enb827eb0d4176”, sometimes it’s just “eth0”, depending on raspbian version(???).

https://wiki.debian.org/NetworkConfiguration#Network_Interface_Names

Hook up a keyboard and monitor and check with ip addr then edit `/etc/systemd/network/25-bridge-br0-en.network` to match.

Configure ZeroTier Network

At my.zerotier.com/network/$NETWORK_ID Settings -> Advanced

  • Delete the default Managed Route. Add the new Managed Route $ZT_ROUTE

  • Change IPV4 Auto-Assign to Advanced,

  • Remove existing Pool. Create new Pool with start and end from $ZT_POOL

  • For documentation purposes, assign $BR_ADDR to the ZeroTier bridge member

 

It should be working now. Next steps

Either it worked, and you can ssh back in to $BR_ADDR after a minute, or it didn’t work and the Pi isn’t on the network anymore and you need to use the keyboard and monitor to figure out what went wrong.

Appendix

  1. Configure bridge with DHCP

I can ping the bridge, but not behind it

Sometimes, iptables rules apply:

echo "0" > /proc/sys/net/bridge/bridge-nf-call-iptables

or

iptables -A FORWARD -p all -i br0 -j ACCEPT

https://serverfault.com/questions/162366/iptables-bridge-and-forward-chain

FAQ

  1. Why is the Managed Route /23 and the LAN subnet /24?

    Say you have a laptop that is on the ZeroTier network and you bring it home. Now it’s WiFi address and ZeroTier address are in the same subnet. Which interface/address should your laptop use for internet access? https://en.wikipedia.org/wiki/Longest_prefix_match

  2. Why is an app on my phone not working over ZeroTier?

    Unfortunately the iOS and Android VPN APIs won’t let ZeroTier use multicast/broadcast. These are typically how apps auto-discover services on the LAN. 😭 Stay tuned for an article on bridging a ZeroTier network and a WiFi access point.

 

References