Ubuntu VM as bridge to LAN

Hello all. I am having a hard time getting a bridge set up. I have an Ubuntu VM setup on my local network and ZTO is installed. I used the following to set up routing.

sudo sysctl -w net.ipv4.ip_forward=1 #also edited sysctl.conf to make it permanent
Set the aliases to the interfaces
sudo iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE
sudo iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT
sudo apt install iptables-persistent
sudo bash -c iptables-save > /etc/iptables/rules.v4 # This doesn't work as is, I had to change it to | sudo tee /etc/iptables/rules.v4

Rebooted the VM and its online with the controller. However, devices that are not on the LAN are not able to ping to devices on the LAN. They can ping the ZTO address of the VM though, however.

I’m looking for any suggestions on getting this working. I appreciate any help.

I am surprised there hasn’t been any response. I guess the bridging function isn’t working or most people don’t have a use for it?

Well I got it working on ubuntu server 22.04… however currently with the firewall off…
My examples below shows how to bridge a vlan interface with a zt interface but offcourse the vlan can be replaced by a normal ethernet interface.
The machine has one ethernet interface that is connected to a trunk in the switch and vlan100 is the basic LAN with internet access.

First for the node that shall act as a bridge, you need to at zerotier central edit the settings and tick “do not auto assign IP” and “allow ethernet bridging”
make sure IPv6 is turned off
also adjust the dhcp range so that you have some addresses outside the scope.
The subnet size need to be change from the default /24 to /23 to work with bridging.

Since some switches gets confused (and may block traffic) if the bridge has a different mac than the first enslaved interface… if ew are on ubuntu 22.04 or above we need to change the macaddresspolicy in
change it from “persistent” to “none”

Then at your ubuntu box you need to tell zerotier not to take any settings from the central by:
sudo zerotier-cli set NETWORK_ID allowManaged=0
now connect to the zt network, sudo zerotier-cli join [network-id]
and hopfully you get a new interface starting with z… and it shall NOT have an IP address assigned

How did you create the bridge interface?
Do you use netplan ?

my netplan file looks like this:

# Let NetworkManager manage all devices on this system
  version: 2
  renderer: networkd
         dhcp4: false

         id: 100
         link: eno1
         dhcp4: true

         id: 201
         link: eno1
         dhcp4: false

          - vlan201
        dhcp4: false
        addresses: []  # Set the desired IP address and subnet mask
        macaddress: 00:21:28:a2:5c:41 # Set the MAC of vlan201 (first interface at the bridge)

Make sure that the “master interface” that you enslave to the bridge do NOT have an IP set

The timing issue:
Since zerotier service needs to start AFTER the network part the zt interface can not be added to the bridge in the netplan configuration, and since you most likely want the function to be persistent over reboot etc. you need to trigger this from a systemd service file or a bash script that is set to run at boot with a delay by cron.

Create a systemd service file :slight_smile:

sudo nano /etc/systemd/system/zerotier-bridge.service 

change [ZEROTIER_INTERFACE] to your interface zt*:


Description=Wait for zerotier interface & add it to the bridge interface 




ExecStartPre=/bin/bash -c 'for i in {1..40}; do ip link show {ZEROTIER_INTERFACE} && break || sleep 10; done' 

ExecStart=/usr/sbin/brctl addif br0 {ZEROTIER_INERFACE} 




Start and enable service:

sudo systemctl daemon-reload 

sudo systemctl start zerotier-bridge.service 

sudo systemctl enable zerotier-bridge.service 

Check that the service added the zt interface:

sudo brctl show 

And finally fix the MTU issue:
create a zerotier central API token, read more hete

populate the token to the env parameter
sudo export ZEROTIER_API_TOKEN=[put your token here]
replace the {NETWORK_ID} in the command below with the actual networkID

curl -X POST "https://my.zerotier.com/api/network/{NETWORK_ID}" -H "Authorization: bearer ${ZEROTIER_API_TOKEN}" -d '{"config": {"mtu": 1500}}' 

This is needed because zt defaults to an MTU=2800 that will make the bridge with typically MTU=1500 to lose packets. If you linking over older mobile networks you might want to set even a lower MTU value…

Now you can do a Ip -a to see that your bridge has the right IP, MAC and MTU
and try to reach other devices… you may also make sure routing is in place.

Best regards,

1 Like

Thank you. I am currently out of the country but will give this a shot when I get back. I tried with 20.04 but I think, just to make sure all things are equal, I will just spool up a new VM with 22.04 so I can follow your working model. I appreciate it.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.