Tailnet Gateway

Selective Tailnet Service Gateway

Who it is for: anyone with a LAN device that must reach a specific service on a Tailscale or Headscale tailnet but cannot or should not run a Tailscale client.

A LAN client connects to the ESP32's address and listen port; the ESP32 forwards over WireGuard to one Tailnet service; other LAN devices are refused.
The LAN client connects to the ESP32; the ESP32 carries the connection over WireGuard.

Requirements

Example: a WiFi sensor at another home needs your MQTT broker, but cannot install Tailscale. Keep the sensor on its existing LAN; configure its broker address as the ESP32's LAN address and listen port. The gateway forwards that connection to the broker's Tailnet peer. Follow the two-home MQTT example.

Procedure

  1. Open Network → LAN → Tailnet and choose a template or the guided setup.
  2. Set protocol, listen port on the ESP32, Tailnet destination (100.x.y.z or a MagicDNS name), destination port and allowed source.
  3. Optionally set an expiry for temporary access.
  4. Press Test destination: the ESP32 performs one bounded TCP handshake with the service.
  5. Enable the rule and point the LAN client at ESP-IP:listen-port.

Example

Protocol            TCP
Listen port         18830
Tailnet destination broker.your-tailnet.ts.net
Destination port    1883
Allowed source      192.0.2.20/32
Client connects to  192.0.2.50:18830

Verify

See the actual firmware interface before configuring your first rule.

Common problems

Limits

IPv4 TCP/UDP, up to 8 rules, one Tailnet IPv4 destination per rule. It is a port forwarder, not transparent routing. Throughput depends on the microcontroller, radio/uplink and direct or DERP path. Use it for control and small services rather than bulk transfers.

Security

A source CIDR is not client identity: anyone who can use that address can use the service. The remote peer sees the ESP32's tailnet identity and its own ACL still decides. Protect the Web UI with a password. Rule commands over MQTT carry the rule's binding token so a stale command cannot act on a replaced rule.

Full guide: docs/SERVICE-GATEWAY.md.