mirror of
https://github.com/go-gost/x.git
synced 2026-10-19 16:16:32 +00:00
dc9c7444b92ed08339147efa15bc38374da6ec7f
The bypass was evaluated once per connection, which authorizes the first request and nothing after it. A keep-alive request naming another host re-dialed without a check, a request served from the HTTP cache needed no dial and so passed no check, a request arriving after a reload was still judged by the policy that had been in force when the connection opened, and an HTTP/2 :authority was never checked at all. With MITM enabled the same holes applied to HTTPS, since the decrypted stream is handed to the HTTP path. State the invariant instead of patching the sites one by one: every request forwarded to an upstream is authorized against the bypass in effect at the time of that request. CheckBypass is that one check, called from the four request-handling paths in the two sniffer copies. In the HTTP loop it replaces the pre-loop check rather than adding to it, so the file ends up with one check site instead of two. A reload now reaches established connections at their next request. That is a behaviour change, and it is what closes the cache and reload paths. Tunnels stay authorized at establishment: a TLS connection without MITM, a websocket after upgrade and a CONNECT tunnel have no later request to check. CheckBypass is nil-receiver safe because h2Handler can be built without handle options, and a data path should not panic over that. Measured cost against a 269-pattern bypass: 645 ns for a host that matches nothing (full wildcard scan), 149 ns for an exact hit.
x
The implementation layer for the GOST proxy framework. Every interface defined in core/ is implemented here — handlers, listeners, dialers, connectors, plus config parsing, registries, and all cross-cutting concerns.
Package layout
| Directory | Purpose |
|---|---|
handler/ |
Protocol handlers (http, socks4/5, ss, ssh, tunnel, tun, dns, redirect, etc.) |
listener/ |
Protocol listeners (tcp, tls, ws, http2/3, quic, kcp, icmp, tun, udp, etc.) |
dialer/ |
Outbound dialers (tcp, tls, ws, http2/3, quic, grpc, ssh, wg, kcp, icmp, etc.) |
connector/ |
Destination connectors (http, socks4/5, ss, ssh, relay, tunnel, direct, etc.) |
config/ |
Config struct, YAML/JSON parsing, and service construction |
registry/ |
Typed global registries for all component types |
service/ |
Accept loop wiring listener + handler |
chain/ |
Multi-hop forwarding chain and route implementation |
router/ |
Route table router (destination-based routing) |
hop/ |
Node group with load-balanced selection |
selector/ |
Load-balancing strategies (round-robin, random, weighted, hash) |
auth/, bypass/, admission/ |
Authentication, bypass rules, admission control |
resolver/, hosts/ |
DNS resolution and host mapping |
limiter/ |
Traffic, connection, and rate limiters |
recorder/, observer/ |
Traffic recording and observability |
ingress/, sd/, routing/ |
Ingress control, service discovery, routing rules |
logger/, metrics/, api/ |
Logging, Prometheus metrics, Web API |
metadata/, ctx/ |
Metadata key-value system and context propagation |
internal/ |
Shared internals — not importable externally |
Component pattern
Every handler, listener, dialer, and connector follows the same pattern: init() registers a constructor into a global registry, the constructor takes functional options, and Init(metadata.Metadata) extracts typed configuration from the metadata key-value map.
See CLAUDE.md for detailed architecture and conventions.
Languages
Go
100%