sh0rch/packetveil

eBPF WireGuard Traffic Obfuscator (QUIC, SIP, SYSLOG, RANDOM)

Rust

94

256 commits

updated Jul 5, 2026

See the code

README

gutd v3 — WireGuard Traffic Obfuscator (TC/XDP eBPF)

CI Release

Benchmark: gutd vs wg-obfuscator

ToolTCP BandwidthUDP BandwidthUDP Loss
gutd (eBPF) (v3.0.16)865 Mbits/sec776 Mbits/sec0.26%
gutd (Userspace) (v3.0.16)621 Mbits/sec451 Mbits/sec52%
wg-obfuscator (v1.5)244 Mbits/sec165 Mbits/sec85%
* Performance measured using iperf3 between 2 isolated network namespaces on GitHub Actions Ubuntu 22.04 runners. See test logic and full logs. Last updated: 2026-07-03 08:23

gutd v3 transparently obfuscates WireGuard UDP traffic using a Linux TC/XDP eBPF datapath. On egress the TC BPF program wraps each WireGuard packet in a chosen obfuscation envelope, masks the payload with a ChaCha keystream and optionally pads it. On ingress the XDP program validates, strips the envelope and restores the original packet before WireGuard sees it. WireGuard is completely unaware of gutd. A pure userspace mode (wire-compatible with the eBPF path) is available for older kernels, unprivileged containers, MikroTik RouterOS, and Windows.

Obfuscation Modes

Modeobfs=Wire appearanceAnti-probingPorts
QUIC (default)quicFake QUIC Long Header + SNI (looks like HTTPS/3)XDP replies with QUIC Version Negotiationany UDP
GUTgutGOST-like random UDP — no QUIC/TLS signaturessilent dropany UDP
SIP/RTPsipSignaling packets wrapped in SIP headers; data in RTP framesXDP replies with 200 OK / 401 / 403ports[0] = SIP (5060), ports[1+] = RTP (≥ 2 required)
SyslogsyslogPayload base64-encoded inside a fake syslog messagesilent dropany UDP (514 typical)

All modes apply ChaCha payload masking on top of the envelope. Both peers must use the same mode.

Features

  • Four obfuscation modes: QUIC, GUT (GOST-like random UDP), SIP/RTP, Syslog — selectable per peer
  • Active DPI probe deflection at XDP layer (QUIC: Version Negotiation; SIP: 200 OK/401/403)
  • WireGuard payload masking with ChaCha (4 rounds by default)
  • TC egress hook on a veth pair, XDP ingress hook on the physical NIC
  • Port striping: multiple UDP ports per peer with per-packet rotation
  • Keepalive probabilistic drop to suppress WireGuard timing fingerprints
  • Variable padding to obscure packet sizes
  • Hot reload via SIGHUP (BPF map update, no restart)
  • Pure userspace fallback mode (zero eBPF requirements, ~500 Mbps capable)
  • Cross-platform: Linux (eBPF + userspace), Windows (userspace), RouterOS (userspace)
  • Multi-peer support (one veth pair + BPF program per peer)
  • Static musl build, zero OS dependencies — runs in empty scratch containers
  • IPv4 and IPv6 outer transport
  • Dynamic peer endpoint learning for clients behind NAT (peer_ip = dynamic)
  • Stats via gutd status or SIGUSR1 signal

Quick Start

Generate a shared key and create a minimal config on both peers:

gutd genkey          # → prints 256-bit hex key
# /etc/gutd/gutd.conf  (Linux)
# C:\ProgramData\gutd\gutd.conf  (Windows)
[peer]
peer_ip    = 203.0.113.10    # remote peer public IP
ports      = 41000
key        = <output of gutd genkey>
# obfs = quic               # quic (default) | gut | sip | syslog

MTU note: The obfuscation envelope adds overhead on top of the WireGuard packet. Set your WireGuard interface MTU accordingly (see MTU reference below):

ModeOverheadRecommended WG MTU
quic16 bytes1420 (default)
gut10 bytes1420
sip22 bytes (RTP+GUT)1400
syslogbase64 expansion800

Running

# eBPF mode (default on Linux, requires root and kernel ≥ 5.17)
sudo ./gutd /etc/gutd/gutd.conf

# Pure userspace mode (Linux — no eBPF, no root with capabilities)
GUTD_USERSPACE=1 ./gutd /etc/gutd/gutd.conf

# Windows (always userspace, run as Administrator for install)
gutd.exe gutd.conf

# Reload config without restart (Linux)
sudo kill -HUP $(pgrep gutd)

Build

# Linux (default, with eBPF)
cargo build --release

# Linux static musl binary
./build-musl.sh

# Windows (userspace only, cross-compile from Linux)
cargo build --release --target x86_64-pc-windows-gnu --no-default-features

See BUILD.md for cross-compilation and musl details.

MTU Reference

Each obfuscation mode adds a different amount of overhead to every WireGuard packet. You must set the WireGuard interface MTU lower than the default 1420 for modes that add more than 16 bytes, otherwise oversized frames will be silently dropped by the network link.

