Feature: Transparent subnet mapping for overlapping networks #2386

Open
opened 2025-11-20 07:09:01 -05:00 by saavagebueno · 1 comment
Owner

Originally created by @Kimmax on GitHub (Oct 17, 2025).

Problem

Netbird currently supports overlapping routes through its route selection feature.

While this makes it possible to connect multiple networks with identical subnets, it introduces usability friction.
I manage several networks with the same subnet, but I can only connect to one at a time. Selecting routes manually via the CLI or UI is cumbersome.
Additionally, this method does not allow simultaneous access to hosts with identical IPs in different networks.

Proposed Solution

This issue also exists with traditional VPN gateways. I’ve previously solved it by mapping each network to a unique subnet using iptables and the NETMAP target.

Example:

(customerA)
iptables -t nat -A PREROUTING -d 10.1.1.0/24 -i wt0 -j NETMAP --to 192.168.1.0/24

(customerB)
iptables -t nat -A PREROUTING -d 10.1.2.0/24 -i wt0 -j NETMAP --to 192.168.1.0/24

(omitting the obvious need for SNAT here for scoping)

By adding routes to the mapped network via the VPN gateways (in Netbird’s case, using the mapped subnet as the resource CIDR range), any host in overlapping subnets becomes reachable through its 10.1.x.0/24 counterpart.

Alternatives Considered

DNS-based routing with echo domains

Example:

192.168.0.10.customerA.some.tld A 192.168.0.10
192.168.0.10.customerB.some.tld A 192.168.0.10

Each *.customerX.some.tld domain used as the resource target + corresponding routing peer.
This approach allows simultaneous access to multiple networks without switching active routes.

However:

  • Once a route is established (e.g., accessing 192.168.0.10.customerA.some.tld), subsequent connection attempts to 192.168.0.10.customerX.some.tld won’t replace the first established route.
  • It still doesn’t allow parallel access to identical IPs across networks.

Netbird on all network hosts

Of course I can install a Netbird client on each host, but this would make it impossible to monitor eg switches or other equipment not supporting a direct client install and no possibility for distributed monitoring. Also some devices simply can't have a client installed for administrative(stupid) reasons.

Additional Notes

I attempted adding custom NETMAP rules directly to iptables on the routing peer, but they appear to conflict with Netbird’s internal routing logic, likely because Netbird manages PREROUTING rules on the WireGuard interface.

I'm open for discussion and entirely different suggestions :)
Thanks!

Originally created by @Kimmax on GitHub (Oct 17, 2025). ## Problem Netbird currently supports overlapping routes through its [route selection feature](https://docs.netbird.io/how-to/resolve-overlapping-routes). While this makes it possible to connect multiple networks with identical subnets, it introduces usability friction. I manage several networks with the same subnet, but I can only connect to one at a time. Selecting routes manually via the CLI or UI is cumbersome. Additionally, this method does not allow simultaneous access to hosts with identical IPs in different networks. ## Proposed Solution This issue also exists with traditional VPN gateways. I’ve previously solved it by mapping each network to a unique subnet using `iptables` and the `NETMAP` target. **Example:** ```bash (customerA) iptables -t nat -A PREROUTING -d 10.1.1.0/24 -i wt0 -j NETMAP --to 192.168.1.0/24 (customerB) iptables -t nat -A PREROUTING -d 10.1.2.0/24 -i wt0 -j NETMAP --to 192.168.1.0/24 ``` (omitting the obvious need for `SNAT` here for scoping) By adding routes to the mapped network via the VPN gateways (in Netbird’s case, using the mapped subnet as the resource CIDR range), any host in overlapping subnets becomes reachable through its `10.1.x.0/24` counterpart. ## Alternatives Considered ### DNS-based routing with echo domains **Example:** ``` 192.168.0.10.customerA.some.tld A 192.168.0.10 192.168.0.10.customerB.some.tld A 192.168.0.10 ``` Each `*.customerX.some.tld` domain used as the resource target + corresponding routing peer. This approach allows simultaneous access to multiple networks without switching active routes. However: - Once a route is established (e.g., accessing `192.168.0.10.customerA.some.tld`), subsequent connection attempts to `192.168.0.10.customerX.some.tld` won’t replace the first established route. - It still doesn’t allow parallel access to identical IPs across networks. ### Netbird on all network hosts Of course I can install a Netbird client on each host, but this would make it impossible to monitor eg switches or other equipment not supporting a direct client install and no possibility for distributed monitoring. Also some devices simply can't have a client installed for administrative<sup><sup><sup>(stupid)</sup></sup></sup> reasons. ## Additional Notes I attempted adding custom `NETMAP` rules directly to `iptables` on the routing peer, but they appear to conflict with Netbird’s internal routing logic, likely because Netbird manages `PREROUTING` rules on the WireGuard interface. I'm open for discussion and entirely different suggestions :) Thanks!
saavagebueno added the feature-request label 2025-11-20 07:09:01 -05:00
Author
Owner

