508 lines
12 KiB
Markdown
508 lines
12 KiB
Markdown
# ZeroTier Gateway Configuration Guide
|
|
## Accessing Remote Subnets Through a Raspberry Pi Gateway
|
|
|
|
This guide explains how to configure a Raspberry Pi (or any Linux device) as a ZeroTier gateway to access remote subnets that are not directly on the ZeroTier network.
|
|
|
|
---
|
|
|
|
## Network Topology
|
|
|
|
```
|
|
ZeroTier Clients (10.121.16.0/24)
|
|
↓ (ZeroTier tunnel)
|
|
Raspberry Pi5 Gateway (10.121.16.37)
|
|
↓ (eth0: 192.168.170.172)
|
|
Teltonika Router (192.168.170.1)
|
|
↓
|
|
Target Subnet (192.168.178.0/24)
|
|
```
|
|
|
|
---
|
|
|
|
## Prerequisites Check
|
|
|
|
Before starting configuration, gather this information:
|
|
|
|
### 1. Identify Your Network Interfaces
|
|
|
|
```bash
|
|
# List all network interfaces
|
|
ip addr show
|
|
|
|
# List ZeroTier networks
|
|
sudo zerotier-cli listnetworks
|
|
```
|
|
|
|
**Record:**
|
|
- Gateway's local IP: `_________________` (e.g., 192.168.170.172)
|
|
- Gateway's ZeroTier IP: `_________________` (e.g., 10.121.16.37)
|
|
- ZeroTier interface name: `_________________` (e.g., ztnhhth2eu)
|
|
- ZeroTier network subnet: `_________________` (e.g., 10.121.16.0/24)
|
|
- Local interface name: `_________________` (e.g., eth0)
|
|
- Next-hop router IP: `_________________` (e.g., 192.168.170.1)
|
|
- Target subnet: `_________________` (e.g., 192.168.178.0/24)
|
|
|
|
### 2. Check Current Routing
|
|
|
|
```bash
|
|
# View routing table
|
|
ip route show
|
|
|
|
# Check for existing routes to target subnet
|
|
ip route show | grep <TARGET_SUBNET>
|
|
```
|
|
|
|
---
|
|
|
|
## Step-by-Step Configuration
|
|
|
|
### STEP 1: Enable IP Forwarding
|
|
|
|
**Check if already enabled:**
|
|
```bash
|
|
cat /proc/sys/net/ipv4/ip_forward
|
|
# Should return: 1 (if enabled) or 0 (if disabled)
|
|
```
|
|
|
|
**Enable IP forwarding:**
|
|
```bash
|
|
# Enable temporarily (lost on reboot)
|
|
sudo sysctl -w net.ipv4.ip_forward=1
|
|
|
|
# Make permanent
|
|
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
|
|
|
|
# Verify
|
|
cat /proc/sys/net/ipv4/ip_forward
|
|
```
|
|
|
|
✅ **Checkpoint:** Should show `1`
|
|
|
|
---
|
|
|
|
### STEP 2: Configure Static Route to Target Subnet
|
|
|
|
**Add the route:**
|
|
```bash
|
|
# Template:
|
|
sudo ip route add <TARGET_SUBNET> via <NEXT_HOP_ROUTER> dev <LOCAL_INTERFACE>
|
|
|
|
# Example:
|
|
sudo ip route add 192.168.178.0/24 via 192.168.170.1 dev eth0
|
|
```
|
|
|
|
**Verify the route:**
|
|
```bash
|
|
ip route show | grep <TARGET_SUBNET>
|
|
# Example output: 192.168.178.0/24 via 192.168.170.1 dev eth0
|
|
```
|
|
|
|
**Make persistent (create systemd service):**
|
|
```bash
|
|
sudo nano /etc/systemd/system/static-routes.service
|
|
```
|
|
|
|
**Paste this content (adjust values):**
|
|
```ini
|
|
[Unit]
|
|
Description=Static routes for remote subnet access
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/sbin/ip route add 192.168.178.0/24 via 192.168.170.1 dev eth0
|
|
RemainAfterExit=yes
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
**Enable the service:**
|
|
```bash
|
|
sudo systemctl enable static-routes.service
|
|
sudo systemctl start static-routes.service
|
|
sudo systemctl status static-routes.service
|
|
```
|
|
|
|
✅ **Checkpoint:** Test ping from gateway to target subnet
|
|
```bash
|
|
ping -c 4 <TARGET_IP>
|
|
# Example: ping -c 4 192.168.178.10
|
|
```
|
|
|
|
---
|
|
|
|
### STEP 3: Configure NAT/Masquerading
|
|
|
|
**Why needed:** Makes ZeroTier traffic appear to come from the gateway's local IP, enabling return traffic.
|
|
|
|
**Add masquerading rule:**
|
|
```bash
|
|
# Template:
|
|
sudo iptables -t nat -A POSTROUTING -s <ZT_SUBNET> -d <TARGET_SUBNET> -o <LOCAL_INTERFACE> -j MASQUERADE
|
|
|
|
# Example:
|
|
sudo iptables -t nat -A POSTROUTING -s 10.121.16.0/24 -d 192.168.178.0/24 -o eth0 -j MASQUERADE
|
|
```
|
|
|
|
**Verify the rule:**
|
|
```bash
|
|
sudo iptables -t nat -L POSTROUTING -v -n | grep <ZT_SUBNET>
|
|
# Should show: MASQUERADE rule with your subnets
|
|
```
|
|
|
|
✅ **Checkpoint:** Rule should be visible in iptables
|
|
|
|
---
|
|
|
|
### STEP 4: Configure Firewall FORWARD Rules
|
|
|
|
**⚠️ CRITICAL STEP - Most common issue!**
|
|
|
|
**Check current FORWARD policy:**
|
|
```bash
|
|
sudo iptables -L FORWARD -v -n
|
|
# Look at the first line: Chain FORWARD (policy ???)
|
|
```
|
|
|
|
If policy is **DROP** or you don't see rules for your ZeroTier interface, you MUST add them:
|
|
|
|
**Add FORWARD rules:**
|
|
```bash
|
|
# Allow traffic from ZeroTier to local network
|
|
sudo iptables -I FORWARD -i <ZT_INTERFACE> -o <LOCAL_INTERFACE> -j ACCEPT
|
|
|
|
# Allow return traffic (established connections)
|
|
sudo iptables -I FORWARD -i <LOCAL_INTERFACE> -o <ZT_INTERFACE> -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
|
|
# Example:
|
|
sudo iptables -I FORWARD -i ztnhhth2eu -o eth0 -j ACCEPT
|
|
sudo iptables -I FORWARD -i eth0 -o ztnhhth2eu -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
```
|
|
|
|
**Verify FORWARD rules:**
|
|
```bash
|
|
sudo iptables -L FORWARD -v -n | head -20
|
|
# Should show ACCEPT rules for your ZeroTier interface
|
|
```
|
|
|
|
✅ **Checkpoint:** Rules should appear at the top of FORWARD chain
|
|
|
|
---
|
|
|
|
### STEP 5: Make Firewall Rules Persistent
|
|
|
|
**Install iptables-persistent:**
|
|
```bash
|
|
sudo apt-get update
|
|
sudo apt-get install -y iptables-persistent
|
|
```
|
|
|
|
**Save current rules:**
|
|
```bash
|
|
sudo iptables-save | sudo tee /etc/iptables/rules.v4
|
|
```
|
|
|
|
**Verify saved rules:**
|
|
```bash
|
|
sudo cat /etc/iptables/rules.v4 | grep -A 5 "POSTROUTING"
|
|
sudo cat /etc/iptables/rules.v4 | grep -A 5 "FORWARD"
|
|
```
|
|
|
|
---
|
|
|
|
### STEP 6: Configure ZeroTier Central (Web Interface)
|
|
|
|
**Go to:** https://my.zerotier.com
|
|
|
|
1. Select your ZeroTier network
|
|
2. Scroll to **Managed Routes** section
|
|
3. Click **Add Route** or **Submit Route**
|
|
4. Add:
|
|
- **Destination:** `<TARGET_SUBNET>` (e.g., 192.168.178.0/24)
|
|
- **Via:** `<GATEWAY_ZT_IP>` (e.g., 10.121.16.37)
|
|
5. Click **Submit**
|
|
|
|
**Wait 30-60 seconds for route to propagate to clients**
|
|
|
|
✅ **Checkpoint:** Route should appear in ZeroTier Central UI
|
|
|
|
---
|
|
|
|
### STEP 7: Configure Return Route on Next-Hop Router (Optional but Recommended)
|
|
|
|
**On your router (e.g., Teltonika at 192.168.170.1):**
|
|
|
|
Add static route:
|
|
- **Destination/Network:** `<ZT_SUBNET>` (e.g., 10.121.16.0/24)
|
|
- **Subnet Mask:** 255.255.255.0 (or /24)
|
|
- **Gateway/Next Hop:** `<GATEWAY_LOCAL_IP>` (e.g., 192.168.170.172)
|
|
|
|
**Why needed:** Without this, devices on the target subnet won't know how to send replies back to ZeroTier clients.
|
|
|
|
⚠️ **Note:** If using masquerading (Step 3), this may not be strictly required, but it's good practice.
|
|
|
|
---
|
|
|
|
## Verification & Testing
|
|
|
|
### Test 1: From Gateway to Target Subnet
|
|
```bash
|
|
# On the gateway (Pi5)
|
|
ping -c 4 <TARGET_IP>
|
|
# Example: ping -c 4 192.168.178.10
|
|
```
|
|
**Expected:** Should work ✅
|
|
|
|
---
|
|
|
|
### Test 2: From ZeroTier Client to Target Subnet
|
|
|
|
**On client machine (e.g., X230):**
|
|
|
|
```bash
|
|
# Check ZeroTier route exists
|
|
ip route show | grep <TARGET_SUBNET>
|
|
# Should show: 192.168.178.0/24 via 10.121.16.37 dev ztXXXXXX
|
|
|
|
# Test connectivity
|
|
ping -c 4 <TARGET_IP>
|
|
# Example: ping -c 4 192.168.178.10
|
|
|
|
# Trace the route
|
|
traceroute <TARGET_IP>
|
|
# Should show: hop 1 = gateway ZT IP, then target
|
|
```
|
|
|
|
**Expected:** Should work ✅
|
|
|
|
---
|
|
|
|
## Troubleshooting Checklist
|
|
|
|
If ping from ZeroTier client doesn't work, check these in order:
|
|
|
|
### 1. ✓ Verify ZeroTier Route on Client
|
|
```bash
|
|
ip route show | grep <TARGET_SUBNET>
|
|
```
|
|
**Fix:** Wait for ZeroTier Central routes to propagate (up to 60 seconds), or restart ZeroTier:
|
|
```bash
|
|
sudo systemctl restart zerotier-one
|
|
```
|
|
|
|
---
|
|
|
|
### 2. ✓ Verify IP Forwarding on Gateway
|
|
```bash
|
|
cat /proc/sys/net/ipv4/ip_forward
|
|
```
|
|
**Should be:** `1`
|
|
**Fix:** Run Step 1 again
|
|
|
|
---
|
|
|
|
### 3. ✓ Verify Static Route on Gateway
|
|
```bash
|
|
ip route show | grep <TARGET_SUBNET>
|
|
```
|
|
**Should show:** Route via next-hop router
|
|
**Fix:** Run Step 2 again
|
|
|
|
---
|
|
|
|
### 4. ✓ Verify NAT/Masquerading Rule
|
|
```bash
|
|
sudo iptables -t nat -L POSTROUTING -v -n | grep <ZT_SUBNET>
|
|
```
|
|
**Should show:** MASQUERADE rule
|
|
**Fix:** Run Step 3 again
|
|
|
|
---
|
|
|
|
### 5. ✓ Verify FORWARD Rules (MOST COMMON ISSUE!)
|
|
```bash
|
|
sudo iptables -L FORWARD -v -n | head -20
|
|
```
|
|
**Should show:**
|
|
- ACCEPT rule for `<ZT_INTERFACE> → <LOCAL_INTERFACE>`
|
|
- ACCEPT rule for `<LOCAL_INTERFACE> → <ZT_INTERFACE>` (RELATED,ESTABLISHED)
|
|
|
|
**Fix:** Run Step 4 again
|
|
|
|
---
|
|
|
|
### 6. ✓ Check Packet Counters
|
|
```bash
|
|
# Check if packets are being processed
|
|
sudo iptables -t nat -L POSTROUTING -v -n | grep <ZT_SUBNET>
|
|
sudo iptables -L FORWARD -v -n | grep <ZT_INTERFACE>
|
|
```
|
|
**Look for:** `pkts` column should increase when you ping
|
|
**If 0 packets:** Traffic is being blocked before reaching that rule
|
|
|
|
---
|
|
|
|
### 7. ✓ Traceroute from Client
|
|
```bash
|
|
traceroute <TARGET_IP>
|
|
```
|
|
**Diagnose:**
|
|
- **Stops at gateway:** FORWARD rules or routing issue on gateway
|
|
- **Reaches target but no response:** Return routing issue (check Step 7)
|
|
- **Doesn't reach gateway:** ZeroTier route not configured
|
|
|
|
---
|
|
|
|
### 8. ✓ Test from Gateway First
|
|
```bash
|
|
# On gateway
|
|
ping <TARGET_IP>
|
|
```
|
|
**If this fails:** Problem is between gateway and target (routing, firewall on router, etc.)
|
|
**If this works but client fails:** Problem is in gateway's forwarding/firewall
|
|
|
|
---
|
|
|
|
## Quick Reference Commands
|
|
|
|
### Check Configuration Status
|
|
```bash
|
|
# IP forwarding
|
|
cat /proc/sys/net/ipv4/ip_forward
|
|
|
|
# Routing table
|
|
ip route show
|
|
|
|
# NAT rules
|
|
sudo iptables -t nat -L POSTROUTING -v -n
|
|
|
|
# FORWARD rules
|
|
sudo iptables -L FORWARD -v -n
|
|
|
|
# ZeroTier status
|
|
sudo zerotier-cli listnetworks
|
|
```
|
|
|
|
### View Real-Time Traffic
|
|
```bash
|
|
# Watch iptables counters update
|
|
watch -n 1 'sudo iptables -t nat -L POSTROUTING -v -n'
|
|
watch -n 1 'sudo iptables -L FORWARD -v -n'
|
|
```
|
|
|
|
### Reset/Remove Configuration
|
|
```bash
|
|
# Remove static route
|
|
sudo ip route del <TARGET_SUBNET>
|
|
|
|
# Remove NAT rule (use exact match from -L output)
|
|
sudo iptables -t nat -D POSTROUTING -s <ZT_SUBNET> -d <TARGET_SUBNET> -o <LOCAL_INTERFACE> -j MASQUERADE
|
|
|
|
# Remove FORWARD rules (by number, check with -L --line-numbers)
|
|
sudo iptables -L FORWARD --line-numbers
|
|
sudo iptables -D FORWARD <LINE_NUMBER>
|
|
```
|
|
|
|
---
|
|
|
|
## Common Issues & Solutions
|
|
|
|
### Issue 1: "RTNETLINK answers: File exists"
|
|
**Cause:** Route already exists
|
|
**Solution:** Remove existing route first, then add new one
|
|
```bash
|
|
sudo ip route del <TARGET_SUBNET>
|
|
sudo ip route add <TARGET_SUBNET> via <NEXT_HOP> dev <INTERFACE>
|
|
```
|
|
|
|
### Issue 2: Ping works from gateway but not from ZeroTier clients
|
|
**Cause:** Missing FORWARD rules (policy DROP)
|
|
**Solution:** Add FORWARD rules (Step 4)
|
|
|
|
### Issue 3: Masquerading shows 0 packets
|
|
**Cause:** Traffic is blocked before reaching POSTROUTING chain
|
|
**Solution:** Check FORWARD chain rules
|
|
|
|
### Issue 4: Route not appearing on ZeroTier clients
|
|
**Cause:** ZeroTier Central route not configured or not propagated
|
|
**Solution:**
|
|
- Check ZeroTier Central web interface
|
|
- Wait 60 seconds
|
|
- Restart ZeroTier: `sudo systemctl restart zerotier-one`
|
|
|
|
### Issue 5: Connection works briefly then stops
|
|
**Cause:** Rules not persistent, lost on reboot
|
|
**Solution:** Save iptables rules (Step 5) and create systemd service for routes (Step 2)
|
|
|
|
---
|
|
|
|
## Example: Complete Configuration
|
|
|
|
**Network:**
|
|
- ZeroTier subnet: 10.121.16.0/24
|
|
- Gateway ZT IP: 10.121.16.37
|
|
- Gateway local IP: 192.168.170.172
|
|
- ZT interface: ztnhhth2eu
|
|
- Local interface: eth0
|
|
- Next-hop router: 192.168.170.1
|
|
- Target subnet: 192.168.178.0/24
|
|
|
|
**Commands:**
|
|
```bash
|
|
# 1. Enable IP forwarding
|
|
sudo sysctl -w net.ipv4.ip_forward=1
|
|
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
|
|
|
|
# 2. Add static route
|
|
sudo ip route add 192.168.178.0/24 via 192.168.170.1 dev eth0
|
|
|
|
# 3. Add masquerading
|
|
sudo iptables -t nat -A POSTROUTING -s 10.121.16.0/24 -d 192.168.178.0/24 -o eth0 -j MASQUERADE
|
|
|
|
# 4. Add FORWARD rules
|
|
sudo iptables -I FORWARD -i ztnhhth2eu -o eth0 -j ACCEPT
|
|
sudo iptables -I FORWARD -i eth0 -o ztnhhth2eu -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
|
|
# 5. Save rules
|
|
sudo apt-get install -y iptables-persistent
|
|
sudo iptables-save | sudo tee /etc/iptables/rules.v4
|
|
|
|
# 6. Configure ZeroTier Central
|
|
# Go to https://my.zerotier.com → Add route: 192.168.178.0/24 via 10.121.16.37
|
|
|
|
# 7. Test
|
|
ping 192.168.178.10
|
|
```
|
|
|
|
---
|
|
|
|
## Post-Configuration Checklist
|
|
|
|
- [ ] IP forwarding enabled and persistent
|
|
- [ ] Static route configured and persistent (systemd service)
|
|
- [ ] NAT/Masquerading rule added and saved
|
|
- [ ] FORWARD rules added and saved
|
|
- [ ] ZeroTier Central managed route configured
|
|
- [ ] Return route on next-hop router configured (optional)
|
|
- [ ] Tested from gateway: ping works ✅
|
|
- [ ] Tested from ZeroTier client: ping works ✅
|
|
- [ ] Rebooted gateway and verified everything still works ✅
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- This configuration acts as a **route-based gateway**, not a site-to-site VPN
|
|
- All traffic is routed, not bridged
|
|
- Clients must use ZeroTier to access the remote subnet
|
|
- The gateway Pi must remain online for access to work
|
|
- Consider security: you're exposing a remote network to ZeroTier users
|
|
- Monitor the gateway: `htop`, `iftop`, or `vnstat` for traffic monitoring
|
|
|
|
---
|
|
|
|
**Document Version:** 1.0
|
|
**Last Updated:** February 16, 2026
|
|
**Tested On:** Raspberry Pi 5, Ubuntu 24.04, Debian 12 |