A
Verification by default
TLS certificate and hostname checks remain enabled unless an explicit development-only environment override is set.
Case study 05 / HTTP and TLS
A concurrent forward proxy that accepts clear-text HTTP, establishes verified TLS upstream, applies reloadable access controls, and relays framed HTTP/1.1 responses.
A proxy sits between two independently framed connections and has to remain correct when clients, origins, DNS, TLS, or policy fail.
The downstream side accepts ordinary HTTP proxy requests. The upstream side resolves the requested host, establishes TLS, verifies the certificate and hostname, rewrites the request, and streams the response back without losing message boundaries.
At the same time, the process must isolate concurrent clients, enforce hostname and resolved-IP rules, and produce useful HTTP errors rather than leaking socket failures to the browser.
GET and HEAD are accepted in absolute proxy form or origin form with a Host header.
The requested hostname and every resolved address are compared with the current forbidden-sites snapshot.
The proxy connects upstream with OpenSSL, validates the certificate chain, and verifies the requested hostname.
Content-Length, chunked, HEAD, and connection-close responses are streamed using their actual termination rules.
A
TLS certificate and hostname checks remain enabled unless an explicit development-only environment override is set.
B
Checking both the hostname and resolved addresses prevents a permitted name from silently reaching a forbidden destination address.
C
Downstream keep-alive is used only when the response boundary is known; close-delimited responses end the client connection.
D
Malformed requests, blocked sites, unsupported methods, DNS failures, upstream errors, capacity limits, and timeouts become distinct responses.
Policy changes should not require stopping the service or leaving newly forbidden connections active.
Sending SIGINT reloads the forbidden-sites file into a new immutable snapshot while the proxy remains running. New requests immediately use the replacement rule set.
The proxy also reevaluates active upstream destinations. Connections covered by a newly loaded hostname or IP rule are shut down so the policy change applies to existing work as well as future requests.
The integration suite creates a locally trusted TLS origin and exercises GET, HEAD, X-Forwarded-For, unsupported methods, concurrent requests, ACL reload, blocked responses, persistent requests, chunked responses, malformed input, and structured access logging.
A forwarding service needs enough evidence to explain what happened without retaining response bodies.
Each completed request produces an RFC 3339 access-log entry with the client address, request line, returned status, and relayed byte count. X-Forwarded-For is created or extended so the origin receives the downstream address chain.
Worker cleanup is centralized so client sockets, upstream sockets, and TLS objects are released consistently across success, parse errors, access-control rejection, and connection failure.
The proxy demonstrates HTTP, TLS, concurrency, and policy mechanics; it is not intended as an anonymous or production security gateway.
It supports GET and HEAD rather than tunneling arbitrary HTTPS with CONNECT, uses a fixed worker capacity, and does not provide caching, authentication, content inspection, or distributed policy management.
The project originated in CSE 156/L at UC Santa Cruz in Winter 2025. After the original university-hosted source was lost, the published implementation was reconstructed from the surviving specification and expanded with stronger TLS verification, broader framing coverage, automated tests, and detailed cleanup documentation.