Skip to content

feat(ohttp): forward ingress OHTTP over TLS to a gateway#170

Merged
imlk0 merged 1 commit into
masterfrom
wasm-cors
Jul 14, 2026
Merged

feat(ohttp): forward ingress OHTTP over TLS to a gateway#170
imlk0 merged 1 commit into
masterfrom
wasm-cors

Conversation

@imlk0

@imlk0 imlk0 commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds ingress-side ohttp.tls (bool) + ohttp.tls_ca_certs (list of PEM file paths) config so the ingress wraps its OHTTP-encrypted POST in HTTPS (https://host:port/path) when tls: true, terminating at a TLS-terminating gateway in front of the egress. Default (null/omitted/false) keeps plain http:// — additive and backward compatible.

Motivation: a TLS-terminating gateway (e.g. an HTTPS load balancer) may sit in front of the egress. The ingress must post the OHTTP ciphertext to the gateway over HTTPS so the gateway can terminate TLS before forwarding the raw OHTTP-over-HTTP bytes to the egress.

The scheme lives on the OHTTP forwarding layer (not the endpoint), so it covers every ingress mode (Mapping / HttpProxy / Socks5 / Netfilter / Hook).

Changes

  • tng/src/config/ingress.rsOHttpArgs.tls: Option<bool> + tls_ca_certs: Vec<String>. tls_ca_certs is #[cfg(not(wasm))]: a browser has no filesystem, so the field does not exist on wasm; providing it in a wasm config is a parse error (deny_unknown_fields). New serde unit tests for defaults + round-trip.
  • tng/src/tunnel/ingress/protocol/ohttp/security/mod.rsscheme_from_tls(Option<bool>) -> &'static str (Some(true)⇒"https", else "http"); build_ohttp_http_client builds the reqwest client and (native) loads CAs via reqwest::Certificate::from_pem_bundle with fail-fast with_context labels at ingress startup; wasm builds a plain client (browser controls TLS). construct_base_url emits {scheme}://{authority}{path}. Errors preserve the chain (no string-formatting); logging uses ?error structured form. Unit tests for CA-loading success / missing-path / malformed-PEM / no-CA.
  • tng-testsuiteAppType::TlsTcpProxy TLS-terminating raw-TCP proxy fixture (tokio-rustls acceptor + bidirectional tokio::io::copy) mirroring load_balancer.rs; embedded webpki-compliant CA/server/key PEMs in tests/ohttp/tls_fixtures.rs (critical CA:TRUE+certSign+SKI/AKI on the CA; CA:FALSE+digitalSignature/keyEncipherment+serverAuth+SANs on the server). Dev-deps: tokio-rustls, rustls-pemfile, tempfile.
  • End-to-end test tests/ohttp/ohttp_tls.rs::test_ohttp_forwarded_over_tlsno_ra on both sides, inserts the TlsTcpProxy between ingress and egress, and proves the full path: client → ingress (TLS-wrapped OHTTP POST to https://192.168.1.1:20002) → gateway (TLS termination) → plain TCP 127.0.0.1:20001 (egress mapping-in) → egress OHTTP decap → backend. Passes.
  • docs/configuration.md + docs/configuration_zh.md — document both fields (bilingual).
  • CLAUDE.md — ban hard-wrapping prose in human-readable Markdown.

Verification

  • cargo fmt --check clean.
  • cargo clippy -p tng -p tng-testsuite --all-targets Finished (no new warnings from this change; pre-existing tokio::spawn disallowed-method lints are consistent across all existing app/*.rs fixtures).
  • cargo build -p tng -p tng-testsuite --tests EXIT 0.
  • cargo test -p tng --lib security:: → 65 passed.
  • cargo test -p tng-testsuite --test ohttp_tls → 1 passed (e2e).

Compatibility

Additive only — new optional fields with backward-compatible defaults. No existing config/endpoint/protocol breaks. Not logged in version_compatibility.md (no breaking change).

Add ingress-side `ohttp.tls` (bool) + `ohttp.tls_ca_certs` (list of PEM file
paths) config so the ingress wraps its OHTTP-encrypted POST in HTTPS
(`https://host:port/path`) when `tls: true`, terminating at a TLS-terminating
gateway in front of the egress. Default (`null`/omitted, or `false`) keeps
plain `http://`, preserving pre-existing behavior (additive, backward
compatible).

The scheme lives on the OHTTP forwarding layer, so it applies to every
ingress mode (Mapping / HttpProxy / Socks5 / Netfilter / Hook).

- tng/config: `OHttpArgs.tls` + `tls_ca_certs`. `tls_ca_certs` is
  `#[cfg(not(wasm))]` — a browser has no filesystem, so the field does not
  exist on wasm; providing it in a wasm config is a parse error
  (`deny_unknown_fields`).
- tng/ohttp: `scheme_from_tls` + `build_ohttp_http_client` (native loads
  CAs via `reqwest::Certificate::from_pem_bundle`, fail-fast at ingress
  startup with `with_context` labels; wasm builds a plain client — browser
  controls TLS). `construct_base_url` emits `{scheme}://`.
- tng-testsuite: `AppType::TlsTcpProxy` TLS-terminating raw-TCP proxy
  fixture (tokio-rustls acceptor + bidirectional copy) and embedded
  webpki-compliant CA/server/key PEMs. End-to-end test
  `ohttp_tls::test_ohttp_forwarded_over_tls` exercises the full path
  (client -> ingress-https -> gateway TLS-term -> egress OHTTP-decap ->
  backend), `no_ra` on both sides.
- docs: `configuration.md` + `configuration_zh.md` document both fields.
- CLAUDE.md: ban hard-wrapping prose in human-readable Markdown.
@shankailun-aliyun

Copy link
Copy Markdown
Collaborator

@imlk0 ,您好,您的请求已接收,请耐心等待结果。

@shankailun-aliyun

Copy link
Copy Markdown
Collaborator

@imlk0 ,您好,未检测到有镜像需要构建,如需重新检测请评论 /start

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

@imlk0
imlk0 merged commit cf4e3ab into master Jul 14, 2026
32 of 34 checks passed
@imlk0
imlk0 temporarily deployed to github-pages July 14, 2026 08:02 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants