docs: add Site-to-VPN scenario guide

New dedicated guide for letting clientless devices on a local network
initiate connections to NetBird peers (the reverse of VPN-to-Site).
Covers static-route and DNAT options, DNS resolution via dnsmasq, and
explains why the target peer always observes the routing peer's NetBird
IP as the source.

- Add src/pages/manage/network-routes/use-cases/by-scenario/site-to-vpn.mdx
- Wire it into NavigationDocs.jsx
- Update the site-to-site overview table row to point at the new page
- Replace the stub Site-to-VPN subsection in site-to-site-office.mdx
  with a pointer to the new guide
This commit is contained in:
Jack Carter
2026-05-12 17:35:19 +02:00
parent 02a4eef0a1
commit 836c084653
4 changed files with 356 additions and 16 deletions

View File

@@ -262,6 +262,10 @@ export const docsNavigation = [
title: 'Site-to-Site: Cloud',
href: '/manage/network-routes/use-cases/by-scenario/site-to-site-cloud',
},
{
title: 'Site-to-VPN',
href: '/manage/network-routes/use-cases/by-scenario/site-to-vpn',
},
{
title: 'Exit Nodes',
href: '/manage/network-routes/use-cases/by-scenario/exit-nodes',

View File

@@ -178,21 +178,11 @@ ping 10.0.0.100 # HQ server
## Site-to-VPN: Office Systems Reaching Remote Workers
Some scenarios require office systems to initiate connections to remote workers (monitoring, management tools, etc.).
### Configuration
1. Create a network route for the office network (as above)
2. On the office system that needs to reach remote workers, add a route to the NetBird network:
```bash
# Route to NetBird network through the routing peer
sudo ip route add 100.64.0.0/10 via 10.0.0.50
```
Where `10.0.0.50` is the routing peer's office IP.
3. Create two access policies allowing traffic in both directions
Some scenarios require office systems without NetBird to initiate
connections to NetBird-connected peers (monitoring, backups, management
tools, etc.). See [Site-to-VPN](/manage/network-routes/use-cases/by-scenario/site-to-vpn)
for the full step-by-step guide, including DNS resolution and the
per-service port-forwarding alternative.
## Best Practices for Business Deployments

View File

@@ -0,0 +1,346 @@
import { Note, Warning } from '@/components/mdx'
# Site-to-VPN: Clientless Devices Reaching NetBird Peers
This guide shows how to let a device that does **not** have NetBird installed
initiate a connection to a NetBird peer over the overlay — the reverse of the
more common VPN-to-Site direction.
## What You'll Achieve
After following this guide, a clientless device on your local network can
reach a NetBird peer by its overlay IP or NetBird DNS name. Typical examples:
- An on-premise monitoring system pushing metrics to a NetBird-connected
collector
- A legacy server initiating outbound backups to a NetBird peer in the cloud
- An office printer reporting status to a NetBird-connected management
application
```
Clientless Device ──► Routing Peer ──► NetBird Tunnel ──► NetBird Peer
(no NetBird) (peer) (peer)
```
<Note>
Site-to-VPN is implemented with [Network Routes](/manage/network-routes). The newer [Networks](/manage/networks) feature does not yet expose
the routed CIDR as a policy source, which is required for this scenario.
</Note>
<Warning>
With Network Routes, the overlay peer will always observe the **routing
peer's NetBird IP** as the source of the request, not the clientless
device's local IP. See [Source IP Behavior](#source-ip-behavior) below for
the details and why this is the case.
</Warning>
## Prerequisites
- A [NetBird cloud account](https://app.netbird.io/) or [self-hosted instance](/selfhosted/selfhosted-quickstart)
- A Linux device on the local network to serve as the routing peer (a small
VM, NUC, or Raspberry Pi works)
- A separate device that will run the NetBird peer the clientless device
needs to reach
- The ability to either add a static route on the clientless device (or its
upstream router), or to install a port-forwarding rule on the routing peer
— both options are covered below
## Example Setup
- **Local site:** `192.168.50.0/24`
- **Routing peer (`site-router`):** site IP `192.168.50.10`, NetBird IP
assigned at enrollment
- **Clientless device:** `192.168.50.20`
- **Target NetBird peer (`backup-collector`):** runs the NetBird client; we
reach it on TCP port `8080`
## Step 1: Create Setup Keys with Groups
Before installing NetBird on the routing peer, create a setup key with an
auto-assigned group so the peer lands in the right place:
1. Go to **Setup Keys** in the NetBird dashboard
2. Click **Create Setup Key**
3. Configure:
- Network Identifier: "Site Routing Peer"
- Auto-assigned groups: create and add `site-routing-peers`
4. Click **Create** and note the key
Repeat for the target peer if it isn't already enrolled — place it in a
group like `backup-collectors`. The target peer is a regular NetBird peer;
nothing special needs to be configured on it for this scenario.
## Step 2: Deploy the Routing Peer
Install NetBird on the routing peer and enroll it:
```bash
curl -fsSL https://pkgs.netbird.io/install.sh | sh
sudo netbird up --setup-key YOUR_SITE_SETUP_KEY
```
Confirm the peer appears in the dashboard and shows the `site-routing-peers`
group.
## Step 3: Enable IP Forwarding on the Routing Peer
The routing peer needs to forward packets between its local interface and
the NetBird wireguard interface:
```bash
sudo sysctl -w net.ipv4.ip_forward=1
echo 'net.ipv4.ip_forward=1' | sudo tee /etc/sysctl.d/99-netbird-routing.conf
```
NetBird installs its own `FORWARD` chain on the routing peer that allows
established/related return traffic. No additional iptables rules are needed
on the routing peer itself when masquerade is enabled on the route (next
step) — NetBird handles the source NAT.
## Step 4: Create the Network Route
In the NetBird dashboard:
1. Go to **Network Routes** and click **Add Route**
2. Configure:
- **Network Identifier:** `site-50`
- **Network range:** `192.168.50.0/24`
- **Routing Peer:** `site-router` (or use the `site-routing-peers` group)
- **Distribution Groups:** `backup-collectors` (the group containing the
peers the clientless device will reach)
- **Masquerade:** **Enabled** (required — see
[Source IP Behavior](#source-ip-behavior))
- **Access Control Groups:** leave empty for site-to-VPN (these only
apply to the VPN-to-Site direction)
3. Click **Add Route**
The route advertises the site's CIDR onto the overlay, which gives the
target peer a return path for any traffic that originates from the site.
## Step 5: Create the Access Policy
The routing peer needs to be allowed to reach the target peer over the
overlay:
1. Go to **Access Control** → **Policies** and click **Add Policy**
2. Configure:
- **Name:** `Site Router to Backup Collector`
- **Protocol:** `TCP`
- **Ports:** `8080` (or `All` to allow any port)
- **Source Groups:** `site-routing-peers`
- **Destination Groups:** `backup-collectors`
3. Click **Add Policy**
Because the route has masquerade enabled, traffic from the clientless
device will appear on the overlay as originating from the routing peer's
NetBird IP. The policy authorises that flow.
## Step 6: Direct Site Traffic Through the Routing Peer
You have two options for getting the clientless device's traffic to the
routing peer. Pick whichever fits your environment.
### Option A: Static Route (recommended)
Tell the clientless device — or the site's upstream router — to send
traffic destined for NetBird's CIDR (`100.64.0.0/10`) through the routing
peer.
**On a Linux clientless device:**
```bash
sudo ip route add 100.64.0.0/10 via 192.168.50.10
# Persist via /etc/network/interfaces, netplan, or NetworkManager
```
**On Windows:**
```powershell
route -p add 100.64.0.0 mask 255.192.0.0 192.168.50.10
```
**On a site router that issues DHCP:** add a classless static route option
(DHCP option 121) pointing `100.64.0.0/10` to the routing peer. Every
device on the network will then learn the route automatically.
The clientless device can now reach the target peer by its NetBird IP:
```bash
curl http://100.x.x.x:8080/
```
To use NetBird's DNS names instead of IPs, see
[Resolving NetBird DNS Names](#resolving-netbird-dns-names) below.
### Option B: Per-Service Port Forwarding
If you cannot change routing on the site (or only want to expose specific
services), DNAT the service on the routing peer instead:
```bash
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 18080 \
-j DNAT --to-destination <TARGET_PEER_NETBIRD_IP>:8080
```
Where `eth0` is the routing peer's site-facing interface. The clientless
device now reaches the service through the routing peer's local IP:
```bash
curl http://192.168.50.10:18080/
```
Each forwarded service needs its own DNAT rule. This is a good fit for a
small number of well-known services and avoids any client-side changes.
## Test Connectivity
From the clientless device:
```bash
# Option A (static route): reach by NetBird IP
curl -v http://<TARGET_PEER_NETBIRD_IP>:8080/
# Option B (DNAT): reach via the routing peer's site IP
curl -v http://192.168.50.10:18080/
```
Verify on the target peer that the request arrived:
```bash
# Replace with whatever the target peer is listening with
sudo ss -tnp | grep :8080
```
The connection's remote address on the target peer will be the **routing
peer's NetBird IP**, not the clientless device's local IP.
## Resolving NetBird DNS Names
By default, the clientless device has no way to resolve `*.netbird.cloud`
hostnames — that lookup happens locally on each NetBird peer. You can
publish those names to the site by running a forwarding resolver on the
routing peer.
A minimal `dnsmasq` configuration on the routing peer:
```ini
# /etc/dnsmasq.d/netbird.conf
bind-interfaces
listen-address=192.168.50.10
interface=eth0
# Forward NetBird-managed names to this peer's local NetBird resolver.
# The NetBird daemon listens on the peer's NetBird IP, port 53.
server=/netbird.cloud/<ROUTING_PEER_NETBIRD_IP>
# Everything else to upstream
server=8.8.8.8
server=1.1.1.1
```
Then point the clientless device's DNS at `192.168.50.10` (via DHCP,
`/etc/resolv.conf`, or static configuration) and use the NetBird hostname
directly:
```bash
curl http://backup-collector.netbird.cloud:8080/
```
<Note>
The NetBird daemon binds its DNS resolver on the peer's own NetBird IP,
not on `127.0.0.1`. Substitute the routing peer's actual NetBird IP into
the `server=/netbird.cloud/...` line — you can find it with
`netbird status` on the routing peer.
</Note>
## Source IP Behavior
With Network Routes, the target peer always sees the **routing peer's
NetBird IP** as the source — regardless of which clientless device on the
site initiated the connection. Two routes lead to this:
- With **masquerade enabled** on the route, NetBird installs a MASQUERADE
rule on the routing peer's outbound wireguard interface, rewriting the
source IP at the routing peer.
- With **port forwarding (Option B)**, the routing peer SNATs the DNAT'd
flow so that return traffic comes back to the routing peer.
You **cannot** preserve the clientless device's local IP all the way to
the target peer through Network Routes. The target peer's per-peer access
control list matches sources by NetBird IP, and there is no field on a
legacy Network Route that registers the site CIDR as a policy source.
Disabling masquerade does not help here: the target peer will receive
packets with the site source IP, but they will be dropped by its access
control because that IP is not in any allowed source group.
If preserving the original source IP is a hard requirement, you have two
choices:
1. **Run the access policy with the destination group empty of per-peer
ACL** — practically, this means structuring policies so that no policy
has the target peer as a destination, which removes the per-peer ACL on
it entirely. This trades security for visibility and is rarely
appropriate.
2. **Use the [Networks](/manage/networks) feature instead** for any
destinations where preserved source IP matters. Networks' Resources
model is designed around CIDR-bearing groups and can carry the original
source through to the destination's ACL. The Site-to-VPN direction is
still limited there at the time of writing — track the
[Networks documentation](/manage/networks) for updates.
## Troubleshooting
**Connection times out from the clientless device.**
Check that the static route or DNAT rule is in place:
```bash
# On the clientless device, Option A:
ip route get <TARGET_PEER_NETBIRD_IP>
# Should show "via 192.168.50.10 dev <iface>"
# On the routing peer, Option B:
sudo iptables -t nat -L PREROUTING -n -v
# Should show your DNAT rule with non-zero packet counters when traffic flows
```
**Routing peer receives packets but they don't reach the target peer.**
Check that IP forwarding is enabled and confirm the target peer is reachable
from the routing peer directly:
```bash
# On the routing peer
cat /proc/sys/net/ipv4/ip_forward # should be 1
curl http://<TARGET_PEER_NETBIRD_IP>:8080/ # should succeed
```
If the second command fails, the access policy is wrong — verify the policy
allows `site-routing-peers` → target peer's group on the required port.
**Target peer receives packets but drops them.**
If you disabled masquerade on the route, the target peer will see the raw
site source IP and drop the packets at its per-peer access control. Enable
masquerade on the route to fix this.
```bash
# On the target peer, watch for drops:
sudo iptables -L INPUT -n -v | grep DROP
# DROP counter on the wt0 interface increasing means the packet
# was rejected by access control.
```
**DNS resolution returns NXDOMAIN.**
Confirm the routing peer's NetBird IP is correct in `dnsmasq.conf` (it
changes if the peer is re-enrolled), and that `dnsmasq` is not bound to
`lo` — binding loopback causes it to refuse forwarding to its own
`127.0.0.1`-co-located NetBird resolver.
## Related
- [Network Routes — Concept](/manage/network-routes)
- [Site-to-Site: Office Networks](/manage/network-routes/use-cases/by-scenario/site-to-site-office)
- [Configuring Routes with Access Control](/manage/network-routes/use-cases/by-configuration/access-control)
- [Site-to-Site Overview](/use-cases/site-to-site)

View File

@@ -82,7 +82,7 @@ Your Laptop ──────► NetBird Tunnel ──────► Exit Node
|-------------|----------|----------------|
| Access home devices from my laptop | VPN-to-Site | [Networks](/manage/networks/use-cases/by-scenario/access-home-devices) |
| Access office resources while traveling | VPN-to-Site | [Networks](/manage/networks/use-cases/by-scenario/remote-worker-access) |
| Let an office server connect to my laptop | Site-to-VPN | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-office) only |
| Let an office server connect to my laptop | Site-to-VPN | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-vpn) only |
| Connect two home networks together | Site-to-Site | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-home) only |
| Link branch offices | Site-to-Site | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-office) only |
| Bridge cloud VPC with on-premise network | Site-to-Site | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-cloud) only |