UDP over QUIC, when one layer of encryption just isn't enough 😉
  • Go 95.9%
  • Shell 2.8%
  • Makefile 0.7%
  • Batchfile 0.6%
Find a file
Alex Katlein 2b30f09686
All checks were successful
Build / build (push) Successful in 3m9s
Release / release (push) Successful in 1m45s
feat: make max auth retries configurable via environment variable
- introduced `UOQ_CLIENT_AUTH_RETRIES` to override default retry attempts
- added helper function `getAuthRetries` to handle env parsing and fallback
- increased default `MaxAuthRetries` from 3 to 10
2026-05-16 09:54:41 +02:00
.forgejo/workflows chore: removed gosec 2026-05-13 21:36:43 +02:00
init chore: more init files 2026-05-14 09:59:52 +02:00
internal feat: make max auth retries configurable via environment variable 2026-05-16 09:54:41 +02:00
.editorconfig feat: Implemented client and server modes 2026-05-12 22:45:40 +02:00
.gitignore chore: Added actions 2026-05-13 05:53:29 +02:00
.golangci.yml refactor: code quality improvements 2026-05-14 09:31:03 +02:00
.goreleaser.yml refactor: rename main file to uoq.go and update references 2026-05-15 13:35:26 +02:00
go.mod refactor: rename main file to uoq.go and update references 2026-05-15 13:35:26 +02:00
go.sum refactor: replace log with zerolog for structured logging 2026-05-15 13:05:42 +02:00
integration_test.go feat: auto route is now the default behavior, can be disabled by flag 2026-05-15 13:42:47 +02:00
LICENSE feat: Implemented client and server modes 2026-05-12 22:45:40 +02:00
Makefile chore: added caching of Go binaries in workflows 2026-05-13 21:10:38 +02:00
README.md feat: auto route is now the default behavior, can be disabled by flag 2026-05-15 13:42:47 +02:00
uoq.go refactor: rename main file to uoq.go and update references 2026-05-15 13:35:26 +02:00

uoq

uoq (UDP over QUIC, pronounced OOCK) is a simple proxy that tunnels UDP packets through QUIC datagrams. It's designed to help bypass restrictive firewalls or multiplex UDP-based services on a single port (e.g., 443) using QUIC SNI.

Installation

go install codeberg.org/vemilyus/uoq@latest

Usage

Server

The server listens for QUIC connections and forwards received datagrams to a target UDP address.

# Using self-signed certificates
uoq server -l 4433 -r 127.0.0.1:8080 --insecure

# Using your own certificates
uoq server -l 4433 -r 127.0.0.1:8080 --cert cert.pem --key key.pem

Client

The client listens for local UDP packets and forwards them to a uoq server via QUIC.

Note

To enable SNI (Server Name Indication), use the domain name of the remote host instead of its IP address in the -r flag.

uoq client -l 8080 -r server.example.com:443

Use --insecure with the client if the server uses a self-signed certificate.

Routing for VPNs (e.g., WireGuard)

On Linux, macOS, and Windows, a specific route to the remote server via your default gateway is added automatically. This ensures that the QUIC packets sent by the uoq client to the remote server are not routed back into the VPN tunnel. You can disable this behavior with the --no-auto-route flag.

On other systems, or if you prefer a manual setup, you should add a permanent route to the remote host:

# Example (Linux/macOS)
ip route add server.example.com via <default-gateway>

Advanced Use Case: Caddy + layer4

You can use uoq behind Caddy with the layer4 module to multiplex QUIC traffic on port 443. This allows you to run uoq alongside a web server on the same port by routing based on the Server Name Indication (SNI).

exec also requires the exec module.

{
    events {
        on cert_obtained exec pkill -HUP uoq
        
        # Example reload commands for other init systems:
        # systemd: exec systemctl reload uoq-server
        # OpenRC:  exec rc-service uoq-server reload
        # FreeBSD: exec service uoq_server reload
        # launchd: exec launchctl kill HUP system/com.uoq.server
        # Windows: exec nssm restart uoq-server
    }

    layer4 {
        # Listen on UDP 443
        udp/:443 {
            @uoq quic sni uoq.example.com
            route @uoq {
                proxy udp/127.0.0.1:4433
            }
        }
    }
}

uoq.example.com {
# to have Caddy handle the certificate (ACME, etc...)
}

example.com {
# reverse proxy to something else
}

In this setup, Caddy handles the UDP/443 listener and routes traffic for uoq.example.com to the uoq server listening on 127.0.0.1:4433. The uoq server then handles the QUIC connection and forwards the datagrams to the final target. The events block ensures that whenever Caddy obtains or renews a certificate, it signals all uoq processes with SIGHUP to reload their certificates. Caddy can also handle other services (like standard HTTPS) on the same port by matching different SNIs or protocols.

Features

  • High performance via QUIC datagrams.
  • Authentication via pre-shared secret.
  • Automatic certificate reloading.
  • Minimal overhead.

Init Systems

Configuration files for various init systems (systemd, OpenRC, FreeBSD rc, launchd, and Windows NSSM) can be found in the init directory.

License

BSD 3-Clause License. See LICENSE for details.