Skip to content

refactor: generalize and harden masquerade reverse proxy - #1669

Open
giveup wants to merge 2 commits into
HyNetworks:masterfrom
giveup:codex/masquerade-proxy-refactor
Open

refactor: generalize and harden masquerade reverse proxy#1669
giveup wants to merge 2 commits into
HyNetworks:masterfrom
giveup:codex/masquerade-proxy-refactor

Conversation

@giveup

@giveup giveup commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Refactor masquerade.proxy into a reusable, production-ready single-upstream reverse proxy and improve the HTTP behavior of the masquerade server.

Motivation

The masquerade proxy should behave like a normal Go web application backed by quic-go, rather than trying to imitate a specific server implementation.

Unauthenticated requests should be handled entirely by the configured backend, while authenticated Hysteria requests continue to use the existing proxy protocol. The reverse proxy therefore needs reliable support for common HTTP application behavior such as streaming responses, request streaming, WebSocket upgrades, trailers, cancellation, connection reuse, and graceful shutdown.

What's New

  • Move the reusable reverse proxy implementation into extras/masq.
  • Preserve existing HTTP, HTTPS, Unix socket, rewriteHost, xForwarded, path, query, and error-handling behavior.
  • Preserve streaming behavior through the TCP masquerade response writer:
    • SSE over HTTP/1.1 and HTTP/2
    • Explicit response flushing
    • Streaming request bodies
    • Client cancellation
  • Preserve common HTTP proxy behavior:
    • WebSocket upgrades
    • Response trailers
    • HEAD requests
    • Range requests
    • Informational responses
  • Add an optional masquerade.proxy.flushInterval setting.
    • The default value is unchanged.
    • A negative duration flushes after every response write.
  • Strip Hysteria authentication and congestion-control headers before forwarding requests to the backend.
  • Remove upstream Alt-Svc headers so the backend cannot advertise an incorrect or private endpoint.
  • Add masquerade.advertisedQUICPort for deployments where the public QUIC port differs from the local UDP listener port.
    • When omitted, the existing behavior is preserved and the UDP listener port is advertised.
  • Correct HTTP-to-HTTPS redirects for custom ports and IPv6 hosts.
  • Reduce the authentication mutex scope so a failed authentication request can stream from the backend without blocking later authentication attempts.
  • Integrate masquerade HTTP/HTTPS servers into the main server lifecycle:
    • Stop accepting new requests during shutdown.
    • Allow in-flight requests up to 10 seconds to complete.
    • Force-close remaining connections after the grace period.
    • Close idle upstream connections after listener shutdown.
  • Keep the proxy focused on a single upstream. This does not add routing, load balancing, health checks, upstream h2c, or additional TLS configuration.

Example

masquerade:
  type: proxy
  proxy:
    url: http://127.0.0.1:8080
    rewriteHost: false
    xForwarded: true
    flushInterval: -1ms
  listenHTTP: :80
  listenHTTPS: :443
  forceHTTPS: true
  advertisedQUICPort: 8443

advertisedQUICPort is only needed when the public QUIC port differs from the local UDP listener port:

listen: :443

masquerade:
  type: proxy
  proxy:
    url: unix:///run/backend.sock
  listenHTTPS: :443
  advertisedQUICPort: 8443

If advertisedQUICPort is omitted, the port from listen is used.

Tests

  • python3 hyperbole.py format
  • python3 hyperbole.py tidy
  • python3 hyperbole.py test core
  • cd extras && go test ./masq
  • cd app && go test ./cmd
  • cd core && go test -race ./server
  • cd extras && go test -race ./masq
  • cd app && go test -race ./cmd
  • cd core && go vet ./server
  • cd extras && go vet ./masq
  • cd app && go vet ./cmd

giveup and others added 2 commits August 24, 2026 15:39
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant