Skip to main content

Protect an app you cannot change

The application is a vendor appliance, an unmaintained internal service, or something with a change freeze on it. You cannot add a library, you cannot patch it this quarter, and a CVE has just been published against the stack it runs on.

The answer is to move the security boundary off the application and in front of it.

Terminate, inspect, forward

In proxy mode Synapse sits in the request path: it terminates TLS, applies policy, and forwards to the unchanged application over its existing port. The application needs no modification and does not need to know it is behind anything.

What you gain at that point:

WAFRefuse requests by path, method, header, body or threat score
TLS terminationYour certificates, or SNI passthrough to a backend that holds them
Load balancingWeighted backends and health checks in front of one fragile service
Content scanningInspect selected uploads before they reach the app
Event exportStructured records of what was refused and why

Virtual patching

The practical use of the WAF here is narrow and specific: block the exact request shape that reaches the vulnerability, and leave everything else alone. That buys time until the real fix ships.

http.request.method == "POST" and starts_with(http.request.path, "/admin")

Rules are wirefilter expressions with a documented field list, so the rule you write is checked at load rather than failing open at runtime.

First match wins

Evaluation short-circuits at the first matching rule. An allow placed below a broad block never runs — the block has already decided. Order exceptions above the rules they are meant to escape.

Turning it on

# /etc/synapse/config.yaml
mode: "proxy"

proxy:
address_http: "0.0.0.0:80"
address_tls: "0.0.0.0:443"
upstream:
conf: "/etc/synapse/upstreams.yaml"

Upstreams are a separate hot-reloaded file, so backends change without a restart. The v2 schema and the migration table are in Configuration.

On Kubernetes, the same thing is driven from native Ingress objects instead — see Kubernetes Ingress.

See it happen first

Four of the playground scenarios are exactly this case — XSS Attack, SQL Injection, Path Traversal and CSRF Attack — an unmodified application behind a WAF that refuses the request shape.

Where this stops working

  • Only traffic through the proxy is protected. Anything that reaches the application by another route — a second interface, an internal caller, a management port — bypasses every rule here. Pair it with firewall rules that make the proxy the only path in.
  • A WAF rule is a shape, not a fix. It blocks the exploit you described. A variant that reaches the same bug differently gets through.
  • Terminating TLS means holding certificates. If that is unacceptable, passthrough is available, but then the WAF and content scanning have nothing to read.
  • You have added a hop. Health checks and timeouts now matter; they are configured under proxy.upstream.

See also