Files
claudetools/docs/forum-posts/tailscale-missing-vlan-subnet-route.md
Mike Swanson 7c8488ad14 sync: Auto-sync from acg-guru-5070 at 2026-03-19 19:25:24
Synced files:
- Session log 2026-03-19 updated (autostart, ScreenConnect, Flarum forum, theme, Node.js)
- docs/forum-posts/ recovered from old btrfs home (7 forum post guides)

Machine: acg-guru-5070
Timestamp: 2026-03-19 19:25:24

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 19:26:44 -07:00

117 lines
3.5 KiB
Markdown

# Fix: Remote VLAN Not Reachable via Tailscale - Missing Subnet Route
## Environment
- Tailscale: 1.94.2
- Remote site: Dataforth (192.168.0.0/24 main LAN, 192.168.100.0/24 VLAN100 for phones)
- Tailscale exit nodes advertising routes: pfSense-2 (172.16.0.0/22), D2TESTNAS (192.168.0.0/24)
- Target: FreePBX PBX at 192.168.100.2 on VLAN100
## Problem
A FreePBX phone system at 192.168.100.2 (VLAN100) was unreachable via Tailscale from a remote workstation, even though other devices on the same site's main LAN (192.168.0.0/24) were reachable.
```bash
ping 192.168.0.6 # Works - on main LAN, routed via D2TESTNAS
ping 192.168.100.2 # Fails - 100% packet loss
```
## Diagnosis
Check what subnet routes Tailscale peers are advertising:
```bash
tailscale status --json | python3 -c "
import json,sys
d=json.load(sys.stdin)
for k,v in d.get('Peer',{}).items():
routes = v.get('PrimaryRoutes', [])
if routes:
print(f\"{v['HostName']}: {routes}\")
"
```
Output:
```
pfSense-2: ['172.16.0.0/22']
D2TESTNAS: ['192.168.0.0/24']
```
**192.168.100.0/24 (VLAN100) is not being advertised by any Tailscale node.** The PBX is on a separate VLAN that no Tailscale peer is routing.
Also verify the local machine is accepting routes:
```bash
# Check if --accept-routes is enabled
tailscale status
# Look for health warning: "Some peers are advertising routes but --accept-routes is false"
# If present, enable it:
sudo tailscale set --accept-routes
```
Check local routing table:
```bash
ip route | grep 192.168.100
# Empty - no route exists
```
## Fix
The VLAN subnet needs to be advertised by a Tailscale node that has a leg on that network. Two options:
### Option A: Add Route to Existing Tailscale Node (Recommended)
On the pfSense or gateway that bridges VLAN100, update the Tailscale advertised routes to include the phone VLAN:
```bash
# On pfSense-2 (or whichever node routes VLAN100):
tailscale set --advertise-routes=172.16.0.0/22,192.168.100.0/24
```
Then approve the new route in the Tailscale admin console (if using ACLs) or it auto-approves if `--advertise-routes` auto-approval is enabled.
### Option B: Add Route to D2TESTNAS (if it has VLAN access)
If the NAS has a trunk port or tagged VLAN interface for VLAN100:
```bash
# On D2TESTNAS:
tailscale set --advertise-routes=192.168.0.0/24,192.168.100.0/24
```
### Option C: Connect Directly to Site WiFi (Workaround)
If you're physically at the site, connect to the local WiFi network that has routing to VLAN100. This bypasses the need for Tailscale routing entirely.
```bash
# After connecting to Dataforth WiFi:
ping 192.168.100.2
# Works - local routing handles the VLAN
```
## Verification
After adding the route:
```bash
# Check the route appears
tailscale status --json | python3 -c "
import json,sys
d=json.load(sys.stdin)
for k,v in d.get('Peer',{}).items():
routes = v.get('PrimaryRoutes', [])
if routes:
print(f\"{v['HostName']}: {routes}\")
"
# Should now show: pfSense-2: ['172.16.0.0/22', '192.168.100.0/24']
# Test connectivity
ping 192.168.100.2
# Should respond
```
## Why This Happens
Tailscale subnet routing is explicit — each subnet that should be reachable via the mesh must be advertised by a node on that network. VLANs are separate broadcast domains, so even though 192.168.0.0/24 and 192.168.100.0/24 are at the same physical site, they require separate route advertisements.
This is easy to miss when a site has multiple VLANs — the main LAN works fine via Tailscale, but phone VLANs, management VLANs, IoT VLANs, etc. are silently unreachable until explicitly advertised.