This commit is contained in:
Mateusz Gruszczyński committed 2026-10-05 09:30:21 +02:00
1 parent 1dea7f55c8
commit c819f0a335
151 files changed
+7610 -4264

No files matched your search

+1 -1
View File
@@ -502,7 +502,7 @@ or changed/restart-pending settings return 404; denied peers 403; invalid tokens
401; non-GET 405; exhausted scrape capacity 429. No administrative actions are
available there. Admin `/api/metrics` and `/metrics` remain session-protected
previews on the admin listener, even when the dedicated endpoint is disabled.
See PROMETHEUS.md for the full settings and metric contract. Docker discovery is an independent collector group (`include_docker_vhosts`) and exports only dedicated `rust_proxy_docker_vhost_*` / `rust_proxy_docker_backend_*` families; ordinary vhost/backend families exclude dynamic Docker routes.
See PROMETHEUS.md for the full settings and metric contract. Traffic analytics is an independent collector group (`include_traffic`) that exports bounded country, fixed User-Agent/method/source, status/cache and configured-route aggregates without raw IP/path/full-UA labels. Docker discovery is an independent collector group (`include_docker_vhosts`) and exports only dedicated `rust_proxy_docker_vhost_*` / `rust_proxy_docker_backend_*` families; ordinary vhost/backend families exclude dynamic Docker routes.
## 0.7 renewal and host access
+1 -1
View File
@@ -1,4 +1,4 @@
# Administration API access - 0.25.4
# Administration API access - 0.25.5
## Sign-in boundary
+1 -1
View File
@@ -1,4 +1,4 @@
# Installing and updating RustProxy 0.25.4
# Installing and updating RustProxy 0.25.5
The scripts prepare a Linux/systemd installation. This source archive is **not a
verified production build**: Rust/Cargo, real CA operations, live systemd startup
+1 -1
View File
@@ -19,7 +19,7 @@ The live path is separate from configured file/syslog sinks. Request processing
## User-Agent, country and Traffic analytics
Structured access entries expose `user_agent` and `country` as selectable source fields in addition to the standard entry. User-Agent capture is enabled by default and is bounded before it enters retained logging/analytics state. Country capture is disabled by default because it requires a GeoIP lookup. With country capture disabled, GeoIP is kept off the normal request path unless a configured country access rule or country rate-limit already requires the lookup; in those policy cases the lookup still occurs for enforcement, but the country is not retained in access logs unless capture is enabled.
Structured access entries expose `user_agent` and `country` as selectable source fields in addition to the standard entry. User-Agent capture is enabled by default and is bounded before it enters retained logging/analytics state. Country capture is disabled by default. Normally country resolution uses the local GeoIP database; for a vhost with verified Cloudflare client-IP mode, RustProxy first accepts a valid single `CF-IPCountry` value from a direct Cloudflare edge and falls back to GeoIP of the verified effective client IP. With country capture disabled, country resolution is kept off the normal request path unless a configured country access rule or country rate-limit already requires it; in those policy cases resolution still occurs for enforcement, but the country is not retained in access logs unless capture is enabled.
The authenticated **Traffic** workspace aggregates completed requests per vhost without database writes. The request path uses a bounded non-blocking queue, and high-cardinality dimensions use fixed-capacity approximate top tables. The page shows aggregate requests, 5xx errors, request/response bytes and mean duration plus top countries, User-Agents, effective client IPs, paths, routes, methods, status classes and cache outcomes. Donut charts summarize countries, User-Agents, client IPs, methods, status classes and cache outcomes while the bounded tables retain exact displayed labels/counts from the approximate TOP state. The lists are process-lifetime diagnostics, are not persisted across restart, and may drop analytics samples under overload rather than applying backpressure to proxy traffic. Country rankings are populated only while country capture is enabled. Client-IP rankings use the same verified effective client identity used by ACL/logging after trusted-proxy processing.
+4
View File
@@ -1,5 +1,9 @@
# Deployment and configuration migration history
## 0.25.4 -> 0.25.5
There is no SQLite schema or saved-configuration migration. Existing `cloudflare_client_ip` vhost settings remain opt-in. When enabled and the direct peer is a verified Cloudflare edge, RustProxy now prefers a valid `CF-IPCountry` value for country analytics/logging and country policy evaluation, falling back to the installed GeoIP database when that header is unavailable or invalid.
## 0.25.3 -> 0.25.4
There is no SQLite schema or saved-configuration migration. Schema 8 and the existing 512-row `configuration_history` retention remain unchanged. Version 0.25.4 adds an authenticated restore operation that validates a retained document and saves it as a new revision; existing history is not rewound or overwritten.
+29 -4
View File
@@ -2,8 +2,8 @@
RustProxy exposes Prometheus text exposition 0.0.4 on a dedicated read-only
listener. It is independent from administrator browser sessions and does not
export request paths, query strings, cookies, credentials, backend URLs or ACME
account secrets.
export raw client IPs, request paths, query strings, full User-Agent strings, cookies,
credentials, backend URLs or ACME account secrets.
## Configuration
@@ -18,6 +18,7 @@ account secrets.
"allow_trusted_network_without_token": false,
"include_system": true,
"include_vhosts": true,
"include_traffic": true,
"include_backends": true,
"include_docker_vhosts": true,
"include_cache_domains": true,
@@ -68,6 +69,8 @@ The exporter represents all scalar fields currently sampled by `diagnostics::Vie
| GeoIP | loaded state plus IPv4/IPv6 range counts |
| Cache | hot entries/bytes, global hit ratio and counters, cold entries/bytes and movement/error counters, fill bytes, cold queue bytes/items, active cold read/write bytes, combined transient bytes, configured-domain hot/cold occupancy, hit ratio and decision data |
| Vhosts | desired enable/domain/path/cache settings, per-vhost traffic/status/error/byte counters and cumulative exchange-duration histogram |
| Traffic analytics | independent live collector (`include_traffic`): capture-state gauges, per-vhost request/error/body-byte/duration totals; approximate bounded top countries; fixed User-Agent families; fixed HTTP method families; status classes; cache outcomes; serving source (`web_server`, `reverse_proxy`, `local_response`, `unresolved`); and currently configured route IDs |
| Built-in Web Server | configured Web Service count/info, PHP and directory-listing flags, vhost/route source metadata, plus actual request traffic through the shared vhost counters and Traffic serving-source metrics |
| Redirect/404 hosts | desired enable state, domain/rule counts and local-response status |
| Backends | pool readiness/policy info, bounded backend status, health/drain/backup, active work and configured request-concurrency/queue limits, requests/errors/bytes, weight, separate active/passive failure state, active/passive successes and health-failure totals, unconditional HTTP-5xx/timeout/connect/I/O/slow-response observation counters, DNS/TLS/header-timeout/read-timeout/send-timeout diagnostics, capacity rejection/queue-timeout counters, plus `passive_http_5xx_total`, `passive_timeouts_total`, `passive_connect_errors_total`, `passive_io_errors_total` and `passive_slow_total` aliases, health transitions, last status, current/EWMA latency, last-probe/failure/ejection/recovery timestamps, traffic rate, and retry attempt/success totals for ordinary vhosts |
| Docker vhosts | separate `rust_proxy_docker_vhost_*` and `rust_proxy_docker_backend_*` families: configured agents/assignments/domains, vhost traffic/status/duration plus backend readiness, health, requests/errors/bytes, latency/EWMA, separate active/passive failure state, unconditional observation counters and matching passive-health aliases, transitions and probe results |
@@ -77,8 +80,9 @@ The exporter represents all scalar fields currently sampled by `diagnostics::Vie
| Inventory | listeners/protocol flags, vhost/redirect/404/stream/ACL counts, request capacity and available permits, config revision and restart-required state |
Values unavailable on the running OS are omitted rather than fabricated. Series
labels are bounded by configured IDs/domains, finite states and fixed protocol/status
families. Per-request URLs and arbitrary Host input are never labels.
labels are bounded by configured IDs/domains, finite states, fixed protocol/status/UA/method/source
families, or the finite two-letter country space. Per-request URLs, raw client IPs, full
User-Agent values and arbitrary Host input are never labels.
This is complete for **currently implemented bounded diagnostic views**. It does
not intentionally expose secrets, raw configuration documents, access-log entries
@@ -112,6 +116,27 @@ Vhost rate:
sum by (vhost) (rate(rust_proxy_vhost_requests_total[5m]))
```
Web Server traffic rate:
```promql
sum by (vhost) (rate(rust_proxy_traffic_source_requests_total{source="web_server"}[5m]))
```
Top country snapshot from bounded Traffic analytics:
```promql
sum by (country) (rust_proxy_traffic_country_requests)
```
Country series are populated when **Settings -> Logging -> Capture country** is enabled; User-Agent family series follow **Capture User-Agent**. The exporter never turns those request-path captures on by itself.
Current capture state is exposed as `rust_proxy_traffic_country_capture_enabled` and `rust_proxy_traffic_user_agent_capture_enabled`. Configured-route snapshots use `rust_proxy_traffic_route_requests`; raw URL paths are never exported as labels.
Fixed User-Agent families:
```promql
sum by (family) (rust_proxy_traffic_user_agent_family_requests_total)
```
Vhost p95 exchange lifetime:
```promql
+3 -2
View File
@@ -8,7 +8,8 @@ This is the canonical index for the current project documentation. The authentic
- [ROADMAP](../ROADMAP.md) - planned and completed release scope.
- [CHANGELOG](../CHANGELOG.md) - user/operator-visible changes by release.
- [TODO](TODO.md) - open work only; completed work is not retained as TODO.
- [0.25.4 release audit](V0.25.4_AUDIT.md) - retained configuration restore, CAS/audit behavior and release gates.
- [0.25.5 release audit](V0.25.5_AUDIT.md) - Cloudflare country analytics consistency, Revision History modal styling and release gates.
- [0.25.4 release audit](V0.25.4_AUDIT.md) - historical retained configuration restore, CAS/audit behavior and release gates.
- [0.25.3 release audit](V0.25.3_AUDIT.md) - historical request-method policy, location ACL/country controls, hashed request IDs and configuration-history scope.
- [0.25.2 release audit](V0.25.2_AUDIT.md) - historical live backup, internal symlink and resumed-origin recovery scope.
- [0.25.1 release audit](V0.25.1_AUDIT.md) - historical Traffic/module-split release scope and compiler-regression guards.
@@ -59,7 +60,7 @@ This is the canonical index for the current project documentation. The authentic
## Historical or version-labelled context
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone; they are not current-release documentation. The current audit is [V0.25.4_AUDIT.md](V0.25.4_AUDIT.md); [V0.25.3_AUDIT.md](V0.25.3_AUDIT.md) records the prior request-policy/history milestone and [V0.25.2_AUDIT.md](V0.25.2_AUDIT.md) records the prior backup/session hardening milestone and [V0.25.1_AUDIT.md](V0.25.1_AUDIT.md) records the prior Traffic/module-split milestone and [V0.25.0_AUDIT.md](V0.25.0_AUDIT.md) remains the Web Server foundation audit.
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone; they are not current-release documentation. The current audit is [V0.25.5_AUDIT.md](V0.25.5_AUDIT.md); [V0.25.4_AUDIT.md](V0.25.4_AUDIT.md) records the prior retained-history restore milestone and [V0.25.3_AUDIT.md](V0.25.3_AUDIT.md) records the prior request-policy/history milestone and [V0.25.2_AUDIT.md](V0.25.2_AUDIT.md) records the prior backup/session hardening milestone and [V0.25.1_AUDIT.md](V0.25.1_AUDIT.md) records the prior Traffic/module-split milestone and [V0.25.0_AUDIT.md](V0.25.0_AUDIT.md) remains the Web Server foundation audit.
Older context documents such as [INTEGRATIONS_040](INTEGRATIONS_040.md), [MANAGEMENT](MANAGEMENT.md), [SECURITY_AUDIT](SECURITY_AUDIT.md), [ACME_RFC2136](ACME_RFC2136.md) and older version audits remain available for traceability but should not override the current functional/technical documents above.
+2 -2
View File
@@ -339,6 +339,6 @@ place while switching; switching alone never writes configuration. Security is
not a separate sidebar item. Use arrow keys/Home/End in the tab bar.
The Prometheus card controls enabled, bind IP/port, URL path, client CIDRs,
bearer-token environment variable name and optional collectors. Only the variable
name is exported; supply the actual secret to the service separately. See
bearer-token environment variable name and optional collectors, including the bounded
Traffic analytics collector. Only the variable name is exported; supply the actual secret to the service separately. See
PROMETHEUS.md for immediate revocation, restart rules and scrape configuration.
+12 -5
View File
@@ -1,11 +1,18 @@
# Verification report - RustProxy 0.25.4
# Verification report - RustProxy 0.25.5
## Scope
RustProxy 0.25.4 adds restore from the retained manual-configuration history introduced in 0.25.3. Selecting an older retained revision validates that historical document through the normal configuration update pipeline and saves it as the next revision instead of rewinding history. SQLite remains at schema 8 with the existing 512-revision retention limit, so upgrading from 0.25.3 requires no database migration.
RustProxy 0.25.5 is a patch release for dashboard consistency and observability: Revision History used a separate rounded modal style, Cloudflare-backed vhosts resolved Traffic country from local GeoIP without consulting Cloudflare's verified country header, Prometheus did not expose the bounded Traffic dimensions or an explicit built-in Web Server serving-source view, the mobile dashboard rendered the full section list permanently across the top of the page, and the dashboard lacked a compact About surface. The top bar now exposes project About information and uses the full Documentation label. The patch keeps SQLite schema 8 and the existing configuration format.
## Source contracts reviewed
- Revision History now uses the shared dashboard dialog rule with square corners; the dedicated history dialog retains only layout dimensions/overflow and no longer duplicates color, background, border, shadow or backdrop appearance declarations. Calendar/diff sub-panels no longer add local rounded corners.
- Dashboard widths up to 850 px now hide the main section list behind an accessible `aria-expanded` Menu control. Opening shows a two-column section grid; selecting a section, pressing Escape or clicking outside closes it. Desktop navigation keeps the existing sidebar behavior.
- The authenticated top bar exposes an About dialog with author Mateusz Griszczynski, an Open Source notice and the canonical Git repository link; the documentation action is labeled Documentation. The About dialog uses the same square-corner modal styling and adds no new server route.
- Cloudflare client-IP mode still requires the direct transport peer to match the built-in Cloudflare edge CIDRs. After a successful verified `CF-Connecting-IP` override, one valid two-letter `CF-IPCountry` value is normalized and preferred for country policy/logging/Traffic; missing, duplicate, malformed and `XX` values fall back to local GeoIP of the verified effective client IP.
- Prometheus `include_traffic` defaults on and exports bounded per-vhost Traffic totals, country top values, fixed User-Agent families, fixed method families, status classes, cache outcomes, serving source and configured route IDs. Raw effective client IPs, raw request paths and full User-Agent strings remain excluded from exporter labels.
- Traffic serving source is recorded as one fixed value (`web_server`, `reverse_proxy`, `local_response`, `unresolved`) and the exporter adds configured Web Service inventory plus vhost/route source metadata. This makes pure Web Server traffic explicit while preserving the existing shared vhost request/status/byte/duration counters.
- The bundled Grafana dashboard adds a Traffic vhost variable and panels for Web Server request rate, queue drops, countries, User-Agent families, source rates, methods, status classes, cache outcomes, capture-state gauges and configured-route traffic.
- Vhost and location `method_policy` values validate and normalize HTTP methods; host and selected-location policies are cumulative and deny with 405 before upstream work. Allow-list denial includes `Allow`.
- Custom locations can select an `acl_profile_id` and add inline IP ACL plus country access policy. Profile and inline rules are compiled with the route and checked before authentication/backend selection; a location cannot weaken a vhost denial.
- Every observed exchange receives a fresh 64-hex SHA-256 `request_id`, overwrites inbound `X-Request-ID` before forwarding, and reuses the same value for diagnostics/logging. Custom header rules continue to protect `X-Request-ID`.
@@ -37,7 +44,7 @@ RustProxy 0.25.4 adds restore from the retained manual-configuration history int
- Pure Web Server vhosts no longer present backend diagnostics as though an origin pool existed; their Backends summary identifies `Web Server`, while mixed static/proxy vhosts retain backend diagnostics.
- Status payloads expose fixed-cardinality per-vhost metrics independently of backend pools. The Vhosts dashboard uses those counters for Web Server-only request/active/error values, EWMA latency and byte-rate traffic while retaining backend health details for reverse-proxy sources.
- Logging settings are split into Outputs, JSON format and Error log sub-tabs inside one card, matching the Cache subsection layout. `route`, `cache_effective_enabled` and `transform_effective_enabled` are accepted by the same backend validator that saves custom JSON mappings, and the regression test validates then renders those fields.
- Structured logging now exposes `user_agent` and `country`. User-Agent capture defaults on; country capture defaults off and GeoIP resolution is skipped unless capture or an existing country ACL/rate-limit needs it.
- Structured logging exposes `user_agent` and `country`. User-Agent capture defaults on; country capture defaults off. Country resolution is skipped unless capture or an existing country ACL/rate-limit needs it; verified Cloudflare mode prefers trusted `CF-IPCountry`, otherwise local GeoIP is used.
- The authenticated Traffic workspace uses a bounded 2048-sample non-blocking queue, at most 64 vhost buckets and 32-entry approximate top tables for countries, User-Agents, effective client IPs, paths, routes, methods, status classes and cache outcomes. It never writes per-request analytics to SQLite. The Traffic UI is split into Overview, Clients, Requests and Delivery sub-tabs. Countries/methods/status/cache use donut summaries; User-Agent, effective client IP, path, route and request/response byte volume use bounded horizontal bar charts from the same in-memory TOP state.
- Sustained-traffic memory maintenance calls `malloc_trim(0)` every 60 seconds on Linux/glibc to release already-free allocator pages and trims HOT objects only when above the configured waterline and idle past the configured age. It does not periodically reload vhosts, purge active objects or reset bounded upstream keep-alive pools.
- Cache compatibility currently includes vhost configuration, so a cache-affecting vhost save can purge cache during snapshot publication; replacing the compiled snapshot also retires its upstream clients after outstanding references drain. These mechanisms explain why a manual vhost save can visibly reduce RSS without implying that reloads are required for steady-state operation.
@@ -51,11 +58,11 @@ RustProxy 0.25.4 adds restore from the retained manual-configuration history int
## Implemented automated coverage
Rust unit tests in `src/web_server/tests.rs` cover GET/HEAD/index/slash redirect, MIME/length, validators, valid/invalid range handling, If-Range, escaped/repeated directory listings, per-directory index-before-listing fallback, generic 403/HEAD behavior, MIME overrides/default MIME, cache rules, source headers, `try_files`, rewrite redirect/internal behavior, `.htaccess` WordPress-style front-controller routing, nested DirectoryIndex/MIME/Header/Expires behavior, strict-mode rejection and PHP-source protection, hardening probe/method blocking and fingerprint-header stripping, precompressed representations/ranges, download headers, PHP FastCGI fixture execution/failure-source-disclosure behavior, request-body 413 enforcement, custom FastCGI/PHP_VALUE validation and reserved-parameter rejection, direct traversal rejection and Unix/Linux symlink policy. `src/traffic/tests.rs` includes bounded-table and effective-client-IP view coverage. Configuration tests cover pure static vhosts without a pool, mixed Web Server/Reverse Proxy routing, reuse of one Web Service by multiple vhosts, unknown service references and backward-compatible default source behavior. Vhost tests cover method-policy normalization/allow/block behavior, database tests cover retained configuration revision documents, actor metadata and previous-revision lookup, and admin tests cover restoring revision 1 as revision 3 while preserving the previous document and emitting `config.restore`. ACL tests include encoded traversal/separator/malformed-encoding cases.
Rust unit tests in `src/web_server/tests.rs` cover GET/HEAD/index/slash redirect, MIME/length, validators, valid/invalid range handling, If-Range, escaped/repeated directory listings, per-directory index-before-listing fallback, generic 403/HEAD behavior, MIME overrides/default MIME, cache rules, source headers, `try_files`, rewrite redirect/internal behavior, `.htaccess` WordPress-style front-controller routing, nested DirectoryIndex/MIME/Header/Expires behavior, strict-mode rejection and PHP-source protection, hardening probe/method blocking and fingerprint-header stripping, precompressed representations/ranges, download headers, PHP FastCGI fixture execution/failure-source-disclosure behavior, request-body 413 enforcement, custom FastCGI/PHP_VALUE validation and reserved-parameter rejection, direct traversal rejection and Unix/Linux symlink policy. `src/traffic/tests.rs` includes bounded-table, effective-client-IP view and fixed Prometheus User-Agent/method family coverage. Configuration tests cover pure static vhosts without a pool, mixed Web Server/Reverse Proxy routing, reuse of one Web Service by multiple vhosts, unknown service references and backward-compatible default source behavior. Vhost tests cover method-policy normalization/allow/block behavior, database tests cover retained configuration revision documents, actor metadata and previous-revision lookup, and admin tests cover restoring revision 1 as revision 3 while preserving the previous document and emitting `config.restore`. ACL tests include encoded traversal/separator/malformed-encoding cases.
Rust-independent release checks additionally validate UI/JSON/language/source contracts and reproducible packaging.
A compiler-enabled external build subsequently exposed one module-privacy error in the new history split (`CONFIG_HISTORY_CAPACITY` was private to `db::history`) and one unused `country_resolved` assignment in the location GeoIP branch. The source package now exposes the capacity to its parent module with `pub(super)`, references it through `history::CONFIG_HISTORY_CAPACITY`, and removes the dead assignment. This workspace still has no Rust/Cargo toolchain, so compiler confirmation of the corrected tree remains a release-host gate.
During the prior 0.25.4 compiler gate, an external build exposed one module-privacy error in the history split (`CONFIG_HISTORY_CAPACITY` was private to `db::history`) and one unused `country_resolved` assignment in the location GeoIP branch. Both were corrected before the 0.25.5 baseline: the capacity is exposed to its parent module with `pub(super)`, referenced through `history::CONFIG_HISTORY_CAPACITY`, and the dead assignment is removed. This workspace still has no Rust/Cargo toolchain, so compiler confirmation of the 0.25.5 tree remains a release-host gate.
### Modular source-tree verification
+27
View File
@@ -0,0 +1,27 @@
# RustProxy 0.25.5 release audit
RustProxy 0.25.5 is a patch release for Traffic country consistency behind Cloudflare, broader bounded Prometheus/Grafana observability, dashboard Revision History styling, compact mobile navigation and top-bar project information. SQLite remains at schema 8 and no saved-configuration migration is introduced.
## Implemented changes
- `cloudflare_client_ip` remains opt-in per vhost and still accepts `CF-Connecting-IP` only when the direct transport peer belongs to the built-in Cloudflare edge CIDRs.
- A trusted Cloudflare request may additionally provide one `CF-IPCountry` header. RustProxy accepts only a two-letter ASCII country code, normalizes it to uppercase, rejects duplicates and treats `XX`/non-country values as unresolved.
- When the Cloudflare client-IP override succeeds, the trusted Cloudflare country is preferred for country policy evaluation, retained country logging and bounded Traffic country analytics. Missing or invalid country values fall back to the local GeoIP lookup of the verified effective client IP.
- Requests that do not use verified Cloudflare client-IP mode keep the previous GeoIP behavior. Untrusted clients cannot make `CF-IPCountry` authoritative by sending it directly.
- Revision History now participates in the same shared square-corner `dialog` styling as vhost, logs, audit and certificate dialogs. Its duplicate color/background/border/backdrop/shadow declarations and local rounded corners were removed.
- At dashboard widths up to 850 px, the main navigation is collapsed behind a square-corner Menu control instead of rendering every section across the page header. It expands as a two-column list and closes after section selection, Escape or an outside click; desktop navigation remains unchanged.
- The authenticated dashboard top bar now includes an About dialog identifying author Mateusz Griszczynski, the project as Open Source, and the canonical source repository. The former short Docs action is labeled Documentation; no new public administration route is added.
- Prometheus now has an independent `include_traffic` collector (default on) for bounded Traffic analytics. It exports per-vhost totals plus countries, fixed User-Agent families, fixed HTTP method families, status classes, cache outcomes, configured routes and a fixed serving-source dimension (`web_server`, `reverse_proxy`, `local_response`, `unresolved`).
- Raw client IPs, request paths and full User-Agent strings remain available only to the authenticated Traffic/logging surfaces and are intentionally never emitted as Prometheus labels. Country values are restricted to two-letter uppercase codes; route labels are restricted to currently configured route identifiers.
- Built-in Web Server observability now includes configured service inventory, PHP/directory-listing flags, vhost/route source metadata and request traffic by serving source. Pure Web Server vhosts continue to use the same vhost-wide request/status/byte/duration counters as proxy-backed vhosts.
- The bundled Grafana dashboard adds a Traffic-vhost filter plus Web Server request rate, Traffic queue drops, top countries, User-Agent families, serving-source rates, method rates, status classes, cache outcomes, capture-state gauges and configured-route traffic.
## Regression coverage
- `src/forwarding/tests.rs` checks that Cloudflare country is accepted only from a Cloudflare peer, normalized, rejected for `XX`, malformed values and duplicate headers.
- Source-contract checks verify the 0.25.5 release identity, shared Revision History modal rule, absence of the old history-only backdrop/radius declarations, the Cloudflare country preference/fallback path, collapsed mobile navigation behavior, About dialog metadata/link, and the Documentation top-bar label.
- Traffic aggregation now also keeps fixed User-Agent-family, method-family and serving-source counters for Prometheus while preserving the existing raw bounded top tables used by the authenticated Traffic UI.
## Verification gate
Run the repository checks included with the release archive. Static/source-contract, language, documentation, packaging, shell, JavaScript and Docker Agent checks may run without Rust where supported. A compiler-enabled release host must still run `cargo fmt --all`, `cargo check --locked --all-targets` and `cargo test --locked --all-targets` before production acceptance.
+4 -1
View File
@@ -13,7 +13,10 @@ use built-in HTML pages unless a configured custom error page replaces them.
Cloudflare mode trusts `CF-Connecting-IP` only when the **direct peer** is inside the
compiled Cloudflare edge CIDRs. An arbitrary client sending that header directly does
not become trusted. The verified address becomes the effective client IP for ACLs,
rate limiting, country lookup and forwarded metadata.
rate limiting and forwarded metadata. On the same verified Cloudflare hop, a single
two-letter `CF-IPCountry` value is accepted as the country source for country policy,
logging and Traffic analytics. Missing, duplicate, invalid and Cloudflare `XX` values
fall back to the local GeoIP lookup of that verified effective client IP.
Vhost listener editing is now selection-only. Listener addresses/IPs and transport
settings live under Settings > Listeners; a vhost selects one or more named endpoints.