Reach a Private LAN
Reach a NAS, a database or an admin page on a private network, from anywhere, through one machine on that network. The machine runs nfltr wg serve and forwards only to the destinations you allow. The WireGuard tunnel is end to end from laptop to LAN machine: the relay forwards sealed packets and holds no WireGuard key. Each laptop reaches only the machine it names in its own account.
Goal
From your laptop, curl a web server on the LAN at http://192.168.1.20:8080/, which has no public address.
Prerequisites
- A machine on the LAN (call it the LAN machine) with the
nfltrCLI and an API key of your account saved withnfltr config add-api-key. - Your laptop with the
nfltrCLI and an API key of the same account, saved the same way. It can be the LAN machine's key: the laptop connects as its own session. - macOS or Windows laptop: nothing else (step 3 uses a local SOCKS5 proxy). Linux laptop: root, for a real network interface (step 4).
1. Find the target's LAN address
Use the host you want to reach. In this tutorial it is a small web server on the LAN machine itself, at the LAN machine's own address:
$ LAN_IP=$(ipconfig getifaddr en0); echo "$LAN_IP"
192.168.1.20
$ LAN_IP=$(hostname -I | awk '{print $1}'); echo "$LAN_IP"
192.168.1.20
$ echo 'hello from the LAN' > index.html
$ python3 -u -m http.server 8080
Serving HTTP on :: port 8080 (http://[::]:8080/) ...
2. Serve the LAN, allowing only what you need
On the LAN machine. --allow is required: the destinations tunnel traffic may reach, as CIDRs, IPs or hosts, each optionally with :port. Anything else is refused and logged. Here, one host and one port:
$ nfltr wg serve --name home-lan --allow "$LAN_IP:8080"
nfltr dev starting WireGuard agent
agent-id: home-lan
server: grpc.nfltr.xyz:443 (tls=true)
allow: 192.168.1.20:8080
Connected — WireGuard agent active
Wider rules: --allow 192.168.1.0/24 (the whole subnet), --allow 10.0.0.5:5432,nas.lan:445 (a list), --allow all (everything the LAN machine can reach). Leave it running.
3. Connect from the laptop (macOS, Windows, or Linux without root)
nfltr wg socks5 opens a WireGuard tunnel to home-lan and a SOCKS5 proxy on your laptop:
$ nfltr wg socks5 home-lan --listen 127.0.0.1:1080
nfltr wg socks5 dev
server: grpc.nfltr.xyz:443
public key: 3kQv...Xw= (paired: false)
WireGuard session to home-lan: address 100.64.0.3, exit key Hx7r...9A=
SOCKS5 proxy listening on 127.0.0.1:1080 (through WG tunnel to home-lan)
Point any SOCKS-aware tool at it. --socks5-hostname makes curl resolve names on the LAN side too, so nas.lan-style names work:
$ curl -s --socks5-hostname 127.0.0.1:1080 "http://$LAN_IP:8080/"
hello from the LAN
Browsers, git (git config http.proxy socks5h://127.0.0.1:1080) and ssh (ssh -o ProxyCommand='nc -X 5 -x 127.0.0.1:1080 %h %p' user@192.168.1.20) work the same way.
4. Or route the subnet on Linux
On a Linux laptop with root, nfltr wg connect creates a real network interface (nfltr0) routing the CIDRs you name through the tunnel, so every program reaches the LAN directly, with no proxy settings. Run it as root with the key in the environment:
$ sudo --preserve-env=NFLTR_API_KEY nfltr wg connect home-lan --allowed-ips 192.168.1.0/24
$ curl -s http://192.168.1.20:8080/
hello from the LAN
In a container, run it with --cap-add NET_ADMIN --device /dev/net/tun. The LAN machine still forwards only to its --allow list, whatever --allowed-ips says.
The relay passes each side the other's WireGuard key. To stop a relay in the middle from swapping in its own, give the LAN machine and every laptop the same pairing key file and add --e2ee-key-file on both ends (wg connect takes it too):
$ nfltr wg serve --name home-lan --allow "$LAN_IP:8080" --e2ee-key-file pairing.key
$ nfltr wg socks5 home-lan --listen 127.0.0.1:1080 --e2ee-key-file pairing.key
5. Clean up
Press Ctrl+C in the nfltr wg socks5 terminal, then in the nfltr wg serve terminal on the LAN machine (and stop the demo web server).
# Ctrl+C in the nfltr wg socks5 terminal
# Ctrl+C in the nfltr wg serve terminal
If it goes wrong
| You see | Meaning and fix |
|---|---|
Error: --allow is required: list the destinations this agent may forward to | nfltr wg serve never forwards by default. Name what the tunnel may reach, or --allow all. |
curl fails with exit code 97, and the LAN machine logs wg forwarder: refused destination outside --allow … dst=192.168.1.20:9999 | The destination is not in the --allow list. Restart wg serve with a wider list. |
Error: nfltr wg connect needs a Linux kernel TUN; on this system use: nfltr wg socks5 home-lan | macOS and Windows have no kernel TUN for nfltr: use nfltr wg socks5 (step 3). |
the client and the exit disagree on --e2ee-key-file | Only one end has a pairing key. Set the same --e2ee-key-file on both ends, or on neither. |
Error: home-lan: no handshake with the exit within 20s: WireGuard handshake failed; check that --e2ee-key-file matches on both ends, and the LAN machine logs wg: a client's handshake failed | Both ends have a pairing key, but not the same one. Copy the same key file to both ends. |
Error: home-lan: cannot reach the relay at … (3 attempts) | The laptop cannot reach the relay's gRPC address. Unset NFLTR_SERVER to use the hosted relay (grpc.nfltr.xyz:443), or fix the address. |
no WireGuard exit by that name is available to this key | No wg serve of your account is running under that name. Check the name, and that the LAN machine is connected. |
curl to 127.0.0.1 or localhost through the proxy reaches your own laptop | Those names are always local. Use the LAN machine's LAN address (192.168.x.x) to reach services on it. |
Next
- SSH to one machine behind NAT
- End-to-end encryption: what the WireGuard tunnel protects