VPN Networking with TUN Devices¶
GOST first introduced TUN (and TAP) device support in v2.9. In v3 (beta.4), the implementation was changed from the songgao/water library to wireguard-go, with added heartbeat and authentication mechanisms.
The design philosophy for TUN devices in GOST is simplicity and lightness — no overly complex configuration, minimal data processing. If it meets specific use cases, that's sufficient. For more complex applications, WireGuard itself can be used directly.
TUN devices have many uses, most commonly for building VPNs. This post covers GOST-based TUN VPN networking.
VPN Networking¶
This is the most common VPN use case: connecting multiple LANs so they can reach each other. For example, accessing the company network from home, or accessing both home and company networks while traveling.
GOST's TUN uses a client-server model — a public server is required as a relay to connect and route clients.
Assume the following:
- Machine C1 on the company network (192.168.100.0/24)
- Machine C2 on the home network (192.168.101.0/24)
- Machine C3 on an external network (192.168.102.0/24)
- Server S on a public network (192.168.1.0/24, public IP 1.2.3.4)
First, run the TUN server on S (ensure UDP port 8421 is open):
services:
- name: tun
addr: :8421
handler:
type: tun
listener:
type: tun
metadata:
net: 192.168.123.1/24
routes:
- "192.168.100.0/24 192.168.123.2"
- "192.168.101.0/24 192.168.123.3"
The TUN device on server S has IP 192.168.123.1, with routing rules:
- Traffic to 192.168.100.0/24 → forward to 192.168.123.2
- Traffic to 192.168.101.0/24 → forward to 192.168.123.3
Then run clients on C1, C2, and C3.
Client C1 - 192.168.123.2¶
Client C2 - 192.168.123.3¶
Client C3 - 192.168.123.4¶
The critical part is the client route configuration:
- C1's route to 192.168.101.0/24 allows C1 to reach C2's network
- C2's route to 192.168.100.0/24 allows C2 to reach C1's network
- C3's routes to both networks allow C3 to reach both C1 and C2
iptables Configuration¶
TUN devices can communicate with each other, but accessing their respective LANs requires IP forwarding via iptables:
Heartbeat¶
The keepAlive parameter enables heartbeats, which serve two purposes:
- Connection health: GOST's TUN uses UDP. Heartbeats let the client detect network connectivity. After timeout (3 heartbeat periods), the client reinitializes the connection.
- Dynamic routing: The server maintains a dynamic client mapping table (client TUN IP ↔ client UDP connection IP:PORT). Heartbeats update this mapping. If the server restarts, client heartbeats repopulate the table.
Authentication¶
The above configuration works, but clients can set arbitrary TUN IPs, potentially causing conflicts. Enable server-side authentication for better control:
services:
- name: tun
addr: :8421
handler:
type: tun
auther: tun
listener:
type: tun
metadata:
net: 192.168.123.1/24
authers:
- name: tun
auths:
- username: 192.168.123.2
password: userpass1
- username: 192.168.123.3
password: userpass2
- username: 192.168.123.4
password: userpass3
The server assigns each client a TUN IP and credentials. Clients must use the assigned IP (net) and passphrase to join the network.
Secure Transport¶
GOST's TUN data is transmitted in plaintext. For encryption, use a forwarding chain with an encrypted tunnel — TCP-based (TLS, WSS, gRPC) or UDP-based (KCP, QUIC).
services:
- name: tun
addr: :0
handler:
type: tun
chain: chain-0
metadata:
keepAlive: true
ttl: 10s
listener:
type: tun
metadata:
net: 192.168.123.2/24
route: 192.168.101.0/24
forwarder:
nodes:
- name: target-0
addr: :8421
chains:
- name: chain-0
hops:
- name: hop-0
nodes:
- name: node-0
addr: 1.2.3.4:443
connector:
type: relay
dialer:
type: wss
Using a forwarding chain also allows the server to hide the TUN service port (8421), exposing only the tunnel port (443) for better VPN stealth.