ModeHeader added by gutdMax safe WG MTU*
quic16 bytes (QUIC short header)1420
gut10 bytes (GUT header)1420
sip22 bytes (RTP 12 + GUT 10)1400
syslogbase64 expansion (~4/3×)800

* For a 1500-byte outer link MTU (standard Ethernet). Adjust proportionally for PPPoE (1492) or other links.

SIP special requirement: sip mode requires at least 2 portsports[0] carries SIP signaling packets and ports[1+] carry RTP data frames. gutd will refuse to start with fewer than 2 ports in SIP mode.

Kernel Compatibility (eBPF mode)

gutd eBPF programs use bpf_loop (kernel ≥ 5.17) and noinline BPF subprograms. The BPF verifier complexity budget (processed insns) varies significantly across kernel versions due to verifier improvements in state pruning and precision tracking.

KernelQUICGUTSyslogSIPNotes
≥ 6.1Fully tested; 6.1 uses -mcpu=v3 + verifier-safe clamps
5.17 – 6.0⚠️⚠️⚠️Only GUT mode is reliable
< 5.17No bpf_loop; use userspace mode

⚠️ = may fail to load depending on kernel config and compiler optimization. Use GUTD_USERSPACE=1 as a fallback on older kernels.

# Correct SIP config example
[peer]
obfs  = sip
ports = 5060, 10000, 10001   # [0]=signaling  [1+]=RTP
mtu   = 1400
sni   = sip.example.com
key   = <shared key>

Documentation

DocumentDescription
doc/configuration.mdFull config reference, obfs modes, MTU tuning
doc/running.mdAll running modes: basic, P2P, RouterOS, relay
doc/architecture.mdEgress/ingress datapath, userspace daemon, security
doc/testing.mdUnit and integration tests
doc/troubleshooting.mdTroubleshooting, firewall notes
BUILD.mdBuild instructions
METRICS.mdStats counters

License

Dual-licensed: userspace code under MIT, eBPF/kernel code under GPL-2.0-only. See LICENSE.

docker-scratch
dpi-bypass
ebpf
http3
linux
mikrotik-container
obfs
obfuscation
openwrt
quic
random-noise
rust
systemd
wg-obfs
wgobfs
wg-obfuscator
windows
wireguard

Contributors

sh0rch

216 commits

jason-sirius

1 commits

sh0rch/packetveil

eBPF WireGuard Traffic Obfuscator (QUIC, SIP, SYSLOG, RANDOM)

Rust

94

256 commits

updated Jul 5, 2026

See the code

README

gutd v3 — WireGuard Traffic Obfuscator (TC/XDP eBPF)

CI Release

Benchmark: gutd vs wg-obfuscator

ToolTCP BandwidthUDP BandwidthUDP Loss
gutd (eBPF) (v3.0.16)865 Mbits/sec776 Mbits/sec0.26%
gutd (Userspace) (v3.0.16)621 Mbits/sec451 Mbits/sec52%
wg-obfuscator (v1.5)244 Mbits/sec165 Mbits/sec85%
* Performance measured using iperf3 between 2 isolated network namespaces on GitHub Actions Ubuntu 22.04 runners. See test logic and full logs. Last updated: 2026-07-03 08:23

gutd v3 transparently obfuscates WireGuard UDP traffic using a Linux TC/XDP eBPF datapath. On egress the TC BPF program wraps each WireGuard packet in a chosen obfuscation envelope, masks the payload with a ChaCha keystream and optionally pads it. On ingress the XDP program validates, strips the envelope and restores the original packet before WireGuard sees it. WireGuard is completely unaware of gutd. A pure userspace mode (wire-compatible with the eBPF path) is available for older kernels, unprivileged containers, MikroTik RouterOS, and Windows.

Obfuscation Modes

Modeobfs=Wire appearanceAnti-probingPorts
QUIC (default)quicFake QUIC Long Header + SNI (looks like HTTPS/3)XDP replies with QUIC Version Negotiationany UDP
GUTgutGOST-like random UDP — no QUIC/TLS signaturessilent dropany UDP
SIP/RTPsipSignaling packets wrapped in SIP headers; data in RTP framesXDP replies with 200 OK / 401 / 403ports[0] = SIP (5060), ports[1+] = RTP (≥ 2 required)
SyslogsyslogPayload base64-encoded inside a fake syslog messagesilent dropany UDP (514 typical)

All modes apply ChaCha payload masking on top of the envelope. Both peers must use the same mode.

