Skip to content

Commit

Permalink
Merge pull request #212 from junkurihara/develop
Browse files Browse the repository at this point in the history
0.9.3
  • Loading branch information
junkurihara authored Nov 1, 2024
2 parents 6d1e9b8 + 4b5c254 commit 3984de4
Show file tree
Hide file tree
Showing 23 changed files with 168 additions and 604 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ jobs:
platform: linux/arm64
tags-suffix: "-slim"

- target: "musl"
build-feature: "-slim-pq"
platform: linux/amd64
tags-suffix: "-slim-pq"

- target: "musl"
build-feature: "-slim-pq"
platform: linux/arm64
tags-suffix: "-slim-pq"

- target: "gnu"
build-feature: "-s2n"
platform: linux/amd64
Expand All @@ -44,6 +54,26 @@ jobs:
platform: linux/arm64
tags-suffix: "-s2n"

- target: "gnu"
build-feature: "-pq"
platform: linux/amd64
tags-suffix: "-pq"

- target: "gnu"
build-feature: "-pq"
platform: linux/arm64
tags-suffix: "-pq"

- target: "gnu"
build-feature: "-s2n-pq"
platform: linux/amd64
tags-suffix: "-s2n-pq"

- target: "gnu"
build-feature: "-s2n-pq"
platform: linux/arm64
tags-suffix: "-s2n-pq"

- target: "gnu"
build-feature: "-webpki-roots"
platform: linux/amd64
Expand Down
37 changes: 37 additions & 0 deletions .github/workflows/release_docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ jobs:
jqtype/rpxy:latest
ghcr.io/junkurihara/rust-rpxy:latest
- target: "default-pq"
dockerfile: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64
build-args: |
"CARGO_FEATURES=--no-default-features --features=http3-quinn,cache,rustls-backend,acme,post-quantum"
tags-suffix: "-pq"
# Aliases must be used only for release builds
aliases: |
jqtype/rpxy:pq
ghcr.io/junkurihara/rust-rpxy:pq
- target: "default-slim"
dockerfile: ./docker/Dockerfile-slim
build-contexts: |
Expand All @@ -42,6 +53,20 @@ jobs:
jqtype/rpxy:slim
ghcr.io/junkurihara/rust-rpxy:slim
- target: "default-slim-pq"
dockerfile: ./docker/Dockerfile-slim
build-args: |
"CARGO_FEATURES=--no-default-features --features=http3-quinn,cache,rustls-backend,acme,post-quantum"
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-pq"
# Aliases must be used only for release builds
aliases: |
jqtype/rpxy:slim-pq
ghcr.io/junkurihara/rust-rpxy:slim-pq
- target: "s2n"
dockerfile: ./docker/Dockerfile
build-args: |
Expand All @@ -54,6 +79,18 @@ jobs:
jqtype/rpxy:s2n
ghcr.io/junkurihara/rust-rpxy:s2n
- target: "s2n-pq"
dockerfile: ./docker/Dockerfile
build-args: |
"CARGO_FEATURES=--no-default-features --features=http3-s2n,cache,rustls-backend,acme,post-quantum"
"ADDITIONAL_DEPS=pkg-config libssl-dev cmake libclang1 gcc g++"
platforms: linux/amd64,linux/arm64
tags-suffix: "-s2n-pq"
# Aliases must be used only for release builds
aliases: |
jqtype/rpxy:s2n-pq
ghcr.io/junkurihara/rust-rpxy:s2n-pq
- target: "webpki-roots"
dockerfile: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64
Expand Down
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
[submodule "submodules/rustls-acme"]
path = submodules/rustls-acme
url = [email protected]:junkurihara/rustls-acme.git
[submodule "submodules/s2n-quic"]
path = submodules/s2n-quic
url = [email protected]:junkurihara/s2n-quic.git
branch = rustls-pq
4 changes: 4 additions & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
edition = "2021"
newline_style = "Unix"
tab_spaces = 2
max_width = 130
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

## 0.10.0 (Unreleased)

## 0.9.3

### Improvement

- Feat: Support post-quantum `X25519Kyber768Draft00` for incoming and outgoing TLS initiation. This is non-default feature [feature: `post-quantum`].
- Feat: emit WARN messages if there exist unused and unsupported options specified in configuration file.
- Docs: `rpxy.io` is now available for the official website of `rpxy`.
- Refactor: lots of minor improvements
- Deps

## 0.9.2

