NAT Traversal
Connect nodes across different networks
NAT Traversal
Connect OctoMY™ nodes when they're on different networks or behind NAT.
Pro Tip
If you control your router, port forwarding is the most reliable method. Zoo hole punching works automatically for most home networks but may struggle with corporate firewalls.
Understanding NAT
The problem
When devices are behind NAT routers:
- They have private IPs (192.168.x.x, 10.x.x.x)
- They can't receive incoming connections directly
- Two nodes on different NATs can't connect peer-to-peer
[Remote] [NAT/Router] Internet [NAT/Router] [Agent]
192.168.1.10 --> Public IP A ----X---- Public IP B <-- 192.168.2.20
↑
Direct connection blocked!
OctoMY™ solutions
- UDP Hole Punching - Nodes coordinate via Zoo to establish direct connection
- Zoo Relay - Traffic relays through Zoo when hole punching fails
- Port Forwarding - Manual router configuration for guaranteed access
Method 1: Zoo-assisted hole punching
This is the automatic, preferred method.
How it works
Remote Zoo Agent
│ │ │
│ 1. Register ────────►│◄──────── Register 1. │
│ │ │
│ 2. Request Agent ───►│ │
│ │──── Coordinate ──────► │
│ │ │
│ 3. Punch! ──────────────────── Punch! ─────── │
│ │ │
│ 4. Direct UDP ◄────────────────────────────► │
│ │ │
Prerequisites
- Both nodes can reach a Zoo server
- NAT type is not "Symmetric" on both ends
- UDP is not blocked by firewalls
Enable Zoo connection
On both nodes:
- Open ☰ Menu → Settings
- Go to Connection section
- Enable Use Zoo for NAT Traversal
- Enter Zoo server address (default:
zoo.octomy.org:8123)
NAT type compatibility
| NAT Type A | NAT Type B | Hole Punch? |
|---|---|---|
| Full Cone | Any | ✓ Works |
| Restricted | Full Cone | ✓ Works |
| Restricted | Restricted | ✓ Works |
| Port Restricted | Full/Restricted | ✓ Works |
| Symmetric | Full Cone | ✓ Works |
| Symmetric | Symmetric | ✗ Needs relay |
Method 2: Zoo Relay
When hole punching fails, Zoo can relay traffic.
When it's used
- Symmetric NAT on both ends
- Corporate firewalls blocking UDP
- As fallback when hole punching times out
How it works
Remote ────────► Zoo ────────► Agent
encrypted encrypted
Enable relay
Relay is automatic when hole punching fails. To force relay:
./remote --personality MyController --force-relay
Relay limitations
| Aspect | Impact |
|---|---|
| Latency | +20-100ms |
| Bandwidth | Limited by Zoo server |
| Privacy | Traffic passes through Zoo |
Method 3: Port forwarding
Manual router configuration for guaranteed direct access.
When to use
- You have router access
- Need lowest possible latency
- Hole punching isn't reliable on your network
Step 1: Get your local IP
# Linux
ip addr show | grep "inet 192"
# Example output: inet 192.168.1.105/24
Step 2: Configure router
Access your router admin (usually 192.168.1.1 or 192.168.0.1).
Navigate to: Port Forwarding / Virtual Server / NAT
Create rule:
| Field | Value |
|---|---|
| Name | OctoMY™ Agent |
| Protocol | UDP |
| External Port | 8124 |
| Internal IP | 192.168.1.105 |
| Internal Port | 8124 |
Step 3: Find your public IP
curl ifconfig.me
# Example: 203.0.113.50
Step 4: Share connection info
Give Remote users your public IP and port:
- Address:
203.0.113.50:8124 - Or use QR pairing which includes this info
Step 5: Test
From outside your network:
nc -zvu 203.0.113.50 8124
Method 4: VPN
Use a VPN to put both nodes on the same virtual network.
Options
| VPN Type | Complexity | Latency |
|---|---|---|
| WireGuard | Low | Low |
| OpenVPN | Medium | Medium |
| Tailscale | Very Low | Low |
| ZeroTier | Very Low | Low |
Tailscale example
Easiest option for personal use:
# Install on both devices
curl -fsSL https://tailscale.com/install.sh | sh
# Start and authenticate
sudo tailscale up
# Get Tailscale IPs
tailscale ip -4
# Example: 100.64.0.1 (Agent), 100.64.0.2 (Remote)
# Use Tailscale IPs for OctoMY
./agent --personality MyRobot --bind 100.64.0.1
Checking your NAT type
Using STUN
# Install stun client
sudo apt install stun-client
# Check NAT type
stun stun.l.google.com:19302
NAT types explained
| Type | Description | Hole Punch? |
|---|---|---|
| Open/None | Public IP, no NAT | Always works |
| Full Cone | Any external host can send | Easy |
| Restricted Cone | Only hosts you contacted can reply | Works |
| Port Restricted | Only exact port can reply | Works |
| Symmetric | Different port for each destination | Difficult |
Testing NAT traversal
Test 1: Zoo connectivity
# Check if you can reach Zoo
nc -zvu zoo.octomy.org 8123
Test 2: Hole punch test
On both nodes, enable debug logging:
./agent --personality MyRobot --debug 2>&1 | grep -i "hole\|punch\|nat"
Look for:
- "NAT type detected: ..."
- "Hole punch initiated"
- "Direct connection established"
Test 3: Connection path
In the UI:
- Open ☰ Menu → Utilities → Connection Info
- Check "Connection Type": Direct / Relayed / Local
Optimizing NAT traversal
Reduce hole punch time
./agent --personality MyRobot \
--punch-attempts 5 \
--punch-interval 200
Prefer direct connections
./agent --personality MyRobot \
--relay-timeout 10000 \
--prefer-direct
Multiple Zoo servers
Configure fallback Zoo servers:
Settings → Connection → Zoo Servers:
1. zoo.octomy.org:8123 (primary)
2. zoo2.octomy.org:8123 (fallback)
Corporate/enterprise networks
Corporate firewalls often block UDP entirely.
Solutions
- Request UDP whitelist - Ask IT to allow UDP 8123-8126
- Use TCP fallback - Enable in settings (slower)
- VPN - Use corporate VPN from both locations
- Zoo relay - Usually works if HTTPS works
Check if UDP is blocked
# Try reaching any UDP service
nc -zvu 8.8.8.8 53
# If this fails, UDP is blocked
Troubleshooting
"NAT Traversal Failed"
- Check both nodes can reach Zoo
- Verify NAT types (both Symmetric = needs relay)
- Try forcing relay mode
- Check firewall isn't blocking UDP
"Connection Unstable"
NAT mappings expire. Solutions:
- Decrease keepalive interval
- Check router NAT timeout settings
- Use relay for consistency
"High Latency via Relay"
The relay path is longer. Options:
- Try hole punching again later
- Set up port forwarding
- Use VPN for direct connection
"Works Sometimes"
Symmetric NAT picks random ports. Try:
- More punch attempts
- Different Zoo server
- Port forwarding
Self-hosting Zoo
For private networks or reduced latency:
# Run your own Zoo server
./zoo --port 8123 --bind 0.0.0.0
# Configure nodes to use it
./agent --zoo my-zoo-server.local:8123
See Zoo Reference for full setup.