# VNT: a Rust mesh VPN for building a virtual LAN across sites

> VNT connects machines behind NAT into one virtual network using a shared network id and server address. It ships as a desktop client, a web UI and a CLI, and the 2.x rewrite is not compatible with 1.0.

**vnt-dev/vnt** — An efficient VPN. 简便高效的异地组网、内网穿透工具

- Repository: https://github.com/vnt-dev/vnt
- Website: https://rustvnt.com
- Stars: 3,228 · Forks: 358
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/vnt-dev-vnt

## What VNT solves, and for whom

VNT builds a virtual LAN out of machines that are not on the same physical network. The README lists remote desktop, multiplayer games, reaching a NAS at home and cross-region collaboration as the intended uses. The unit of organisation is not a tunnel between two endpoints but a network identified by a number. Every device that enters the same network id against the same server joins the same virtual LAN and receives a virtual IP from a range the server sets. The README states the device count is unlimited.

The audience is split by tolerance for a terminal. The desktop client is described as the recommended path for general users, with a Windows installer that works out of the box. vnt2_web is for people who want browser-based management, which the README frames as suited to servers and NAS boxes without a desktop environment. vnt2_cli plus vnt2_ctrl is the scripted and automated route. The three are not separate products; they are front ends over the same core, and the repository layout reflects that, with vnt-core, vnt-ipc and vnt-web as workspace members alongside the binaries defined in Cargo.toml.

## How the virtual network is formed

The mechanism visible in the README is a peer mesh with a server for rendezvous and relay. A client connects to the server, authenticates into a network id, and receives a virtual IP. Peers then attempt direct connections; traffic that cannot go direct falls back to the server. The topics on the repository include p2p and nat, which matches that design. The 2.0 notes mention hole punching handled through rustp2p, and a user-space TCP/IP stack used for QUIC proxying and for the no-adapter egress mode.

The virtual adapter is where the modes diverge. device_mode accepts no, tun or tap, with tun as the default. no creates no adapter at all and only provides an egress and port mapping, which the README notes avoids the need for administrator rights. tun is a layer 3 adapter carrying IPv4 packets. tap is layer 2 and passes full Ethernet frames, translating IPv4 and handling ARP so it can interoperate with TUN and no nodes. Windows TUN uses a bundled wintun.dll; Windows TAP needs administrator rights and a pre-installed tap-windows driver with hardware id tap0901. Android only supports TUN, because it runs through VpnService.

The 2.0 notes add two things worth separating. One is multi-server connections for failover and load balancing, where a fixed virtual IP lets the local network come up immediately while server connections are established in the background. The other is serverless operation: with a fixed virtual IP and at least one peer_address seed, nodes form a multi-hop graph through an authenticated direct handshake and gossip announcements. That is a different topology from the server-relay default and is configured, not automatic.

## Installing VNT and joining a first network

The README points to GitHub Releases for platform packages rather than to a package manager, so the first step is downloading the build for your platform. The CLI binaries are what the README demonstrates. To join a network you supply the network id with -k and the server address with -s. The README gives the public server 101.35.230.139:6660 as an option for trying it out.

```bash
./vnt2_cli -k 123456 -s 101.35.230.139:6660
```

After starting, the device should receive a virtual IP from the range the server configures. Other machines using the same -k value and the same server address join the same virtual LAN. The README's verification step is to ping the other device's virtual IP; a reply means the network is up.

If you run the CLI in the background, the companion control binary reports state rather than starting a network itself:

```bash
./vnt2_ctrl info
```

The web front end starts differently. Running vnt2_web prints an access URL containing a token, and it listens on 127.0.0.1:19099 by default. The token can be pinned with --token or the VNT_WEB_TOKEN environment variable. Configurations are then added in the browser, again with only a network id and a server address, and started from there.

```bash
./vnt2_web
```

On Windows, creating the virtual adapter requires running the program as administrator. The README's fix is to right-click and choose to run as administrator. If you would rather not touch system networking at all, setting device_mode to no avoids the adapter and the elevated permissions.

## The password setting is the security boundary

VNT's encryption story is conditional, and the README is direct about it. Setting a password, via -p or --password on the command line or the password key in the configuration file, turns on end-to-end encryption between nodes using ChaCha20-Poly1305. The server then forwards ciphertext it cannot decrypt. Every device in the same virtual network must use the same password or they cannot talk to each other.

Without a password, node-to-node traffic is not encrypted, and the README states that traffic relayed through the server is in principle visible to the server. That is a real exposure when using the public server, and the README recommends running your own server for stability and privacy in production use. Separately, the client-to-server link supports tcp-tls, quic and wss, and can be bound to a server certificate to prevent a fake server from impersonating the real one. That protects the transport to the server; it is not the same thing as the node password, which protects payload between peers.

The IKEv2 and WireGuard interop flags deserve their own warning. --allow-ikev2 and --allow-wireguard, or allow_ikev2 and allow_wireguard in the config file, let VNT nodes reach clients that connect to the server over those protocols. Both are off by default. Both trust plaintext IPv4 injected by an authenticated server and force traffic to those device types through the server. The README states plainly that these paths are not covered by the VNT node password's end-to-end encryption. Enabling either flag widens what the server can see for that traffic.

## Where VNT is the wrong tool

