Skip to content
ProxerProxerv0.13.0

Routing and Trusted Proxies

Host routing, root routes, subdomain routes, and forwarded headers.

Proxer routes by host. That sounds ordinary, but it is the main thing to get right when a tunnel sits behind DNS, TLS, and a reverse proxy.

Start the server with the public root domain:

proxer server --listen 0.0.0.0:8080 --domain proxy.example.com --token dev-token

A client without --subdomain gets a server-assigned random subdomain:

proxer http 3000 --server wss://proxy.example.com --token dev-token

The client prints the assigned public URL, such as https://px-k7m3q9t2ab.proxy.example.com. Reconnects during the same run keep using that assigned subdomain.

Use --subdomain @ when you intentionally want the root route:

proxer http 3000 --server wss://proxy.example.com --subdomain @ --token dev-token

Requests for proxy.example.com go to that root-route client. Root routing is intended for servers started with --domain; without one, Proxer derives routes from the first host label.

A client with --subdomain demo registers demo.proxy.example.com:

proxer http 3000 --server wss://proxy.example.com --subdomain demo --token dev-token

Requests for unknown hosts return 404. Direct localhost or IP-based requests are not automatically routed to a connected client.

Without DNS, send the host header yourself:

curl -H 'Host: demo.proxy.example.com' http://127.0.0.1:8080/

If the host header is wrong, Proxer cannot know which tunnel you meant.

For an internet-facing server, it is normal to terminate TLS in Caddy, Traefik, NGINX, a load balancer, or another reverse proxy. Forward HTTP and WebSocket traffic from that proxy to Proxer over loopback or a private network.

Keep the original host. For Traefik, that usually means leaving passHostHeader enabled.

Then tell Proxer which TCP peers may provide forwarded headers:

proxer server \
--listen 0.0.0.0:8080 \
--domain proxy.example.com \
--trusted-proxy loopback \
--trusted-proxy private \
--token "$PROXER_TOKEN"

Environment variable form:

PROXER_TRUSTED_PROXIES=loopback,private,10.42.0.0/16 proxer server --domain proxy.example.com

Trusted proxy values can be loopback, private, an IP literal, or a CIDR range.

When a peer is trusted, Proxer may use X-Forwarded-For, X-Real-IP, X-Forwarded-Host, and X-Forwarded-Proto from that peer. Your reverse proxy must overwrite or strip inbound X-Forwarded-* and X-Real-IP headers from external clients before forwarding. Do not trust proxy addresses you do not control.

Without trusted proxies, Proxer ignores forwarded host, protocol, and client-IP headers for routing decisions.

For public deployments, set --domain. Without it, Proxer derives a subdomain route from the first label of the request host. That can be useful for local experiments, but it is easy to surprise yourself once real DNS and reverse proxies are involved.

All internal endpoints live under /__proxer__/:

/__proxer__/control
/__proxer__/health/live
/__proxer__/health/ready

Do not route those paths to your app. The public Proxer server handles them before application routing.