@Kimmax commented on GitHub (Oct 17, 2025):

I eventually got it to work by utilizing network namespaces on my routing peer. It's not pretty, but makes all subnets available in parallel with no conflicts.
If someone tries to replicate this, let this inspire you:

Namespaces

  • default (no need to create)
  • router

Interfaces

  • eth0 (your uplink) goes into ns router
  • one veth pair
    • veth-default stays in ns default
    • veth-router goes into ns router

Subnets

  • LAN (original)
    192.168.1.0/24
  • Transit
    10.254.254.0/24 (or something smaller, needs two ips)
  • Mapped (this is what you use externally for reaching LAN)
    10.0.1.0/24

IPs

  • eth0
    192.168.1.254
  • veth-default
    10.254.254.1
  • veth-router
    10.254.254.254
  • something you want to reach
    192.168.1.123 / 10.0.1.123 (mapped)

Rules in ns router

-A FORWARD -i veth-router -o eth0 -j ACCEPT
-A FORWARD -i eth0 -o veth-router -m state --state RELATED,ESTABLISHED -j ACCEPT
-A PREROUTING -t nat -i veth-router -d 10.0.1.0/24 -j NETMAP --to 192.168.1.0/24
-A POSTROUTING -t nat -o eth0 -j MASQUERADE

Netbird

  • Network, add
    • Ressource, use the mapped CIDR here (10.0.1.0/24)
    • the Routing peer in question
    • a policy so you can reach the peer and get the route served

Keep in mind that moving eth0 from default to router will nuke all it's ips, dns servers and search domains. Depending on your setup, in my case resolvectl, you need to reattach them in the router ns.

Now try reaching something from the mapped subnet from some Netbird client ✌️

@Kimmax commented on GitHub (Oct 17, 2025): I eventually got it to work by utilizing network namespaces on my routing peer. It's not pretty, but makes all subnets available in parallel with no conflicts. If someone tries to replicate this, let this inspire you: **Namespaces** - default (no need to create) - router **Interfaces** - eth0 (your uplink) goes into ns router - one veth pair - veth-default stays in ns default - veth-router goes into ns router **Subnets** - LAN (original) 192.168.1.0/24 - Transit 10.254.254.0/24 (or something smaller, needs two ips) - Mapped (this is what you use externally for reaching LAN) 10.0.1.0/24 **IPs** - eth0 192.168.1.254 - veth-default 10.254.254.1 - veth-router 10.254.254.254 - something you want to reach 192.168.1.123 / 10.0.1.123 (mapped) **Rules in ns router** ``` -A FORWARD -i veth-router -o eth0 -j ACCEPT -A FORWARD -i eth0 -o veth-router -m state --state RELATED,ESTABLISHED -j ACCEPT -A PREROUTING -t nat -i veth-router -d 10.0.1.0/24 -j NETMAP --to 192.168.1.0/24 -A POSTROUTING -t nat -o eth0 -j MASQUERADE ``` **Netbird** - Network, add - Ressource, use the mapped CIDR here (10.0.1.0/24) - the Routing peer in question - a policy so you can reach the peer and get the route served Keep in mind that moving eth0 from default to router will nuke all it's ips, dns servers and search domains. Depending on your setup, in my case resolvectl, you need to reattach them in the router ns. Now try reaching something from the mapped subnet from some Netbird client ✌️
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: SVI/netbird#2386