Skip to content
MoliSync
Documentation menu
Documentation Reverse proxy

Reverse proxy & mTLS

MoliSync trusts identity headers only from configured proxy CIDRs. The proxy must verify the client certificate, strip any inbound identity headers and then set fresh values.

Trust order

  1. Terminate TLS and request a client certificate.
  2. Verify the certificate chain and, where applicable, revocation.
  3. Remove inbound X-Client-* headers.
  4. Set the verified result, fingerprint and subject from the proxy's own variables.
  5. Forward WebSocket upgrades and disable request and response buffering.

Nginx example

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_request_buffering off;
proxy_buffering off;

proxy_set_header X-Client-Verify $ssl_client_verify;
proxy_set_header X-Client-DN $ssl_client_s_dn;

# nginx has no SHA-256 variable: $ssl_client_fingerprint is SHA-1 (40 hex) and
# the server rejects it with invalid_client_fingerprint. Forward the whole
# certificate instead and let the server hash it.
proxy_set_header X-Client-Fingerprint "";
proxy_set_header X-Client-Cert $ssl_client_escaped_cert;

Server side: set MOLISYNC_PROXY_CERT_HEADER=X-Client-Cert, and mount the same CA bundle into the container to enable MOLISYNC_PROXY_CLIENT_CA_FILE (optional, strongly recommended: the server then verifies the chain instead of trusting the header).

Note

proxy_set_header X-Client-Fingerprint ""; blanks the digest header. Blanking it without forwarding X-Client-Cert leaves the server with no identity for pinning: P2P falls back to the relay and the client shows "经服务端中继传输".

Proxies that can compute SHA-256 do not need cert_header; Caddy, for example, exposes it as {http.request.tls.client.fingerprint}.

Map the headers

Tell the control plane which header names it should read:

VariableValue in the example
MOLISYNC_PROXY_VERIFY_HEADERX-Client-Verify
MOLISYNC_PROXY_FINGERPRINT_HEADERX-Client-Fingerprint
MOLISYNC_PROXY_CERT_HEADERX-Client-Cert (optional, whole certificate)
MOLISYNC_PROXY_CLIENT_CA_FILECA path (optional, verifies the certificate header)
MOLISYNC_PROXY_DN_HEADERX-Client-DN

Network boundary

Only the proxy and the control plane should join molisync-internal (subnet 172.28.0.0/24 in the example). Keep MOLISYNC_PROXY_TRUSTED_CIDRS as narrow as that network allows.

Caution

Anyone who can reach the service on the trusted network can forge identity headers. Never expose the Go service directly to the public internet, and never let clients join that network.

Checklist

  • Client certificate verification enabled and tested with a trusted certificate.
  • Inbound X-Client-* headers stripped at the edge.
  • MOLISYNC_PROXY_TRUSTED_CIDRS matches only the proxy network.
  • WebSocket upgrade and streaming (no buffering) verified.
  • Health check still points at the real listen port.