Features

  • Four obfuscation modes: QUIC, GUT (GOST-like random UDP), SIP/RTP, Syslog — selectable per peer
  • Active DPI probe deflection at XDP layer (QUIC: Version Negotiation; SIP: 200 OK/401/403)
  • WireGuard payload masking with ChaCha (4 rounds by default)
  • TC egress hook on a veth pair, XDP ingress hook on the physical NIC
  • Port striping: multiple UDP ports per peer with per-packet rotation
  • Keepalive probabilistic drop to suppress WireGuard timing fingerprints
  • Variable padding to obscure packet sizes
  • Hot reload via SIGHUP (BPF map update, no restart)
  • Pure userspace fallback mode (zero eBPF requirements, ~500 Mbps capable)
  • Cross-platform: Linux (eBPF + userspace), Windows (userspace), RouterOS (userspace)
  • Multi-peer support (one veth pair + BPF program per peer)
  • Static musl build, zero OS dependencies — runs in empty scratch containers
  • IPv4 and IPv6 outer transport
  • Dynamic peer endpoint learning for clients behind NAT (peer_ip = dynamic)
  • Stats via gutd status or SIGUSR1 signal

Quick Start

Generate a shared key and create a minimal config on both peers:

gutd genkey          # → prints 256-bit hex key
# /etc/gutd/gutd.conf  (Linux)
# C:\ProgramData\gutd\gutd.conf  (Windows)
[peer]
peer_ip    = 203.0.113.10    # remote peer public IP
ports      = 41000
key        = <output of gutd genkey>
# obfs = quic               # quic (default) | gut | sip | syslog

MTU note: The obfuscation envelope adds overhead on top of the WireGuard packet. Set your WireGuard interface MTU accordingly (see MTU reference below):

ModeOverheadRecommended WG MTU
quic16 bytes1420 (default)
gut10 bytes1420
sip22 bytes (RTP+GUT)1400
syslogbase64 expansion800

Running

# eBPF mode (default on Linux, requires root and kernel ≥ 5.17)
sudo ./gutd /etc/gutd/gutd.conf

# Pure userspace mode (Linux — no eBPF, no root with capabilities)
GUTD_USERSPACE=1 ./gutd /etc/gutd/gutd.conf

# Windows (always userspace, run as Administrator for install)
gutd.exe gutd.conf

# Reload config without restart (Linux)
sudo kill -HUP $(pgrep gutd)

Build

# Linux (default, with eBPF)
cargo build --release

# Linux static musl binary
./build-musl.sh

# Windows (userspace only, cross-compile from Linux)
cargo build --release --target x86_64-pc-windows-gnu --no-default-features

See BUILD.md for cross-compilation and musl details.

MTU Reference

Each obfuscation mode adds a different amount of overhead to every WireGuard packet. You must set the WireGuard interface MTU lower than the default 1420 for modes that add more than 16 bytes, otherwise oversized frames will be silently dropped by the network link.

ModeHeader added by gutdMax safe WG MTU*
quic16 bytes (QUIC short header)1420
gut10 bytes (GUT header)1420
sip22 bytes (RTP 12 + GUT 10)1400
syslogbase64 expansion (~4/3×)800

* For a 1500-byte outer link MTU (standard Ethernet). Adjust proportionally for PPPoE (1492) or other links.

SIP special requirement: sip mode requires at least 2 portsports[0] carries SIP signaling packets and ports[1+] carry RTP data frames. gutd will refuse to start with fewer than 2 ports in SIP mode.

Kernel Compatibility (eBPF mode)

gutd eBPF programs use bpf_loop (kernel ≥ 5.17) and noinline BPF subprograms. The BPF verifier complexity budget (processed insns) varies significantly across kernel versions due to verifier improvements in state pruning and precision tracking.

KernelQUICGUTSyslogSIPNotes
≥ 6.1Fully tested; 6.1 uses -mcpu=v3 + verifier-safe clamps
5.17 – 6.0⚠️⚠️⚠️Only GUT mode is reliable
< 5.17No bpf_loop; use userspace mode

⚠️ = may fail to load depending on kernel config and compiler optimization. Use GUTD_USERSPACE=1 as a fallback on older kernels.

# Correct SIP config example
[peer]
obfs  = sip
ports = 5060, 10000, 10001   # [0]=signaling  [1+]=RTP
mtu   = 1400
sni   = sip.example.com
key   = <shared key>

Documentation

DocumentDescription
doc/configuration.mdFull config reference, obfs modes, MTU tuning
doc/running.mdAll running modes: basic, P2P, RouterOS, relay
doc/architecture.mdEgress/ingress datapath, userspace daemon, security
doc/testing.mdUnit and integration tests
doc/troubleshooting.mdTroubleshooting, firewall notes
BUILD.mdBuild instructions
METRICS.mdStats counters

License

Dual-licensed: userspace code under MIT, eBPF/kernel code under GPL-2.0-only. See LICENSE.

docker-scratch
dpi-bypass
ebpf
http3
linux
mikrotik-container
obfs
obfuscation
openwrt
quic
random-noise
rust
systemd
wg-obfs
wgobfs
wg-obfuscator
windows
wireguard

Contributors

sh0rch

216 commits

jason-sirius

1 commits

Languages

Rust

52.9%

C

23.0%

Shell

20.8%

Python

2.0%

Makefile

1.1%