Files
RustProxy/docs/ACCESS.md
T
2026-10-27 12:18:20 +01:00

13 KiB

Access, authentication and traffic protection

Access control can be configured globally, on a Vhost and on selected Custom locations. Policies are cumulative: a more specific allow rule does not cancel a denial at a broader level. Changes should be tested with both an allowed and a denied client.

Global block / allow policy (0.34.13)

Settings → Rules & headers → Global block / allow applies to public HTTP traffic across all vhosts, redirects and not-found hosts before upstream access. In addition to the existing User-Agent deny patterns, use the global country block/allow list (ISO two-letter codes), client IP/CIDR and allow-only DNS ACL, HTTP method policy, request Content-Type denylist and shared per-IP rate limit. All are disabled by default except previously configured User-Agent blocking. An explicit IP allow does not bypass the country policy: both must permit a request. Missing GeoIP country is allowed for country block mode and denied for country allow mode.

Global restrictions add to per-vhost and path rules. Rate-limit requests are counted for each client IP across vhosts. Prefer a conservative shared ceiling to avoid blocking shared NAT clients. A global method denial returns 405, the content-type/ACL/UA policy returns 403, and the shared rate limiter returns 429 with Retry-After. Admin and TCP/UDP stream listeners are outside this HTTP scope. For global response headers, use the adjacent Security headers subtab; see Security.

IP, country and DDNS rules

  • IP/CIDR ACL: allow or deny IPv4/IPv6 networks. Use reusable ACL profiles for settings shared by several domains. Both ordinary and Docker Vhosts use a searchable multi-select with selected badges and a preview of IP/CIDR rules, country restrictions and the default policy; the selection changes presentation only, not ACL evaluation. A Vhost can select up to eight profiles (acl_profile_ids, or one legacy acl_profile_id); Docker assignments can override or inherit the agent's profile selection.
  • DNS/DDNS: an ACL allow rule may use a hostname, such as allow office.example.ddns.net; deny with DNS is not supported. Records are refreshed periodically; unknown, failed or expired resolutions authorize nobody under the allow rule. This is appropriate for a trusted, controlled DDNS record, not a replacement for login.
  • Country access: allow-only or blocking based on the configured GeoIP database. Allow-only mode fails closed when a country cannot be determined. Keep the GeoIP database updated in Settings → GeoIP updates.
  • Cloudflare client IP: enable the integration only when traffic really arrives through a controlled Cloudflare/trusted-proxy boundary. Never trust arbitrary client-supplied forwarding headers as an identity proof.

Multiple profiles on one Vhost: For different explicit allowlists, allows are combined (logical OR). Explicit IP denies and blocked countries take precedence over allows from every selected profile. If no explicit allow or deny matches, fallback allows only when all selected profile defaults permit it (country allow-only requires a listed country). One selected profile uses the pre-existing ACL behavior exactly. The separate inline Vhost ACL, country policy, location ACL and global host ACL remain restrictive scopes (logical AND): a deny there cannot be overridden by a profile allow. Do not mix broadly permissive profiles with blocking profiles without checking the effective result from both an allowed and a blocked IP/country.

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, 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 selects exactly one of Basic Auth, Tinyauth, Authelia and authentik. 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 for a configuration example and limits.

HTTP methods and rate limits

Method policies allow, block or leave methods unrestricted. A denied method returns 405, while typical ACL/country denials return 403. Per-client rate limits can configure request count, window and burst with optional country overrides; exceeding the limit returns 429 with Retry-After. Limits are application controls, not a replacement for upstream DDoS protection.

