Skip to content

vey-proxy: add http_guard public-edge HTTP reverse proxy - #104

Merged
zh-jq merged 38 commits into
mainfrom
http-guard
Sep 17, 2026
Merged

zh-jq merged 38 commits into
mainfrom
http-guard

Conversation

@zh-jq

@zh-jq zh-jq commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@zh-jq
zh-jq force-pushed the http-guard branch 2 times, most recently from 70bab93 to 76cea04 Compare September 8, 2026 00:31
zh-jq and others added 7 commits September 13, 2026 00:02
Inspect the first client bytes and only serve HTTP/1.x, auto-detect TLS,
and match SNI against TLS-capable sites while plaintext Host uses a
separate HTTP table. Tenant identity goes to ICAP as X-Tenant-Username.

Co-authored-by: Cursor <cursoragent@cursor.com>
Origin H2 is multiplexed from a site pool without 1:1 client binding;
config splits shared HTTP from H1/H2, with optional H2C and H2 Websocket.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reuse is per-origin: http_expose and http_guard read
http.h1.upstream_keepalive (enabled by default) instead of a server key.

Co-authored-by: Cursor <cursoragent@cursor.com>
Parse and reload checks for the always-on site H2 pool, plus a TLS origin
coverage path so http_guard HTTP/2 does not share the H1 plaintext site.

Co-authored-by: Cursor <cursoragent@cursor.com>
Share one TLS client per site. HTTP/2 origin sets h2 on the connection
Ssl instead of a second SslCtx.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reuse one client connection in the existing pycurl and requests suites
instead of extra curl invocations in coverage shells.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@zh-jq
zh-jq force-pushed the http-guard branch 4 times, most recently from 8ca4f85 to a5453a5 Compare September 13, 2026 14:20
zh-jq and others added 9 commits September 13, 2026 23:34
Co-authored-by: Cursor <cursoragent@cursor.com>
…raffic

Co-authored-by: Cursor <cursoragent@cursor.com>
Count payload after transfer-coding is removed so H1 chunked framing is not
included, and record each side independently.

On failure record the size completed on that hop so far. An H1 chunked body
is forwarded as on-wire bytes, so the payload written is not counted as it
goes out; report a lower bound there that excludes data still held in the
copy buffer.

Restore the pending chunk on H2 write errors, so the size received is not
undercounted by a whole chunk on the paths that report it.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
add_invalid_param() was incrementing user_blocked, so username-parameter
rejections never appeared on server.forbidden.invalid_param.

Co-authored-by: Cursor <cursoragent@cursor.com>
H2 tasks only enabled local error replies after the origin was ready, so
checkout_or_connect failures left the client with no response.

Co-authored-by: Cursor <cursoragent@cursor.com>
RFC 9113 requires Host to identify the same entity as :authority after
scheme-based normalization. Mismatches return 409, matching HTTP/1.

Co-authored-by: Cursor <cursoragent@cursor.com>
H1 and H2 checkout on the same worker, TLS, and the server's configured
escaper so different escapers do not mix, while servers sharing that
escaper can still reuse connections. Move the pools under site/pool/.

Co-authored-by: Cursor <cursoragent@cursor.com>
zh-jq and others added 5 commits September 14, 2026 23:12
H1 Upgrade and H2 CONNECT with :protocol=websocket share task_type
Websocket and CONNECT-style tunnel logs. Other CONNECT or Upgrade is
rejected; H1 WebSocket always opens a new origin connection.

Co-authored-by: Cursor <cursoragent@cursor.com>
Site tenants are not visitors, so they no longer share UserContext.
Forbidden stats and ACL stay on TenantContext; request and traffic
stats stay on the site.

Co-authored-by: Cursor <cursoragent@cursor.com>
Origin TLS still follows site tls_client. Client https:// absolute-form
is accepted without becoming https_forward or requiring a TLS client hop.

Co-authored-by: Cursor <cursoragent@cursor.com>
Buffer the origin reader only while parsing the Upgrade response, take
leftover bytes with into_parts after 101, and reject unexpected 1xx
instead of looping for a final status.

