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 the old one 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/

1 2 3 4 5 6 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:

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

 

Update the Operating System

1 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:

1 curl -s https://install.zerotier.com | sudo bash

Let’s set some shell variables now

1 2 3 4 NETWORK_ID=<your-network-id> BR_IF="br0" BR_ADDR=<your-bridge-address> GW_ADDR=<your-gateway-address>

 

Join ZeroTier Network

1 2 sudo zerotier-cli join $NETWORK_ID sudo zerotier-cli listnetworks

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

1 sudo zerotier-cli set $NETWORK_ID allowManaged=0

 

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

1 sudo apt remove --purge --auto-remove dhcpcd5 fake-hwclock ifupdown isc-dhcp-client isc-dhcp-common openresolv

Enable systemd-networkd

1 2 3 4 sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf; sudo systemctl enable systemd-networkd; sudo systemctl enable systemd-resolved; sudo systemctl enable systemd-timesyncd;
  1. Configure interfaces

    1 sudo zerotier-cli set $NETWORK_ID allowManaged=0

    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.

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0.network [Match] Name=$BR_IF [Network] Address=$BR_ADDR Gateway=$GW_ADDR DNS=1.1.1.1 EOF cat << EOF | sudo tee /etc/systemd/network/br0.netdev [NetDev] Name=$BR_IF Kind=bridge EOF cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0-zt.network [Match] Name=$ZT_IF [Network] Bridge=$BR_IF EOF cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0-en.network [Match] Name=eth0 # might be en* [Network] Bridge=$BR_IF EOF

    Review configuration

    1 tail -n+0 /etc/systemd/network/*

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

    If it looks good:

    1 sudo reboot

    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

    1 2 3 4 5 6 7 cat << EOF | sudo tee /etc/systemd/network/25-bridge-br0.network [Match] Name=$BR_IF [Network] DHCP=yes EOF

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