diff --git a/AGENTS.md b/AGENTS.md index 8da3d19..77944bd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # RustProxy source and documentation maintenance -Current source version: **0.34.8**. The Cargo package and binary are named `rust-proxy`. +Current source version: **0.34.9**. 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 9dd0382..4565505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # 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.8. +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.9. + +## 0.34.9 — experimental TLS post-quantum key exchange (source candidate) + +- **Settings → TLS policy:** new disabled-by-default experimental `post_quantum` toggle. When enabled with TLS 1.3, inbound TCP TLS and HTTP/3 QUIC use an explicit aws-lc-rs provider, prioritizing the hybrid **X25519MLKEM768** key-exchange group while retaining classical alternatives. When disabled, the original ring provider is retained. This changes KEX, not TLS cipher suites or certificate signing; no change to upstream/client-side TLS providers. +- **Per-vhost TLS override:** may opt out when global PQC is enabled; cannot enable PQC if the global policy disables it. TLS 1.3 is required. Existing per-vhost policies lacking the field continue to default to non-PQC. HTTP/3 continues to require exactly matching global policy. +- **UI/docs/API:** English/Polish switch and key-exchange group readout, authenticated Reader guide linked from the TLS policy page, OpenAPI and regression unit tests. ## 0.34.8 diff --git a/Cargo.lock b/Cargo.lock index 30f340d..1cdadf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -202,6 +202,29 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "aws-lc-rs" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] + [[package]] name = "axum" version = "0.8.9" @@ -488,6 +511,15 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "cmov" version = "0.5.4" @@ -669,6 +701,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.18.0" @@ -769,6 +807,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-channel" version = "0.3.34" @@ -1881,7 +1925,7 @@ dependencies = [ [[package]] name = "rust-proxy" -version = "0.34.8" +version = "0.34.9" dependencies = [ "anyhow", "arc-swap", @@ -1970,6 +2014,7 @@ version = "0.23.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" dependencies = [ + "aws-lc-rs", "once_cell", "ring", "rustls-pki-types", @@ -2003,6 +2048,7 @@ version = "0.103.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", diff --git a/Cargo.toml b/Cargo.toml index 45f996e..293a127 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust-proxy" -version = "0.34.8" +version = "0.34.9" edition = "2021" rust-version = "1.99" description = "RustProxy - independent reverse proxy with local administration" @@ -40,7 +40,7 @@ url = "2.5" base64 = "0.22" sha1 = "0.10" -rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] } +rustls = { version = "0.23", default-features = false, features = ["ring", "aws_lc_rs", "std", "tls12"] } ring = "0.17" tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] } hyper-rustls = { version = "0.27", default-features = false, features = ["ring", "http1", "http2", "tls12"] } diff --git a/README.md b/README.md index b56fabf..2bbb343 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# RustProxy 0.34.8 +# RustProxy 0.34.9 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. @@ -16,6 +16,10 @@ RustProxy combines a reverse proxy, static/PHP web server, certificate managemen Features and default settings vary by component; configure only the capabilities you need. The [documentation index](docs/README.md) covers each workflow, including prerequisites, security boundaries, troubleshooting and API access. +## 0.34.9 — experimental PQC (source candidate) + +- **Settings → TLS policy:** opt-in experimental TLS 1.3 hybrid post-quantum key exchange (X25519MLKEM768), using aws-lc-rs only for enabled frontend TLS policies. Classic key-exchange groups remain enabled for client compatibility. Off by default; cipher-suite choices remain separate. HTTP/3 and per-vhost TLS overrides follow the selected policy. Details and rollback: [TLS PQC guide](docs/TLS_POST_QUANTUM.md) (also in the authenticated panel Reader). + ## 0.34.8 - **Docker vhosts:** automatic hostname uses the container name, without image or port suffix; prior auto-generated names are updated while custom names and aliases are preserved. Docker Agent **1.0.1**. @@ -103,4 +107,4 @@ The authenticated **`/docs`** page includes the guides and a separate interactiv ## Status of this source archive -Version **0.34.8** is provided as a **source release candidate**. Configuration, ACL and TLS changes require native compilation and integration testing on the target systems before a production deployment is declared. See [Installation](docs/INSTALL.md) and [Roadmap](ROADMAP.md). +Version **0.34.9** is provided as a **source-only experimental candidate**. PQC dependencies were provisionally locked using published crate metadata, not checked by Cargo in the packaging environment. Run `cargo metadata --locked`, `cargo check --locked --all-targets`, `cargo test --locked --all-targets` and protocol compatibility checks on your target system before production deployment. See [Installation](docs/INSTALL.md) and [Roadmap](ROADMAP.md). diff --git a/SHA256SUMS b/SHA256SUMS index 6161cd3..483955e 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -1,12 +1,12 @@ 61bf40a0572889dc8b0dda9eae4e93e44b0de9364b3c798106c85700ffb37c23 .dockerignore 4140a2956264b44f259e6a37fc00ba02097bbe68b09296e04d3d243c1287129b .env.example 9e6356475bf587091bab72246ec9e325b498f7e48a6220e9a18baa50d0a385a6 .gitignore -e9aa7d23f867dabab4b254154dc81833511138f7679ef7d0583afcdff2ff231e AGENTS.md -82fea9271a4c7a112334076c5c76b6bb2f354b362aef6fe7c7822d4477c50e6a CHANGELOG.md -3bce5792c1588ec7de8d97239d7e9e3304ce21eb76c619f48e6e62577c6cfac5 Cargo.lock -15821dc3b17d2da6d139b91a885269a817457d271fbeabb49c3d68bccc5efd22 Cargo.toml +237ed6e2c0d4fa1f125180c349856749c13820b72593b5fc58e1b58cce47c840 AGENTS.md +4f695dd4ded1ef0c6fbe421ae9bc01993140ddbb4f77cb7a46dd8191a2584ddb CHANGELOG.md +310d60da6c7f501ccdde86b93ee1d5b0102033ba71ac9bb42a4e3ce184692ef9 Cargo.lock +c18c0ba1a22a8534a4cf3b6db907f41f04e0b6cb47cd305a21af139a06e303fb Cargo.toml 25c7f3c8162cbf5cc156439774118a81dae9fdc52b611ec7e40c230fc99a772c Dockerfile -ca24bbf88f886637f91735daba5a7eee83cac13dc3b49085ca9eb56cd102f789 README.md +fb75f6ff1fee8e5af4c89943c67b7e75cbac048254cecc3dc9fd0ea33d53ac25 README.md ae6d14ada6fde7d0b8514840b821678418cf5b1816c18434e3b7fb2ae27a0b21 ROADMAP.md da8311e3db945290666324a2f24bf4521b365272d7ac3f862ded1be993eea646 UPDATE_CHECK.toml 7309cfaa188c7a1fcf30be1b8313ee99c00b7fe5d6d626ddefcc7345fa066112 build.rs @@ -44,11 +44,12 @@ f1baabe34e8a1b204d7c78e2f558c019c156b03adfa6ddecb931b4b8a5501f78 docs/INSTALL.m 888cdc8c56e10b8a7615012e192e085bf2899d0ec9b3ddfb5731e7de6ab5bcde docs/MIGRATION.md 140b95ad778261455f269f2144a1c61c2315bd3b85300fb613822eacddf3cfc2 docs/MONITORING.md d5894c07c68ec4230987767198434abee13b0e525842fea21bcbe752fa82742b docs/PHP_FPM.md -0aa40fce348f18b4e9b319c25cd81d42f418502bba31511e349a8f82ab4992ce docs/README.md +8b22a8f738f62cb27faf97683cc467de0fba02ab5999217b502f24a38f10ab4b docs/README.md 490a6dbe870f2b1fd4ec7816768dde6c86fa7957fc9de2d2f075e123c9222222 docs/RESPONSE_DELIVERY.md e2b36152c13d65621a367c69dd400118dae1e4426a4d2b2139d2f63fa30442d6 docs/SECURITY.md bbef60ff1771da9f48af812987766e1e479408873ae2f079b13f1d5c62ecc6ff docs/STREAMS.md -5bedc7d8b9fcaa80cacea225b1f6750101a7ac1b34eb9ce58310ec60329e380d docs/TRANSPORT.md +11157c4bd43f51ea84ef7bde040cca3e818f2ada04a43b6bf1620c477abb53f7 docs/TLS_POST_QUANTUM.md +43a2c6230f95f81bf4efd1575a4f7cdc8b02244df38e19b1ec9c3cd736d3afe6 docs/TRANSPORT.md 8542c4a5c9d5dfe474459099546ae590b4c4d3f363f0bba9721c6107643c2d3a docs/TROUBLESHOOTING.md 25b32d0d906333969df9e6a0a8c1b399cd34ad177b601219ba8ade8e164d3887 docs/VHOSTS.md 05efc113d33be361bac25c90064b1865cf2f574dabd0eaa73bdddda229b2946e docs/WEB_SERVER.md @@ -76,8 +77,8 @@ cb01fdef286f38b442dd9252c23c4f8e44eb72e9ecdd99adb926e8e9f6318bb1 integrations/r 96563a83e87cfb33e238c2a970ce36b1a1b51e91318d09b123c3755002ba2646 integrations/routeros-oci-build/build-routeros-oci.sh 3f267cafa16006e5456ade78ee2d5fae02cc7ce747839523068ffd8d7c98798a integrations/routeros-oci-build/docker-entrypoint.sh 13189fa546c3488dddd8efc80c47f6da5241e5fc28b79cbfe795414ea05c7a4f langs/README.md -c04792fcc2e2e237b28e22d64f2db44964f26b779db09622f2162d0f068d5526 langs/en_US.json -95564b46ad8526610dc04d5696b4f26d4c5b46fdbd38290c4850d57d45e90c49 langs/pl_pl.json +9f83bd975c041421a42ecd00bedcfd3bd6285d9397412644a9375ffdf4bcff5a langs/en_US.json +28f5738f0635a71b5a13cdc1647aa281c0d124ef12561ef28e9e51cbafbd2ee3 langs/pl_pl.json a99ad040be10fa028351e290b9363236b3513a1cadbdc9fb9e0260d517b9b0ae make_zip.py e830d37dd1f81a4b0aa7d535f5bba69e34e433b0fd99cc8ee0b296786c32379a migrations/0002_admin.sql 20112cc82192098b8d602f1c4f7ca08712e9e1366c845fabb92753187c370d35 migrations/0003_certificate_renewals.sql @@ -135,15 +136,15 @@ a402209141667fdce69698a60dc0b867248effa191494d0a0d93d468d7df9476 src/admin/cert 521ac794501570cfa2e8e50c3a5cec2ca08ee4dbce8ac9c0e0310c09612f1062 src/admin/config_reload.rs 159c3970d25fa29acf2483fc9422b003e5d63884713f62baa8375e4a4020730e src/admin/dashboard_presets.rs aae1ca0e70d987830bd63948d431f54302083148177c1b551565be12df7fe771 src/admin/documentation.rs -d4a249e8c2bf06a12fbd561fcdf5a5211aa5ed0e0dcd5111b84bbb13b3640c49 src/admin/documentation/documents.rs -67b901485d5858d5b5bf78a6260035db32241531d99481754c3533fdf404facb src/admin/documentation/tests.rs +da28dd57087df138913b784b71dca11d36c68100f2f100f452fbf4e4d7982433 src/admin/documentation/documents.rs +67fa0e842f6789ed38e101ed6717072736e85c34af873d1a27d7efee5dc0c83d src/admin/documentation/tests.rs 1ce779b84aa8f47bdb3c34f83593c1f2f06d2235f0319847096cfcd035434168 src/admin/file_log_search.rs ab18acf6fb4ac86fb22635b9219a12dac76d24952c8f15538486267a9b4b7855 src/admin/file_logs.rs d58a2ed83319176de4e66790ed292447c9497ae031464ec55cfe27174acb639a src/admin/file_logs_io.rs 282352eda7957477e7da44f16b90984b26a4a67a8755833bc0a6b34eaf93e3af src/admin/file_logs_query.rs f66ff718f82a326f80808b0a5088bd05a48625be802e5ba305fff3c344b59948 src/admin/logging_api.rs 1ba0520c6348246cbb35b60e596e99dc600137c0696de86508cf06587bd86563 src/admin/mod.rs -7bce0ba5a9fe3d1de2b10a29e58d88300e09ffcce50e6d94e68240c78db944b8 src/admin/openapi.json +8e1012a8ec776c3525310b03a70f274955dce9de3528109070ea11de0ff5c16c src/admin/openapi.json 7cfd6593ac9bcea3d1b9e61bbcb7ed98d65ed3190f54f94c1e104541f4fbb4f5 src/admin/operations.rs f14afb6ae141053d83d0dc59df835b20e38a37a9e83f86f0f2053f2bd5d9ce57 src/admin/panel_assets.rs f5127855c2994d052678865df36d703b74f4a0afc633daf7718b10da18d26e37 src/admin/panel_content.rs @@ -155,7 +156,7 @@ f5127855c2994d052678865df36d703b74f4a0afc633daf7718b10da18d26e37 src/admin/pane 6930b4f4b45257772b321b20a9becdf9bc4610274852948ba38c2d0cdf02dfaf src/admin/refresh_preferences.rs 00b5dd3090792986217b28c69bf826748145129e5517b260d95019b1d7b2ebb2 src/admin/router.rs e135431cb078ddb483165581123c64af8f00ea67acb3a395ec3e53c85d0d0d45 src/admin/session.rs -0c86d94b714cfff26e184541ed3bfcb317c88e45afe084d5f3b28558946dd9b3 src/admin/status.rs +09cc50a86960897371730cc1abed83f4f640c86b680ec7ff6d6b84c7e96a3c0b src/admin/status.rs 2d5b4c28fd0bd48b06890fa8ec44a2296de948c1f88eb2909f4b495710d4e13e src/admin/status_live.rs 8315c856cd50f1072593ecb30c274d42d82f078b5fb93e7c68a8857cd81b0841 src/admin/status_system.rs cadd7dca29b9aad8c77c7bc23dd249ea37a15adfa4d636a8ef00273a91ce35dc src/admin/tail.rs @@ -183,7 +184,7 @@ fa00bce2651308a4e0b1303cc0146be17ed4794b67b2f0cebfaf861558d8c78c src/admin/web/ 8386710827e5ccc9432fb46413368f94afc1016425404a6092b460903636837e src/admin/web/app/stream-dashboard.js 7f89bfae66e2a08a05a112733864e908f036bb1ee3d8b5b9ff23783b870acd96 src/admin/web/app/web-overview.js 849b2ca9d183bdf6cb1e04651cda52da55b8a631e11ab1d827a052c8436bbd76 src/admin/web/cache-panel.js -02a9f5a61379e68e1723e64ef4c589500e9a993adcb02fe352f1cf9456c90c52 src/admin/web/certificate-api.js +e9788a9d1e0bce8775f612a5c842afea8a0dcf01301acdef4b69ff6a52d2ef45 src/admin/web/certificate-api.js 560a8e047182fbcee08aa4f8d999400a8a5ddca0b6a4640efd46f6b5c34fde91 src/admin/web/dashboard-defaults.json 14213011cfb6ac334c8711b76bbdde97588a7b7ba4eb2592a1e387f877d6cbe0 src/admin/web/dashboard-widgets.json 50d1ebcbaf4d0b2968da23bb943fc3f67131c5d32df3f61d23ff37aad9da5b81 src/admin/web/demo.html @@ -207,7 +208,7 @@ e6c4d91d1542d0a5b47bb8736f9539d43a6713df5a473b635519d5b7eac2eb9c src/admin/web/ 0a5fff35555153f59d4346933030a67b6e1a8768cee7a47cfa2fcf1a2c564f63 src/admin/web/favicon.svg 7cbdef9192a9dee1f8eac42b85f52b3190f7f6efae50004aa7ad116a910e4036 src/admin/web/file-logs.js b14e7b3578322f309627f6fe965cc16abcf85da3437c9070be6caecae1908743 src/admin/web/host404.js -43ea73b9f4e87025aa5c74cbe6062bf419b44956ea929d9132088583d5bf2dde src/admin/web/index.html +ede1f17067ac1622c66dfaa54bf7b7bbb0ce160ee883235be743ef5b2aa83243 src/admin/web/index.html 7915a06cebb3dfa2c51833c326586920691ba4431b1f984429b039333f9c2a93 src/admin/web/integrations.js 7a12f020fc587205694978ab41b660e9a80487d413fbf6e34fc525eabc58308f src/admin/web/login-keys.json cbd41678eadd994dc5252628ee8ef9551fa9f7d8694ca5abd206240d9a96ad30 src/admin/web/login.html @@ -217,14 +218,14 @@ c2e5f554810b8e34fb47361fb90a01073a2e332ee26d82e030956fad3ec1f83e src/admin/web/ a8afc6e70950bc70b98725eb049d73cff35dc3a3ee659229a15a8e08d3eb4f12 src/admin/web/partials/overview-metrics.html 3928afce2ed6d5f2d3e29475dd29e4c3bd3c6df180ad5119beaff0c7a58e3b3b src/admin/web/prometheus-token.js 90d9a0836662135b79fb6f183c4f3eff60f8a64392d6c5795ccf1d8ef6862263 src/admin/web/redirects.js -be9b78bee4ef0026608191d36a2aed831f93c1baaa5bc73da86bf09bc217ce76 src/admin/web/settings.js +3ee4508cdda0b0b0e0f880ecac4b085368098b46240d24f2e6efed21c96bd5e9 src/admin/web/settings.js 8eadbada619b15087783dcfa0e889a81f88e78034d084c5ab616f7912b835940 src/admin/web/status_200.html 6feb1996b1caa9d19e0dc56eae7ca5b48b7e7cdf0a93bb2e4b527fb8f13a2fe5 src/admin/web/streams.js 38716fae968aeb8f6a8510f28bb9054a73a438a969c3b69f9c9d921acfed6e06 src/admin/web/style.css d290c048450655b3eeae7c6ec54a82d645d1965513694ab29fdf7eef796a1abd src/admin/web/traffic-panel.js dfb4ded2fefb90fc1e2d33370cdef10b040a85cb43235ea9dbc1d73bef823a79 src/admin/web/transform-panel.js a55f45dad5b540def419f8487161fb506b7e52744c76a5e661c7a5fa0a98a426 src/admin/web/vhosts/core.js -73925be3157bae23cd0a4058a596ac5eb7311f3cd719f7006974e4731c2d4843 src/admin/web/vhosts/editor.js +d88d89c8071d2458aef278498a5a7863fb45c374fca801b0b3a9de402c455b4c src/admin/web/vhosts/editor.js 8338ce13b5e3e3f421437631124cb691aeb5b9e17409d256b4b9bcac457b3c59 src/admin/web/vhosts/health.js b3239e67901f1796d7a974ade0796f2e3590ff8064628a5629b78c7f6ce2f32e src/admin/web/vhosts/protocol.js 8c3da49973c62333559b0e3588c02beb0b425c025eac5cfa82a1bb968f70d9dd src/admin/web/vhosts/rates.js @@ -302,7 +303,7 @@ fbea01fea1213d98aea812c1b78d5db289e09200b98ae514d742235cd3fa70e1 src/config/int 75839458ddbc7480ec4492a95eeb67b617ba7d62f7b67e7a767a3453b74dbcbc src/config/route_policy_tests.rs 40e9483d7b2450f55d29b46c408727f4e331b85ecda44fbd7b96bd9a09f02655 src/config/routing.rs dd9a6ad8f58e0cdd1ae74f3f972fee0ac14383cd8b8f518403b9a36c169f35bd src/config/snapshot.rs -b7b0f851b4ca459fe8844a2e4f9cdcfc1135dec4c06f99beeea008c5b35c2ba5 src/config/tests.rs +e943525706c51846adbac23d4a4f4b1a22bd20103b3004b7de1cd1e5e270ca50 src/config/tests.rs f35de0ee1516ece6bbfd2b2a7db7d1e0f5048b0ec47cf2a3765dffb799abfd93 src/config/transport_tests.rs eb04a8922da26e45c9b6005c0cdf1b1ddf2da3c3b680650b22a1d1f16d17a4b2 src/db.rs c290d0cb02dfa5d2c60ecabac1cfb20c8884e3d14cca1944906c6d8e677f1784 src/db/api_tokens.rs @@ -329,7 +330,7 @@ c1b49bef28d87712e4c46138e70b52c4bcfb1a00196579031fac043d0b4aaa7b src/geoip/upda 9a912dad0b8d1e10410fd95d0da3684656092ef85cf8b23eda4ffe7fb92921d8 src/geoip/update_tests.rs 61a2b01db9010f9debfb38b43a26bf588438a5e470dff938e4e54f9d7ba46732 src/headers/mod.rs e4f07bfb7eb75b6897ef812870caff158679a3046d64582428abe8c6df490dbe src/headers/tests.rs -d7c764af29c132e3d8d1fae1bdbe6bf20a27046dc294f83761fea335726f2306 src/http3.rs +b458510eb89ae8bf8fda84989073c6e64c69f2b12fde96c454b33f9df6a57df2 src/http3.rs 0cc484bf0cc59a55a13e0e70435833a9a7a22ad7dfb5b9f86e059cf70a80cc2d src/http3/body.rs 741972222414c280104acbcd8f8071bed9cbfcfa2f503c487c11c56f553f53cd src/http3/diagnostics.rs 49ce4452ef7973cafa2e4071e2e14be0e16000e931a6501e4dc613652e49e230 src/http3/identity.rs @@ -450,8 +451,8 @@ df98becda799b6bf4ff5e2fec7d0e0a486e6b7eca6f9f5ad49ffdafd49a4f498 src/tls.rs 2ff3c219f87bd82677045a4809d3d94921c5b230bbc2f3e7131b07548f73ea7e src/tls/external_paths.rs f88a6c8c2e35c3aa58b7763c71a5a2cec82a34f24478a98b0960b81659a1ec4c src/tls/external_paths_tests.rs 7b4c0f58b3a1e1791bb3c682a001b78bfdbbdafdbc143db8063b3f22dc168616 src/tls/server_config.rs -9d6f048e791a3b7152904d1728258d298ad9d34aa3f83d13baf1b09a6fb7601d src/tls/tests.rs -d9d79edf5a8ef6e3b39a21d35dd5ec6e5a336047117918949e7ec6f5b20ed3f1 src/tls/types.rs +68a29d90f1675c7d97953e50ebccd4fa21c47fd0a4d8a0838b436ee84399afe0 src/tls/tests.rs +bf0ccec8909e678aaed84d358058b1fa865b38e09d10471b02fca76eea38633d src/tls/types.rs a535c8526b38de2990da7781e158b9ea70ef8c1f6fae0aac5ce6e9da21d3a309 src/traffic/mod.rs dc8a83fae47da0d86e6ce0a329cb5274233264df56eebdb56b9bf37cb7be2bb4 src/traffic/tests.rs 65fcac840f8b5f1508213e3f374aa318b450b0f9f90ba827c5ea935b9c60bee7 src/transform/apply.rs diff --git a/docs/README.md b/docs/README.md index b115490..f1054a1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # RustProxy documentation -Practical guides for **RustProxy 0.34.8**. 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.9**. 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 @@ -19,6 +19,7 @@ Practical guides for **RustProxy 0.34.8**. This index and the listed pages are a - [Cache](CACHE.md) — HOT/COLD storage, privacy, TTL and invalidation. - [Response delivery](RESPONSE_DELIVERY.md) — compression, static transformations and response headers. - [HTTP transport](TRANSPORT.md) — HTTPS/H2/H3, WebSockets, origin protocols and timeouts. +- [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. ## Integrations and operations diff --git a/docs/TLS_POST_QUANTUM.md b/docs/TLS_POST_QUANTUM.md new file mode 100644 index 0000000..7feb9f2 --- /dev/null +++ b/docs/TLS_POST_QUANTUM.md @@ -0,0 +1,53 @@ +# Experimental post-quantum TLS key exchange (PQC) + +**Version:** RustProxy 0.34.9 (source candidate). **Default: off.** This is an experimental opt-in feature and not a production compatibility guarantee. + +## What it does + +Post-quantum cryptography (PQC) aims to protect key exchange from attackers with future quantum computing capabilities. **X25519MLKEM768** combines a conventional X25519 ephemeral key agreement with post-quantum **ML-KEM-768** in one TLS 1.3 *hybrid key-exchange group*. Both contributions protect the derived traffic secret. This is **not a TLS cipher suite**: AES-GCM or ChaCha20-Poly1305 and ordinary X.509 RSA/ECDSA certificates remain in use. It does not change certificate signatures to post-quantum algorithms, and does not make all parts of TLS quantum-safe. + +When enabled, RustProxy uses the `aws-lc-rs` cryptography provider for selected incoming TLS policies, offering X25519MLKEM768 first and classical key-exchange groups as fallback. When disabled it keeps the existing `ring` TLS provider. The selected key exchange depends on client support and negotiation; turning the switch on does not imply every connection uses PQC. It does **not** change outbound/backend, update-check, certificate-automation or other HTTP client TLS settings. + +For implementation details see [rustls defaults and PQC](https://rustls.dev/docs/rustls/manual/_05_defaults/index.html) and [X25519MLKEM768 rustls API](https://docs.rs/rustls/0.23.45/rustls/crypto/aws_lc_rs/kx_group/static.X25519MLKEM768.html). + +## Enable + +1. Make a configuration backup; ensure that **TLS 1.3** is enabled. +2. Open **Settings → TLS policy** and enable **Experimental post-quantum key exchange (PQC)**. Keep your current **cipher suite** list unless you have a specific reason to change it. The KEX group is enabled by the switch, **not** by adding X25519MLKEM768 to the cipher-suite textarea. +3. Select **Validate, save and apply**. The TLS status reports the configured key-exchange groups, not the group used by each individual connection. +4. Test HTTPS, HTTP/1.1, HTTP/2 and (if enabled) HTTP/3 on staging with a client that supports hybrid KEX, and with older clients that use classical KEX. + +`post_quantum` is stored on the global policy (the default is false): + +```json +{"tls": {"policy": {"tls12": true, "tls13": true, "cipher_suites": [], "post_quantum": true}}} +``` + +This fragment illustrates the `tls` field; do not replace your full configuration with it. + +### Per-vhost behavior + +A Vhost **inherits** the global TLS policy by default. If it has an explicit `tls_policy` override, the override may disable PQC, but it cannot enable PQC while the global setting is disabled. Existing overrides that do not contain `post_quantum` are treated as `false`, even after you enable PQC globally. HTTP/3 Vhosts require their override, if any, to match the global TLS policy exactly, including PQC. Update or remove conflicting overrides before enabling PQC on H3. + +The administration TLS listener also uses the global policy when administration HTTPS is enabled. Open connections keep their negotiated keys; only **new handshakes** use the updated policy. + +## Test negotiated group + +Requires **OpenSSL 3.5+** with `X25519MLKEM768` support: + +```bash +openssl s_client -connect example.com:443 -servername example.com \ + -tls1_3 -groups X25519MLKEM768 -brief +``` + +Check for `Protocol version: TLSv1.3` and `Negotiated TLS1.3 group: X25519MLKEM768` (format depends on OpenSSL). Compare with a classic-only client using `-groups X25519` and test TLS 1.2 if it is enabled. For HTTP/3, also use an actual QUIC/H3 client and test with UDP blocked to verify fallback to H2/H1; `openssl s_client` does not test QUIC. + +If your TLS connection ends at a CDN, load balancer or TLS-terminating proxy, the test shows **that intermediary**, not RustProxy. To check RustProxy, connect to its listener directly while preserving SNI, and verify its actual certificate. + +## Caveats and rollback + +- Hybrid handshakes are larger and can hit MTU/middlebox limits, especially over QUIC. Measure connection errors, handshake latency, memory and CPU under expected load. Some legacy clients and devices may reject hybrid negotiation. +- Enabling the switch changes the incoming TLS cryptographic provider to `aws-lc-rs`; some uncommon certificates, algorithms or hardware platforms may behave differently. `aws-lc-rs` requires a native C/C++ build toolchain; CMake may be needed for some build modes (non-FIPS commonly does not require it). The `ring` provider remains used where the switch is off and for existing outbound integrations. +- A non-empty cipher-suite allowlist must contain suites supported by the selected provider; invalid combinations are rejected. PQC requires TLS 1.3. +- For immediate rollback, **uncheck PQC in Settings → TLS policy and save**, and if necessary remove per-Vhost overrides that require PQC. Confirm new connections negotiate classic X25519. Existing sessions cannot renegotiate in place; close/reconnect them to retest. Keep the prior binary and backups available for a full rollback. +- **Release verification:** this 0.34.9 source candidate has not undergone native Cargo build, TLS handshake, QUIC interoperability or production load testing. Verify the provisionally updated `Cargo.lock` with `cargo metadata --locked` (and refresh it with Cargo if needed), then run `cargo check --all-targets`, `cargo test --all-targets`, `cargo build --release`, and protocol tests before deployment. See the release changelog and source verification notes. diff --git a/docs/TRANSPORT.md b/docs/TRANSPORT.md index ea1ed56..277f8b1 100644 --- a/docs/TRANSPORT.md +++ b/docs/TRANSPORT.md @@ -55,6 +55,8 @@ WebSockets normally use HTTP/1.1 Upgrade. HTTP/2/HTTP/3 client requests can stil ## TLS and trust +**Experimental (0.34.9):** Settings → TLS policy has a disabled-by-default **Post-quantum key exchange (PQC)** switch for hybrid TLS 1.3 X25519MLKEM768. This is a TLS key-exchange group, not a cipher suite. See [Post-quantum TLS](TLS_POST_QUANTUM.md) for prerequisites, fallback, HTTP/3 and rollback. + Public HTTPS requires a correct certificate with hostname coverage. Administration TLS is separate. Backend `https://` encrypts traffic, but **upstream certificate verification is opt-in by default** in the current backend model; enable it and specify CA/name where needed. Private/loopback addresses and routing to a local RustProxy listener require explicit risk overrides. ## Timeouts, request bodies and streaming diff --git a/langs/en_US.json b/langs/en_US.json index 33c7fc4..c18939d 100644 --- a/langs/en_US.json +++ b/langs/en_US.json @@ -991,6 +991,13 @@ "tls13": "TLS 1.3", "tlsPolicy": "TLS policy", "tlsPolicyHelp": "This is the global TLS policy inherited by every TLS host in the application. Per-vhost policy may only narrow it. HTTP/3 requires TLS 1.3.", + "tlsPqcLabel": "Experimental post-quantum key exchange (PQC)", + "tlsPqcHelp": "TLS 1.3 only: enable hybrid X25519MLKEM768; classic key exchange remains available for older clients. Key exchange groups are not cipher suites. Disabled by default.", + "tlsPqcDocs": "What is PQC? Compatibility, risks and testing (documentation)", + "tlsPqcKeyExchangeGroups": "Available key exchange groups", + "tlsPqcTls13Required": "PQC requires TLS 1.3 to be enabled.", + "tlsPqcGlobalRequired": "Enable PQC in Settings > TLS policy before enabling it for a Vhost.", + "tlsPqcVhostHelp": "The global PQC switch must be on. A Vhost override can disable PQC; HTTP/3 requires the Vhost TLS policy to exactly match the global policy.", "tlsCiphers": "Cipher suites (one per line; empty = rustls defaults)", "tlsAvailableCiphers": "Available cipher suites", "tlsPolicyVersionRequired": "Enable at least one TLS version.", diff --git a/langs/pl_pl.json b/langs/pl_pl.json index 5646ef0..10d1e90 100644 --- a/langs/pl_pl.json +++ b/langs/pl_pl.json @@ -991,6 +991,13 @@ "tls13": "TLS 1.3", "tlsPolicy": "Polityka TLS", "tlsPolicyHelp": "To globalna polityka TLS dziedziczona przez każdy host TLS w aplikacji. Ustawienia per-vhost mogą ją tylko zawężać. HTTP/3 wymaga TLS 1.3.", + "tlsPqcLabel": "Eksperymentalna postkwantowa wymiana kluczy (PQC)", + "tlsPqcHelp": "Tylko TLS 1.3: włącza hybrydową grupę X25519MLKEM768; starsze klienty mogą używać klasycznych grup. Grupa wymiany kluczy nie jest szyfrem TLS. Domyślnie wyłączone.", + "tlsPqcDocs": "Czym jest PQC? Zgodność, ryzyka i testowanie (dokumentacja)", + "tlsPqcKeyExchangeGroups": "Dostępne grupy wymiany kluczy", + "tlsPqcTls13Required": "PQC wymaga włączonego TLS 1.3.", + "tlsPqcGlobalRequired": "Najpierw włącz PQC w Ustawienia > Polityka TLS.", + "tlsPqcVhostHelp": "Globalny przełącznik PQC musi być włączony. Nadpisanie w vhoście może wyłączyć PQC; przy HTTP/3 polityka musi być identyczna z globalną.", "tlsCiphers": "Szyfry (jeden na linię; puste = domyślne rustls)", "tlsAvailableCiphers": "Dostępne szyfry", "tlsPolicyVersionRequired": "Włącz co najmniej jedną wersję TLS.", diff --git a/src/admin/documentation/documents.rs b/src/admin/documentation/documents.rs index 1881b33..53da759 100644 --- a/src/admin/documentation/documents.rs +++ b/src/admin/documentation/documents.rs @@ -24,6 +24,7 @@ pub(super) static READER_DOCUMENTS: &[(&str, &str, &str)] = &[ reader_doc!("docs/CACHE.md", "guides"), reader_doc!("docs/RESPONSE_DELIVERY.md", "guides"), reader_doc!("docs/TRANSPORT.md", "guides"), + reader_doc!("docs/TLS_POST_QUANTUM.md", "guides"), reader_doc!("docs/STREAMS.md", "guides"), reader_doc!("docs/ACME_PROVIDERS.md", "guides"), reader_doc!("docs/DOCKER_DISCOVERY.md", "guides"), diff --git a/src/admin/documentation/tests.rs b/src/admin/documentation/tests.rs index 56e4312..5a7d1d2 100644 --- a/src/admin/documentation/tests.rs +++ b/src/admin/documentation/tests.rs @@ -6,13 +6,22 @@ mod tests { let value: Value = serde_json::from_slice(reader_bundle()).unwrap(); let documents = value["documents"].as_array().unwrap(); assert!(documents.iter().any(|doc| doc["path"] == "README.md")); - assert!(documents.iter().any(|doc| doc["path"] == "docs/WEB_SERVER.md")); + assert!(documents + .iter() + .any(|doc| doc["path"] == "docs/WEB_SERVER.md")); assert!(documents.iter().any(|doc| doc["path"] == "docs/PHP_FPM.md")); + assert!(documents + .iter() + .any(|doc| doc["path"] == "docs/TLS_POST_QUANTUM.md")); assert!(documents.iter().all(|doc| { doc["path"].as_str().is_some_and(|value| !value.is_empty()) && doc["title"].as_str().is_some_and(|value| !value.is_empty()) - && doc["category"].as_str().is_some_and(|value| !value.is_empty()) - && doc["content"].as_str().is_some_and(|value| !value.is_empty()) + && doc["category"] + .as_str() + .is_some_and(|value| !value.is_empty()) + && doc["content"] + .as_str() + .is_some_and(|value| !value.is_empty()) })); } diff --git a/src/admin/openapi.json b/src/admin/openapi.json index d980e3e..bcb697d 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.8", + "version": "0.34.9", "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": [ @@ -622,6 +622,11 @@ "items": { "type": "string" } + }, + "post_quantum": { + "type": "boolean", + "default": false, + "description": "Experimental hybrid X25519MLKEM768 TLS 1.3 key exchange. Can only be enabled for a Vhost when enabled in the global TLS policy. HTTP/3 Vhosts must match the global policy." } }, "additionalProperties": false, @@ -772,7 +777,35 @@ }, "tls": { "type": "object", - "properties": {}, + "properties": { + "policy": { + "type": "object", + "description": "Global TLS policy inherited by frontends, including experimental post-quantum key exchange.", + "properties": { + "tls12": { + "type": "boolean", + "default": true + }, + "tls13": { + "type": "boolean", + "default": true + }, + "cipher_suites": { + "type": "array", + "items": { + "type": "string" + }, + "description": "TLS cipher suites, independent of key exchange groups." + }, + "post_quantum": { + "type": "boolean", + "default": false, + "description": "Experimental hybrid X25519MLKEM768 TLS 1.3 key exchange. Requires tls13=true, uses aws-lc-rs for frontend TLS; classic groups remain as fallback." + } + }, + "additionalProperties": false + } + }, "additionalProperties": true }, "cache": { diff --git a/src/admin/status.rs b/src/admin/status.rs index 86864a7..1c5e604 100644 --- a/src/admin/status.rs +++ b/src/admin/status.rs @@ -223,8 +223,9 @@ fn status_payload(state: &App) -> Value { }); payload["tls"] = json!({ "policy": &snapshot.envelope.config.tls.policy, - "cipher_suites": crate::tls::cipher_suite_names(), - "effective_cipher_suites": snapshot.envelope.config.tls.policy.effective_cipher_suites() + "cipher_suites": crate::tls::cipher_suite_names_for(snapshot.envelope.config.tls.policy.post_quantum), + "effective_cipher_suites": snapshot.envelope.config.tls.policy.effective_cipher_suites(), + "key_exchange_groups": snapshot.envelope.config.tls.policy.key_exchange_groups() }); payload } diff --git a/src/admin/web/index.html b/src/admin/web/index.html index e426ffd..9a557bb 100644 --- a/src/admin/web/index.html +++ b/src/admin/web/index.html @@ -3071,6 +3071,19 @@ +
+ +

TLS 1.3 only: prioritize hybrid + X25519MLKEM768 with classic key exchanges as fallback. This is a key exchange + group, not a cipher suite. Disabled by default.

+ Learn about PQC, compatibility + and testing (documentation) +
+