### Improvement
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace.package]
version = "0.9.2"
version = "0.9.3"
authors = ["Jun Kurihara"]
homepage = "https://github.com/junkurihara/rust-rpxy"
repository = "https://github.com/junkurihara/rust-rpxy"
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@

[^pure_rust]: Doubtfully can be claimed to be written in pure Rust since current `rpxy` is based on `aws-lc-rs` for cryptographic operations.

By default, `rpxy` provides the *TLS connection sanitization* by correctly binding a certificate used to establish a secure channel with the backend application. Specifically, it always keeps the consistency between the given SNI (server name indication) in `ClientHello` of the underlying TLS and the domain name given by the overlaid HTTP HOST header (or URL in Request line) [^1]. Additionally, as a somewhat unstable feature, our `rpxy` can handle the brand-new HTTP/3 connection thanks to [`quinn`](https://github.com/quinn-rs/quinn), [`s2n-quic`](https://github.com/aws/s2n-quic) and [`hyperium/h3`](https://github.com/hyperium/h3).[^h3lib] Furthermore, `rpxy` supports the automatic issuance and renewal of certificates via [TLS-ALPN-01 (RFC8737)](https://www.rfc-editor.org/rfc/rfc8737) of [ACME protocol (RFC8555)](https://www.rfc-editor.org/rfc/rfc8555) thanks to [`rustls-acme`](https://github.com/FlorianUekermann/rustls-acme).
By default, `rpxy` provides the *TLS connection sanitization* by correctly binding a certificate used to establish a secure channel with the backend application. Specifically, it always keeps the consistency between the given SNI (server name indication) in `ClientHello` of the underlying TLS and the domain name given by the overlaid HTTP HOST header (or URL in Request line) [^1]. Additionally, as a somewhat unstable feature, our `rpxy` can handle the brand-new HTTP/3 connection thanks to [`quinn`](https://github.com/quinn-rs/quinn), [`s2n-quic`](https://github.com/aws/s2n-quic) and [`hyperium/h3`](https://github.com/hyperium/h3).[^h3lib] Furthermore, `rpxy` supports the automatic issuance and renewal of certificates via [TLS-ALPN-01 (RFC8737)](https://www.rfc-editor.org/rfc/rfc8737) of [ACME protocol (RFC8555)](https://www.rfc-editor.org/rfc/rfc8555) thanks to [`rustls-acme`](https://github.com/FlorianUekermann/rustls-acme), and the hybridized post-quantum key exchange [`X25519Kyber768Draft00`](https://datatracker.ietf.org/doc/draft-tls-westerbaan-xyber768d00/)[^kyber] for TLS incoming and outgoing initiation thanks to [`rustls-post-quantum`](https://docs.rs/rustls-post-quantum/latest/rustls_post_quantum/).

[^h3lib]: HTTP/3 libraries are mutually exclusive. You need to explicitly specify `s2n-quic` with `--no-default-features` flag. Also note that if you build `rpxy` with `s2n-quic`, then it requires `openssl` just for building the package.

[^kyber]: This is not yet a default feature. You need to specify `--features post-quantum` when building `rpxy`. Also note that `X25519Kyber768Draft00` is a draft version yet this is widely used on the Internet. We will update the feature when the newest version (`X25519MLKEM768` in [`ECDHE-MLKEM`](https://www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-02.html)) is available.

This project is still *work-in-progress*. But it is already working in some production environments and serves a number of domain names. Furthermore it *significantly outperforms* NGINX and Caddy, e.g., *1.5x faster than NGINX*, in the setting of a very simple HTTP reverse-proxy scenario (See [`bench`](./bench/) directory).

[^1]: We should note that NGINX doesn't guarantee such a consistency by default. To this end, you have to add `if` statement in the configuration file in NGINX.
Expand Down
4 changes: 2 additions & 2 deletions config-example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ listen_port = 8080
listen_port_tls = 8443

# Optional. If you listen on a custom port like 8443 but redirect with firewall to 443
# When you specify this, the server sends a redirection response 301 with specified port to the client for plaintext http request.
# Otherwise, the server sends 301 with the same port as `listen_port_tls`.
# When you specify this, the server uses this port in an "Alt-SVC" header for e.g. indicating support for HTTP/3 and also sends a redirection response 301 with specified port to the client for plaintext http request
# Otherwise, the server sends Alt-SVC and 301 with the same port as `listen_port_tls`.
# https_redirection_port = 443

# Optional for h2 and http1.1
Expand Down
2 changes: 2 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ Differences among tags are summarized as follows.
- `latest`: Built from the `main` branch with default features, running on Ubuntu.
- `latest-slim`, `slim`: Built by `musl` from the `main` branch with default features, running on Alpine.
- `latest-s2n`, `s2n`: Built from the `main` branch with the `http3-s2n` feature, running on Ubuntu.
- `*-pq`: Built with the `post-quantum` feature. This feature supports the post-quantum key exchange using `rustls-post-quantum` crate.

### Nightly Builds

- `nightly`: Built from the `develop` branch with default features, running on Ubuntu.
- `nightly-slim`: Built by `musl` from the `develop` branch with default features, running on Alpine.
- `nightly-s2n`: Built from the `develop` branch with the `http3-s2n` feature, running on Ubuntu.
- `*-pq`: Built with the `post-quantum` feature. This feature supports the hybridized post-quantum key exchange using `rustls-post-quantum` crate.

## Caveats

Expand Down
10 changes: 7 additions & 3 deletions rpxy-acme/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,29 @@ readme.workspace = true
edition.workspace = true
publish.workspace = true

[features]
post-quantum = ["rustls-post-quantum"]

[dependencies]
url = { version = "2.5.2" }
rustc-hash = "2.0.0"
thiserror = "1.0.64"
thiserror = "1.0.66"
tracing = "0.1.40"
async-trait = "0.1.83"
base64 = "0.22.1"
aws-lc-rs = { version = "1.10.0", default-features = false, features = [
"aws-lc-sys",
] }
blocking = "1.6.1"
rustls = { version = "0.23.14", default-features = false, features = [
rustls = { version = "0.23.16", default-features = false, features = [
"std",
"aws_lc_rs",
] }
rustls-platform-verifier = { version = "0.3.4" }
rustls-acme = { path = "../submodules/rustls-acme/", default-features = false, features = [
"aws-lc-rs",
] }
tokio = { version = "1.40.0", default-features = false }
rustls-post-quantum = { version = "0.1.0", optional = true }
tokio = { version = "1.41.0", default-features = false }
tokio-util = { version = "0.7.12", default-features = false }
tokio-stream = { version = "0.1.16", default-features = false }
3 changes: 3 additions & 0 deletions rpxy-acme/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ impl AcmeManager {
domains: &[String],
runtime_handle: Handle,
) -> Result<Self, RpxyAcmeError> {
#[cfg(not(feature = "post-quantum"))]
// Install aws_lc_rs as default crypto provider for rustls
let _ = rustls::crypto::CryptoProvider::install_default(rustls::crypto::aws_lc_rs::default_provider());
#[cfg(feature = "post-quantum")]
let _ = rustls::crypto::CryptoProvider::install_default(rustls_post_quantum::provider());

let acme_registry_dir = acme_registry_dir
.map(|v| v.to_ascii_lowercase())
Expand Down
10 changes: 7 additions & 3 deletions rpxy-bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ publish.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
# default = ["http3-quinn", "cache", "rustls-backend", "acme", "post-quantum"]
# default = ["http3-s2n", "cache", "rustls-backend", "acme", "post-quantum"]
default = ["http3-quinn", "cache", "rustls-backend", "acme"]
# default = ["http3-s2n", "cache", "rustls-backend", "acme"]
http3-quinn = ["rpxy-lib/http3-quinn"]
Expand All @@ -22,17 +24,18 @@ rustls-backend = ["rpxy-lib/rustls-backend"]
webpki-roots = ["rpxy-lib/webpki-roots"]
cache = ["rpxy-lib/cache"]
acme = ["rpxy-lib/acme", "rpxy-acme"]
post-quantum = ["rpxy-lib/post-quantum"]

[dependencies]
rpxy-lib = { path = "../rpxy-lib/", default-features = false, features = [
"sticky-cookie",
] }

mimalloc = { version = "*", default-features = false }
anyhow = "1.0.89"
anyhow = "1.0.91"
rustc-hash = "2.0.0"
serde = { version = "1.0.210", default-features = false, features = ["derive"] }
tokio = { version = "1.40.0", default-features = false, features = [
serde = { version = "1.0.214", default-features = false, features = ["derive"] }
tokio = { version = "1.41.0", default-features = false, features = [
"net",
"rt-multi-thread",
"time",
Expand All @@ -47,6 +50,7 @@ futures-util = { version = "0.3.31", default-features = false }
clap = { version = "4.5.20", features = ["std", "cargo", "wrap_help"] }
toml = { version = "0.8.19", default-features = false, features = ["parse"] }
hot_reload = "0.1.6"
serde_ignored = "0.1.10"

# logging
tracing = { version = "0.1.40" }
Expand Down
17 changes: 16 additions & 1 deletion rpxy-bin/src/config/toml.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
constants::*,
error::{anyhow, ensure},
log::warn,
};
use rpxy_lib::{reexports::Uri, AppConfig, ProxyConfig, ReverseProxyConfig, TlsConfig, UpstreamUri};
use rustc_hash::FxHashMap as HashMap;
Expand Down Expand Up @@ -229,7 +230,21 @@ impl ConfigToml {
pub fn new(config_file: &str) -> std::result::Result<Self, anyhow::Error> {
let config_str = fs::read_to_string(config_file)?;

toml::from_str(&config_str).map_err(|e| anyhow!(e))
// Check unused fields during deserialization
let t = toml::de::Deserializer::new(&config_str);
let mut unused = rustc_hash::FxHashSet::default();

let res = serde_ignored::deserialize(t, |path| {
unused.insert(path.to_string());
})
.map_err(|e| anyhow!(e));

if !unused.is_empty() {
let str = unused.iter().fold(String::new(), |acc, x| acc + x + "\n");
warn!("Configuration file contains unsupported fields. Check typos:\n{}", str);
}

res
}
}

Expand Down
8 changes: 5 additions & 3 deletions rpxy-certs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ publish.workspace = true

[features]
default = ["http3"]
post-quantum = ["rustls-post-quantum"]
http3 = []

[dependencies]
rustc-hash = { version = "2.0.0" }
tracing = { version = "0.1.40" }
derive_builder = { version = "0.20.2" }
thiserror = { version = "1.0.64" }
thiserror = { version = "1.0.66" }
hot_reload = { version = "0.1.6" }
async-trait = { version = "0.1.83" }
rustls = { version = "0.23.14", default-features = false, features = [
rustls = { version = "0.23.16", default-features = false, features = [
"std",
"aws_lc_rs",
] }
Expand All @@ -30,10 +31,11 @@ rustls-webpki = { version = "0.102.8", default-features = false, features = [
"std",
"aws_lc_rs",
] }
rustls-post-quantum = { version = "0.1.0", optional = true }
x509-parser = { version = "0.16.0" }

[dev-dependencies]
tokio = { version = "1.40.0", default-features = false, features = [
tokio = { version = "1.41.0", default-features = false, features = [
"rt-multi-thread",
"macros",
] }
7 changes: 5 additions & 2 deletions rpxy-certs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ mod log {
use crate::{error::*, log::*, reloader_service::DynCryptoSource};
use hot_reload::{ReloaderReceiver, ReloaderService};
use rustc_hash::FxHashMap as HashMap;
use rustls::crypto::{aws_lc_rs, CryptoProvider};
use rustls::crypto::CryptoProvider;
use std::sync::Arc;

/* ------------------------------------------------ */
Expand Down Expand Up @@ -44,8 +44,11 @@ where
T: CryptoSource<Error = RpxyCertError> + Send + Sync + Clone + 'static,
{
info!("Building certificate reloader service");
#[cfg(not(feature = "post-quantum"))]
// Install aws_lc_rs as default crypto provider for rustls
let _ = CryptoProvider::install_default(aws_lc_rs::default_provider());
let _ = CryptoProvider::install_default(rustls::crypto::aws_lc_rs::default_provider());
#[cfg(feature = "post-quantum")]
let _ = CryptoProvider::install_default(rustls_post_quantum::provider());

let source = crypto_source_map
.iter()
Expand Down
3 changes: 3 additions & 0 deletions rpxy-certs/src/server_crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ mod tests {

#[tokio::test]
async fn test_server_crypto_base_try_into() {
#[cfg(not(feature = "post-quantum"))]
let _ = CryptoProvider::install_default(rustls::crypto::aws_lc_rs::default_provider());
#[cfg(feature = "post-quantum")]
let _ = CryptoProvider::install_default(rustls_post_quantum::provider());

let mut server_crypto_base = ServerCryptoBase::default();

Expand Down
Loading

0 comments on commit 3984de4

Please sign in to comment.