Pure userspace WireGuard server
801
Pure userspace WireGuard server skeleton using wireguard-go plus gVisor-backed netstack, designed for container/cloud deployment where host TUN is unavailable.
This starter now focuses on a single transparent data path.
TCP and UDP are handled by the gVisor netstack and forwarded upstream through transparent proxy connections based on the original destination address and port.
ICMP is handled separately in the transparent NAT wrapper. Local echo requests to the server IP are answered locally, and remote ICMP echo traffic is relayed with PMTU-aware error handling.
IPv6 is enabled only when WG_IPS contains IPv6 CIDRs. To disable IPv6, remove IPv6 prefixes from WG_IPS.
cmd/wguserspace: application entrypoint.internal/config: env parsing and validation.internal/wg: WireGuard userspace device and IPC config generation.internal/forwarder: TCP/UDP transparent forwarding.internal/transparentnat: ICMP relay, local echo handling, and packet rewriting.deployments/docker: Dockerfile and compose setup.WG_PRIVATE_KEY: base64 WireGuard private key (required).WG_LISTEN_PORT: UDP listen port (default 51820).WG_MTU: interface MTU (default 1420).WG_IPS: comma-separated CIDRs assigned to server tunnel stack (required).
10.66.0.1/24,fd66::1/64WG_DNS: optional comma-separated DNS IPs for tunnel resolver behavior.WG_DEFAULT_KEEPALIVE_SEC: peer keepalive default (default 25).WG_PEERS_JSON: JSON array of peers:[
{
"public_key": "<client base64 public key>",
"preshared_key": "<optional base64 psk>",
"allowed_ips": ["10.66.0.2/32"],
"persistent_keepalive_sec": 25
}
]
WG_LOG_LEVEL: WireGuard device log level, one of silent, error, or verbose (default silent).OUTBOUND_DIAL_TIMEOUT: upstream dial timeout (default 10s).UDP_SESSION_TIMEOUT: UDP session idle expiration window (default 30s).UDP_IDLE_IO_TIMEOUT: UDP socket read/write deadline while session is active (default 3s).LOG_PACKET_SOURCES: logs observed TCP/UDP/ICMP source addresses at forwarder ingress for troubleshooting (default false).LOG_ICMP_TRACE: enables verbose ICMP relay and PMTU trace logging (default false).go build ./cmd/wguserspace
export WG_PRIVATE_KEY="..."
export WG_IPS="10.66.0.1/24,fd66::1/64"
export WG_PEERS_JSON='[{"public_key":"...","allowed_ips":["10.66.0.2/32"]}]'
go run ./cmd/wguserspace
The binary automatically loads .env from the current working directory if it exists.
This makes sudo ./wguserspace work without manually sourcing environment variables first.
cp .env.example .env
docker compose -f deployments/docker/compose.yaml up --build
Use a normal WireGuard client profile:
PublicKey = server public key derived from WG_PRIVATE_KEY.Endpoint = <server-ip>:<WG_LISTEN_PORT>.AllowedIPs = tunnel IP ranges (IPv4 and/or IPv6).PresharedKey optional if configured in server peer JSON.The handshake and cryptography remain standard WireGuard behavior via wireguard-go.
If you want IPv4-only operation, remove IPv6 CIDRs from WG_IPS. The server will then avoid configuring IPv6 in the netstack and transparent forwarding layers.
Content type
Image
Digest
sha256:1d978df84…
Size
2.6 MB
Last updated
5 months ago
docker pull devontm/wg-userspace