Basic Auth, Tinyauth, Authelia and authentik

  • Basic Auth: protect selected Vhosts with configured credentials. Use HTTPS so credentials are not sent over plaintext.
  • Tinyauth: add a verification URL and an HTTPS login URL. RustProxy makes a bounded, body-free authorization request and can pass specifically allowed identity headers upstream. An origin URL automatically uses /api/auth/nginx (or set that path explicitly). This Nginx auth-request integration sends X-Original-URL and X-Original-Method, with a validated X-Forwarded-For and X-Real-IP for Tinyauth IP ACLs. It does not send X-Forwarded-Host or X-Forwarded-URI to the verifier, avoiding the conflicting auth module headers rejection introduced in Tinyauth 5.2.0 while keeping compatibility with earlier versions that implement the Nginx endpoint. Tinyauth has its own timeout and private-backend policy.
  • Provider-neutral gateway error pages (0.34.15): One embedded src/admin/web/error_auth_provider.html template renders a self-contained HTML page for Tinyauth, Authelia, authentik, and future providers, using only the safe provider display name and the failure category. It replaces the three vendor-specific error_tinyauth_*.html source files while preserving the familiar Tinyauth response titles and statuses. For example: 502 Tinyauth connection error if its HTTP client cannot reach Tinyauth (DNS/TCP/TLS/transport), 504 Tinyauth timeout if the auth deadline expires, or 502 Tinyauth verification error for unexpected verifier status or invalid/oversized data. The page always retains the HTTP error status, Content-Type: text/html; charset=utf-8, Cache-Control: private, no-store and X-Content-Type-Options: nosniff. Backend URLs, protocol errors and identity data are not shown to visitors. All of these cases deny access to the protected origin. HTTP 401/403 and configured login redirects remain unchanged. These auth-specific pages take precedence over custom Vhost/general HTTP error pages so the failure remains distinguishable. The generic failure marker also protects Basic Auth denials and provider login redirects from being replaced by Vhost pages. HTTPS-verifier transport errors are classified as connection failures, truncated/oversized/invalid verifier responses as verification failures, and verification deadlines as timeouts.
  • Point the verifier URL directly at the private Tinyauth service (for example http://tinyauth:3000/api/auth/nginx), rather than routing it through a second public proxy that might inject conflicting headers. Do not disable Tinyauth's header-spoofing protections. Confirm that Tinyauth trusts only the actual RustProxy address/network when enabling Tinyauth IP-based access controls (TINYAUTH_AUTH_TRUSTEDPROXIES).
  • Authelia (0.34.15): select Authelia under Vhost → Authentication. Enter the internal service origin (for example http://authelia:9091) and the public HTTPS login portal (for example https://auth.example.com); RustProxy calls /api/authz/forward-auth. It forwards trusted X-Forwarded-*, X-Original-URL and X-Original-Method metadata, verifies the provider result, returns provider-approved 302/303 login redirects only to the configured portal origin, and forwards configured Remote-* identity headers after stripping client-forged values. A 200 verifier response alone grants access. 401/403 deny; transport failures return 502 and timeouts 504. The Authelia session.cookies domains and authelia_url are defined in Authelia itself: protecting unrelated registered domains generally requires a login URL/cookie configuration within each domain, not one cookie from a single unrelated site.
  • authentik (0.34.15): select authentik and enter the private outpost origin (for example http://authentik:9000), not an /if/flow login URL. RustProxy calls /outpost.goauthentik.io/auth/nginx, forwards verified X-Authentik-* identity headers, and responds to a 401 with a same-origin login start at /outpost.goauthentik.io/start?rd=.... RustProxy reserves /outpost.goauthentik.io (and descendants) on the protected application hostname and forwards them to the configured outpost without checking authentication again, after ordinary global/Vhost IP/country/rate rules. No manual Custom Location is needed for that path. In authentik create a separate Proxy Provider → Forward auth (single application) for each protected external application URL, assign it to the serving outpost, then enable that Vhost's integration. Multiple unrelated domains can share the same authentik installation; they do not share a browser cookie across domains.
  • Adding another provider: Keep the new vendor's Settings and Compiled implementation under src/<provider>/mod.rs and its tests under src/<provider>/tests.rs. Implement the auth_provider::Provider trait for runtime authorization, optional reserved_path/serve_reserved hooks for same-host callbacks, and (for Nginx-compatible providers) the shared forward_auth::Adapter. Add an enabled-by-default-false Vhost settings field, validate mutual exclusivity in auth_provider::Selection, compile it into the single CompiledFrontend.auth_provider slot, and register the method in the panel. Reuse auth_provider::deny / auth_provider::gateway_failure instead of adding separate HTML templates. Existing tinyauth, authelia, and authentik configuration keys remain backward compatible.
  • Per-provider security: The verifier/outpost connection uses TLS certificate verification for HTTPS with optional additional CA, explicit private-backend opt-in and the existing safe-address/local-listener restrictions. Only allowlisted response identity fields and bounded session cookies reach applications/browsers. Inaccessible, malformed or timed-out authorization services deny origin access. Both Authelia and authentik are disabled by default; old Tinyauth settings are retained when inactive. Only one of the four authentication methods can be enabled for one Vhost. Protected responses bypass shared caching. Confirm both allowed/denied requests, logins, sessions, redirects and WebSockets with the actual provider before rollout.

Minimal Vhost configuration examples (inside a Vhost object)

Authelia:

"authelia": {
  "enabled": true,
  "url": "http://authelia.internal:9091",
  "login_url": "https://auth.example.com",
  "allow_private": true
}

authentik (same URL for the outpost check and its reserved public path):

"authentik": {
  "enabled": true,
  "url": "http://authentik.internal:9000",
  "allow_private": true
}

Set basic_auth.enabled, tinyauth.enabled, and the other provider's enabled to false for these examples. These are fragments, not whole Vhost documents. Protect the public provider portal with a separate Vhost without forward auth to avoid recursive redirects.

Do not use a User-Agent blocklist as the primary access control: HTTP clients can forge their User-Agent freely.

Headers, sessions and internal services

Custom request/response headers support set/append/remove within allowed names. Security headers can be configured at Vhost scope; check interactions with HSTS and CSP in browsers. Hostnames, forwarding identity, request IDs, hop-by-hop framing and WebSocket negotiation are protected by validation. Never expose the administration HTTP listener through a public Vhost just to bypass its local-access default.

Streams are separate. TCP/UDP Stream listeners do not run HTTP auth, GeoIP Vhost rules, headers, cache or TLS termination. Restrict them with firewall rules and protections on the actual protocol/backend.

Practical verification

Test allowed/denied IPs, private application login, denied HTTP methods, country policies, websocket handshakes and rate-limit recovery. Use Logs to identify 403/405/429 responses. For origin-side client IP settings, see Configuration and Security.