Co-authored-by: Cursor <cursoragent@cursor.com>
Read the origin response once like H1: 1xx is a protocol error, 2xx
starts relaying, and other statuses are forwarded to the client.
Checkout of the origin H2 sender is now a task method.

Co-authored-by: Cursor <cursoragent@cursor.com>
…tered

inspect H2 is covered via the intercept acceptor (select callback).
http_guard uses OpensslServerConfigBuilder, which called the client
set_alpn_protos API; a handshake test shows selected ALPN was None, so
H2 clients fell back to 1.1 and serve/http_guard/task/h2 stayed at 0%.

Co-authored-by: Cursor <cursoragent@cursor.com>
zh-jq and others added 3 commits September 15, 2026 08:17
Sites without tls_server were dropped from the TLS host table, so Host
matching after the default-cert handshake always 400'd. H2 still requires
the site's own certificate.

Co-authored-by: Cursor <cursoragent@cursor.com>
Unmatched SNI and Host are rejected locally instead of falling through to set_default. H2 always carries the pinned site; global_tls_server remains the H1 certificate fallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move origin checkout and early H2 errors onto H2TaskContext. H2Forward and Websocket logs record client and upstream stream ids.

Co-authored-by: Cursor <cursoragent@cursor.com>
zh-jq and others added 5 commits September 15, 2026 23:56
H1 forward and websocket already have the site at construction, so keep SiteContext on the task instead of Arc<Site> and a duplicated keepalive field. SNI pin is that same context, so drop pinned_host from H1TaskContext. Socket speed limits shrink site and tenant in one place.

Co-authored-by: Cursor <cursoragent@cursor.com>
A site pool is all TLS or all cleartext; reload with a different tls_client replaces the pool. Keep matching on the server escaper only.

Co-authored-by: Cursor <cursoragent@cursor.com>
A blocked tenant is forbidden when a new reverse-proxy request starts.
Idle checks still cancel a blocked visitor. Document the split in Sphinx.

Co-authored-by: Cursor <cursoragent@cursor.com>
Match http_guard: the pipeline writer extracts check_run, and the
forward task reads site and tenant from SiteContext instead of Arc<Site>.

Co-authored-by: Cursor <cursoragent@cursor.com>
zh-jq and others added 3 commits September 16, 2026 21:48
Take site-pool connections with if-let and `?` instead of an intermediate
Option, and drop an unnecessary Host clone in http_expose lookup.

Co-authored-by: Cursor <cursoragent@cursor.com>
Acquire user and site alive-request permits through notes so they drop
with the task, and drop the started/post_stop Drop impls that only
existed to release them.

Co-authored-by: Cursor <cursoragent@cursor.com>
Honor tenant user block_and_delay at site entry before sending 403,
matching visitor blocked-user auth.

Co-authored-by: Cursor <cursoragent@cursor.com>
zh-jq and others added 5 commits September 16, 2026 22:58
Fold http_guard H1 adaptation.rs back into the task so send_response
stays with the common path, and extract run_without_adaptation like
http_proxy. Align expose/proxy body dispatch to the same early-return
shape.

Co-authored-by: Cursor <cursoragent@cursor.com>
Untrusted drain now runs under the matched site's rate, alive, speed, and
idle limits, and counts request-header plus body bytes on site traffic.

Co-authored-by: Cursor <cursoragent@cursor.com>
Give H2 connection/forward/websocket their own directories and H2Connection logs.
Record connection_id, origin TCP keys, and site/tenant on reverse-proxy tasks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Give each accepted stream its own dispatch task that logs only the error
or the spawned H2Forward/Websocket. Fold origin ping into H2TaskContext
and treat ping failure as a closed origin connection.

Co-authored-by: Cursor <cursoragent@cursor.com>
Drop WebSocketTaskStats on the H2 websocket task and record received vs
copied sizes from H2BodyTransfer instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
@zh-jq
zh-jq merged commit aed81f4 into main Sep 17, 2026
76 of 77 checks passed
@zh-jq
zh-jq deleted the http-guard branch September 17, 2026 00:40
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.

1 participant