diff --git a/AGENTS.md b/AGENTS.md index c882af4..3fcadff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # RustProxy source and documentation maintenance -Current source version: **0.34.13**. The Cargo package and binary are named `rust-proxy`. +Current source version: **0.34.14**. The Cargo package and binary are named `rust-proxy`. Before editing, read [README.md](README.md), [ROADMAP.md](ROADMAP.md), the relevant [documentation guide](docs/README.md) and the actual code and tests. Historical release experiments are not current specifications. Use the bundled `src/admin/openapi.json` for API routes and payloads; the source implementation is authoritative for runtime behavior. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f74816..2276857 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Changelog -Release history focused on **features, settings, default behavior, compatibility and fixes**. Changes to internal code structure and preliminary performance experiments are intentionally omitted. Historical descriptions reflect their respective releases; consult the current documentation for the settings available in 0.34.13. +Release history focused on **features, settings, default behavior, compatibility and fixes**. Changes to internal code structure and preliminary performance experiments are intentionally omitted. Historical descriptions reflect their respective releases; consult the current documentation for the settings available in 0.34.14. + +## 0.34.14 — Tinyauth gateway error pages (source candidate) + +- **Tinyauth outage:** when RustProxy cannot reach the Tinyauth verifier (connect, DNS, TLS or transport error), it returns a built-in **502 Tinyauth connection error** HTML page rather than plain `502 Bad Gateway`. The page is local and self-contained; no failed authentication is bypassed and no backend address, certificate detail or transport error is revealed to the caller. +- **Tinyauth compatibility patch:** the Nginx verifier now receives one consistent auth-request header set. RustProxy removes ForwardAuth module markers (`X-Forwarded-Host`, `X-Forwarded-URI`) while preserving the verified client IP and original request URL. This resolves the `conflicting auth module headers` rejection introduced in Tinyauth 5.2.0 without disabling anti-spoofing checks. Added regression tests for conflicting module headers and forged client identity. Use the internal `/api/auth/nginx` endpoint. +- **Tinyauth timeout:** a verifier request that exceeds the configured deadline returns a distinct **504 Tinyauth timeout** page. Invalid verifier responses, unexpected HTTP statuses and oversized identity/response data return **502 Tinyauth verification error**. All retain no-store and the authenticated-request isolation marker, so Vhost/global error-page overrides do not mask Tinyauth's diagnostic category. + ## 0.34.13 — Global security, section-based configuration API and panel UX (source candidate) diff --git a/Cargo.lock b/Cargo.lock index bca4c19..46866e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1925,7 +1925,7 @@ dependencies = [ [[package]] name = "rust-proxy" -version = "0.34.13" +version = "0.34.14" dependencies = [ "anyhow", "arc-swap", diff --git a/Cargo.toml b/Cargo.toml index 99b7afc..90fc7a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust-proxy" -version = "0.34.13" +version = "0.34.14" edition = "2021" rust-version = "1.99" description = "RustProxy - independent reverse proxy with local administration" diff --git a/README.md b/README.md index 646a0f8..181a309 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ -# RustProxy 0.34.13 +# RustProxy 0.34.14 RustProxy combines a reverse proxy, static/PHP web server, certificate management and traffic monitoring in one service with a browser administration panel. It supports several domains and backends without requiring a separate proxy configuration language. +## Changes in 0.34.14 + +- Preserves Tinyauth Nginx auth-request compatibility with old and new versions supporting `/api/auth/nginx`. +- Uses a separate, locally embedded **Tinyauth connection error (502)**, **Tinyauth timeout (504)** or **Tinyauth verification error (502)** page for failed authorization checks, without allowing access to protected origins. The existing built-in **Bad Gateway (502)** page and all standard HTTP error templates stay unchanged. No extra configuration is needed; HTTP status codes retain their existing meaning (502 for verifier errors, 504 for verifier timeouts). + ## Main capabilities | Area | Available features | diff --git a/SHA256SUMS b/SHA256SUMS index 581a494..60897b7 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -1,12 +1,12 @@ 61bf40a0572889dc8b0dda9eae4e93e44b0de9364b3c798106c85700ffb37c23 .dockerignore 4140a2956264b44f259e6a37fc00ba02097bbe68b09296e04d3d243c1287129b .env.example 9e6356475bf587091bab72246ec9e325b498f7e48a6220e9a18baa50d0a385a6 .gitignore -754db9d80640bdb05116d14cf91e1b69bfbbcfee2c522659ace4a4c7d48bb10d AGENTS.md -df0f23d242cc45064e2e822bbd1fc8297acffa89f71eed2c0d4314695107d5a1 CHANGELOG.md -b548ffccc83f59c886fd111bbfb63b40b34c35889f752e44e586c8e22131cfb8 Cargo.lock -bb70eb65066a0aa23859a2ae006ba1bb75ff86b87afd4fa6160eae78a8d42af9 Cargo.toml +9a882c75ba505b097de65a1073accd3ccb30395b2454f3c3fb9b25c7b2d9bd6e AGENTS.md +3e27930459e3225a19aa5174bb9523df3613c009b7b4fe117311b528f740ec61 CHANGELOG.md +11b42e2c29662b09b6ff1a575ec45a98856daa6cbc2c0351afa9f1fa4a11b1b5 Cargo.lock +f3cc334705c920f910dbc0fce374b7223c2e6a66abe614cf8074c6e89da1d537 Cargo.toml 25c7f3c8162cbf5cc156439774118a81dae9fdc52b611ec7e40c230fc99a772c Dockerfile -3b0ef7ac49dfb35375780c53c48c03004fe240e68bb7337d3c8c5ad0a0e15998 README.md +750f73027faed6039b06f75f87c5a3c1e646ea396a64750688d2ca1344ab72bf README.md e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 ROADMAP.md da8311e3db945290666324a2f24bf4521b365272d7ac3f862ded1be993eea646 UPDATE_CHECK.toml ac07b3bdd46c787989e93f55ebd6ea3d7f5b150ef36f2422e2b58df3f6b7543a build.rs @@ -27,7 +27,7 @@ d660f46f7ef8c539dd3f5486a31d5a1254b9737be8a278c7f9352c254558f8ac docker-agent/m e52b31d0abf65ae3034f6cb367cca113633014ce8d1d799ad4dd5624d2c7b8bb docker-agent/network.go 634790f35ff4627df2a78cec2ed371f6e9ec9df00afb386075595fc7f3ed72eb docker-agent/rustproxy-docker-agent.service 5220d669171ec3ad65f50e0bc8de5178dadaa4904def8e1a4f61002aa9e9a55b docker-agent/server.go -aa1be1593874450822055e72be2228c914e0b146c04ab8247d7a957afee9da22 docs/ACCESS.md +93aa788dc1205bc9386a95a39b30a3862a42ba6a2e90e82fc5bfe681fc7db6a7 docs/ACCESS.md 147755fb33e9e91098a4d2dfbe6df8b0d92d602e002d568e64a0f815641be2c2 docs/ACME_PROVIDERS.md ba40dd0ec51e0992c0fecd12934b9875e5e7252eced8db533cb79ec01ac8dcc7 docs/API.md 2362ab34020d4e0dcd70e280e9539ef7764b63212856ee08a3a55906c48f6421 docs/API_ACCESS.md @@ -39,20 +39,20 @@ dc670d912a6a946160c2f8528c9bb710ec38ebe406dcb7dcaf18fb2653f667b6 docs/CUSTOM_LO e350c5081085b79e579d1500fa07feee94a709adaf6dfde7b3d9af124a78d184 docs/DASHBOARD.md 11a08bf2110bbeabc924eb049a30177a216af5607ccdaf8be9178e751f78a2c4 docs/DOCKER_DISCOVERY.md c891ee5272e2e47e1a8f97133a413e2330844103d543fb5cbcc4d0724d59a1a5 docs/INSTALL.md -37001cbf8ed248ca05ec40f12dd9876d33f6e0c97dcb21eb2e6f53c3d97a60bb docs/INTEGRATIONS.md +7c97df0b89e230851fe5211f5b295aac1f71a0f64385bf165d2aa7db893fdf74 docs/INTEGRATIONS.md 694cb7b15c5bbdc94cecd15dc516c05dcb3467849322cdd125b872d36dee4699 docs/LOGS.md 888cdc8c56e10b8a7615012e192e085bf2899d0ec9b3ddfb5731e7de6ab5bcde docs/MIGRATION.md 27ba3ed337963d9cd05ba382666eed9c414f58c52e5897b4c1c45603f412b456 docs/MONITORING.md d5894c07c68ec4230987767198434abee13b0e525842fea21bcbe752fa82742b docs/PHP_FPM.md -42603310536acefd915f3a629c653664056fa4282801ce0ebae19025b2359649 docs/README.md +0f66cef23c9a8caa378497787811edcb4f48e31b72bbd958b2862a9549d78077 docs/README.md 490a6dbe870f2b1fd4ec7816768dde6c86fa7957fc9de2d2f075e123c9222222 docs/RESPONSE_DELIVERY.md a7c5b01ad1e6aeb27bccf1085504854b70ed4bf020b481915aafcc4a8aeb1f54 docs/SECURITY.md bbef60ff1771da9f48af812987766e1e479408873ae2f079b13f1d5c62ecc6ff docs/STREAMS.md 6508819f181e2a935ffa117451915aa5568a31e2890c57fa10e04543db82f3e7 docs/TLS_POST_QUANTUM.md 43a2c6230f95f81bf4efd1575a4f7cdc8b02244df38e19b1ec9c3cd736d3afe6 docs/TRANSPORT.md -8542c4a5c9d5dfe474459099546ae590b4c4d3f363f0bba9721c6107643c2d3a docs/TROUBLESHOOTING.md +df0d5e9e83ec3827ecf6887801137569118f8f29680b0dda23887723f8d4e030 docs/TROUBLESHOOTING.md e14c02f2c95daf5779d1aa5300751162b63fdd968832a1f0c2f191fa00ace6dc docs/VHOSTS.md -25fd98fd7257bb371472ac32cb8d508f5ee3d785a6feb01fc45cc80a3d3afc54 docs/WEB_SERVER.md +7e7eab2ba76c262e4000184f80f9a5cb69c7896fe7a046c0d3d84dc211c4b751 docs/WEB_SERVER.md 5502e8ce44276213803b66c58e3a4d804a1354f5ed5d83f47ee805e8c44ab088 examples/acl-headers.json 2431dd88a2d9ad2cf3cd4b8fcdfa602563ab1013c612d8917fddbe7febfb2dc3 examples/cache-dashboard.json e31ac05a99615e4ea6c4c9a8b2e090968583fe3959f838a600b5740cb170f8c5 examples/config.json @@ -64,7 +64,7 @@ b26833cb4251f9390a44192ecc827ff7f052fd19016a5ccf7498c94503ab4ce3 examples/mock- d242de9614fbb52933b4accd32f4715ca94107abe4a3b1d7e088362b07a6ba60 examples/vhosts-balanced.json af2bdb1343a8141069e94ccd2c7f92574ad848437e2f9fdb5c7576a9a18ef4a5 examples/vhosts-private.json 1b8974af79a5026e0648ceab58a32f233e1760e21e7465a0d46e9c41fb09964f grafana/README.md -ea8aaf0257a5ab75153ee2fd383a4d5c2ac725c47042f9770949451636d442f1 grafana/rustproxy-overview.json +e775dc98b44bb1c362d8de85ffdee105694807a946029544aa13780c806aac33 grafana/rustproxy-overview.json a05cbbf101b288bf9cf83fedfc5017925a8b360a78f313d31c1a70f15dc1dd22 install-debian13.sh 909e9ab94617ace74a425f15084bf85f3086cc52ba5b28f2b441ff800abc6ef9 install.sh 42f9f1d18c021fc7734b5bd020844bf678725a0e539e2fcbe05ec676f6239eae integrations/README.md @@ -118,7 +118,7 @@ e69813fb1d3a4cdcfb7243964cc323fc21a603087bf2e84188fa42b9d3cee4b5 scripts/runtim 046b4282550f5cb4e53906665c91c7442be70fc68fd0743466fd832582f7c979 scripts/test_stream_tcp.py f0b48ec0cc4411755cc0b4128eebce710375afa99344cb76198cf31074f8eb63 scripts/test_stream_udp.py 22e880e98c7b9d700c7a4c02b9b1d543e5dbd1f4ecdca42813a1083165b32a19 scripts/version.py -5130529d8f55ba9d89c29235a7eac133a80c9e9b2591267b1d082207568abbeb src/acl.rs +a6b2c019978e420dae9c4dea3ea46402b51411a589468b75aada8ace6fda9275 src/acl.rs 68650bf15c8d1147bcfd49b81fb313171d417100758c1b86a6260c4eeb3f765c src/acl/dynamic/mod.rs 1eee2ea2c8dd6068dd0bbb058a06d26436f14767d8efbc2010bbdb4e3e523672 src/acl/dynamic/tests.rs 75120cd3115aea6fc40665086617eab9816f08f556cef8db370806195c7641bf src/acl/tests.rs @@ -132,24 +132,24 @@ c51fd51177a476be6462ca980e9bc13f0d0b41538f520118b80a685130f0dbf0 src/acme/runti 2f02b08d88ad3c1fc9827e5bd3ef463effba633834d9c05e9c0d6d2a0e8869c5 src/acme/runtime_versions.rs cfc13a293c126bb511745859669719a14c72dd7ff6be197bc9e0d0e560deebbd src/acme/tests.rs b28a08ea996befe10949676f40fab5f1036a274c7d0ab1175cf5c43c59849dc3 src/admin/access.rs -69e26e4f06f6084a61b0c40ee2e8d3f027913eaa87d877477f0b9b1fc02589b4 src/admin/api_token_access.rs +3afefdc6640d35bd55f20981e842647573f1ba80248680f99ba79eec9a7c4ce5 src/admin/api_token_access.rs 5f5b150bb8f51f57462e519650093354ae7b40fcb80c4380fd3391a33f4b30f2 src/admin/api_tokens.rs 34e851f725e8605e3c5d9946e56ac035996f3bd9d608169cba3408060d229c9b src/admin/certificate_api.rs 4a8b6406a44508b8ba102fef0d8309e871dbe0cbdbee1e6c8721baaca0c1aee1 src/admin/certificate_inspection_tests.rs fe1934fe1ed611277a55485f187a4f62e1fbc3cd196676e64eb1deee4a4c0323 src/admin/certificates.rs 521ac794501570cfa2e8e50c3a5cec2ca08ee4dbce8ac9c0e0310c09612f1062 src/admin/config_reload.rs -39963903d93ea5b16be834741c7095f7e9bd9fd8fb7dc6ae645d673d0e7f010f src/admin/config_sections.rs +b7b0d3f0df7683b031136c05b314e206f7864e70514fe25165e41fd7a9382854 src/admin/config_sections.rs 159c3970d25fa29acf2483fc9422b003e5d63884713f62baa8375e4a4020730e src/admin/dashboard_presets.rs aae1ca0e70d987830bd63948d431f54302083148177c1b551565be12df7fe771 src/admin/documentation.rs da28dd57087df138913b784b71dca11d36c68100f2f100f452fbf4e4d7982433 src/admin/documentation/documents.rs 6ca14ae276c0e683903cfe326f6733cf33ea05f3abbefd5a22671ea160a58ea6 src/admin/documentation/tests.rs 1ce779b84aa8f47bdb3c34f83593c1f2f06d2235f0319847096cfcd035434168 src/admin/file_log_search.rs -ab18acf6fb4ac86fb22635b9219a12dac76d24952c8f15538486267a9b4b7855 src/admin/file_logs.rs +059218501907355b22bc84e7e0c41ec72565af283f5e97170ce7707ea5874009 src/admin/file_logs.rs d58a2ed83319176de4e66790ed292447c9497ae031464ec55cfe27174acb639a src/admin/file_logs_io.rs 282352eda7957477e7da44f16b90984b26a4a67a8755833bc0a6b34eaf93e3af src/admin/file_logs_query.rs 444d7715406ffd2305a72decf7fdf633aa4c2752cd881c8fa3b95ed971d79820 src/admin/logging_api.rs 243f4a9c3fa99781e19c3952354d2632c0ce65e1dafac729567cbe3c177f94cb src/admin/mod.rs -8b5eaeef6ae3f216afae39abed1d47e58ac41bacd1d3e54ab65e0e02f6cda093 src/admin/openapi.json +cf7393a5a6c101bc739a4cbf73a2abf60ca8fe2184ec84ae244ef9bd5f99c2e1 src/admin/openapi.json 1f4ec45d146e00ef664fae37517f8fcb5455d47daec496c02b2fc15ddec49131 src/admin/operations.rs 257d93a29d0bda96462bcf695aba8d0ec0f9412c379e066ec46ae8ee034e3a53 src/admin/panel_assets.rs f5127855c2994d052678865df36d703b74f4a0afc633daf7718b10da18d26e37 src/admin/panel_content.rs @@ -159,13 +159,13 @@ b3c3c2d33c150eb42ce210c6074e5eff6a8af9391118012e413bc9323d3ae50c src/admin/pref 62ecbae5dee00aeeca3eb806e2605372471dfab971cde8f66f11e711df8fcea1 src/admin/public/mod.rs 7a00e4ab943f74d2b1bdcbfab7f9cd3f584e9f59536b4aca6c4c31f5f5508d12 src/admin/public/tests.rs 6930b4f4b45257772b321b20a9becdf9bc4610274852948ba38c2d0cdf02dfaf src/admin/refresh_preferences.rs -6d7f3f67b9a0723ba443b09ab3668b5c84bd825613b1200a91b181f9c116977c src/admin/router.rs +cc3aa1b094b0d869d141754ac2877817ec40a362acfd7fc3167ea3c9f1ff1a18 src/admin/router.rs e135431cb078ddb483165581123c64af8f00ea67acb3a395ec3e53c85d0d0d45 src/admin/session.rs 09cc50a86960897371730cc1abed83f4f640c86b680ec7ff6d6b84c7e96a3c0b src/admin/status.rs 2d5b4c28fd0bd48b06890fa8ec44a2296de948c1f88eb2909f4b495710d4e13e src/admin/status_live.rs 8315c856cd50f1072593ecb30c274d42d82f078b5fb93e7c68a8857cd81b0841 src/admin/status_system.rs cadd7dca29b9aad8c77c7bc23dd249ea37a15adfa4d636a8ef00273a91ce35dc src/admin/tail.rs -0d304b616bd03fbd63bcbd371fae1034ef4e1e9cf28da7320f53d8fd307fc0a8 src/admin/tests.rs +d5af049839db73e4d44f2b4455d072c6fb167ac2bd87b3f4aab0ef1d1a2e1209 src/admin/tests.rs c18c369124368f58524652565102817ed69fd25b222b0c5e737ef7632b45dcfb src/admin/web/acl-picker.js 48fcd818c522fe80f2c7b2e218f87de6a7772ffd0a24e93502780b03ec78e335 src/admin/web/acme.js 86abf50f39862d821cd2e43ca425671aa85289272915132c5a9a5dd1fc4182e2 src/admin/web/api-tokens.js @@ -193,8 +193,8 @@ b7ead49224a4ec67181d3f24f9d9634bd6d76756f826a4d5d993300637d1d8f3 src/admin/web/ 596205feca534302699120b84848cb0f3e9ef2ad7ba24eac18d5751532a40194 src/admin/web/cache-panel.js e9788a9d1e0bce8775f612a5c842afea8a0dcf01301acdef4b69ff6a52d2ef45 src/admin/web/certificate-api.js 9d000e98497b3387641500d5273d23eda45d532c714f22e187572928da152a97 src/admin/web/css/00-tokens.css -c6be9f713a97cad7f6d71408944f99f547201a707c277ebc88212ea3823f7065 src/admin/web/css/10-base.css -4aae1657e8f5faa755cab0399769e6179364148f80243e742fc7a5e6e237b3e6 src/admin/web/css/20-shell.css +51437cbc5ec2d9690a685f9ad1c9235e503049adc4438e1b10ed232a9909b862 src/admin/web/css/10-base.css +195a6af7f54f310d936d32b1074e3c5daeaac1a8c687b8dff0223be8ea34eb36 src/admin/web/css/20-shell.css 707d08b7b8505c7346d5a98f3a8058f10577ddac7b9e6a5a9894285bde9e300a src/admin/web/css/30-overview.css ce5ffb911d7e4cd2317ca047534921132b6f93efd70a26673f0c428e55320a4d src/admin/web/css/40-editors.css 6537a3f97d046b8325c744a281a74f8c4005a8bbcd97284ecf7eb5b6973ae1df src/admin/web/css/50-settings.css @@ -222,6 +222,9 @@ f2cb26eec86b6c03151072f847153df8aea612d840ca8b76367f41b9605bce64 src/admin/web/ ff72fc4c6a11907a16234c4b3c7d7f7bcf82eb72868dc3fbf654b04aff806fc8 src/admin/web/error_502.html 386b9dc3aecebe7727f7cf7bbd2a02ab036a3abf01315975111a51559128df73 src/admin/web/error_503.html e6c4d91d1542d0a5b47bb8736f9539d43a6713df5a473b635519d5b7eac2eb9c src/admin/web/error_504.html +ce598fadd521ee000f05f7d29d70cdeca684a53dbd946a38af204fb2a9248b1b src/admin/web/error_tinyauth_connection.html +daa9ef52d96b21c492380486d1cf476c715dcd6c339b431887cc31776de966c8 src/admin/web/error_tinyauth_timeout.html +026361d7c3c3b596daa290feaa734f042fabdf236369cd4bebc39795f0c4fc96 src/admin/web/error_tinyauth_verification.html 0a5fff35555153f59d4346933030a67b6e1a8768cee7a47cfa2fcf1a2c564f63 src/admin/web/favicon.svg 7cbdef9192a9dee1f8eac42b85f52b3190f7f6efae50004aa7ad116a910e4036 src/admin/web/file-logs.js 3f0525ca1d4e088ccd4988b8a117b26a8cf8c12213b24c37081d41b68d2b0ff2 src/admin/web/host404.js @@ -254,11 +257,11 @@ b2f948bcc3dbd24952c7b1b02d41d06757f49f0c38a78caf51f8f8a687d8480d src/auth/files 25b9f78a7eee277902d375266bd0f023b79794bcdf646214fc161c5e6dab72d1 src/auth/store.rs 745226cabb007819370fc6aa680995a03a8a13fa057dacfab0fcc21d0c43bbe4 src/auth/tests.rs 32a25e53ac9542424debeaf1b637155bd4e60abd8692df082729d81232eb90b3 src/backup.rs -76aa2afe9e7302be39b3512f30d0448d9134300f8ae930d64ada40cf3ad4a8a3 src/backup/archive.rs +0f07cac0259e849773466a6fd468fbe84ea34bdb79745dae8ace286b8c707727 src/backup/archive.rs 15213c87d4393739328ebf0eacfcb45f864ac12d7bd7509f750a241032f6c7e9 src/backup/ownership.rs 37f44cf3ecd71c7e817c76462c4c7de7ca6ecd68c0544f6429a861cdcde1fbdd src/backup/snapshot.rs -ece7a5eda4b57bae8f5d819a309cb411b95b1845f5746ac162dee51456365857 src/backup/tests.rs -f5afae218f3a6f91bc2f1f5a90094630ce5b7ca574de61807b5a317b13937ec2 src/backup/validation.rs +859cec0bcd604f205d7d8e14d1c810e33d97fd7cf00ddcc30877bcea7c5fc2b5 src/backup/tests.rs +5293e1b06f82654929805b53b9092a82b7503a54b34da3e882a999c5f14ee579 src/backup/validation.rs eec564a7ef886d18ab75289025a47d62bb702f07d63f92d2f83b7afeecebbb15 src/balance.rs 8f7975b488fad31f8d83ffedf8a5b6774b86b59290ce0711e779bf2496d5503f src/balance/health.rs 344631248c71164187497a10d177d8eaa3e2f4a08111520d2536ec89ae55e1e0 src/balance/lease_runtime.rs @@ -274,11 +277,11 @@ d789bf40cf9433e2fd16409d112210fe93154588b1ac9bddc9c7f78e1db14426 src/balance/po b75ff512a1c6344483e00d2c67578ceea6b5472c279da0246f3622daa68d7e16 src/cache/cold/cleanup.rs b0ac49535454f50349b5d808c9ebf3a2506c94e63a47dbf802c47fdaacf9ed61 src/cache/cold/cold_tier_tests.rs 3c3897980c31a69d96f9295689d1ae19f2190da758c69ee7a0541f4171288bb8 src/cache/cold/demotion.rs -e80f84449412c4ae7bc753672a554160519bf1f186b5707252c3286cbe13f02e src/cache/cold/startup.rs +17b2a157b03f43f49ed05f1f3391aef025a453b748056c67229cb3ceaa53bb7a src/cache/cold/startup.rs 83095bc93132f306c537b31ba929669fedac99af3c4f133d0533b5ed7ac4e6ed src/cache/cold/worker.rs a36a4a255a0fd2c38449bbc462b9c0e21488eae108c70326ab2a0e4c7cee0f97 src/cache/collapse.rs 346fdb40d85627b583a01fa17c65e45c822dc7216198cdeadbb3d07904286fa3 src/cache/dashboard.rs -54785b64ab4a7b0382b84b4a313d1996c4b6986d69f1e598293f29122afbad33 src/cache/dashboard_tests.rs +be3d80cd340edb47755190a668e2f2a2776940665f95ae7110893b706eb94faa src/cache/dashboard_tests.rs 8b5a8c04a8ee115497635d2faf08eab5ca4db4225c6c70110675685346f9c0e5 src/cache/fill.rs 675d18afb53f25c56cba49bbb431fa39ecd9d7bdd192c7b39b0698225de7a2a2 src/cache/invalidation.rs c1357a13658e1ed5158084d3a41ba9ea906512774a5863ce9c56cb508d3fa6c8 src/cache/invalidation/ban.rs @@ -294,65 +297,65 @@ e9c6ab0c2be9f96573f826e6a1b9e4c2b8b526f779e72e95a6463ae07e45ab55 src/cache/look 0c8b0d550e94d4474dcdf991aa0340228dc5f2f904f39350e6e666a16f16fe87 src/cache/model.rs c409174a9aaf20c69dc7b329108d1c26b5672a7341236cf639480df48800d262 src/cache/model/cache.rs 0ec4f6d0adea1ed80a3ca17c68c9c85502491da2904d9d690b4169ab9b025b21 src/cache/model/cold_metadata.rs -9f3143d99ee7e11abdb625cd8deff0af3ede8af716ea99b754e92803d1150bf7 src/cache/model/entry.rs +a6558f1c927b2f2fa0e2536654343a172ebca93ef10363c341cccffa3de0293a src/cache/model/entry.rs ff1c3a1a3bc0d26218dcc943ef951c2a212c180bbf6e4bf1c542ffbf12a9f150 src/cache/model/http_invalidation.rs -81938ee9d96891a6e1c81ac1117c67bd4ce4a1530684eab84521b3de1a503dff src/cache/model/maintenance.rs -19aaf66abe2ad30b973131a020b7ca8ec6d0646a51df5c604c5f8914db898416 src/cache/model/settings.rs -395a82091ae520b78fa606553a0ec590ffb14540b83234cef5bbdcd2e57d39d5 src/cache/model/views.rs +f3f8c8116202bb66e3fc7facd0810fd0194838c73ac36e5d372a71549d8aeb6e src/cache/model/maintenance.rs +18a2ccfa74a959ec7b41754aaaae073169cf20d9f67e97e8b33191fc706eaaf3 src/cache/model/settings.rs +6aa7a03a52508f19ae1ed99036563157eec740b417031933540cab56d35b051a src/cache/model/views.rs e26dce02df9c043329ca164fed215d271781bce8fb03240f528331bf3df6b9d7 src/cache/policy.rs -896b1869f94973b30a0de0faa62a2c89fbc8991b02de0e5988ab4ce1f77b392d src/cache/policy/request.rs -9dd790a35dbc15df8465664ed9fff296fe22847371d667aefe320504ab952b2b src/cache/policy/response.rs -e59efd322f518ebd7b5b154115188f382c2cf7882ca0a401736ba5d685981ea5 src/cache/policy/scope_tests.rs +8437aa9097058b1ad19efedb6e2be50822a7f67f05ce3f7182a82665dd1be881 src/cache/policy/request.rs +eb64c98d53eb38492810a989e348e5ef10c3c63ed60bc30a1f7e06d62916eb7a src/cache/policy/response.rs +12a6d5d9d6711e956391b4b952e8149658b8bf64cfcc0a4c59c281f2630a6aac src/cache/policy/scope_tests.rs 4179c2c1367a9c8ea8432bd5815b7e7afbca820d7589742b3ad4775c0cc8e0bc src/cache/range.rs e1d3f0512d6290b0ac4998f47398a0a7c404db249c5bbdbc4ad4767071013a72 src/cache/stats.rs 8a300f5dad44815401eb23f4f5a157893761852ba4f3005041e0eb3f16892ce3 src/cache/tests.rs -8d9532ea1f30ec431195698a9aba82f2d31083d4b4ee98cb8d9eb47b2b01c7b9 src/cache/tickets.rs +3558b10e6bd36a847afffa4ea888ac7cc0a842be128a8503ab18133e79d5e0c0 src/cache/tickets.rs b7c063ed4c8ca96714e1dc5d279f38fc521da2132faad7bd4f40311352a71e7c src/cache/v022_cache_tests.rs -452ff2f162f70c3e4d9259de4b13a7751874742c6922c5e0e0196eeadee4ccaa src/cache/varnish_compatible_tests.rs +d87f99c48c05ededb0586626d3179391257f54363516119f1567fa0590546485 src/cache/varnish_compatible_tests.rs 5a8022f6f4721f9fabdc715e01127d9299d47ee9981a79d26df1981448487d20 src/compression/mod.rs -2bb1ea392dc18553a03a6ae1c53f52712ae86571ea31b1bcd93c8fdec2cb60ec src/compression/tests.rs +8de82d9188c9c337690c6ec4afdad9fff20651c358e34602a93d8bb8c3d2489a src/compression/tests.rs e695079333ebdc2a6e7b3337cfabef171b3a0a01da0597b77feff70d417f833e src/config.rs 9f6272bd6d1f403cf6324b12472fd5c7d911a387139b57105ba1819e48ea0a54 src/config/backend.rs f4df024acdb24be450822e58108af23db3dc82bf1f77531cd16fe340fc01062c src/config/compile.rs fbea01fea1213d98aea812c1b78d5db289e09200b98ae514d742235cd3fa70e1 src/config/internal_routing.rs -2669ee64cf00ebe5eeafe37dbbdd963c859f3ced9fea97a00c3f1ba2a42a6e57 src/config/model.rs +6e8116efb074397905b41331097cbf81099a21a896b686b4de2e3f210e783620 src/config/model.rs 75839458ddbc7480ec4492a95eeb67b617ba7d62f7b67e7a767a3453b74dbcbc src/config/route_policy_tests.rs 40e9483d7b2450f55d29b46c408727f4e331b85ecda44fbd7b96bd9a09f02655 src/config/routing.rs dd9a6ad8f58e0cdd1ae74f3f972fee0ac14383cd8b8f518403b9a36c169f35bd src/config/snapshot.rs -255b35ca29d25b960d339d2f8088441cea587c556da25de6a159d93f944a9eea src/config/tests.rs +ba5829a5fb65e76e2e3450e897eb2d21105809f1d5e16b630a6faca27ca14252 src/config/tests.rs f35de0ee1516ece6bbfd2b2a7db7d1e0f5048b0ec47cf2a3765dffb799abfd93 src/config/transport_tests.rs -eb04a8922da26e45c9b6005c0cdf1b1ddf2da3c3b680650b22a1d1f16d17a4b2 src/db.rs +e0f46d885ed81ce306a110560cdd2c217dadde054986d89fcec835ebf6939d65 src/db.rs c290d0cb02dfa5d2c60ecabac1cfb20c8884e3d14cca1944906c6d8e677f1784 src/db/api_tokens.rs 892ec0e5985700cca399c861197f6c9d2f1c823d8d95b88abac9d27ae15a069a src/db/certificate_api.rs 5491dd7bb9b3fceac97c4dea63aba6d5c7abcb0fbd06e36ae986e00c79bc07d0 src/db/dashboard_presets.rs 2ff744223934685439374572b83fd639bb3eabdbac168bea4a6501a6e9ce0ee0 src/db/history.rs c05a02618d476e4670b4f9930555f199cac776cdf09edb8fcc1a675695b8f99f src/db/tests.rs dada314e1709e960eb2e225b4d10c3cd12606c62c4bc2c0220aec1ba133e4ade src/demo.rs -5808205f03401e3f2c7f5c826d5de76e83e4b6f94c64ad3e50f505f985f6d26e src/diagnostics.rs +f9e8539223b4f1d254ee960f59cd4dcf719627101dd9e0190fcd7d331b674fa4 src/diagnostics.rs 045593a42a6e4f632e5052c655788f0843faa313fc929265b89509f6dfff91ed src/docker.rs 93a8a3f6ba12761ddcbd19f22f32fb2c0e6948b660fb774ddd7ebdba9b6562a5 src/docker/client.rs f69087a82cf353e9a92fc97ee96510dbe0382efa1c5e53821d16c455a3eb95a4 src/docker/model.rs 810415a436d842b79fa72392cc18977ad9c368d233ce43e135a60119722c9e77 src/docker/reconcile.rs 2e8d4841665cc1d29e6262a1789bb64ced1cecd0036681cc1ef7b5d5bfe22065 src/docker/tests.rs -e36db1ed3188ffe54df7fc4ef76c4b453f23683bb7b8cdf601046e2bd50e0403 src/forwarding.rs +b496edbfcb8fe7875a95835f8b10a0dbd46775227dbd1e5fee555b284c836216 src/forwarding.rs 08d2e08a798abb944a53570f0bdaa08f1266b1107677ceda070091af4c2fc121 src/forwarding/peer_formatting.rs b821e2efd2939cb13d01e402532f33feba6682acb6a7a3223be086c1cd171820 src/forwarding/tests.rs -5cef023035309caa5ca2035a11a77cd485f72092ab1c7670398d415460f84bc2 src/geoip.rs -80850f7acd1ed4c0048b065e9e81740869a8efbb0d9b5d2e83d8ec7fbc494703 src/geoip/mmdb.rs -06aa056d789742cc11c8826c338d985e6a6fb22da6c3530937eec38e35478034 src/geoip/mmdb_tests.rs -d3dc58628683472ef4d205fa5c42f0b7ef83cf90846146d96941cd3b36a40766 src/geoip/tests.rs -70091bdf6f38f03b6df8c8c4407c300677e57f293130122503f936500963d37c src/geoip/update.rs -c1b49bef28d87712e4c46138e70b52c4bcfb1a00196579031fac043d0b4aaa7b src/geoip/update_http.rs -9a912dad0b8d1e10410fd95d0da3684656092ef85cf8b23eda4ffe7fb92921d8 src/geoip/update_tests.rs +c3bbae778cbbdc1bb299152813a2513c6c9f9840114b15bc2613908625d9a79a src/geoip.rs +f551ab3bece770e772fbad46eb88a1e8bf58db4569a22a57eb0fad99abc41e89 src/geoip/mmdb.rs +1e8777b295e6a2de15b55548e8c4c3a4166b1c5af18d4d33bf067d8bece1b590 src/geoip/mmdb_tests.rs +cfc75486e69c310fa6e7bf0448ed39a20cdad9dd8afe75e01592fc7c76a380db src/geoip/tests.rs +3376ea3d018faa5cb8a69da2f1d5b7cdae4bb4b8f28f373f8a0a2996410e1bb7 src/geoip/update.rs +86a16add6757a377264ae6afe071039851d5996e80baca9d4882b71889d7c2d2 src/geoip/update_http.rs +618d5f245a9c7a1a95e1d086cc01bd2aa4f0360f85094f1c2403a5c14a6607be src/geoip/update_tests.rs 61a2b01db9010f9debfb38b43a26bf588438a5e470dff938e4e54f9d7ba46732 src/headers/mod.rs -e4f07bfb7eb75b6897ef812870caff158679a3046d64582428abe8c6df490dbe src/headers/tests.rs +3e9a19c221fa7e63d097c185470b17313da7c200a73ce50f6c069b4dddd37a96 src/headers/tests.rs 1b291ef7b06647ce820111cc802874394e3600b4b2c86ee9a1fbf7eee6cb864a src/http3.rs 0cc484bf0cc59a55a13e0e70435833a9a7a22ad7dfb5b9f86e059cf70a80cc2d src/http3/body.rs 741972222414c280104acbcd8f8071bed9cbfcfa2f503c487c11c56f553f53cd src/http3/diagnostics.rs 49ce4452ef7973cafa2e4071e2e14be0e16000e931a6501e4dc613652e49e230 src/http3/identity.rs 0b41072f6bcf28725c80f471584cd55d4900424ce5d55ac7f6909813788c63fd src/http3/settings.rs 5c550075c7b0fe687ad02095c1cad57b46b579fe21dc5371525b6c77db459886 src/http3/tests.rs -68fb5ab6a889995a66ad12cb6acf88c5d04f0aca572e2ae15f1a9cd171a5f24b src/lib.rs +65cbe42886c89cd6675fe42f2051a8adba6b22d4bd106d93a205321baefd7a01 src/lib.rs e8399753a6ff49b7de19edb0a268bf871c9979a518354160cf07b4669051fcbb src/logging.rs e4be3ad758c3d93ce52dd3b1ab1a87810e5226339400ed997607a5b746354751 src/logging/error_runtime.rs b2ed730006fdc080cf7eafc6d20bb89661c639631c89642d110e0c1319e431b5 src/logging/format.rs @@ -374,7 +377,7 @@ ee401f943bd8b2706c33419ed69102269c08dcb4ceba6f4be2ac0861115874a7 src/metrics/vh 9c96c3e4edb20dd0c36b5c373f1925dd60368e75853002206523072d418d5417 src/not_found/mod.rs fa2fc6c6987a8356a9da92cade10db62426d8863e9cef3c0d4324c45780c5b33 src/not_found/tests.rs d32d757ace8753eccb842c24b7af77061141478d10fe0acdfb05263d19e9a64c src/pages/mod.rs -9d3f4db663016033c4ba0d86e30367bd5a1ab79c8bc121265d410698104fa19c src/pages/tests.rs +0e973bf65f232b5de00f0f39b349a6fe9cec7aa1760184e2474e0c7bde52f7be src/pages/tests.rs 5650a3f70162abd97021e0a51a92cac2c4dd39004426ef99dff36cbb0741aeac src/prometheus.rs 192a780d5874afc158d62a7dbe1687d734635afe9342fff526b8a2f6db4e5633 src/prometheus/core.rs 2321ee667569803dfe6c92c0e98adba0ac8fcdc6a3eacd5857233f1acae93daf src/prometheus/docker_misc.rs @@ -382,17 +385,17 @@ cc909edf740a091f9057912f555dd888b644fa1cb49647fe0e2e1f5dba8ff5af src/prometheus f9aab3297fcf647295849f77cbf99197f4dd27efd6817e54c03451e04972430c src/prometheus/model.rs 2ea975c96fb45bfeeda95583e909abb26328a16e411fa46a1e31b2a359f7e711 src/prometheus/tests.rs 028e1dd9f2ec2afaf699a6b21c2d4b0d96e76f11f5e4ed009c233dadf0f3be51 src/prometheus/traffic.rs -e03f0d6b3f35dae6b98c394837aa0d17e4d73a8306767b4c607868bc00c30286 src/prometheus/vhosts_backends.rs +cdbfa0e7f49200dc70ea6df8f0594399ee3e0c5fc3d279cc336e2d83d0f8a535 src/prometheus/vhosts_backends.rs f1b0254f53b1a4336bd8170ad441ba072b49a114e497b985cb20699b4e375044 src/prometheus/web_php.rs 569eda61453affd053fbe24fa59652289cb12d22b77e64caa38325bbea48f7df src/proxy/body/mod.rs -57a71c9c6e4e0deba5d05963b9870af8f4c4d8dbd321ed4e52cee88746c997f0 src/proxy/body/tests.rs -bbcb1791a0b1dc48ec6f8e37622f1028109e9b614e57466d75c79717ede3cf91 src/proxy/cache_helpers.rs -7e3837d2f6ba7d07ca2cbabda57b315f5a7f4d75a13e5eddf6861a150d0d2ed6 src/proxy/cache_http_invalidation.rs -d134b0eb617f82f9971b3f3461379ea37c57bd0079bf54748d0c434b2ef1b475 src/proxy/cache_http_invalidation_tests.rs +5beeac12ca7f041bdb9b74b2dbc9781f5d5524fcf51294b8b6ad88284754ef20 src/proxy/body/tests.rs +e5e32d86780119dd5eec4c8a369cb1aea44904ab62646e04e458640a3e4358eb src/proxy/cache_helpers.rs +78caad08c548386958f605f82f6c4299ab94a910a1332a1e0817dc53920c96a3 src/proxy/cache_http_invalidation.rs +a86b10ce0707b51e925e11ea14f7f40fa108a196166f62cf40007a97f9e17203 src/proxy/cache_http_invalidation_tests.rs a03b1735daa8fa8e40cf5bd9c6e200d211baf19c30f62522d4237ed56642bce7 src/proxy/cache_plan/mod.rs -3404b03096862de1050088f62cdd811ea1ab61d191f902501173107f81f23b9b src/proxy/cache_plan/tests.rs -a0b9e2e9ab0bc89c7b64bd19365198234b1c5c13f455ea47be122a5660639b17 src/proxy/error_fallback.rs -3efd124f2c27ac2d5b6c6c0ab6a5b91b7b18ce2f3bf097a00fca5475b05e36c0 src/proxy/forward/cache_fast_path_tests.rs +11f11fd8131023d7bfeceb6f4cbf169db994e2b6ca1931167f96ae590d8e0e01 src/proxy/cache_plan/tests.rs +3ba479d72d0e94263acaf2eb84f4de0ff2b0b455ee6a4d3f04bb869a5a30a103 src/proxy/error_fallback.rs +aacc3249b3cbce0726dc16e28ee09d78efc4ac89103675287b1adab870bb4e15 src/proxy/forward/cache_fast_path_tests.rs f7903200756dc6393392560656b23364f0d444d6357d264713b17c63fd8b636b src/proxy/forward/cache_lookup.rs 287012c81144d8f15af4a148ce3ca911d431bc59adff44e697567561aa372bb3 src/proxy/forward/h3_navigation_tests.rs a6580dc359d1f377a48ccc1a902056dc5c2ef86c89180b9b0995068d9817ae8a src/proxy/forward/response.rs @@ -401,20 +404,20 @@ a6580dc359d1f377a48ccc1a902056dc5c2ef86c89180b9b0995068d9817ae8a src/proxy/forw 744daef016d4a6c821ab12eeedaa2f29e2de72e2ac9dae16481d4f43476cb713 src/proxy/forward/success_prepare.rs e9ac9be64f6f83c4ca2cd5d299649f24dd16197712083c6dc10e55c662c65b80 src/proxy/forward/upstream.rs 690ff6a6860a7ca8ecd502657a68e5012b7f176036d6d7033dabc514735dc2f5 src/proxy/forward/web_source.rs -a5e2825d3ba1cbdc9d4afbaa133964ba0585fd776dcd8aa98c9817cc027a6b97 src/proxy/forward_entry.rs +ffbddc99112148dd28b4a81ec0527f608ce89fb412a0a8e99e26942cef13f9b5 src/proxy/forward_entry.rs 9b25f5e3ea4443a63ee6f45d12e1957dd316fe8e85325fc00ea416faaab1025a src/proxy/h2_graceful.rs 684ea1e2a7591a17e3c633576fc66e2a30d6636738fbce61dab5af44f2c51a67 src/proxy/headers/authority_tests.rs 66efc52d64d34667ba7419f8a2da89d2efb1af1f426684f4fff8caccfdf19996 src/proxy/headers/mod.rs -0f9314d1380febe436def36b5f381731e97cbac90625637575f38f3d72eaaace src/proxy/headers/tests.rs -c04451ac8abebf4662ccc3ee4610d5342ad5382da2098f7af5db274d079770b6 src/proxy/identity.rs +af9b044761a56e8a6dc57f9d760b289ff4a6bf37db11dbfcd3ec4da5b8f426b6 src/proxy/headers/tests.rs +9a26952f68cbe94cf1bc4a8ca70776a083b37c599de2297cea126799a1788a3e src/proxy/identity.rs a08ee061e146cb7a08311106f73a04468c89f77b6ad05a2c623621a2ae9faf2a src/proxy/mod.rs -5559efb5984e8da34235e2e5cb34cd6865a34ede20e159bc9f04fc9190a5c09f src/proxy/redirect_helpers.rs +da9148ce6a60226954cc839f606465b8c16a44806f4d5b2e22ad60484509b967 src/proxy/redirect_helpers.rs de1763b89d98607e20f0f6e3c9b546483927cbe5450efc2e5634fe691fd52ad6 src/proxy/request_id/mod.rs -b9a2307c6aa7f16613d935508a61574dfee964020b1b5be86293df2d684615d8 src/proxy/request_id/tests.rs +78bbc1263bcd600527bf71acdf5af92bf186267a9084b076d1f75ad6492df659 src/proxy/request_id/tests.rs 580fefdc7dfb27da73f86f4d2067d46a1f856d2f398b0598d37a743e880d3dac src/proxy/types.rs 37b20f962563babd3602d21ed6326946635281c0b0d97ca59f4e33de170ae93f src/proxy/upstream_helpers.rs -56a921ee4f30da154176998a383bcb5a40d3c7784a04829c59b8e6536728e2d4 src/proxy/web_cache_revalidation/mod.rs -fdc589ed3968915558a98a11c7cadc36145b5b0b0dca9393613391990d138fc3 src/proxy/web_cache_revalidation/tests.rs +3fb4896f2ddf9dad783005e34e6d4ca0032fb5a69ee38865b5e0ecc9d7f97f30 src/proxy/web_cache_revalidation/mod.rs +5522456cc85948228250feac92308d53b130c4a7af98d24f669aca4dfe6999b6 src/proxy/web_cache_revalidation/tests.rs 3d591201595a3b1e928ded20a8736477a47e5acc3bcbde158f7c17547ce155ba src/proxy/websocket.rs f8972bedb1a487fac86177774cd98cf2619fb25af97e57cfac2853db5cbf91a9 src/proxy/websocket/handshake.rs c02d42b5c7eeedbc54c58e98691f7d8e39f8e9be63a48f6d6b4ad6b8ea431b7e src/proxy/websocket/http2_tests.rs @@ -423,7 +426,7 @@ faedf6cc2bd4c42f342a0aa188b634d6b8d280ca0e121032977eadaecb88e9d7 src/proxy/webs a44421714aab37f7ceda19e3ec2512c645d2a3ce5dcb3da5bc7a0d87a442d6a8 src/proxy/websocket/tunnel.rs 999cbf85cb6e917db529e30ba4a5eed1cc9e95a054da7b3039c730bb80061449 src/proxy/websocket/validation.rs 80d0f744f7ad9f0d1edeb0d5c23b13cb40431f6b6f4d10d534ed34d4198e3dfd src/rate_limit/mod.rs -2fcfa9706eb0708519d5181debaf3c85a86e401a8898df72f9eaf0ab72c9df85 src/rate_limit/tests.rs +c85c9f05dac65cde6878bef3ef7258eb9de79ca14c26ca2492e0e13839c40fc3 src/rate_limit/tests.rs e53c40b85792d4804a432e3c97dc13af8e29304bb0d250ee9ab9018bde522eeb src/redirect/mod.rs 811c83ae9fd0f5a13d35b5443cd37843f82b9d600bee4bb136ba9b87732a5347 src/redirect/tests.rs 244d72b3dab36ec505c96d26a967420714fd3807268820f680fb3dcea0e88c0f src/runtime.rs @@ -431,7 +434,7 @@ e53c40b85792d4804a432e3c97dc13af8e29304bb0d250ee9ab9018bde522eeb src/redirect/m 2d610dc36f746215ad3bc1d860ee624a9233886d73a019fd243e51901503fc53 src/runtime/constructors.rs eb2b0eeeb617cad704732d87acb667530144836e26edb0189929b1f25f35c6b5 src/runtime/docker.rs 18f7460e3738386e070f66932cd77240001255447a769d6e19a40573254a1473 src/runtime/external_config.rs -a3b65ac6133979b2905b878e5634537994816abb79480af219a17896c6dc4e33 src/runtime/tests.rs +5999d7e91ee4231da88c5e9c6d8a12ea9f92d20d6dcdb24319f9f90891d7253b src/runtime/tests.rs d7a65497d1faa2f09a09c0a0ef77b444990cfb5ab379c85f6c27c1f9c0c143cc src/runtime/types.rs 11e99eb425887ad12b73d949f4b497fabc6897fee8fc7647fcb3766269c2fdc0 src/runtime/updates.rs e3dbd60953db5a976985dd796e4268b41a0f3df59764c4664015bd41e2578058 src/secret_store/mod.rs @@ -439,16 +442,16 @@ e3dbd60953db5a976985dd796e4268b41a0f3df59764c4664015bd41e2578058 src/secret_sto 98854bfeb35cc5266210b1c33dffb36b8441e27e61d90ded8b681430696d156f src/security/mod.rs 0e5fc2aff856bf6fd959cba12b5ddd1e3b3cbeb0fbaadde906c811cdfafdaae7 src/security/tests.rs 0e8589f56e3229dec556b427b87c2cc5a5a9ffaa9ea84fc2522dc72d3239027d src/server.rs -ad4cfd4a7d6f331a8ce3bf17a6c461dba788bb41994f667033c6963df3b96332 src/server/http.rs -00dbce1ff1ea08774bcfd79d900d71704256e06ab0cc46c379c3d107c99ba50e src/server/http1_connection.rs -1cb8260c74de89c3e13bc225da32cd86fe883acd3c720d0cb2fc44c0c55e940c src/server/listeners.rs -a64bc0d4352ec8d97895978a98b6b66e0459842d1ec410a1d123d5d29d9ef058 src/server/sendfile.rs +4cb5afb53c824f5c87abaa65ba5dc85e937255c4a3dd14af16df9af7e01afb10 src/server/http.rs +533342fb3bf8b52743d3a7102ffe345be9f86d553b16a1ec322e468b44b0a7eb src/server/http1_connection.rs +8e51738b1a2805c1226f537b85791fb687a52edf870cf2971dd9af75375febf7 src/server/listeners.rs +4e94d7cb95ec3e1e7b19884ec11c881e4fda1e57830525356bb1ed44afd6b17d src/server/sendfile.rs 5f6a59c6085c1250a93a70020661d1e8174d3b600b494d16f8eaf7941ee3bb99 src/server/serve/mod.rs 048a05a46108f50bef7da50b0c03b752d76e586b411de8ca3f55313bbdb08aee src/server/serve/tests.rs 669ea1041c103cb952f7a516363c8fe7baf51622f721aabdd57015e0e0279530 src/server/tls_runtime.rs -d0af5ee91ff7f0315d347b3fd41d60b41e9dd095e0d015ecd99f17c4f3a923f7 src/settings.rs -298673b6407b0ceda6ebc2ad4f4d787688cb0a5f144164f74895c745bcc53aa0 src/settings/public_origin.rs -a4fdf54f87bcc96b31e8a0ea400398a70011a044bf2ff3de78a0489b767f9de3 src/settings/tests.rs +d7f52ea1f6c0d037fc92d17872ec38df589815f9d7fbb038e9c1cc584d3534c4 src/settings.rs +b2e2924047019b1ada59c58a4060476151c99be12c0b4092f2cfd201c0756255 src/settings/public_origin.rs +a6a1cc42f0a5e40071b3683ee517c39f3c006ff3843dffaeb49391d58518c4ad src/settings/tests.rs 2ad7888b263e1dd9f0bd588dc35590c9eb232f8fbacd10ea7554cb55b4dbd25b src/stream.rs c7771539fbb94544947e958e410c46b73f9647011e56b1b229ce7035fe21851f src/stream/health.rs c02e85af45590866f20933561f85ea9b4f2ead62c2ce41db75113632670a7b5f src/stream/model.rs @@ -459,18 +462,18 @@ c02e85af45590866f20933561f85ea9b4f2ead62c2ce41db75113632670a7b5f src/stream/mod d9123c623e2a97d09e41edaa29993b4b2c8cba39a3abdf2b48a205aa9a9c2939 src/system_stats/linux/tests.rs 2c7da96822d605193f0208df70de670612259fd8c762c998ae828848cb210e11 src/system_stats/mod.rs 050aa831b1012c4aaade63863f433f01bfacf5d3f95787e57975572116a30ab2 src/system_stats/tests.rs -e7ed064a1706de9a7345e41fb8b6288b4467c12d1653e8afba6dc392c7a3a36a src/tinyauth/mod.rs -0e1d87554db55e724f30c41ec4a5c80bdb8fc9c8cba8700ac509864d4abf8871 src/tinyauth/tests.rs +f0a1109bf7be0dd6a8734be9d47221d99ac993ebfe8f73508191369db69cebcf src/tinyauth/mod.rs +e2ab9180f25b1f3c2723ff5a40d35a5a395a188481b766f2730b18e07500a636 src/tinyauth/tests.rs df98becda799b6bf4ff5e2fec7d0e0a486e6b7eca6f9f5ad49ffdafd49a4f498 src/tls.rs 2af2164ecdf2b7fd9eef7c6e358dec053dfac9aedaa501dbb75df742d18638b2 src/tls/acme_tests.rs -7425ee6c839f85d792e9251c6b9039e72fb49a5820a2266f751e6f4967a5871c src/tls/certificates.rs +84e3da17c59cc90e8575af8158ef4134cd058446a186df675d60106c53dd55ec src/tls/certificates.rs b59a62d723c8683ebd7bb2d2d777d9451064af20b254b98a8c4b9eedfd74bd86 src/tls/external_paths.rs 8d14216afdae33b9dffeb5145d92b8c6fd224c3f8f2baca0cf007b70541daa86 src/tls/external_paths_tests.rs -7b4c0f58b3a1e1791bb3c682a001b78bfdbbdafdbc143db8063b3f22dc168616 src/tls/server_config.rs +b705c6e5b2bd9eac2dd310478fdad1ca47610b80dd2d8c91516fb639b0dc2a5e src/tls/server_config.rs 7c0c06c3009c726043168ae47254a84642dbabbbce1b2e718544414312ca3e9b src/tls/tests.rs d625e2e3f669484432ffc0bf7c1aba94aa5bb709dc4d080daa3bfa8004dee9f2 src/tls/types.rs a535c8526b38de2990da7781e158b9ea70ef8c1f6fae0aac5ce6e9da21d3a309 src/traffic/mod.rs -dc8a83fae47da0d86e6ce0a329cb5274233264df56eebdb56b9bf37cb7be2bb4 src/traffic/tests.rs +bd62b4ecdcf831d183c7720766a11703c8612d614e3abf38d2bff28df34710fd src/traffic/tests.rs 65fcac840f8b5f1508213e3f374aa318b450b0f9f90ba827c5ea935b9c60bee7 src/transform/apply.rs 34a06c2dc635e80690961ef61fe84110f9578f55adf89f92a04668783ccb0a98 src/transform/compile.rs 5a16b628af31fced425903a9d4b6ee83e1fe06ba023d574db16467baefe00ad3 src/transform/css.rs @@ -484,47 +487,47 @@ d13fa462d6df516a4cfaee9f4e184044c5b6345e311aeb3d9058efafe54e4c5e src/transform/ 954b86300c3ea47281acb2f43b0771e838f83ac09eb55e882e42de26aee3128f src/transform/model.rs 4b52257e1a3643910b5e7043852d7218230c0021c31215d90d0f8e384f2ae233 src/transform/svg/mod.rs 0f53c64f442390ee20a59087a10f8f9ffb58053263e9aa848ddabfae1a6f3f51 src/transform/svg/tests.rs -3c99de898e4c516a805fec1bc77007a211550b7d7a563933a81ae635d235a2e6 src/transform/tests.rs +88cd3729caaa48453d7f9e337052fa85c8a74498460a71e2dbe73245c78ccc8d src/transform/tests.rs 8d38f2f7d4ca4dd453cd0e2337614ec704fbd0a36d3e2374cda43f05dfcad663 src/update_check/mod.rs c42d000d1d576721af3ffe930589388693001b8113554a7658f6dcbc665b5d1b src/update_check/tests.rs b7ee3629a8fde0972bc1822b764f5fa2c813a760dd5dfb7f1ce643a7db8f9f75 src/upstream.rs fe9d4deb34cea2408ac5a1030315989f29a6a7d078a46ac1b59d12aa07f67878 src/upstream/client.rs -eb513923f8951c8bf30bad3cbac77d34f5ebbc7af3ba69a08a25bae834f8a016 src/upstream/client_tests.rs -8c88d928b823e4b6ba6d852f74664c770d8b3fce32bc76c583dc1f672fe33f14 src/upstream/protocol_tests.rs +165e048e2b302af28988c1a23f0e88c989c3cf093fc8b36547070871390d8376 src/upstream/client_tests.rs +56b1e4242f8153391cd9a01fbb3017a2dbda9d02e83da6bbfb39ed44854534b5 src/upstream/protocol_tests.rs ae880b40197454ea3fbf4d2113984dc372098b2e54b97e87c83cc319de253377 src/upstream/tests.rs 5c42f1befec267293b6f03eada118a11c90adfb4b32e0134d7f0033c7453c7cc src/user_agent/mod.rs -6d7cb73de7d8c6f3780736480f5f81ef08813f4626fd5ed494aca0552cf214a1 src/user_agent/tests.rs +696a2783a24f7f3d69fb820dc3a772ec49ea46ee017087952a8253363a9b7374 src/user_agent/tests.rs d61c427c1e9cf457f1232b822d73e846e9f329cfbe61215e7ca061d53762155d src/vhost.rs -54b0c1d2f04e5c654123c3422645eb5a0a9609141cc4a1c6addca2d028392772 src/vhost/error_fallback.rs +846707452ccf10962f1763be66b8f56c050b0398b48968015fb799dac289c0d6 src/vhost/error_fallback.rs 9d358be766f767d9e1a42f585edcf7fc1cba8f22e5eaac294a83920425ec03c7 src/vhost/model.rs -e003b935d91791f20d80c59bb46f9bb0820694dcea5d95e65364b53b016284ef src/vhost/redirect.rs +fc8af7342a3b147921e9040116af5dfe680b3df910db2416ada18198bbeea7df src/vhost/redirect.rs dd6e121445402a2ac8744f0e4f23d879b4356f47c1bb00737bd15ba459661978 src/vhost/tests.rs -c95cc8f4549460917633a12ccb352a00a83c0f004b23c0b9ddecba42eee3ea17 src/vhost/validation.rs +a69e6138d77ead1558eb9303c68dc317bdfaadbe297fe973d62d4dba41afae73 src/vhost/validation.rs 8d1eff4b24f01d137414ef5419f75dd281879228adb70409645b11b3c78c20e9 src/web_server/config.rs 9744e8c29ae72a4d9fbc9a76166a97f8292c4c312295ea40d1cb699e03d80a9d src/web_server/config/compile.rs -daeb5e05e4129764102b3f04e62b2dde38a8c7739bb475a13bc8c8f6d5844da1 src/web_server/config/model.rs +5ed79fa5b9c53f95ca200d89a9ba927dda816b61fbdf3b852bd3c9670e3d2d4f src/web_server/config/model.rs a863ad1337fbc353c0f42caea4ac8b3644792e2aa08c37f992b7882b4b8dc6d5 src/web_server/config/validation.rs 86c744216d7132d8294a6e90ba9be5fd871646006313d1c62506d40c81db9b12 src/web_server/fastcgi.rs 002071ef603f1d928a56226b011c76ac5ea2bc55521a0a3fd317c0ced0056c21 src/web_server/fastcgi/protocol.rs -e954308d94848471f6a9d70a50cd2181d17b9c41b2705a3e6c6c0e882a03733b src/web_server/fastcgi/response.rs -b98666353e4af560ab8423d4772d9ad26451dabb1c6d60f5faf547116a2bcd24 src/web_server/filesystem.rs +1ce9c3797f50cb9f27a945fffd1890d9d8e034048c8d4df93a3903905eec1207 src/web_server/fastcgi/response.rs +92d2ab4d7ecb766bbc705f8eba94c1ca33347ffb84b36e0ad0eccfed5915473f src/web_server/filesystem.rs d4fec3682532b0f2d11a0aefcd024f69fb623a39922ddb6c528a2d2de265347d src/web_server/htaccess.rs -66b846cce61345ea6d182db03e4f8eddc5d4a3cbe87f2046523310f1ea13a5a3 src/web_server/htaccess/model.rs +b4646f705e532f682d6152b6827cc7f4f915766ebcb4af89eba9950965673772 src/web_server/htaccess/model.rs 9c57b7c556984f79404d4afeb9841d0280a198b94c42d887bc6d96b7748a0e67 src/web_server/htaccess/parse.rs -66260d159986d41eab0dfde2cb9f0713fc1cc209c2fb47e9023bd24fd37919e8 src/web_server/htaccess/rewrite.rs +6e58e2674940bb0284035856fe9299a0555fee4c566de75e174deb373c3b164f src/web_server/htaccess/rewrite.rs 8ca74d9cc4470045301f70eb4a9fbabd0dbfe74434429148d2230df9f996c06c src/web_server/htaccess/tests.rs -b4a75519d9c7bb4f176126a284ea5da68fe512674200765da0984b245e4278ba src/web_server/metrics.rs +7fe32af33b4d8e079ad724665aa1cfb62f6e98b9406b77168feaac55dac36137 src/web_server/metrics.rs 029bc2b277b2fd7528d5c9f5637453ce6d1d3ec2df7e441f6844cf55edef6b5b src/web_server/mod.rs -67ab8bef567452f123c4b9b46a942b39c93f1f765c128edca7ee808ff1c5e304 src/web_server/request.rs +e9ba6e09ba2c8f8a33410c219d5ea29214cc53e279a43b17c110d24f17a5a71d src/web_server/request.rs d98c80663847d6d83073df074ebff65952755415574708abcc153bd8d3adfaa9 src/web_server/response.rs -c69502a28eec224eeded7cad93159aae3e7c136721a19f4542d5f682e055f61b src/web_server/response/file.rs -cbeb022847e64d30e9d63aac92bee00d29281b3602e1a0589f3c978cbc7c2238 src/web_server/response/file_body/mod.rs -4e91d09fa086d388e384d14b347eff8c74c010915ca7c84171e074872323e341 src/web_server/response/file_body/tests.rs +814d677c56c946d40031cd8228fc3c52061ad0b76fa5aa9d53063d265f82e3d8 src/web_server/response/file.rs +9197a21a6b22da430e26bda2d1c899dcb64ae615069458f75547d4754a8044c3 src/web_server/response/file_body/mod.rs +e5f5fbe702f66bfcbcbc1d1f3cd3d89bdbb929bb86aed94868a2a06a4b9e59e3 src/web_server/response/file_body/tests.rs c63a5935bf8e101f1813e029dd62da7d073eb598453ee98aafe9ffa6f85157c2 src/web_server/response/headers.rs -f826d8816bdb9edab966e10991e45335625ef7d7376169cf6fd1e0e5d01bf868 src/web_server/routing.rs -400e1c8aa2fe857d96036a64499fbc3de44c1e3a53811c5b25101fb843359792 src/web_server/security.rs +da7c69cd4b26289170d6d89ae3a6d41488fdca3f184cd8f63a160217fa26e49d src/web_server/routing.rs +9e584eb4455a18641c2c89f9e9725745c93f32877abf0f0f2fbea9e3d5ef38c3 src/web_server/security.rs b791762b4ab7a43c3be19df84e523faf3dfb4df055f66d02178f93edb60d2204 src/web_server/serve.rs -df888adf893d0b6b99348d19fa07bd9c2b8fc0ce7f411d06be7411afb4311fe0 src/web_server/tests.rs +642ac020745d963554ab382aa755b8f24d140f5f6b8ea8e7c74da59614f1cfe0 src/web_server/tests.rs f00743af2cf4a5952caef7a1dcf68e7817b5599a252a9973e1c22045517c0b0e tests/fixtures/argon2id.json eca68a07c2b1e45fdb8f512294f5a432db3ae5a6aec8fb200b47f155cd9a31d6 tools/README.md 7c30c280d0b0a8bf855eeffab583ca34dc161255f7ef6124148aa979c17c26d3 tools/dev/memory_load.py diff --git a/docs/ACCESS.md b/docs/ACCESS.md index 334f634..e3806f6 100644 --- a/docs/ACCESS.md +++ b/docs/ACCESS.md @@ -32,7 +32,9 @@ Method policies allow, block or leave methods unrestricted. A denied method retu ## Basic Auth and Tinyauth - **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 can use the service's conventional `/api/auth/nginx` path. Tinyauth has its own timeout and private-backend policy. +- **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. +- **Tinyauth error pages (0.34.14):** RustProxy renders built-in, self-contained HTML for verifier failures: `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. +- 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`). - The two authentication integrations should not be enabled simultaneously for the same Vhost. Protected responses bypass unsafe shared caching. Confirm that login redirections and WebSockets behave as expected. Do not use a User-Agent blocklist as the primary access control: HTTP clients can forge their User-Agent freely. diff --git a/docs/INTEGRATIONS.md b/docs/INTEGRATIONS.md index 9e7dc8e..8a2dcc3 100644 --- a/docs/INTEGRATIONS.md +++ b/docs/INTEGRATIONS.md @@ -5,7 +5,7 @@ RustProxy offers built-in integrations and optional helper components. Each has | Integration | Purpose | Setup and limits | |---|---|---| | **Docker agent** | Discover running Docker services and publish generated Vhosts | Install separate agent on Docker host; use Bearer token and TLS certificate pin. [Guide](DOCKER_DISCOVERY.md). | -| **Tinyauth** | Delegate authentication for selected Vhosts | Configure verifier URL/login URL, allowed headers and HTTPS. [Access](ACCESS.md). | +| **Tinyauth** | Delegate authentication for selected Vhosts | Configure verifier URL/login URL, allowed headers and HTTPS. Failed verifier connections return a fail-closed local 502 page; verifier timeouts return 504. [Access](ACCESS.md). | | **ACME / Certbot** | Issue/renew HTTPS certificates | HTTP-01 or DNS-01 via Cloudflare, OVH or RFC2136; protect credentials. [Certificates](ACME_PROVIDERS.md). | | **Prometheus** | Scrape operational metrics | Separate endpoint/token/CIDR rules. [Monitoring](MONITORING.md). | | **Grafana** | Visualize Prometheus results | Example dashboard under `grafana/README.md`. | diff --git a/docs/README.md b/docs/README.md index 9618ede..eec442a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # RustProxy documentation -Practical guides for **RustProxy 0.34.13**. 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.14**. 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 @@ -22,7 +22,7 @@ Practical guides for **RustProxy 0.34.13**. This index and the listed pages are - [Experimental TLS post-quantum key exchange](TLS_POST_QUANTUM.md) — opt-in X25519MLKEM768, compatibility, rollback and validation. - [TCP/UDP Streams](STREAMS.md) — non-HTTP forwarding and its security boundaries. -The Vhosts and Docker discovery guides include the shared adaptive request-rate chart scale introduced in 0.34.11. Version 0.34.12 preserves that adaptive range and adds a disabled-by-default X/Y scale display option under **Settings → Appearance → Charts**. Release 0.34.13 adds global HTTP security policies and UI layout improvements, groups the global User-Agent policy under `global_security`, provides consistent section-based GET/PUT APIs, and moves manual GeoIP refresh to `POST /api/config/geoip/update`. See [Dashboard](DASHBOARD.md). +The Vhosts and Docker discovery guides include the shared adaptive request-rate chart scale introduced in 0.34.11. Version 0.34.12 preserves that adaptive range and adds a disabled-by-default X/Y scale display option under **Settings → Appearance → Charts**. Release 0.34.13 adds global HTTP security policies and UI layout improvements, groups the global User-Agent policy under `global_security`, provides consistent section-based GET/PUT APIs, and moves manual GeoIP refresh to `POST /api/config/geoip/update`. See [Dashboard](DASHBOARD.md). Release 0.34.14 keeps the Tinyauth Nginx-header compatibility patch, adds fail-closed branded Tinyauth 502/504 error pages, without changing the existing generic 502 page, error-code registry, or other standard error templates. See [Access](ACCESS.md) and [Troubleshooting](TROUBLESHOOTING.md). ## Integrations and operations diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 2f49199..c71d420 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -10,7 +10,10 @@ Start with a reproducible request, its hostname/path and the exact listener. Com | HTTP works, HTTPS does not | Trusted certificate, hostname/SAN coverage, TLS listener, port 443 firewall, certificate assignment and whether restart was needed. | | HTTPS/H2 works but H3 fails | UDP firewall/NAT, H3 toggle on TLS listener, browser QUIC support and actual transport negotiation. | | H2 runs at link speed but H3 is slower | Compare the same origin and client with browser H3 vs H2, keeping TLS/cache/compression consistent. Inspect QUIC loss/cwnd/MTU and VM UDP offload, not only total CPU. | -| `502` / `503` / `504` to origin | Backend IP/port, pool eligibility/health, private-address policy, upstream HTTPS verification, protocol `auto`/`h2`, timeout and container/PHP process availability. | +| Ordinary `502` / `503` / `504` to origin | Backend IP/port, pool eligibility/health, private-address policy, upstream HTTPS verification, protocol `auto`/`h2`, timeout and container/PHP process availability. A locally generated ordinary 502 has the generic **Bad gateway** page. | +| `502 Tinyauth connection error` | The authentication backend cannot be reached. Check Tinyauth process, DNS, verifier URL/port, network firewall, TLS/certificate, private backend allowlist and the RustProxy service journal. Do not route the verification URL back through the protected Vhost. | +| `502 Tinyauth verification error` | Tinyauth returned an unexpected status/body or identity headers were too large. Verify `/api/auth/nginx`, proxy header injection and the installed Tinyauth version; check the server journal for details. | +| `504 Tinyauth timeout` | The Tinyauth verification deadline was reached. Check service load/latency and `connect_timeout_seconds` / `timeout_seconds` (Vhost Authentication tab). | | WebSocket handshake fails or disconnects | Vhost WebSockets flag, backend Upgrade support, TLS/frontend protocol path, WebSocket idle limits and auth redirect. | | `403` / `405` / `429` | Applicable IP/ACL/country policy, HTTP methods, rate limit, GeoIP availability, Basic/Tinyauth permissions. | | Cache always BYPASS or MISS | Global + Vhost enablement, cookies/login, origin `Cache-Control`, `Set-Cookie`, `Vary`, TTL, size and exclusion rules. | diff --git a/docs/WEB_SERVER.md b/docs/WEB_SERVER.md index 02d471e..d8c9e77 100644 --- a/docs/WEB_SERVER.md +++ b/docs/WEB_SERVER.md @@ -66,7 +66,7 @@ In **Web Server → Edit → Delivery**, static file delivery, dynamic compressi A Web Service may enable PHP via a shared PHP-FPM profile or its own configuration. PHP is executed by the FPM service, not RustProxy, and must not be exposed as a raw Internet port. Use dedicated pools for different applications. See [PHP-FPM](PHP_FPM.md). -Missing static files return **HTTP 404 Not Found**, unreadable/blocked paths **403 Forbidden**, unsupported static methods **405 Method Not Allowed** (with `Allow: GET, HEAD`), and internal failures **500 Internal Server Error**. The built-in Web Server now uses the existing **application-style HTML error pages** for statuses with a bundled template (including 400, 403, 404, 500 and PHP-FPM gateway errors). Other generated error statuses, such as 405, use the shared styled HTML fallback. Neither internal filesystem paths nor `RustProxy: Web Server ...` diagnostics are included in the public body. Details for 5xx filesystem failures remain in server logs. +Missing static files return **HTTP 404 Not Found**, unreadable/blocked paths **403 Forbidden**, unsupported static methods **405 Method Not Allowed** (with `Allow: GET, HEAD`), and internal failures **500 Internal Server Error**. The built-in Web Server now uses the existing **application-style HTML error pages** for statuses with a bundled template (including 400, 403, 404, 500 and PHP-FPM gateway errors). Other generated error statuses, such as 405, use the shared styled HTML fallback. The regular built-in 502 is styled with RustProxy branding; auth-specific Tinyauth failure pages have their own wording and are served before any origin application is accessed. Neither internal filesystem paths nor `RustProxy: Web Server ...` diagnostics are included in the public body. Details for 5xx filesystem failures remain in server logs. These generated HTML responses retain the actual HTTP status, `Content-Type: text/html; charset=utf-8`, `X-Content-Type-Options: nosniff` and `Cache-Control: no-store`; `HEAD` preserves the matching `Content-Length` but sends no body. Explicit application/origin responses are still passed through without forced replacement, subject to the Vhost error interception options below. diff --git a/grafana/rustproxy-overview.json b/grafana/rustproxy-overview.json index 7ae348a..6c84e2a 100644 --- a/grafana/rustproxy-overview.json +++ b/grafana/rustproxy-overview.json @@ -6868,9 +6868,9 @@ }, "timepicker": {}, "timezone": "browser", - "title": "RustProxy 0.34.13 - Operations", + "title": "RustProxy 0.34.14 - Operations", "uid": "rustproxy-0170", "version": 7, "weekStart": "", - "description": "RustProxy 0.34.13 Prometheus operations dashboard: traffic and errors, vhosts and backends, Docker discovery, cache capacity and pressure, process and system diagnostics, HTTP/2, HTTP/3, TLS, WebSockets, Layer-4 streams, log sinks, Web Server and PHP-FPM. Some metrics are optional depending on exporter collector settings and enabled services." + "description": "RustProxy 0.34.14 Prometheus operations dashboard: traffic and errors, vhosts and backends, Docker discovery, cache capacity and pressure, process and system diagnostics, HTTP/2, HTTP/3, TLS, WebSockets, Layer-4 streams, log sinks, Web Server and PHP-FPM. Some metrics are optional depending on exporter collector settings and enabled services." } \ No newline at end of file diff --git a/src/admin/openapi.json b/src/admin/openapi.json index a4d12e5..801c8c8 100644 --- a/src/admin/openapi.json +++ b/src/admin/openapi.json @@ -2,7 +2,7 @@ "openapi": "3.0.3", "info": { "title": "RustProxy Administration API", - "version": "0.34.13", + "version": "0.34.14", "description": "Administration API for the active panel origin. Sign in through the panel; the same-origin HttpOnly cookie authenticates all private operations. Mutations also require the exact Origin, X-RustProxy-Request: 1 and a session-bound X-CSRF-Token. Loopback HTTP is the default; Settings can enable HTTPS before using a non-loopback administration bind. This document contains no live configuration or credentials. Object schemas marked extensible are summaries: full configuration validation is authoritative in Rust. The API also permits explicitly scoped GeneralApiBearer tokens on a narrow route allowlist, with RO/RW and source CIDR checks; API-token management and Prometheus-token management are browser-session-only." }, "servers": [ diff --git a/src/admin/web/error_tinyauth_connection.html b/src/admin/web/error_tinyauth_connection.html new file mode 100644 index 0000000..7f114e6 --- /dev/null +++ b/src/admin/web/error_tinyauth_connection.html @@ -0,0 +1,37 @@ + + + + + + + 502 - Tinyauth connection error - RustProxy + + + + +
+

