π Simple WireGuard proxy with minimal overhead for WireGuard traffic.
- Encrypts the first 16 bytes as an AES block.
- Adds padding of random length to handshake packets, then encrypts all bytes after the first 16 using XChaCha20-Poly1305.
- β Does not affect tunnel MTU.
- β Minimal processing of data packets.
Packets are padded to the maximum packet size allowed by the MTU, then encrypted using XChaCha20-Poly1305.
- β Full-packet AEAD.
- β
Hides in-tunnel packet sizes.
- The length of a WireGuard data packet is always a multiple of 16.
- Many IPv6 websites cap their outgoing MTU to 1280 for maximum compatibility.
- βοΈ Slight reduction of tunnel MTU.
- βοΈ Increased bandwidth usage.
Release and VCS packages are available in the AUR:
Download from releases.
There are container images maintained by the community:
Build and install the latest version using Go:
go install github.com/database64128/swgp-go/cmd/swgp-go@latestOr clone the repository and build it manually:
go build -trimpath -ldflags '-s -w' ./cmd/swgp-goAll configuration examples and systemd unit files can be found in the docs directory.
swgp-go uses the same PSK format as WireGuard. A base64-encoded PSK can be generated using wg genpsk or openssl rand -base64 32 for use with "proxyPSK". Alternatively, specify a separate PSK file with "proxyPSKFilePath", which can be generated using openssl rand -out psk_file 32.
Make sure to use the right MTU for both server and client. To encourage correct use, by default, swgp-go disables IP fragmentation and drops packets that are bigger than expected. If your network does not work well with this, set "pathMTUDiscovery" to one of the modes below.
| Mode | Behavior | Linux | Windows | macOS | FreeBSD | Other OSes |
|---|---|---|---|---|---|---|
"default" |
App default (equivalent to "do"). |
- | - | - | - | - |
"system" |
System default (usually allows fragmentation; WireGuard uses this). | - | - | - | - | - |
"dont" |
Disable PMTUD and allow fragmentation. | β | β | β | β | β |
"do" |
Enable PMTUD and drop packets that exceed MTU. | β | β | β | β | β |
"probe" |
Like "do", but permit packets above probed MTU. |
β | β | β | β | β |
"want" |
Linux IP_PMTUDISC_WANT behavior. | β | β | β | β | β |
"interface" |
Use interface MTU; no local fragmentation. | β | β | β | β | β |
"omit" |
Like "interface", but permits fragmentation if needed. |
β | β | β | β | β |
Legend: β = supported, β = ignored.
In this example, swgp-go runs a proxy server instance on port 20220. Decrypted WireGuard packets are forwarded to [::1]:20221.
{
"servers": [
{
"name": "server",
"proxyListen": ":20220",
"proxyMode": "zero-overhead",
"proxyPSK": "sAe5RvzLJ3Q0Ll88QRM1N01dYk83Q4y0rXMP1i4rDmI=",
"proxyFwmark": 0,
"wgEndpoint": "[::1]:20221",
"wgFwmark": 0,
"mtu": 1500
}
]
}In this example, swgp-go runs a proxy client instance on port 20222. Encrypted proxy packets are sent to the proxy server at [2001:db8:1f74:3c86:aef9:a75:5d2a:425e]:20220.
{
"clients": [
{
"name": "client",
"wgListen": ":20222",
"wgFwmark": 0,
"proxyEndpoint": "[2001:db8:1f74:3c86:aef9:a75:5d2a:425e]:20220",
"proxyMode": "zero-overhead",
"proxyPSK": "sAe5RvzLJ3Q0Ll88QRM1N01dYk83Q4y0rXMP1i4rDmI=",
"proxyFwmark": 0,
"mtu": 1500
}
]
}If you configure your WireGuard tunnel to be the default network interface for internet access, it is important that traffic from swgp-go is not routed back into the tunnel, which would cause a routing loop. Depending on your operating system and network configuration, there are a few options:
"proxyFwmark": Set to the samefwmarkin your WireGuard configuration. Most reliable, but only available on Linux and FreeBSD."proxyAutoPickInterface": true: Automagically selects a physical egress interface. Should just work on common macOS1 and Windows2 setups."proxyConnListenAddress": Works everywhere, but requires hardcoding the egress address to bind the proxy socket to.
Footnotes
-
Theoretically also works on DragonFly BSD, FreeBSD, NetBSD, and OpenBSD, but not tested. β©
-
Depending on your Windows version and network configuration,
IPV6_PKTINFOmay be ignored by the OS, which can result in a routing loop. WireGuard itself is also affected by this Windows quirk. Consider setting"proxyConnListenAddress", or use WireGuard's pre-up/post-down scripts to add/remove static routes for the proxy server. β©