Skip to content

mrsobakin/wgmux

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WireGuard port multiplexer

wgmux is an eBPF-based hub reflector for WireGuard traffic. It allows two unmodified WireGuard clients behind NAT to establish an e2ee connection, without hub having to decrypt their packets.

Why?

In a typical WireGuard hub-and-spoke configuration, peers communicate through the hub like this:

  1. Alice wants to send a packet to Bob.
  2. Alice encrypts a packet and sends it via Hub.
  3. The Hub decrypts the packet to read the destination and make a routing decision.
  4. The Hub re-encrypts the packet for Bob and forwards it.
  5. Bob receives the packet from Hub and decrypts it.

In this configuration, the hub sees plaintext traffic -- it can snoop on packets and impersonate peers. If the hub gets compromised, so does all communication between peers.

In an ideal world, peers would communicate with each other directly, bypassing the hub entirely. In practice however, due to NAT, that is rarely possible without setting up complex configurations.

wgmux takes a different approach. It assigns each peer a dedicated port on the hub, and routes packets based on port and WireGuard indices, without having to decrypt them at all. This allows true e2ee between peers, even if they don't have a dedicated endpoint.

If you want to know protocol-level details and how it works under the hood, see spec.

Build

make build

The resulting binary is placed in bin/wgmux. It's statically linked, so you can copy it to the target server.

Installation

make build
sudo make install

This installs binary, systemd service and example config.

Edit /etc/wgmux/config.toml with your settings, then start systemd service:

sudo systemctl enable --now wgmux

Usage

Show current sessions and known peers:

wgmux show

Configuration

[Interface]
# WireGuard interface name used for peer endpoint discovery.
Device = "wg0"

# Hub's main WireGuard UDP port (hub wg listen port).
HubPort = 51820

# Network interface where eBPF should be attached (ingress).
Interface = "eth0"

# Optional WireGuard utility binary. Specify "awg" if you use AmneziaWG.
# WgUtil = "wg"

# Optional AmneziaWG compatibility fields.
# S1 = 0
# S2 = 0
# H1 = 1
# H2 = 2
# H3 = 3
# H4 = 4

# WireGuard peers that you want to expose as responders.
[[Peer]]
# Dedicated hub port that initiators use to reach this responder.
Port = 10001

# Responder's WireGuard public key.
PublicKey = "ResponderPublicKey/p+75Ymh5EnfDdKAFp1Ibamjo="

In config terms, an initiator is the side that actively dials through hub by setting responder's peer endpoint to Endpoint=<hub-ip>:<peer-port>.

<peer-port> is the [[Peer]].Port on hub that points to responder's public key. The responder side stays a normal WireGuard peer and replies from whatever endpoint it currently has.

Example WireGuard config on initiator:

[Interface]
PrivateKey = InitiatorPrivateKey/ufgqjNjpUVxI0+I7Dj9xG2c=
Address = 10.0.0.101/32

# We still need to connect to the hub, even if we won't send anything to it.
[Peer]
PublicKey = HubPublicKey/NCS1KtF59AnDCLKSm9tpzzB3fGFtmo=
AllowedIPs = 10.0.0.1/32
Endpoint = vpn.mydomain.com:51820
PersistentKeepalive = 25

[Peer]
PublicKey = ResponderPublicKey/p+75Ymh5EnfDdKAFp1Ibamjo=
AllowedIPs = 10.0.0.102/32
# We are the initiator in this peer pair, so we should set the responder's endpoint to its peer-port.
Endpoint = vpn.mydomain.com:10001

Example WireGuard config on responder:

[Interface]
PrivateKey = ResponderPrivateKey/hSu9lN70p8LIzp0Us5md3GQ=
Address = 10.0.0.102/32

[Peer]
PublicKey = HubPublicKey/NCS1KtF59AnDCLKSm9tpzzB3fGFtmo=
AllowedIPs = 10.0.0.1/32
Endpoint = vpn.mydomain.com:51820
PersistentKeepalive = 25

[Peer]
PublicKey = InitiatorPublicKey/dBkTycIFY6ZKYMFRoP9qtIGo=
AllowedIPs = 10.0.0.101/32
# No hub peer-port endpoint here for this pair.
# Responder receives reflected packets from hub and replies normally.

For each peer pair, ONLY ONE side should be configured as initiator. Do not set both peers to initiate toward each other via hub peer ports. See spec for explanation why.

About

🐿 WireGuard port multiplexer (compatible with AmneziaWG)

Topics

Resources

License

Stars

Watchers

Forks

Contributors