Reaching your own LAN without port forwarding, public URLs, or a VPN concentrator
buhuipaoDEV Community
1 views
Disclosure: I maintain Lantunnel. It is Apache-2.0 and the source is linked at the end.
Every self-hoster hits the same wall. The NAS is at home. The GPU box is at the office. Ollama is on the desktop you walked away from. All of them sit behind NAT, and none of them belong on the public internet.
The usual answers all ask you to give something up. Port forwarding puts a service on the open internet and hopes the auth holds. A public tunnel URL does the same thing with nicer branding. A classic VPN concentrator works, but now every byte between two machines in your own house takes a detour through a box you rent.
Lantunnel is my attempt at a fourth option: a small private mesh where peers talk directly whenever the network allows it, and where the fallback path still cannot read your traffic.
The shape of the system
There are three binaries, and that is the whole thing.
lantunnel-client runs on every device that joins. It imports one signed .peer profile, attaches to the Gateway, and exposes a loopback SOCKS5 proxy on 127.0.0.1:1080 plus optional native routes. Ordinary apps reach the tunnel without knowing it exists.
lantunnel-gateway is a rendezvous point and NAT-traversal signaler. It holds a tunnel's public .scope file, helps two peers punch a direct path, and relays sealed bytes when they cannot. It never holds peer private keys and never sees plaintext.
lantunnel-admin creates the tunnel offline. init-tunnel makes the owner file and the Gateway's public scope; add-peer issues one signed profile per device. It talks to nothing — no account, no callback, no network at all.
Direct first, relay only when the network refuses
New flows try a direct peer-to-peer QUIC path with UDP hole punching. Relay is the fallback, not the default. When two machines are on networks that can be punched through, the Gateway drops out of the data path entirely and the traffic is a straight line between the two peers.
When hole punching fails — symmetric NAT, hostile carrier, corporate egress — the flow falls back to the Gateway. This is where the design has to earn trust, because a relay is exactly the component that could betray you.
Relayed payloads are sealed with XChaCha20-Poly1305 under keys derived from an X25519 exchange between the two peers. The Gateway forwards bytes it cannot decrypt. It is a dumb pipe by construction, not by policy.
Identity is signed, not shared
There is no tunnel password, no group secret, no bearer token to leak into a wiki page.
Every peer holds its own Ed25519 key, proves possession of it on every attachment, and that key never leaves the machine that generated it. One profile per device — a .peer is not meant to be copied around. Revoking a laptop means revoking a laptop, not rotating a shared credential across every device you own.
The access-control list lives on the target machine too. Each client decides what it will serve. Policy sits on the box holding the data, never on the Gateway and never on someone else's server.
Whole-LAN reach, not per-service holes
A peer can export the private subnets it sits on. One client on the home network makes the NAS, the printer, and the dashboard reachable to the rest of the tunnel — without an inbound firewall rule, a public IP, or a hostname anywhere.
In practice people use it for game and media streaming (Sunshine/Moonlight, Jellyfin, Plex), private AI and dev tooling (Ollama, Open WebUI, an internal API, a staging box, a database that must never leave the LAN), and ordinary home-office plumbing (NAS, Home Assistant, cameras, SSH).
Self-hosting the Gateway
If you would rather not depend on anyone, the Gateway is in the repository, it is Apache-2.0, and it is not metered.
# On the public Gateway host
lantunnel-gateway init --public-ip <PUBLIC_IP>
# On the trusted owner machine — the Gateway private key never leaves the Gateway host
lantunnel-admin init-tunnel \
--gateway-transport quic \
--gateway-ip <PUBLIC_IP> \
--gateway-port 8443 \
--gateway-mapping-port 8444 \
--gateway-cert ./server.crt
lantunnel-admin add-peer --tunnel <tunnel-id>.tunnel --name laptop --output laptop.peer
# Back on the Gateway host: only the public scope moves
mkdir -p state/scopes.d && cp <tunnel-id>.scope state/scopes.d/
lantunnel-gateway --config configs/gateway.yaml --check-config
lantunnel-gateway --config configs/gateway.yaml
# On each device
lantunnel-client tunnel import ./laptop.peer
lantunnel-client # desktop UI
lantunnel-client connect '<tunnel_id>' # same runtime, headless
Note what crosses machine boundaries: the Gateway's public certificate goes out to the owner machine, and the public .scope comes back. The tunnel signing key and the Gateway private key each stay where they were generated.
Re-running init preserves the existing config, certificate, and key. At the same config path, a changed IP, transport, data port, or mapping port is refused rather than silently replacing the Gateway identity.
One binary, UI or headless
lantunnel-client opens a desktop window by default and runs the exact same runtime under --headless on a server. There is no separate daemon build and no second code path to keep honest. It runs on macOS, Windows, Linux, Android, and iOS.
If you do not want to run a Gateway
There is a hosted option at lantunnel.app — one permanent free tunnel per account, unlimited direct peer-to-peer traffic, unlimited LAN devices behind each client, and 5 GB/month of encrypted relay fallback for when direct fails. The self-hosted path in the repository stays fully supported and unmetered either way.
Where the details live
The repository has the architecture write-up in CONTEXT.md, the wire protocol in docs/PROTOCOL.md, and a full usage guide in docs/USAGE.md covering LAN exports, access rules, servers, mobile, and troubleshooting.
Source: github.com/lantunnel/lantunnel (Apache-2.0)
I would genuinely like to hear where the NAT traversal falls over for you — the hole-punching path is the part that benefits most from networks I do not have access to.
Under-the-hood breakdown of Huawei’s “Pure HarmonyOS” SDK for engineers and architects.
For the past decade, mobile operating system architecture has been dominated by two paradigms: Android’s JVM-based, garbage-collected model, and iOS’s Darwin/Mach kernel with Swift/Objective-C. Huawei’s Harmony
What do you do when Claude Code proposes one solution, Codex a different one, and Gemini a third? The usual move is to pick an agent up front and take whatever it produces. Orca changes that dynamic: it runs all three at once, each isolated in its own git worktree, and lets you compare the results a
Hi everyone, I wanted a fast, privacy-focused way to track equipment, tools, and inventory using physical NFC tags and QR codes without handing my data over to a third-party SaaS cloud. So, I built an app called GridStorage. A quick note on how it was built: I used AI to help (of course) code this,