NeoMody 26052b8c3b Remove gvisor raw socket hack: icmp.go, icmp_conn.go, wg_stack.go
The raw endpoint approach (ExtractGVisorStack + EnableRawSockets +
NewRawEndpoint) was a dead end — gvisor can't forward ICMP through
WireGuard regardless of raw socket permissions.

spoofPingConn (TCP probe + reply synthesis) is the only working
approach and doesn't need any gvisor internals.
2026-04-03 09:20:28 +08:00

tailnet

Clean-room Tailscale protocol implementation. No fork needed, no platform-specific syscall dependencies.

Why

tailscale.com/tsnet bundles the full Tailscale engine including netmon which calls syscall.NetlinkRIB — blocked on Android. This library reimplements only what's needed: control plane auth, DERP relay, NAT traversal, and WireGuard integration.

Architecture

┌─────────────────────────────────────────────────────────┐
│  outbound.go — Orchestrator                              │
│  Start: register → fetchNetworkMap → startMapPoll        │
│       → initDisco → createWireGuard → startBackground    │
│  API:  DialContext / Listen / Peers / Metrics / Close     │
├─────────────────────────────────────────────────────────┤
│  control.go — Control Plane (888 lines)                  │
│  Noise IK handshake → HTTP/2 over Noise                  │
│  Register / MapLite / MapPoll / SendEndpointUpdate        │
│  noiseTransport: lazy connect + auto-reconnect            │
├──────────────┬──────────────────────────────────────────┤
│ magicbind.go │ derpclient.go        │ disco.go           │
│ conn.Bind    │ DERP relay           │ NAT traversal      │
│              │                      │                     │
│ Send:        │ ConnectRegion        │ STUN endpoint       │
│ 1.lastRecv   │ Send (failover)      │ CallMeMaybe         │
│ 2.BestAddr   │ recvLoop+reconnect   │ Ping/Pong           │
│ 3.DERP       │ healthCheckLoop      │ RTT EWMA+demotion   │
│              │                      │ OnNetworkChange      │
├──────────────┴──────────────────────┴─────────────────────┤
│  netwatch.go — Network change detection                    │
│  Poll interface state + Poke() for platform callbacks      │
├────────────────────────────────────────────────────────────┤
│  funnel.go — Tailscale Funnel TCP proxy                    │
├────────────────────────────────────────────────────────────┤
│  WireGuard (wireguard-go) + netstack (gVisor) or TUN       │
└────────────────────────────────────────────────────────────┘

Files

File Lines Role
control.go 888 Control plane: Noise IK, Register, MapPoll, endpoint updates, key expiry
disco.go 854 NAT traversal: STUN, Ping/Pong, CallMeMaybe, path health (RTT EWMA, demotion/restore)
outbound.go 798 Orchestrator: wires control+DERP+disco+WireGuard, handles MapResponse, WG IPC
derpclient.go 421 DERP relay: per-region connections, health check, auto-reconnect, failover
magicbind.go 368 conn.Bind: multiplexes direct UDP + DERP, symmetric routing, packet metrics
funnel.go 325 Funnel: TCP proxy with TLS termination on netstack listener
netwatch.go 112 Network change: interface state polling + Poke() for instant platform callbacks
mobile/mobile.go 218 gomobile API for Android/iOS
cmd/demo/ 314 CLI demo: netstack mode (listen, dial, self-test)
cmd/tun-demo/ 181 CLI demo: system TUN mode

Key Features

  • MapPoll auto-reconnect — stream disconnect triggers exponential backoff reconnect
  • DERP health monitoring — periodic probes, unhealthy region failover
  • Path health tracking — EWMA RTT baseline, 3x degradation demotion, timeout-based failure counting
  • Symmetric routing — reply to last received address for WireGuard handshake completion
  • Network change detection — polling + Poke() API for Android/iOS callbacks
  • MagicDNS short names — "worker" resolves via search domains from control plane
  • Graceful shutdown — sends empty endpoint update so control marks node offline
  • Metrics — atomic packet counters (direct/DERP), disco stats, exposed via Metrics()
  • Node key expiry — warns at 7d/1d/expired from MapResponse

Dependencies

Uses from tailscale.com (types/crypto only):

  • control/controlbase — Noise IK protocol
  • tailcfg — Protocol message types
  • types/key — Key types (Node, Machine, Disco)
  • derp + derp/derphttp — DERP client
  • disco — Disco message parsing
  • net/stun — STUN binding requests

Does NOT use: wgengine, magicsock, netstack, netmon, ipn, tun

Platforms

Platform Status Notes
Linux Tested labs server, full functionality
Android Tested Samsung S25, VPN bypass (3-layer socket protection)
macOS Tested Development machine
Windows Compiles Cross-compilation verified, untested at runtime
iOS Compiles gomobile API ready, untested at runtime

Build

# Library
go build ./...

# Android shared library
CGO_ENABLED=1 GOOS=android GOARCH=arm64 go build -tags with_gvisor -buildmode=c-shared -o libminising.so ./cmd/android-lib/

# CLI demo
go build -tags with_gvisor -o demo ./cmd/demo/

# Cross-compile Windows
GOOS=windows GOARCH=amd64 go build ./...
Description
No description provided
Readme 27 MiB
Languages
Go 97.6%
Kotlin 2.4%