502 - Tinyauth connection error

+

Unable to connect to the Tinyauth authentication service.

+
+ + + \ No newline at end of file diff --git a/src/admin/web/error_tinyauth_timeout.html b/src/admin/web/error_tinyauth_timeout.html new file mode 100644 index 0000000..865fbb4 --- /dev/null +++ b/src/admin/web/error_tinyauth_timeout.html @@ -0,0 +1,37 @@ + + + + + + + 504 - Tinyauth timeout - RustProxy + + + + +
+

504 - Tinyauth timeout

+

The Tinyauth authentication service did not respond in time.

+
+ + + \ No newline at end of file diff --git a/src/admin/web/error_tinyauth_verification.html b/src/admin/web/error_tinyauth_verification.html new file mode 100644 index 0000000..6208239 --- /dev/null +++ b/src/admin/web/error_tinyauth_verification.html @@ -0,0 +1,37 @@ + + + + + + + 502 - Tinyauth verification error - RustProxy + + + + +
+

502 - Tinyauth verification error

+

The Tinyauth authentication service returned an invalid response.

+
+ + + \ No newline at end of file diff --git a/src/pages/tests.rs b/src/pages/tests.rs index 08757ed..46f5c5f 100644 --- a/src/pages/tests.rs +++ b/src/pages/tests.rs @@ -86,12 +86,27 @@ mod tests { StatusCode::INTERNAL_SERVER_ERROR, "500 - Internal server error", ), - (StatusCode::BAD_GATEWAY, "502 - Bad gateway"), ] { let page = builtin_gateway_error(code).unwrap(); assert!(page.contains(label)); assert!(page.contains("background: #131615")); } + let gateway_502 = builtin_gateway_error(StatusCode::BAD_GATEWAY).unwrap(); + assert!(gateway_502.contains("

502 - Bad gateway

")); + assert!(gateway_502.contains("The upstream service returned an invalid response.")); + assert!(gateway_502.contains("RustProxy")); + assert!(gateway_502.contains("#131615")); + assert!(!gateway_502.contains("Tinyauth")); + // The standard HTTP error registry and its stock pages predate the + // Tinyauth-specific diagnostic pages and must remain unchanged. + assert_eq!( + ERROR_CODES, + [400, 401, 403, 404, 408, 413, 429, 500, 502, 503, 504] + ); + assert_eq!( + BUILTIN_ERROR_CODES, + [400, 401, 403, 404, 408, 410, 413, 429, 500, 502, 503, 504] + ); assert!(builtin_gateway_error(StatusCode::OK).is_none()); assert!(builtin_application_page(StatusCode::OK).contains("200 - OK")); assert!(builtin_application_page(StatusCode::CREATED).contains("background: #131615")); diff --git a/src/tinyauth/mod.rs b/src/tinyauth/mod.rs index 15c3996..f37108e 100644 --- a/src/tinyauth/mod.rs +++ b/src/tinyauth/mod.rs @@ -63,6 +63,51 @@ pub struct Compiled { } #[derive(Clone)] pub struct AuthenticationFailure; + +#[derive(Debug)] +enum CheckError { + Connection(anyhow::Error), + InvalidResponse(anyhow::Error), +} + +#[derive(Debug, Clone, Copy)] +enum GatewayFailure { + Connection, + Timeout, + Verification, +} + +fn gateway_failure(kind: GatewayFailure) -> Response { + let (status, html) = match kind { + GatewayFailure::Connection => ( + StatusCode::BAD_GATEWAY, + include_str!("../admin/web/error_tinyauth_connection.html"), + ), + GatewayFailure::Timeout => ( + StatusCode::GATEWAY_TIMEOUT, + include_str!("../admin/web/error_tinyauth_timeout.html"), + ), + GatewayFailure::Verification => ( + StatusCode::BAD_GATEWAY, + include_str!("../admin/web/error_tinyauth_verification.html"), + ), + }; + let mut response = (status, html).into_response(); + response.headers_mut().insert( + "content-type", + HeaderValue::from_static("text/html; charset=utf-8"), + ); + response.headers_mut().insert( + "cache-control", + HeaderValue::from_static("private, no-store"), + ); + response.headers_mut().insert( + "x-content-type-options", + HeaderValue::from_static("nosniff"), + ); + response.extensions_mut().insert(AuthenticationFailure); + response +} #[derive(Debug, Default)] pub struct Identity { headers: HeaderMap, @@ -220,6 +265,31 @@ fn failure(status: StatusCode) -> Response { response.extensions_mut().insert(AuthenticationFailure); response } + +fn apply_nginx_auth_context( + headers: &mut HeaderMap, + method: &Method, + context: &forwarding::Context, +) -> Result<()> { + context.apply(headers); + + let non_nginx_headers: Vec<_> = headers + .keys() + .filter(|name| { + name.as_str() == "forwarded" + || (name.as_str().starts_with("x-forwarded-") && name.as_str() != "x-forwarded-for") + }) + .cloned() + .collect(); + for name in non_nginx_headers { + headers.remove(name); + } + + headers.insert("x-original-url", context.original_url.parse()?); + headers.insert("x-original-method", method.as_str().parse()?); + Ok(()) +} + impl Compiled { pub fn strip_identity(&self, headers: &mut HeaderMap) { let names: Vec<_> = headers @@ -290,11 +360,18 @@ impl Compiled { }; let (status, headers) = match result { Ok(Ok(value)) => value, - Ok(Err(error)) => { - tracing::debug!(%error,"Tinyauth verification failed"); - return Err(failure(StatusCode::BAD_GATEWAY)); + Ok(Err(CheckError::Connection(error))) => { + tracing::warn!(%error, "Tinyauth backend connection failed"); + return Err(gateway_failure(GatewayFailure::Connection)); + } + Ok(Err(CheckError::InvalidResponse(error))) => { + tracing::warn!(%error, "Tinyauth returned an invalid verification response"); + return Err(gateway_failure(GatewayFailure::Verification)); + } + Err(_) => { + tracing::warn!("Tinyauth verification timed out"); + return Err(gateway_failure(GatewayFailure::Timeout)); } - Err(_) => return Err(failure(StatusCode::GATEWAY_TIMEOUT)), }; if status.is_success() { let mut identity = Identity::default(); @@ -303,7 +380,8 @@ impl Compiled { for value in headers.get_all(name) { size += value.as_bytes().len(); if size > 8192 { - return Err(failure(StatusCode::BAD_GATEWAY)); + tracing::warn!("Tinyauth identity headers exceed the configured limit"); + return Err(gateway_failure(GatewayFailure::Verification)); } identity.headers.append(name.clone(), value.clone()); } @@ -323,24 +401,26 @@ impl Compiled { return Err(response); } } - Err(failure(if status == StatusCode::FORBIDDEN { - StatusCode::FORBIDDEN - } else if status == StatusCode::UNAUTHORIZED { - StatusCode::UNAUTHORIZED - } else { - StatusCode::BAD_GATEWAY - })) + if status == StatusCode::FORBIDDEN || status == StatusCode::UNAUTHORIZED { + return Err(failure(status)); + } + tracing::warn!( + status = status.as_u16(), + "Tinyauth returned an unexpected HTTP status" + ); + Err(gateway_failure(GatewayFailure::Verification)) } async fn check( &self, incoming: &HeaderMap, method: &Method, context: &forwarding::Context, - ) -> Result<(StatusCode, HeaderMap)> { + ) -> std::result::Result<(StatusCode, HeaderMap), CheckError> { let mut request = Request::builder() .method(Method::GET) .uri(self.uri.clone()) - .body(Body::empty())?; + .body(Body::empty()) + .map_err(|error| CheckError::InvalidResponse(error.into()))?; for name in &self.request_headers { for value in incoming.get_all(name) { request.headers_mut().append(name.clone(), value.clone()); @@ -349,27 +429,25 @@ impl Compiled { crate::proxy::headers::strip_hop_by_hop(request.headers_mut()); crate::proxy::headers::strip_admin_cookie(request.headers_mut()); self.strip_identity(request.headers_mut()); - context.apply(request.headers_mut()); + apply_nginx_auth_context(request.headers_mut(), method, context) + .map_err(CheckError::InvalidResponse)?; request .headers_mut() .insert("host", self.backend.host_header.clone()); - request - .headers_mut() - .insert("x-original-url", context.original_url.parse()?); - request - .headers_mut() - .insert("x-original-method", method.as_str().parse()?); let response = self .backend .client .request(request) .await - .context("Tinyauth request failed")?; + .context("Tinyauth request failed") + .map_err(CheckError::Connection)?; let (parts, body) = response.into_parts(); Limited::new(body, 16 * 1024) .collect() .await - .map_err(|e| anyhow::anyhow!("Tinyauth response body: {e}"))?; + .map_err(|error| { + CheckError::InvalidResponse(anyhow::anyhow!("Tinyauth response body: {error}")) + })?; Ok((parts.status, parts.headers)) } } diff --git a/src/tinyauth/tests.rs b/src/tinyauth/tests.rs index ae347d3..e556ad3 100644 --- a/src/tinyauth/tests.rs +++ b/src/tinyauth/tests.rs @@ -9,8 +9,8 @@ mod tests { ..Default::default() } } - fn compiled() -> Compiled { - settings() + fn compile_settings(settings: Settings) -> Compiled { + settings .compile( &ValidationPolicy { proxy_addr: "127.0.0.1:8080".parse().unwrap(), @@ -24,6 +24,23 @@ mod tests { .unwrap() .unwrap() } + fn compiled() -> Compiled { + compile_settings(settings()) + } + fn request_context(incoming: &HeaderMap) -> forwarding::Context { + forwarding::Settings::default() + .compile() + .unwrap() + .context( + incoming, + "192.0.2.5:34567".parse().unwrap(), + "10.0.0.1:443".parse().unwrap(), + true, + &"app.example:443".parse().unwrap(), + &"/private?next=%2Fhome".parse().unwrap(), + ) + .unwrap() + } #[test] fn origin_adds_nginx_endpoint() { assert_eq!( @@ -32,6 +49,57 @@ mod tests { ); } #[test] + fn nginx_auth_context_has_no_conflicting_forward_auth_headers() { + let context = request_context(&HeaderMap::new()); + let mut headers = HeaderMap::new(); + apply_nginx_auth_context(&mut headers, &Method::POST, &context).unwrap(); + + assert_eq!( + headers["x-original-url"], + "https://app.example:443/private?next=%2Fhome" + ); + assert_eq!(headers["x-original-method"], "POST"); + assert_eq!(headers["x-forwarded-for"], "192.0.2.5"); + assert_eq!(headers["x-real-ip"], "192.0.2.5"); + for name in [ + "x-forwarded-host", + "x-forwarded-uri", + "x-forwarded-proto", + "x-forwarded-port", + "forwarded", + ] { + assert!(!headers.contains_key(name), "{name}"); + } + } + #[test] + fn nginx_auth_context_does_not_forward_spoofed_client_metadata() { + let mut headers = HeaderMap::new(); + for (name, value) in [ + ("x-original-url", "https://evil.example/"), + ("x-original-method", "DELETE"), + ("x-forwarded-host", "evil.example"), + ("x-forwarded-uri", "/admin"), + ("x-forwarded-for", "203.0.113.1"), + ("x-real-ip", "203.0.113.1"), + ("forwarded", "for=203.0.113.1"), + ] { + headers.insert(name, value.parse().unwrap()); + } + let context = request_context(&headers); + apply_nginx_auth_context(&mut headers, &Method::GET, &context).unwrap(); + + assert_eq!( + headers["x-original-url"], + "https://app.example:443/private?next=%2Fhome" + ); + assert_eq!(headers["x-original-method"], "GET"); + assert_eq!(headers["x-forwarded-for"], "192.0.2.5"); + assert_eq!(headers["x-real-ip"], "192.0.2.5"); + assert!(!headers.contains_key("x-forwarded-host")); + assert!(!headers.contains_key("x-forwarded-uri")); + assert!(!headers.contains_key("forwarded")); + } + #[test] fn rejects_transport_header_injection_and_unsafe_urls() { for name in [ "host", @@ -118,4 +186,136 @@ mod tests { ) .is_err()); } + + #[tokio::test] + async fn tinyauth_gateway_pages_are_distinct_and_fail_closed() { + use http_body_util::BodyExt; + + for (kind, status, text) in [ + ( + GatewayFailure::Connection, + StatusCode::BAD_GATEWAY, + "Tinyauth connection error", + ), + ( + GatewayFailure::Verification, + StatusCode::BAD_GATEWAY, + "Tinyauth verification error", + ), + ( + GatewayFailure::Timeout, + StatusCode::GATEWAY_TIMEOUT, + "Tinyauth timeout", + ), + ] { + let response = gateway_failure(kind); + assert_eq!(response.status(), status); + assert_eq!( + response.headers()["content-type"], + "text/html; charset=utf-8" + ); + assert_eq!(response.headers()["cache-control"], "private, no-store"); + assert_eq!(response.headers()["x-content-type-options"], "nosniff"); + assert!(response + .extensions() + .get::() + .is_some()); + let body = response.into_body().collect().await.unwrap().to_bytes(); + let html = std::str::from_utf8(&body).unwrap(); + assert!(html.contains(text)); + assert!(html.contains("Access") && html.contains("protected")); + assert!(html.contains("