This commit is contained in:
Mateusz Gruszczyński committed 2026-10-21 14:39:51 +02:00
1 parent e037190c14
commit 5cb3b37627
37 files changed
+1031 -138

No files matched your search

+5 -1
View File
@@ -13,7 +13,11 @@ Access control can be configured globally, on a Vhost and on selected Custom loc
Default deny plus explicit allow exceptions is usually safer for private admin applications. Apply rules to a staging client before enforcing them on a live business-critical service.
In the **Vhost → Security** editor, Traffic policy groups reusable ACL profiles and the separate **inline Vhost IP/CIDR access list** together, followed by HTTP methods, per-IP rates, country policy, country-rate and User-Agent-rate controls. The inline list is not a second version of an assigned profile: both layers remain independently enforced; an allow in one does not cancel a deny in the other. The **Vhost → Authentication** tab is for Basic Auth and Tinyauth only. HSTS, security headers and User-Agent blocking are separate Security groups. **Custom locations → Access** separates its ACL profile, HTTP method, country and inline IP/CIDR fields. These are only layout changes; restriction scopes still combine as described above.
In the **Vhost → Security** editor, Traffic policy groups reusable ACL profiles and the separate **inline Vhost IP/CIDR access list** together, followed by HTTP methods, request Content-Type filtering, per-IP rates, country policy, country-rate and User-Agent-rate controls. The inline list is not a second version of an assigned profile: both layers remain independently enforced; an allow in one does not cancel a deny in the other. The **Vhost → Authentication** tab is for Basic Auth and Tinyauth only. HSTS, security headers and User-Agent blocking are separate Security groups. **Custom locations → Access** separates its ACL profile, HTTP method, country and inline IP/CIDR fields. These are only layout changes; restriction scopes still combine as described above.
## Content-Type request denylist
Ordinary Vhosts can reject selected MIME types under **Vhosts → Security → Request Content-Type**. With the option enabled, an exact media type such as `multipart/form-data` (including parameters) or a family such as `application/*` is rejected with **403** before proxy/Web Server/PHP routing or cache handling. Multiple entries are supported; missing `Content-Type` is not rejected. Ambiguous/malformed headers are denied when filtering is enabled. Docker vhost controls do not expose this setting. See [Vhosts](VHOSTS.md#block-request-content-type-values-ordinary-vhosts) for a configuration example and limits.
## HTTP methods and rate limits
+13 -1
View File
@@ -81,7 +81,19 @@ In **Docker vhosts**, select the service and set:
To deliberately assign a domain not covered by the agent's **named frontend certificate**, enable **Accept certificate/domain mismatch** immediately below **Backend host IP** in the per-service editor and confirm the risk. This records `allow_certificate_mismatch: true` on that publication only. Without consent, the server rejects the incompatible mapping. The client browser may still reject the TLS handshake; a matching SAN certificate is strongly preferred. The agent's own outbound TLS fingerprint validation is unaffected.
Use **Publish** and test the resulting hostname. Edits to an already published service use its own **Apply changes** action; unpublishing does not stop its Docker container. Hidden rows in the page are only a browser view preference, not a security policy.
Use the per-service **Publish** on/off switch to expose or remove the generated Vhost; toggling it saves immediately. Test the resulting hostname with **Open app**. Edits to an already published service use its own **Apply changes** action; switching Publish off removes the proxy publication but does not stop the Docker container. Hidden rows in the page are only a browser view preference, not a security policy.
### Live HTTP request logs
For each published Docker Vhost, **Live logs** appears directly beside **Open app**. It opens RustProxy's authenticated **Live access logs** dialog with this publication's generated Vhost ID already selected. Logs for every hostname alias of the same publication are shown together. The filter stays selected even when no requests have yet been recorded; you can switch back to **All vhosts** inside the dialog. The action waits until an agent status refresh has provided the server-generated Vhost ID, so it may be disabled briefly immediately after publishing.
These are **HTTP requests processed by RustProxy**, not the application's Docker container stdout/stderr. The viewer uses RustProxy's bounded in-memory live request history; requests appear when completed, not as a container terminal stream. Stored Docker stdout/stderr are not retrieved from the agent. The dialog is administrator-only, and no Docker log-reading endpoint is exposed.
### Per-vhost traffic statistics
Every published vhost on an enabled Docker agent has a **Traffic statistics** disclosure directly below **Configure vhost**. It starts collapsed, uses the same six status/requests/active/errors/latency/traffic-per-second tiles and **Lifetime request rate** chart as an ordinary Vhost, and can be opened individually. The **Expand all statistics / Collapse all statistics** toolbar button toggles every published Docker vhost at once (including rows hidden by search or the local Hide action). The chosen disclosure state survives live list refreshes during the current panel session; it resets on sign-out.
Counters come from RustProxy's generated Vhost metrics, not the Docker agent or just the upstream backend: they include requests handled at the proxy frontend, even those rejected before reaching a backend. The request-rate graph is sampled in the browser from cumulative counters **since the panel session started observing this host**; its history is not stored on disk. Traffic/s is the observed delta of ingress plus egress bytes. Missing metrics show `-`. Live updates follow the administration status stream/polling settings; expanding the statistics does not prevent Docker inventory refreshes.
## Troubleshooting
+2
View File
@@ -12,6 +12,8 @@ rust-proxy --data-dir /var/lib/rustproxy --livelogs
The CLI connects to the local administration listener and follows structured request events. It can filter by host, Vhost, backend, route, method, client, protocol, status, cache state and latency; use `filters`, `pause`, `resume`, `detail on` and `quit` in the interactive view. It adapts to a loopback administration HTTPS listener where configured.
For a published Docker application, **Docker vhosts → Live logs** (beside **Open app**) opens this same dialog filtered to the generated Vhost. It includes HTTP traffic for that publication and its aliases. It does **not** display Docker container stdout/stderr; the Docker agent remains inventory-only.
Live viewing is **bounded in memory**. Slow consumers may receive a gap/loss indication and are not allowed to block proxy traffic. Low-level malformed HTTP/TLS/H2/H3 protocol errors can be sent only to persistent sinks rather than appearing in the ordinary live request list. A request ID (`X-Request-ID`) helps correlate an application response with proxy records.
## Stored Logs
+3 -3
View File
@@ -1,6 +1,6 @@
# RustProxy documentation
Practical guides for **RustProxy 0.34.5**. This index and the listed pages are also available in the authenticated panel at **`/docs → Reader`**. The adjacent **API** tab provides the embedded OpenAPI reference. Paths below are links to actual files in the source archive.
Practical guides for **RustProxy 0.34.6**. This index and the listed pages are also available in the authenticated panel at **`/docs → Reader`**. The adjacent **API** tab provides the embedded OpenAPI reference. Paths below are links to actual files in the source archive.
## Getting started
@@ -11,7 +11,7 @@ Practical guides for **RustProxy 0.34.5**. This index and the listed pages are a
## Publishing services
- [Vhosts and backends](VHOSTS.md) — domains, listener bindings, balancing, health and redirects.
- [Vhosts and backends](VHOSTS.md) — domains, listener bindings, request Content-Type filtering, balancing, health and redirects.
- [Custom locations](CUSTOM_LOCATIONS.md) — path routing, rewrites, local responses and error fallbacks.
- [Access and authentication](ACCESS.md) — ACL, country/DDNS, Basic Auth, Tinyauth and rate limits.
- [Static Web Server](WEB_SERVER.md) — document roots, downloads, rules, built-in error pages and file delivery.
@@ -24,7 +24,7 @@ Practical guides for **RustProxy 0.34.5**. This index and the listed pages are a
## Integrations and operations
- [Certificates and automatic renewal](ACME_PROVIDERS.md) — PEM, HTTP-01, DNS-01, Certbot and external certificates.
- [Docker discovery](DOCKER_DISCOVERY.md) — optional Linux agent DEB/RPM or manual installation, TLS/token CLI, networking and generated Vhosts.
- [Docker discovery](DOCKER_DISCOVERY.md) — optional Linux agent DEB/RPM or manual installation, TLS/token CLI, networking, generated Vhosts and their per-service live HTTP logs.
- [Other integrations](INTEGRATIONS.md) — Tinyauth, NPM migration, OPNsense and monitoring tools.
- [Dashboard](DASHBOARD.md) — metrics panels, HIT/MISS/BYPASS/OTHER request mix, presets and configuration history.
- [Monitoring](MONITORING.md) — Prometheus, full JSON and compact `summary` API, traffic, backend and cache observations.
+1 -1
View File
@@ -11,7 +11,7 @@ RustProxy provides several security controls, but it is not a complete Web Appli
## Origin and request trust
- Enforce IP/country/DDNS policies, rate limits and HTTP method rules **before** connecting to backends. A Custom location cannot undo a Vhost-level denial.
- Enforce IP/country/DDNS policies, rate limits, HTTP method rules and ordinary Vhost request **Content-Type** deny rules **before** connecting to backends. A Custom location cannot undo a Vhost-level denial. A Content-Type rule is based on the declared request header; a client can omit or mislabel it, so it does not substitute for application or PHP security patches.
- Private and local backend addresses require deliberate exceptions. Routing to the local administration listener can expose secrets or create routing loops.
- HTTPS to a backend is not proof of identity unless upstream certificate/hostname verification is enabled; current backend defaults do **not** enable verification automatically.
- Honor forwarding identity headers only from correctly configured trusted peers. A client can forge arbitrary `X-Forwarded-*` and User-Agent headers.
+20
View File
@@ -13,6 +13,26 @@ A **Vhost** publishes one or more hostnames on named HTTP/HTTPS listeners. Its s
A Vhost may bind several frontends. Hostnames and selected listeners must match: the existence of a certificate or an upstream does not create DNS entries or a listening socket. Existing Vhosts retain their bindings when new listeners are created.
## Block request Content-Type values (ordinary Vhosts)
Go to **Vhosts → Edit → Security → Request Content-Type**. Enable **Block selected Content-Type values**, enter one MIME pattern per line, then **Save**. The policy is off by default and is available in the regular Vhost editor, not in the Docker vhost editor.
Example patterns:
```text
multipart/form-data
application/xml
image/*
```
- Accepts up to **64** unique patterns: exact `type/subtype` or a media family `type/*`. The policy matches case-insensitively and ignores parameters (`multipart/form-data; boundary=...` matches `multipart/form-data`). Whitespace outside a pattern is trimmed; invalid patterns and duplicates are rejected at save/validation time.
- A matching request receives **HTTP 403** before reading the body, proxying to an upstream, serving a Web Server/PHP-FPM file, choosing a Custom location or returning a cached response. When the policy is enabled, malformed, repeated or ambiguous `Content-Type` values are also denied.
- Requests with no `Content-Type` are **not blocked**. This is header filtering, not content sniffing, body inspection or a comprehensive WAF. Applications can accept unsafe input through other formats and routes.
- Blocked types cannot be used for normal requests either: blocking `multipart/form-data` disables traditional file-upload forms for the selected Vhost. Evaluate legitimate traffic before enabling and test an allowed type and a denied type.
- The policy is stored in the Vhost's `content_type_policy` object, for example `{"enabled":true,"blocked":["multipart/form-data"]}`. Existing Vhosts default to disabled. Changes are applied on the regular configuration publish cycle, without listener restart.
Check with `curl -i -H 'Content-Type: multipart/form-data; boundary=test' --data 'x' https://your-vhost.example/upload` (expected **403**) and a valid application request without the blocked type. Applying this filter is **not a fix for an underlying PHP/application vulnerability**: keep PHP, extensions and application code patched.
## Source and backends
- **Reverse Proxy:** one Vhost has a backend pool. Each member has a configured URL, ID, enabled flag, weight, optional backup/drain state, health settings and capacity limits.