From 5243512f0e530ab2f86a1ad96977006de862fceb Mon Sep 17 00:00:00 2001 From: Jun Kurihara Date: Sun, 14 Jan 2024 22:13:42 +0900 Subject: [PATCH 1/2] feat: support hyper-rustls along with hyper v1 --- rpxy-bin/Cargo.toml | 9 ++-- rpxy-lib/Cargo.toml | 35 +++++++--------- rpxy-lib/src/forwarder/cache/cache_main.rs | 4 ++ rpxy-lib/src/forwarder/client.rs | 49 ++++++++++++---------- 4 files changed, 50 insertions(+), 47 deletions(-) diff --git a/rpxy-bin/Cargo.toml b/rpxy-bin/Cargo.toml index 1d12e026..a080ec0c 100644 --- a/rpxy-bin/Cargo.toml +++ b/rpxy-bin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rpxy" -version = "0.7.0-alpha.1" +version = "0.7.0-alpha.2" authors = ["Jun Kurihara"] homepage = "https://github.com/junkurihara/rust-rpxy" repository = "https://github.com/junkurihara/rust-rpxy" @@ -12,14 +12,13 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["http3-quinn", "cache", "native-tls-backend"] +default = ["http3-quinn", "cache", "rustls-backend"] http3-quinn = ["rpxy-lib/http3-quinn"] http3-s2n = ["rpxy-lib/http3-s2n"] native-tls-backend = ["rpxy-lib/native-tls-backend"] -# Not yet implemented rustls-backend = ["rpxy-lib/rustls-backend"] +rustls-backend-webpki = ["rpxy-lib/rustls-backend-webpki"] cache = ["rpxy-lib/cache"] -native-roots = ["rpxy-lib/native-roots"] [dependencies] rpxy-lib = { path = "../rpxy-lib/", default-features = false, features = [ @@ -42,7 +41,7 @@ rustls-pemfile = "1.0.4" mimalloc = { version = "*", default-features = false } # config -clap = { version = "4.4.14", features = ["std", "cargo", "wrap_help"] } +clap = { version = "4.4.16", features = ["std", "cargo", "wrap_help"] } toml = { version = "0.8.8", default-features = false, features = ["parse"] } hot_reload = "0.1.4" diff --git a/rpxy-lib/Cargo.toml b/rpxy-lib/Cargo.toml index add7ffa9..80bb5a79 100644 --- a/rpxy-lib/Cargo.toml +++ b/rpxy-lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rpxy-lib" -version = "0.7.0-alpha.1" +version = "0.7.0-alpha.2" authors = ["Jun Kurihara"] homepage = "https://github.com/junkurihara/rust-rpxy" repository = "https://github.com/junkurihara/rust-rpxy" @@ -12,7 +12,7 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["http3-quinn", "sticky-cookie", "cache", "native-tls-backend"] +default = ["http3-quinn", "sticky-cookie", "cache", "rustls-backend"] http3-quinn = ["socket2", "quinn", "h3", "h3-quinn"] http3-s2n = [ "h3", @@ -24,8 +24,8 @@ http3-s2n = [ cache = ["http-cache-semantics", "lru", "sha2", "base64"] sticky-cookie = ["base64", "sha2", "chrono"] native-tls-backend = ["hyper-tls"] -rustls-backend = [] # not implemented yet -native-roots = [] #"hyper-rustls/native-tokio"] # not implemented yet +rustls-backend = ["hyper-rustls"] +rustls-backend-webpki = ["rustls-backend", "hyper-rustls/webpki-tokio"] [dependencies] rand = "0.8.5" @@ -52,28 +52,21 @@ thiserror = "1.0.56" http = "1.0.0" http-body-util = "0.1.0" hyper = { version = "1.1.0", default-features = false } -# hyper-util = { version = "0.1.2", features = ["full"] } -hyper-util = { git = "https://github.com/junkurihara/hyper-util", features = [ - "full", -], rev = "784109db021d076b0822ea5344a315e530831973" } +hyper-util = { version = "0.1.2", features = ["full"] } futures-util = { version = "0.3.30", default-features = false } futures-channel = { version = "0.3.30", default-features = false } # http client for upstream -hyper-tls = { git = "https://github.com/junkurihara/hyper-tls", features = [ +hyper-tls = { version = "0.6.0", features = [ "alpn", "vendored", -], rev = "33dafc7251866260b66b0fc93c09f04f1923827f", optional = true } -# hyper-tls = { version = "0.6.0", features = [ -# "alpn", -# "vendored", -# ], optional = true } -# hyper-rustls = { version = "0.24.2", default-features = false, features = [ -# "tokio-runtime", -# "webpki-tokio", -# "http1", -# "http2", -# ] } +], optional = true } +hyper-rustls = { version = "0.26.0", default-features = false, features = [ + "ring", + "native-tokio", + "http1", + "http2", +], optional = true } # tls and cert management for server hot_reload = "0.1.4" @@ -109,7 +102,7 @@ chrono = { version = "0.4.31", default-features = false, features = [ "alloc", "clock", ], optional = true } -base64 = { version = "0.21.6", optional = true } +base64 = { version = "0.21.7", optional = true } [dev-dependencies] diff --git a/rpxy-lib/src/forwarder/cache/cache_main.rs b/rpxy-lib/src/forwarder/cache/cache_main.rs index 02aec937..edb1ec53 100644 --- a/rpxy-lib/src/forwarder/cache/cache_main.rs +++ b/rpxy-lib/src/forwarder/cache/cache_main.rs @@ -46,6 +46,7 @@ pub(crate) struct RpxyCache { } impl RpxyCache { + #[allow(unused)] /// Generate cache storage pub(crate) async fn new(globals: &Globals) -> Option { if !globals.proxy_config.cache_enabled { @@ -254,6 +255,7 @@ struct FileStore { inner: Arc>, } impl FileStore { + #[allow(unused)] /// Build manager async fn new(runtime_handle: &tokio::runtime::Handle) -> Self { Self { @@ -300,6 +302,7 @@ struct FileStoreInner { } impl FileStoreInner { + #[allow(unused)] /// Build new cache file manager. /// This first creates cache file dir if not exists, and cleans up the file inside the directory. /// TODO: Persistent cache is really difficult. `sqlite` or something like that is needed. @@ -436,6 +439,7 @@ struct LruCacheManager { } impl LruCacheManager { + #[allow(unused)] /// Build LruCache fn new(cache_max_entry: usize) -> Self { Self { diff --git a/rpxy-lib/src/forwarder/client.rs b/rpxy-lib/src/forwarder/client.rs index 26c2276f..2e699d05 100644 --- a/rpxy-lib/src/forwarder/client.rs +++ b/rpxy-lib/src/forwarder/client.rs @@ -1,3 +1,4 @@ +#[allow(unused)] use crate::{ error::{RpxyError, RpxyResult}, globals::Globals, @@ -192,7 +193,7 @@ where #[cfg(feature = "rustls-backend")] /// Build forwarder with hyper-rustls (rustls) -impl Forwarder +impl Forwarder, B1> where B1: Body + Send + Unpin + 'static, ::Data: Send, @@ -200,26 +201,32 @@ where { /// Build forwarder pub async fn try_new(_globals: &Arc) -> RpxyResult { - todo!("Not implemented yet. Please use native-tls-backend feature for now."); - // #[cfg(feature = "native-roots")] - // let builder = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots(); - // #[cfg(feature = "native-roots")] - // let builder_h2 = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots(); - // #[cfg(feature = "native-roots")] - // info!("Native cert store is used for the connection to backend applications"); - - // #[cfg(not(feature = "native-roots"))] - // let builder = hyper_rustls::HttpsConnectorBuilder::new().with_webpki_roots(); - // #[cfg(not(feature = "native-roots"))] - // let builder_h2 = hyper_rustls::HttpsConnectorBuilder::new().with_webpki_roots(); - // #[cfg(not(feature = "native-roots"))] - // info!("Mozilla WebPKI root certs is used for the connection to backend applications"); - - // let connector = builder.https_or_http().enable_http1().enable_http2().build(); - // let connector_h2 = builder_h2.https_or_http().enable_http2().build(); - - // let inner = Client::builder().build::<_, Body>(connector); - // let inner_h2 = Client::builder().http2_only(true).build::<_, Body>(connector_h2); + // build hyper client with rustls and webpki, only https is allowed + #[cfg(feature = "rustls-backend-webpki")] + let builder = hyper_rustls::HttpsConnectorBuilder::new().with_webpki_roots(); + #[cfg(feature = "rustls-backend-webpki")] + let builder_h2 = hyper_rustls::HttpsConnectorBuilder::new().with_webpki_roots(); + #[cfg(feature = "rustls-backend-webpki")] + info!("Mozilla WebPKI root certs with rustls is used for the connection to backend applications"); + + #[cfg(not(feature = "rustls-backend-webpki"))] + let builder = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots()?; + #[cfg(not(feature = "rustls-backend-webpki"))] + let builder_h2 = hyper_rustls::HttpsConnectorBuilder::new().with_native_roots()?; + #[cfg(not(feature = "rustls-backend-webpki"))] + info!("Native cert store with rustls is used for the connection to backend applications"); + + let connector = builder.https_or_http().enable_all_versions().build(); + let connector_h2 = builder_h2.https_or_http().enable_http2().build(); + let inner = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone())).build::<_, B1>(connector); + let inner_h2 = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone())).build::<_, B1>(connector_h2); + + Ok(Self { + inner, + inner_h2, + #[cfg(feature = "cache")] + cache: RpxyCache::new(_globals).await, + }) } } From 422889cec016b351d0a24b98bfa46b535063023a Mon Sep 17 00:00:00 2001 From: Jun Kurihara Date: Sun, 14 Jan 2024 22:36:32 +0900 Subject: [PATCH 2/2] chore: updated docker according to the change of features --- .github/workflows/release.yml | 61 +++++++++++------------ .github/workflows/release_docker.yml | 74 ++++++++++++++-------------- CHANGELOG.md | 1 + docker/docker-compose-slim.yml | 4 +- docker/docker-compose.yml | 4 +- rpxy-bin/Cargo.toml | 2 +- rpxy-lib/Cargo.toml | 2 +- 7 files changed, 74 insertions(+), 74 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cee70074..3a388850 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,35 +44,35 @@ jobs: platform: linux/arm64 tags-suffix: "-s2n" - # - target: "gnu" - # build-feature: "-native-roots" - # platform: linux/amd64 - # tags-suffix: "-native-roots" - - # - target: "gnu" - # build-feature: "-native-roots" - # platform: linux/arm64 - # tags-suffix: "-native-roots" - - # - target: "musl" - # build-feature: "-native-roots" - # platform: linux/amd64 - # tags-suffix: "-slim-native-roots" - - # - target: "musl" - # build-feature: "-native-roots" - # platform: linux/arm64 - # tags-suffix: "-slim-native-roots" - - # - target: "gnu" - # build-feature: "-s2n-native-roots" - # platform: linux/amd64 - # tags-suffix: "-s2n-native-roots" - - # - target: "gnu" - # build-feature: "-s2n-native-roots" - # platform: linux/arm64 - # tags-suffix: "-s2n-native-roots" + - target: "gnu" + build-feature: "-webpki-roots" + platform: linux/amd64 + tags-suffix: "-webpki-roots" + + - target: "gnu" + build-feature: "-webpki-roots" + platform: linux/arm64 + tags-suffix: "-webpki-roots" + + - target: "musl" + build-feature: "-webpki-roots" + platform: linux/amd64 + tags-suffix: "-slim-webpki-roots" + + - target: "musl" + build-feature: "-webpki-roots" + platform: linux/arm64 + tags-suffix: "-slim-webpki-roots" + + - target: "gnu" + build-feature: "-s2n-webpki-roots" + platform: linux/amd64 + tags-suffix: "-s2n-webpki-roots" + + - target: "gnu" + build-feature: "-s2n-webpki-roots" + platform: linux/arm64 + tags-suffix: "-s2n-webpki-roots" steps: - run: "echo 'The relese triggering workflows passed'" @@ -81,10 +81,9 @@ jobs: id: "set-env" run: | if [ ${{ matrix.platform }} == 'linux/amd64' ]; then PLATFORM_MAP="x86_64"; else PLATFORM_MAP="aarch64"; fi - if [ ${{ github.ref_name == 'develop' && github.event.client_payload.pull_request.head == 'develop' && github.event.client_payload.pull_request.base == 'main' }} || ${{ github.ref_name == 'main' }}]; then BUILD_NAME=""; else BUILD_NAME="-nightly"; fi if [ ${{ github.ref_name }} == 'main' ]; then BUILD_IMG="latest"; else BUILD_IMG="nightly"; fi echo "build_img=${BUILD_IMG}" >> $GITHUB_OUTPUT - echo "target_name=rpxy${BUILD_NAME}-${PLATFORM_MAP}-unknown-linux-${{ matrix.target }}${{ matrix.build-feature }}" >> $GITHUB_OUTPUT + echo "target_name=rpxy-${PLATFORM_MAP}-unknown-linux-${{ matrix.target }}${{ matrix.build-feature }}" >> $GITHUB_OUTPUT - name: "docker pull and extract binary from docker image" id: "extract-binary" diff --git a/.github/workflows/release_docker.yml b/.github/workflows/release_docker.yml index 4fe9d146..a8249bbe 100644 --- a/.github/workflows/release_docker.yml +++ b/.github/workflows/release_docker.yml @@ -45,7 +45,7 @@ jobs: - target: "s2n" dockerfile: ./docker/Dockerfile build-args: | - "CARGO_FEATURES=--no-default-features --features=http3-s2n,cache,native-tls-backend" + "CARGO_FEATURES=--no-default-features --features=http3-s2n,cache,rustls-backend" "ADDITIONAL_DEPS=pkg-config libssl-dev cmake libclang1 gcc g++" platforms: linux/amd64,linux/arm64 tags-suffix: "-s2n" @@ -54,42 +54,42 @@ jobs: jqtype/rpxy:s2n ghcr.io/junkurihara/rust-rpxy:s2n - # - target: "native-roots" - # dockerfile: ./docker/Dockerfile - # platforms: linux/amd64,linux/arm64 - # build-args: | - # "CARGO_FEATURES=--no-default-features --features=http3-quinn,cache,native-roots" - # tags-suffix: "-native-roots" - # # Aliases must be used only for release builds - # aliases: | - # jqtype/rpxy:native-roots - # ghcr.io/junkurihara/rust-rpxy:native-roots - - # - target: "slim-native-roots" - # dockerfile: ./docker/Dockerfile-slim - # build-args: | - # "CARGO_FEATURES=--no-default-features --features=http3-quinn,cache,native-roots" - # build-contexts: | - # messense/rust-musl-cross:amd64-musl=docker-image://messense/rust-musl-cross:x86_64-musl - # messense/rust-musl-cross:arm64-musl=docker-image://messense/rust-musl-cross:aarch64-musl - # platforms: linux/amd64,linux/arm64 - # tags-suffix: "-slim-native-roots" - # # Aliases must be used only for release builds - # aliases: | - # jqtype/rpxy:slim-native-roots - # ghcr.io/junkurihara/rust-rpxy:slim-native-roots - - # - target: "s2n-native-roots" - # dockerfile: ./docker/Dockerfile - # build-args: | - # "CARGO_FEATURES=--no-default-features --features=http3-s2n,cache,native-roots" - # "ADDITIONAL_DEPS=pkg-config libssl-dev cmake libclang1 gcc g++" - # platforms: linux/amd64,linux/arm64 - # tags-suffix: "-s2n-native-roots" - # # Aliases must be used only for release builds - # aliases: | - # jqtype/rpxy:s2n-native-roots - # ghcr.io/junkurihara/rust-rpxy:s2n-native-roots + - target: "webpki-roots" + dockerfile: ./docker/Dockerfile + platforms: linux/amd64,linux/arm64 + build-args: | + "CARGO_FEATURES=--no-default-features --features=http3-quinn,cache,webpki-roots" + tags-suffix: "-webpki-roots" + # Aliases must be used only for release builds + aliases: | + jqtype/rpxy:webpki-roots + ghcr.io/junkurihara/rust-rpxy:webpki-roots + + - target: "slim-webpki-roots" + dockerfile: ./docker/Dockerfile-slim + build-args: | + "CARGO_FEATURES=--no-default-features --features=http3-quinn,cache,webpki-roots" + build-contexts: | + messense/rust-musl-cross:amd64-musl=docker-image://messense/rust-musl-cross:x86_64-musl + messense/rust-musl-cross:arm64-musl=docker-image://messense/rust-musl-cross:aarch64-musl + platforms: linux/amd64,linux/arm64 + tags-suffix: "-slim-webpki-roots" + # Aliases must be used only for release builds + aliases: | + jqtype/rpxy:slim-webpki-roots + ghcr.io/junkurihara/rust-rpxy:slim-webpki-roots + + - target: "s2n-webpki-roots" + dockerfile: ./docker/Dockerfile + build-args: | + "CARGO_FEATURES=--no-default-features --features=http3-s2n,cache,webpki-roots" + "ADDITIONAL_DEPS=pkg-config libssl-dev cmake libclang1 gcc g++" + platforms: linux/amd64,linux/arm64 + tags-suffix: "-s2n-webpki-roots" + # Aliases must be used only for release builds + aliases: | + jqtype/rpxy:s2n-webpki-roots + ghcr.io/junkurihara/rust-rpxy:s2n-webpki-roots steps: - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c47c8b4..1270cd15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Breaking: `hyper`-1.0 for both server and client modules. - Breaking: Remove `override_host` option in upstream options. Add a reverse option, i.e., `keep_original_host`, and the similar option `set_upstream_host`. While `keep_original_host` can be explicitly specified, `rpxy` keeps the original `host` given by the incoming request by default. Then, the original `host` header is maintained or added from the value of url request line. If `host` header needs to be overridden with the upstream host name (backend uri's host name), `set_upstream_host` has to be set. If both of `set_upstream_host` and `keep_original_host` are set, `keep_original_host` is prioritized since it is explicitly specified. - Breaking: Introduced `native-tls-backend` feature to use the native TLS engine to access backend applications. +- Breaking: Changed the policy of the default cert store from `webpki` to the system-native store. Thus we terminated the feature `native-roots` and introduced `webpki-roots` feature to use `webpki` root cert store. - Redesigned: Cache structure is totally redesigned with more memory-efficient way to read from cache file, and more secure way to strongly bind memory-objects with files with hash values. - Redesigned: HTTP body handling flow is also redesigned with more memory-and-time efficient techniques without putting the whole objects on memory by using `futures::stream::Stream` and `futures::channel::mpsc` - Refactor: lots of minor improvements diff --git a/docker/docker-compose-slim.yml b/docker/docker-compose-slim.yml index 90f5e769..57f9cc98 100644 --- a/docker/docker-compose-slim.yml +++ b/docker/docker-compose-slim.yml @@ -14,8 +14,8 @@ services: additional_contexts: - messense/rust-musl-cross:amd64-musl=docker-image://messense/rust-musl-cross:x86_64-musl - messense/rust-musl-cross:arm64-musl=docker-image://messense/rust-musl-cross:aarch64-musl - # args: # Uncomment when build with native cert store - # - "CARGO_FEATURES=--no-default-features --features=http3-quinn,native-roots" + # args: # Uncomment when build with webpki cert store + # - "CARGO_FEATURES=--no-default-features --features=http3-quinn,webpki-roots" dockerfile: ./docker/Dockerfile-slim # based on alpine and build x86_64-unknown-linux-musl platforms: # Choose your platforms # - "linux/amd64" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index bac5957b..0c95fc67 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -14,8 +14,8 @@ services: # args: # Uncomment when build quic-s2n version # - "CARGO_FEATURES=--no-default-features --features=http3-s2n" # - "ADDITIONAL_DEPS=pkg-config libssl-dev cmake libclang1 gcc g++" - # args: # Uncomment when build with native cert store - # - "CARGO_FEATURES=--no-default-features --features=http3-quinn,native-roots" + # args: # Uncomment when build with webpki root store + # - "CARGO_FEATURES=--no-default-features --features=http3-quinn,webpki-roots" dockerfile: ./docker/Dockerfile # based on ubuntu 22.04 and build x86_64-unknown-linux-gnu platforms: # Choose your platforms # - "linux/amd64" diff --git a/rpxy-bin/Cargo.toml b/rpxy-bin/Cargo.toml index a080ec0c..a64b868e 100644 --- a/rpxy-bin/Cargo.toml +++ b/rpxy-bin/Cargo.toml @@ -17,7 +17,7 @@ http3-quinn = ["rpxy-lib/http3-quinn"] http3-s2n = ["rpxy-lib/http3-s2n"] native-tls-backend = ["rpxy-lib/native-tls-backend"] rustls-backend = ["rpxy-lib/rustls-backend"] -rustls-backend-webpki = ["rpxy-lib/rustls-backend-webpki"] +webpki-roots = ["rpxy-lib/webpki-roots"] cache = ["rpxy-lib/cache"] [dependencies] diff --git a/rpxy-lib/Cargo.toml b/rpxy-lib/Cargo.toml index 80bb5a79..1cda5524 100644 --- a/rpxy-lib/Cargo.toml +++ b/rpxy-lib/Cargo.toml @@ -25,7 +25,7 @@ cache = ["http-cache-semantics", "lru", "sha2", "base64"] sticky-cookie = ["base64", "sha2", "chrono"] native-tls-backend = ["hyper-tls"] rustls-backend = ["hyper-rustls"] -rustls-backend-webpki = ["rustls-backend", "hyper-rustls/webpki-tokio"] +webpki-roots = ["rustls-backend", "hyper-rustls/webpki-tokio"] [dependencies] rand = "0.8.5"