Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
target/
.git/
*.md
!README.md
certs/

87 changes: 14 additions & 73 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,82 +1,23 @@
[workspace]
members = [".", "attested-tls"]
members = ["crates/attested-tls", "crates/attested-tls-proxy"]
default-members = ["crates/attested-tls-proxy"]
resolver = "3"

[package]
name = "attested-tls-proxy"
version = "1.1.1"
edition = "2024"
license = "MIT"
description = "An HTTP attested TLS proxy server and client for secure communication with CVM services"
repository = "https://github.com/flashbots/attested-tls-proxy"
keywords = ["attested-TLS", "CVM", "TDX"]

[dependencies]
attested-tls = { path = "attested-tls", default-features = false }
tokio = { version = "1.48.0", features = ["full"] }
tokio-rustls = { version = "0.26.4", default-features = false, features = [
"aws_lc_rs",
] }
x509-parser = { version = "0.18.0", features = ["verify"] }
thiserror = "2.0.17"
clap = { version = "4.5.51", features = ["derive", "env"] }
rustls-pemfile = "2.2.0"
anyhow = "1.0.100"
pem-rfc7468 = { version = "0.7.0", features = ["std"] }
hyper = { version = "1.7.0", features = ["server", "http2"] }
h2 = "0.4.12"
hyper-util = { version = "0.1.17", features = ["tokio"] }
http-body-util = "0.1.3"
[workspace.dependencies]
bytes = "1.11.1"
http = "1.3.1"
serde_json = "1.0.145"
serde = "1.0.228"
reqwest = { version = "0.13.4", default-features = false, features = [
"rustls-no-provider",
] }
webpki-roots = "1.0.4"
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.20", features = ["env-filter", "json"] }
axum = "0.8.8"
tower-http = { version = "0.6.7", features = ["fs"] }
rsa = { version = "0.9", default-features = false }
p256 = { version = "0.13.2", features = ["pkcs8"] }
pkcs1 = "0.7.5"
pkcs8 = "0.10.2"
http-body-util = "0.1.3"
hyper = "1.7.0"
hyper-util = "0.1.17"
rcgen = "0.14.5"
pin-project-lite = "0.2.16"
pccs = { git = "https://github.com/flashbots/attested-tls", branch = "main" }

[dev-dependencies]
serde_json = "1.0.145"
tempfile = "3.23.0"
tdx-quote = { version = "0.0.5", features = ["mock"] }
attested-tls = { path = "attested-tls", features = ["test-helpers", "mock"] }
jsonrpsee = { version = "0.26.0", features = ["server"] }

[features]
default = []

# Adds support for Microsoft Azure attestation generation and verification
azure = ["attested-tls/azure"]

[package.metadata.deb]
maintainer = "Flashbots Team <devops+ci@flashbots.net>"
depends = "$auto"
section = "network"
priority = "optional"
maintainer-scripts = "pkg/debian"
assets = [
[
"target/reproducible/attested-tls-proxy",
"usr/bin/",
"755",
],
[
"LICENSE",
"usr/share/doc/attested-tls-proxy/",
"644",
],
]
systemd-units = { enable = false, start = false, unit-name = "attested-tls-proxy" }
thiserror = "2.0.17"
tokio = "1.48.0"
tokio-rustls = { version = "0.26.4", default-features = false }
tracing = "0.1.41"
webpki-roots = "1.0.4"
x509-parser = "0.18.0"

[profile.reproducible]
inherits = "release"
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ RUN build_features="$FEATURES"; \
fi; \
fi; \
if [ -n "$build_features" ]; then \
cargo build --release --no-default-features --features "$build_features"; \
cargo build -p attested-tls-proxy --locked --release --no-default-features --features "$build_features"; \
else \
cargo build --release --no-default-features; \
cargo build -p attested-tls-proxy --locked --release --no-default-features; \
fi

# Runtime stage
Expand Down
14 changes: 7 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ endif

.PHONY: build
build: ## Build (release version)
$(BUILD_ENV) cargo build $(FEATURE_ARGS) --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --profile $(BUILD_PROFILE)
$(BUILD_ENV) cargo build -p attested-tls-proxy $(FEATURE_ARGS) --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --profile $(BUILD_PROFILE)

