Introduction
This post serves as a personal reference and guide for setting up a tunnel and NAT configuration using ZeroTier and an EdgeRouter. The goal is to route certain machines from my home network through a virtual server in a different country. My set-up is a bit more complicated than is described here (using a VLAN and different wireless BSSID) but hopefully this simplified example will help anyone else trying to accomplish something similar.
ZeroTier Configuration
The setup begins with ZeroTier running on the EdgeRouter. I’ve configured ZT Managed routes to ensure the 192.168.4.0/24
network is accessible from any ZT host. An essential step in this configuration is verifying the connectivity to the virtual server (one of the ZT hosts) located abroad. This virtual server’s ZeroTier address should be pingable from devices on my home network, regardless of whether they have ZeroTier installed. Similarly the reverse should be true, the virtual server needs to be able to ping hosts residing behind the EdgeRouter.
EdgeRouter Configuration
The EdgeRouter is configured to modify traffic using a specific table. This isn’t applied to any traffic by default but serves as a rule that we can apply to things we select:
protocols {
static {
table 20 {
description "route over virtual server"
route 0.0.0.0/0 {
next-hop 10.147.19.62 {
}
}
}
}
}
Now we can build a modify policy for the firewall that will select all traffic that originates from a selected IP range, and applies the modify table that we just defined. This lets us select packets with a specific origin and set the next hop to be the virtual server.
firewall {
modify SOURCE_ROUTE {
enable-default-log
rule 10 {
action modify
description "Select traffic for virtaul server by source"
modify {
table 20
}
source {
address 192.168.4.128/25
}
}
}
}
Next we need to actually apply that firewall rule to real traffic. Here I apply it to all traffic coming in from eth1 (my local network interface), but note that I actually only modify the source route on half that range. So address 192.168.4.1-192.168.4.127 end up going out my usual default interface, but those in 192.168.4.128-192.168.4.255 are routed over the VPN tunnel.
interfaces {
ethernet eth1 {
address 192.168.4.1/24
description "Local Network"
firewall {
in {
modify SOURCE_ROUTE
}
}
}
}
VPS Configuration
On the virtual server, IP forwarding needs to be enabled and NAT applied:
echo 1 > /proc/sys/net/ipv4/ip_forward
To make this permanent, add net.ipv4.ip_forward = 1
in /etc/sysctl.conf
and apply the changes with sudo sysctl -p
.
Setup NAT with iptables assuming eth0
is the internet interface and zt0
is the ZeroTier interface:
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i zt0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o zt0 -m state --state ESTABLISHED,RELATED -j ACCEPT
Don’t forget to persist IP Tables when you are done
Results
Devices on my LAN within the 192.168.4.128-255
range (assignable via DHCP) have their traffic routed through the virtual server, effectively appearing as if located in another country. On my Edgerouter POE-5, the tunnel achieves around 9Mbit/s. While Wireguard was slightly faster, this setup offers better manageability.