Masquerade
Masquerade is on by default. The routing peer SNATs forwarded traffic to its own LAN-side IP, so the destination network does not need any awareness of NetBird. Turn it off when you need:
- Source IP visibility for auditing, compliance, or application logic.
- The destination network's existing firewalls to filter NetBird peers by their overlay IP.
What changes when masquerade is off
- The original NetBird overlay IP is preserved end-to-end.
- The destination host (or, if it sits in a different subnet, its gateway) must have a return route for the NetBird CIDR (default
100.64.0.0/10) pointing at the routing peer's LAN IP. - High availability stops working — return traffic must flow back through one specific routing peer, so the destination network has no way to follow a failover. See How Routing Peers Work — Masquerade.
Masquerade can only be turned off on Linux routing peers.
Disable masquerade on the routing peer
In the dashboard: Networks → your network → the routing peer row → toggle Masquerade off. The change takes effect within seconds; the routing peer stops SNATing forwarded traffic for this network.
You can also flip it through the API:
curl -X PUT https://api.netbird.io/api/networks/<NETWORK_ID>/routers/<ROUTER_ID> \
-H "Authorization: Token <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"peer": "<PEER_ID>", "masquerade": false, "metric": 9999, "enabled": true}'
The rest of this page covers the return-route prerequisite the destination network needs once masquerade is off.
Inputs to substitute
The examples below use placeholders. Swap in:
100.64.0.0/10— default NetBird CIDR. See Find your account's NetBird range below for the narrower/16you should use in practice.<PEER_LAN_IP>— the routing peer's IP on the destination subnet.<IFACE>— the LAN interface on the destination host. Useip -br addrto identify it.
Find your account's NetBird range
NetBird assigns each account a single /16 block from inside the 100.64.0.0/10 CGNAT range (one of 64 possible blocks such as 100.64.0.0/16, 100.121.0.0/16, 100.127.0.0/16, …). The block is chosen randomly per account and can be customised. Use that /16 for the return route below — not the whole /10 — so you don't funnel unrelated CGNAT ranges through your routing peer.
Read it off any enrolled peer:
$ netbird status | grep "NetBird IP"
NetBird IP: 100.121.195.4/16
# → this account's block is 100.121.0.0/16
Wherever the examples below show 100.64.0.0/10, use your account's /16 instead.
Test the route before making it persistent
Add the route temporarily on the destination host:
sudo ip route add 100.64.0.0/10 via <PEER_LAN_IP>
From a NetBird peer, confirm reachability with a protocol/port your NetBird policy allows — for example curl http://<destination-ip>:<port>, or nc -zv <destination-ip> <port> for a non-HTTP service. Then remove the test route before committing the persistent version:
sudo ip route del 100.64.0.0/10 via <PEER_LAN_IP>
Persistent configuration
Pick one of the methods below — your host uses one network manager, not both:
- Netplan if
/etc/netplan/already has yaml files (most Ubuntu hosts). - systemd-networkd otherwise (Debian Server, minimal installs, or hosts using systemd-networkd directly without a netplan frontend).
Netplan (Ubuntu 18.04+)
On Ubuntu Server, /etc/netplan/ usually already has a yaml from cloud-init (50-cloud-init.yaml) or the installer (00-installer-config.yaml). Append a new entry to the interface's routes: list (don't add a second routes: key — YAML won't accept that). The addresses: and default-route values shown below are placeholders for whatever is already in your file — not values to copy as-is:
network:
version: 2
ethernets:
<IFACE>: # destination's LAN interface, e.g. eth0
addresses: [192.168.1.50/24] # existing
routes:
- to: default # existing
via: 192.168.1.1
- to: 100.64.0.0/10 # add this
via: <PEER_LAN_IP> # routing peer's local IP on this subnet
If /etc/netplan/ is empty (uncommon, but possible on minimal installs or when netplan was just apt installed), create /etc/netplan/01-netbird.yaml with the full stanza, substituting real values for addresses: and the default gateway.
Apply:
sudo netplan apply
Recent netplan versions require 0600 permissions on yaml files under /etc/netplan/. Set with sudo chmod 0600 /etc/netplan/*.yaml if netplan apply warns.
systemd-networkd
Either append to the relevant .network file in /etc/systemd/network/, or drop a snippet into /etc/systemd/network/<IFACE>.network.d/100-netbird.conf:
[Route]
Destination=100.64.0.0/10
Gateway=<PEER_LAN_IP>
Apply:
sudo networkctl reload
The drop-in path only takes effect when a .network file already matches the interface. Run networkctl status <IFACE> and check the Network File line to confirm which one — on netplan-managed hosts it's generated under /run/systemd/network/.
Verify after reboot
ip route show 100.64.0.0/10
Expect output like (where 192.168.1.10 stands for the routing peer's LAN IP — not the destination's own address):
100.64.0.0/10 via 192.168.1.10 dev eth0
Trailing fields such as proto static, onlink, or metric 100 may appear depending on the network manager — those are normal.
Then send a request from a NetBird peer and confirm the destination logs the original overlay IP:
# from a NetBird peer
curl http://<destination-ip>:<port>
# on the destination, tail the relevant log or capture briefly:
sudo tcpdump -ni <IFACE> "src net 100.64.0.0/10 and port <port>"
The source IP should fall inside your account's /16 (e.g. 100.121.x.x), not the routing peer's LAN IP.
Security considerations
The return route exposes the destination subnet to whatever NetBird range you configured — your account's /16 if you narrowed it (recommended), otherwise the full 100.64.0.0/10. The OS-level route does no filtering on its own — source IP transparency is the whole reason masquerade is off, so tighten access at the NetBird policy layer with source groups, ports, and posture checks. If only a subset of the destination subnet should reach NetBird peers, add host-level firewall rules (iptables, nftables, firewalld) alongside the route.