.PHONY: build-dev
build-dev: ## Build (debug version)
cargo build $(FEATURE_ARGS)
cargo build -p attested-tls-proxy $(FEATURE_ARGS)

##@ Debian Packages

Expand All @@ -95,18 +95,18 @@ build-deb: install-cargo-deb ## Build Debian package

.PHONY: lint
lint: ## Run the linters
cargo fmt -- --check
cargo fmt --all -- --check
cargo clippy --workspace $(FEATURE_ARGS) -- -D warnings

.PHONY: test
test:
cargo test --verbose $(FEATURE_ARGS)
cargo test --workspace --verbose $(FEATURE_ARGS)

.PHONY: lt
lt: lint test ## Run "lint" and "test"

.PHONY: fmt
fmt: ## Format the code
cargo fmt
cargo fix --allow-staged
cargo clippy $(FEATURE_ARGS) --fix --allow-staged
cargo fmt --all
cargo fix --workspace --allow-staged
cargo clippy --workspace $(FEATURE_ARGS) --fix --allow-staged
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This is a reverse HTTP proxy allowing a normal HTTP client to communicate with a

This is designed to be an alternative to [`cvm-reverse-proxy`](https://github.com/flashbots/cvm-reverse-proxy). Unlike `cvm-reverse-proxy` this uses post-handshake remote-attested TLS, meaning regular CA-signed TLS certificates can be used.

Details of the remote-attested TLS protocol are in [attested-tls/README.md](attested-tls/README.md). This is provided as a separate crate for other uses than HTTP proxying.
Details of the remote-attested TLS protocol are in [crates/attested-tls/README.md](crates/attested-tls/README.md). This is provided as a separate crate for other uses than HTTP proxying.

The proxy-client, on starting, immediately connects to the proxy-server and an attestation-verification exchange is made. This attested-TLS channel is then re-used for requests from that proxy-client instance. If the channel is lost, the client reconnects automatically and repeats the attestation exchange before forwarding subsequent requests.

Expand Down Expand Up @@ -94,14 +94,35 @@ Proxy-client to proxy-server connections use TLS 1.3.

The protocol name `flashbots-ratls/1` must be given in the TLS configuration for ALPN protocol negotiation during the TLS handshake. Future versions of this protocol will use incrementing version numbers, eg: `flashbots-ratls/2`.

Immediately after the TLS handshake, an attestation exchange is made. Details of how this works are in the [attested-tls protocol specification](attested-tls/README.md#protocol-specification).
Immediately after the TLS handshake, an attestation exchange is made. Details of how this works are in the [attested-tls protocol specification](crates/attested-tls/README.md#protocol-specification).

Following a successful attestation exchange, the client can make HTTP requests, and the server will forward them to the target service.

As described above, the server will inject measurement data into the request headers before forwarding them to the target service, and the client will inject measurement data into the response headers before forwarding them to the source client.

The proxy client and proxy server support HTTP/2 and HTTP/1.1 over their attested-TLS channel, with HTTP/2 preferred. The HTTP protocol is combined with the attested-TLS protocol version in ALPN, producing `flashbots-ratls/1+h2` or `flashbots-ratls/1+http/1.1`. A negotiated `flashbots-ratls/1` value without an HTTP suffix falls back to HTTP/1.1.

## Repository layout and development

- `crates/attested-tls`: the attested TLS protocol library.
- `crates/attested-tls-proxy`: the HTTP proxy library and CLI. HTTP forwarding
lives in `src/http`; its public API is also re-exported at the crate root.

Run the commands below from the repository root. The proxy is the default
workspace member, so existing `cargo run -- ...` commands still work. Build
artifacts remain in the root `target/` directory.

```sh
cargo build -p attested-tls-proxy --locked
cargo test --workspace --features azure --all-targets --locked
cargo clippy --workspace --features azure --locked -- -D warnings
cargo fmt --all -- --check
```

Omit `--features azure` on systems without the TPM dependencies described below.
To install from a local checkout, use `cargo install --path crates/attested-tls-proxy --locked`.
Docker and Compose commands also run from the repository root.

## Dependencies and feature flags

The `azure` feature, for Microsoft Azure attestation requires [tpm2](https://tpm2-software.github.io) to be installed. On Debian-based systems this is provided by [`libtss2-dev`](https://packages.debian.org/trixie/libtss2-dev), and on nix `tpm2-tss`. This dependency is currently not packaged for MacOS, meaning currently it is not possible to compile or run with the `azure` feature on MacOS.
Expand Down
77 changes: 77 additions & 0 deletions crates/attested-tls-proxy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
[package]
name = "attested-tls-proxy"
version = "1.1.1"
edition = "2024"
license = "MIT"
readme = "../../README.md"
description = "An HTTP attested TLS proxy server and client for secure communication with CVM services"
repository = "https://github.com/flashbots/attested-tls-proxy"
keywords = ["attested-TLS", "CVM", "TDX"]

[dependencies]
attested-tls = { path = "../attested-tls", default-features = false }
tokio = { workspace = true, features = ["full"] }
tokio-rustls = { workspace = true, features = ["aws_lc_rs"] }
x509-parser = { workspace = true, features = ["verify"] }
thiserror.workspace = true
clap = { version = "4.5.51", features = ["derive", "env"] }
rustls-pemfile = "2.2.0"
anyhow = "1.0.100"
pem-rfc7468 = { version = "0.7.0", features = ["std"] }
hyper = { workspace = true, features = ["server", "http2"] }
h2 = "0.4.12"
hyper-util = { workspace = true, features = ["tokio"] }
http-body-util.workspace = true
bytes.workspace = true
http.workspace = true
serde_json.workspace = true
serde = "1.0.228"
reqwest = { version = "0.13.4", default-features = false, features = [
"rustls-no-provider",
] }
webpki-roots.workspace = true
tracing.workspace = true
tracing-subscriber = { version = "0.3.20", features = ["env-filter", "json"] }
axum = "0.8.8"
tower-http = { version = "0.6.7", features = ["fs"] }
rsa = { version = "0.9", default-features = false }
p256 = { version = "0.13.2", features = ["pkcs8"] }
pkcs1 = "0.7.5"
pkcs8 = "0.10.2"
rcgen.workspace = true
pin-project-lite = "0.2.16"
pccs = { git = "https://github.com/flashbots/attested-tls", branch = "main" }

[dev-dependencies]
tempfile.workspace = true
tdx-quote = { version = "0.0.5", features = ["mock"] }
attested-tls = { path = "../attested-tls", features = ["test-helpers", "mock"] }
jsonrpsee = { version = "0.26.0", features = ["server"] }

[features]
default = []

# Adds support for Microsoft Azure attestation generation and verification
azure = ["attested-tls/azure"]

[package.metadata.deb]
maintainer = "Flashbots Team <devops+ci@flashbots.net>"
depends = "$auto"
section = "network"
priority = "optional"
maintainer-scripts = "../../pkg/debian"
assets = [
[
# cargo-deb resolves this prefix to the workspace target and selected profile.
"target/release/attested-tls-proxy",
"usr/bin/",
"755",
],
[
"../../LICENSE",
"usr/share/doc/attested-tls-proxy/",
"644",
],
]
systemd-units = { enable = false, start = false, unit-name = "attested-tls-proxy" }

6 changes: 2 additions & 4 deletions build.rs → crates/attested-tls-proxy/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ fn emit_git_rerun_hints() {
let manifest_dir =
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_owned()));

for git_dir in [
manifest_dir.join(".git"),
manifest_dir.join("..").join(".git"),
] {
for ancestor in manifest_dir.ancestors() {
let git_dir = ancestor.join(".git");
if git_dir.exists() {
println!("cargo:rerun-if-changed={}", git_dir.join("HEAD").display());
println!(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! A one-shot attested TLS proxy client which sends a single GET request and returns the response
use crate::{AttestationGenerator, AttestationVerifier, ProxyClient, ProxyError};
use crate::http::{AttestationGenerator, AttestationVerifier, ProxyClient, ProxyError};
use tokio_rustls::rustls::pki_types::CertificateDer;

/// Split an `attested-get` target into a proxy target and an optional request path.
Expand Down Expand Up @@ -90,7 +90,7 @@ async fn attested_get_with_client(
#[cfg(test)]
mod tests {
use super::*;
use crate::{
use crate::http::{
ProxyServer,
attestation::AttestationType,
file_server::static_file_server,
Expand Down
Loading
Loading