ZeroTier Advanced Configuration
ZeroTier Advanced Configuration
Section titled “ZeroTier Advanced Configuration”This guide covers advanced ZeroTier configuration topics for RouterOS deployments: flow rules for traffic steering on the ZeroTier controller, customising how managed routes integrate with RouterOS routing, extending ZeroTier to local networks via Layer 2 bridging, and diagnosing connectivity problems.
Familiarity with ZeroTier fundamentals is assumed.
Flow Rules
Section titled “Flow Rules”ZeroTier networks support a rules engine that can filter, tag, and steer traffic at the controller level. Rules apply to all members of a network before traffic is forwarded — similar to an ACL on a managed switch, but enforced across the virtual network.
Rule Language Basics
Section titled “Rule Language Basics”Flow rules use a condition-action syntax. Each rule is a statement terminated by a semicolon. Rules are evaluated top-to-bottom; the first matching rule’s action applies.
Basic structure:
[condition ...] action;Conditions match packet attributes. Multiple conditions on one line are ANDed together:
| Condition | Description |
|---|---|
ethertype ipv4 | Ethernet frame type is IPv4 |
ethertype arp | Ethernet frame type is ARP |
ethertype ipv6 | Ethernet frame type is IPv6 |
dport 22 | Destination TCP/UDP port 22 |
sport 22 | Source TCP/UDP port 22 |
ipprotocol tcp | IP protocol is TCP |
ipprotocol udp | IP protocol is UDP |
not <condition> | Negate a condition |
Actions determine what happens when conditions match:
| Action | Description |
|---|---|
accept | Allow the packet |
drop | Silently discard the packet |
redirect <zt-address> | Redirect traffic to a specific member |
break | Stop rule evaluation without accept or drop |
Common Flow Rule Examples
Section titled “Common Flow Rule Examples”Allow only IPv4, IPv6, and ARP — drop everything else:
accept ethertype ipv4;accept ethertype ipv6;accept ethertype arp;drop;Block Telnet across the network:
drop dport 23 ipprotocol tcp;accept;Block SSH originating from a specific ZeroTier member (using ZeroTier address):
drop chr a84ac5c10a dport 22;accept;The chr (check route) condition matches packets from a specific ZeroTier node address.
Restrict traffic to IPv4 only — block raw Ethernet broadcasts and non-IP:
drop not ethertype ipv4 and not ethertype arp and not ethertype ipv6;accept;Applying Flow Rules
Section titled “Applying Flow Rules”In ZeroTier Central:
- Open your network and navigate to the Flow Rules tab
- Enter rules in the text editor (one statement per line, semicolon-terminated)
- Click Save — the controller pushes rules to all online members within seconds
For self-hosted controllers, POST the rules string to the controller API:
PUT /controller/network/<network-id>{ "rules": "<rules string>"}Traffic Tagging and Capabilities
Section titled “Traffic Tagging and Capabilities”ZeroTier supports a tagging system for finer-grained rule matching without hardcoding ZeroTier addresses.
Tags are key-value pairs assigned to members in ZeroTier Central. Rules can match on tag values:
# Drop traffic between members where tag 1 values differdrop tand 1;accept;Capabilities grant members permission to override rules. A member with a capability can perform actions that rules would otherwise block. Capabilities are assigned per-member in ZeroTier Central and referenced in rules using cap:
# Members without capability 2 cannot reach port 22drop not cap 2 dport 22;accept;This pattern is useful for jump hosts or management systems that need broader access than ordinary members.
Custom Managed Routes
Section titled “Custom Managed Routes”ZeroTier Central pushes managed routes to all authorized members. RouterOS installs these as dynamic routes in the main routing table, where they participate in standard route selection alongside static and protocol-learned routes.
Controlling Route Distance
Section titled “Controlling Route Distance”Managed routes from ZeroTier default to a distance that may conflict with or override existing static routes. Adjust the route distance to control preference:
/zerotier interface set [find] route-distance=50Lower values are preferred. Set a higher distance (e.g., 50 or 100) to make ZeroTier managed routes function as backup paths, only used when no lower-distance route exists for the same destination.
Suppressing the Default Route
Section titled “Suppressing the Default Route”If the ZeroTier controller advertises a default route (0.0.0.0/0), RouterOS installs it in the routing table, which can redirect all traffic through the ZeroTier network. To prevent this:
/zerotier interface set [find] route-distance=200Or disable route installation entirely and manage routes manually:
# Do not install controller-pushed routes; manage routing manually/ip route add dst-address=10.147.17.0/24 gateway=zerotier1 comment="ZeroTier subnet"Multiple ZeroTier Networks
Section titled “Multiple ZeroTier Networks”A single RouterOS router can participate in multiple ZeroTier networks simultaneously. Each membership creates a separate ZeroTier interface with its own IP address and route set:
# Join first network/zerotier interface add network=a84ac5c21a88c768 name=zt-corp
# Join second network/zerotier interface add network=b12de4f89c11a221 name=zt-iotEach interface appears independently in the routing table. Routes from each network are tagged with their respective interface:
/ip route print where gateway~"zt-"When the same prefix is reachable via multiple ZeroTier networks, route distance and interface order determine which path is preferred.
Policy Routing with ZeroTier
Section titled “Policy Routing with ZeroTier”By default, ZeroTier managed routes affect all traffic matching those prefixes. Use RouterOS policy routing to restrict ZeroTier-learned routes to specific source traffic.
ROS v7 — routing tables and rules:
# Create a dedicated routing table for ZeroTier-bound traffic/routing table add name=to-zt fib
# Add a route to a remote ZeroTier-connected subnet in the policy table/ip route add dst-address=10.147.17.0/24 gateway=zt-corp routing-table=to-zt
# Apply the policy table only to traffic from the guest VLAN/routing rule add src-address=192.168.50.0/24 action=lookup table=to-ztAlternative: mangle-based mark-routing:
# Mark routing for traffic from a specific subnet/ip firewall mangle add chain=prerouting \ src-address=192.168.60.0/24 \ action=mark-routing new-routing-mark=to-zt passthrough=no
# Route marked traffic through the ZeroTier interface/ip route add dst-address=0.0.0.0/0 gateway=zt-corp routing-mark=to-ztThis pattern routes a subnet’s traffic through ZeroTier without affecting the rest of the router’s forwarding.
Bridging ZeroTier to Local Networks
Section titled “Bridging ZeroTier to Local Networks”Bridging connects the ZeroTier virtual network at Layer 2, extending the same Ethernet broadcast domain to local devices. This allows ZeroTier members to communicate with LAN devices as if on the same physical switch.
Prerequisites
Section titled “Prerequisites”Before configuring RouterOS, enable bridging permissions in ZeroTier Central:
- Open your ZeroTier network settings
- Under Advanced, enable Allow Bridging for the member that will bridge
- Also enable Allow Global IPs if bridged devices need IPs outside the ZeroTier managed range
Without these controller-side permissions, bridged traffic is dropped by ZeroTier’s rules engine.
RouterOS L2 Bridge Setup
Section titled “RouterOS L2 Bridge Setup”Create a bridge and add both the ZeroTier interface and local LAN ports:
# Create bridge/interface bridge add name=zt-bridge protocol-mode=none
# Add local LAN interface (adjust to your interface name)/interface bridge port add bridge=zt-bridge interface=ether2
# Add ZeroTier interface to the bridge/interface bridge port add bridge=zt-bridge interface=zt-corpAssign an IP to the bridge interface for router management access:
/ip address add address=192.168.88.1/24 interface=zt-bridgeFirewall Considerations for Bridging
Section titled “Firewall Considerations for Bridging”RouterOS does not apply the forward chain to bridged traffic by default. If you use the RouterOS firewall to filter bridged packets, enable bridge firewall processing:
/ip settings set rp-filter=no
/ip firewall filteradd chain=forward in-interface=zt-bridge action=accept comment="ZeroTier bridge traffic"For environments requiring filtering, use the bridge firewall instead:
/interface bridge settings set use-ip-firewall=yesARP and IP Assignment
Section titled “ARP and IP Assignment”With L2 bridging active, DHCP and ARP cross the ZeroTier boundary. ZeroTier members on the remote side of the bridge send ARP requests that traverse the virtual network to the bridged LAN.
If a DHCP server runs on the bridged LAN, remote ZeroTier members that use their ZeroTier-assigned IP (rather than a bridged IP) will not receive DHCP leases — they are already IP-addressed by the ZeroTier controller. This is expected behavior.
To give remote ZeroTier members IPs from the LAN subnet rather than the ZeroTier pool, remove or disable ZeroTier-managed IP assignment for those members and rely on the LAN DHCP server instead.
Troubleshooting
Section titled “Troubleshooting”Diagnostic Commands
Section titled “Diagnostic Commands”Start troubleshooting by checking interface and peer state:
# Full interface status including ZeroTier node ID, network, and auth state/zerotier interface print detail
# Peer list with latency and path type (DIRECT or RELAY)/zerotier peer printExpected healthy output:
/zerotier peer printFlags: E - enabled# ZT-ADDRESS LATENCY ROLE PATH0 E a84ac5c10a 8ms LEAF DIRECT1 E a84ac5c10b 45ms LEAF DIRECT2 E a84ac5c10c 180ms LEAF RELAYPeers showing RELAY are reachable but traversing ZeroTier’s relay infrastructure instead of a direct path.
Enabling Debug Logging
Section titled “Enabling Debug Logging”Enable ZeroTier log topics to capture detailed events:
# General ZeroTier events (recommended starting point)/system logging add topics=zerotier action=memory
# Enable debug-level logging (verbose — disable after capture)/system logging add topics=zerotier,debug action=memory
# Read captured logs/log print where topics~"zerotier"Remove debug logging after investigation:
/system logging remove [find topics~"zerotier"]RELAY Path — Peers Not Establishing Direct Connections
Section titled “RELAY Path — Peers Not Establishing Direct Connections”RELAY means ZeroTier cannot establish a direct UDP path between peers. Traffic still flows but with higher latency and lower throughput.
Causes and fixes:
| Cause | Fix |
|---|---|
| Upstream firewall blocks UDP 9993 | Allow outbound UDP 9993 on the router’s WAN |
| Symmetric NAT on upstream ISP/router | Forward UDP 9993 from WAN to the RouterOS router |
| RouterOS firewall drops incoming UDP 9993 | Add input chain accept rule (see below) |
| CGNAT (carrier-grade NAT) | Request a public IP or use a ZeroTier moon (relay anchor) |
Add the firewall rule to permit ZeroTier traffic on the router input:
/ip firewall filter add \ chain=input \ protocol=udp \ dst-port=9993 \ action=accept \ comment="ZeroTier UDP" \ place-before=0For port forwarding if RouterOS is behind an upstream NAT:
/ip firewall nat add \ chain=dstnat \ protocol=udp \ dst-port=9993 \ action=dst-nat \ to-addresses=<RouterOS-WAN-IP> \ to-ports=9993Traffic Flows Between Peers but Not to LAN
Section titled “Traffic Flows Between Peers but Not to LAN”If ZeroTier peers can ping each other’s ZeroTier IP but cannot reach LAN devices on the far side:
1. Verify allow-forwarding is enabled:
/zerotier interface print detailIf allow-forwarding=no, enable it:
/zerotier interface set [find] allow-forwarding=yes2. Check forward chain rules:
/ip firewall filter print chain=forwardAdd rules to permit traffic between ZeroTier and LAN if missing:
/ip firewall filteradd chain=forward in-interface=zt-corp out-interface=bridge-local \ action=accept comment="ZeroTier to LAN"add chain=forward in-interface=bridge-local out-interface=zt-corp \ action=accept comment="LAN to ZeroTier"3. Check routes are present on both routers:
/ip route print where dst-address=192.168.20.0/24If the remote LAN route is missing, add it manually or verify the controller’s managed routes include it.
4. Verify NAT is not interfering:
If srcnat/masquerade covers the ZeroTier interface, remote routers see the ZeroTier IP as the source and may lack a return route. Remove masquerade for ZeroTier-to-ZeroTier traffic:
/ip firewall nat print chain=srcnatAdd a no-masquerade exception if needed:
/ip firewall nat add \ chain=srcnat \ src-address=192.168.10.0/24 \ dst-address=192.168.20.0/24 \ action=accept \ place-before=0 \ comment="No NAT for ZeroTier routed traffic"MTU and Large Packet Issues
Section titled “MTU and Large Packet Issues”ZeroTier encapsulates traffic in UDP, reducing the effective MTU. If connections work for small packets (ping) but fail or stall for larger transfers, MTU mismatch is the likely cause.
ZeroTier’s default path MTU is typically 1280–1400 bytes depending on the path. Clamp TCP MSS to match:
/ip firewall mangle add \ chain=forward \ protocol=tcp \ tcp-flags=syn \ in-interface=zt-corp \ action=change-mss \ new-mss=clamp-to-pmtu \ comment="ZeroTier MSS clamp"
/ip firewall mangle add \ chain=forward \ protocol=tcp \ tcp-flags=syn \ out-interface=zt-corp \ action=change-mss \ new-mss=clamp-to-pmtu \ comment="ZeroTier MSS clamp outbound"Alternatively, test with an explicit MSS value:
/ip firewall mangle set [find comment~"ZeroTier MSS"] new-mss=1280Verifying End-to-End Connectivity
Section titled “Verifying End-to-End Connectivity”# Ping a remote ZeroTier peer by its ZeroTier IP/ping 10.147.17.2 interface=zt-corp count=5
# Ping a device on the remote LAN/ping 192.168.20.1 src-address=192.168.10.1 count=5
# Traceroute to diagnose where packets stop/tool traceroute 192.168.20.1 src-address=192.168.10.1If traceroute stops at the remote ZeroTier IP, the remote router lacks a return route or has a firewall rule blocking the traffic.
See Also
Section titled “See Also”- ZeroTier - ZeroTier fundamentals and basic configuration
- Policy Routing - Routing rules and tables in RouterOS v7
- Firewall Filter - RouterOS firewall filter chain reference
- Bridge - RouterOS bridge configuration