The clearest limitation is the 1.0 to 2.0 break. The README says the 2.0 line was refactored as a whole and is not compatible with 1.0. Anyone with existing 1.0 deployments and configuration files has a migration problem, and the README does not document a migration path. There is one related guardrail: the old no_tun config key was removed, and the program prompts for migration rather than silently starting in TUN mode. That is better than a silent behaviour change, but it is a single key, not a migration guide.

Platform coverage is another constraint. Android 2.0 is published as a separate repository, and the README says more platforms will follow. The repository itself is Rust with a Tauri desktop shell, and the binaries defined in Cargo.toml are the CLI, the control tool and the web server, so the desktop client is built from vnt-desktop rather than from the root binary list. If your estate is mostly mobile, check the Android client separately before assuming parity.

There is also a topology mismatch for some users. If what you actually need is a routed site-to-site link between two known gateways with static addressing, a virtual LAN that hands out addresses from a server-defined range adds a layer you may not want. The same applies if you cannot accept that a server participates in the connection at all. The serverless mode exists for that case, but it requires a fixed virtual IP and at least one peer_address seed, and the README does not describe how the multi-hop graph behaves when seeds go offline.

## How VNT differs from WireGuard-based overlays

The natural comparison is a WireGuard-based mesh such as Tailscale or NetBird. The difference is in what the server knows. WireGuard itself is a point-to-point tunnel with no notion of a network id or an address allocator, so those overlays add a coordination service that distributes keys and routes. VNT folds the equivalent into its own server, and the server assigns virtual IPs from a range it defines. The network id is the whole join credential in the simple case, which is why the password setting matters so much: with no password, the id is effectively the only secret.

VNT's interop flags are the other divergence. The README describes allowing IKEv2 and WireGuard clients that terminate at the VNT server to reach VNT nodes. A WireGuard-only overlay has no equivalent, because there is nothing else to interoperate with. The trade-off is that those two paths bypass the node password's end-to-end encryption, so interop costs you the property that makes the password worth setting.

The serverless mode is the closest thing to a genuinely different approach here. Rather than a coordination server, nodes with a fixed virtual IP and a peer_address seed form a multi-hop graph through authenticated direct handshakes and gossip announcements. The README does not describe how that graph is maintained or how conflicts between fixed addresses are resolved, so treat it as a feature to evaluate rather than a drop-in replacement for the server model.

## Maintenance, licence and upgrade cost

The repository is not archived and the last push was on 2026-09-19, with releases v2.0.9 on 2026-09-13, v2.0.8 on 2026-09-07 and v2.0.7 on 2026-09-05. The 2.0 line is moving in short increments, and each increment carries the usual risk of a fast-moving project: configuration keys can be removed, as no_tun was. Pin a version rather than tracking the latest release, and read the release notes before upgrading a network you depend on.

The licence is Apache-2.0, declared both in the repository metadata and in Cargo.toml and package.json. Apache-2.0 permits commercial use and modification and includes a patent grant, with the usual obligations around notices and attribution. This is a description of the licence text, not legal advice; if you redistribute a modified build, have someone check the notice requirements against your distribution.

Upgrade cost is dominated by the 1.0 incompatibility rather than by the licence. There is no stated support window for 1.0, and the README does not describe a supported upgrade path. A team still on 1.0 should treat a move to 2.0 as a redeployment, not a version bump.

## Conclusion

Adopt VNT if you need a virtual LAN across NAT and are comfortable running a server or using the public one at 101.35.230.139:6660, and set a password with -p or the password config key before moving real traffic. Do not adopt it if you need a documented migration path from 1.0, or if you depend on IKEv2 or WireGuard interop with end-to-end encryption, since --allow-ikev2 and --allow-wireguard are off by default and those paths are not protected by the node password. Verify first that the virtual IP range your server assigns does not collide with your existing subnets.

## FAQ

### How do I install VNT?

The README directs you to GitHub Releases for the platform packages rather than a package manager. There are three entry points: the desktop client for general users, vnt2_web for browser-based management, and vnt2_cli with vnt2_ctrl for scripting.

### Is VNT traffic encrypted?

Only if you set a password, via -p or --password on the command line or the password key in the configuration file. With a password, node-to-node data uses ChaCha20-Poly1305 end-to-end and the server forwards ciphertext it cannot decrypt. Without one, the README states that traffic relayed through the server is in principle visible to the server.

### Why does VNT need administrator rights on Windows?

Creating the virtual adapter requires elevated permissions, and the README says to run the program as administrator. If you do not want to modify system networking, setting device_mode to no skips the adapter and avoids the requirement.

### Can VNT run without a server?

The 2.0 notes describe serverless operation: with a fixed virtual IP and at least one peer_address seed, nodes form a multi-hop graph through an authenticated direct handshake and gossip announcements. The README does not document how that graph behaves when seeds go offline.

### Is VNT 2.0 compatible with VNT 1.0?

No. The README states that 2.0 was refactored as a whole and is not compatible with 1.0, and it does not document a migration path. The removed no_tun key is the one exception where the program prompts for migration instead of silently starting in TUN mode.

## Sources

- [License: Apache-2.0](https://github.com/vnt-dev/vnt/blob/main/LICENSE)
- [Project website](https://rustvnt.com)
- [README](https://github.com/vnt-dev/vnt/blob/main/README.md)
- [Releases](https://github.com/vnt-dev/vnt/releases)
- [vnt-dev/vnt on GitHub](https://github.com/vnt-dev/vnt)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/vnt-dev-vnt
