mirror of
https://github.com/go-gost/x.git
synced 2026-10-20 00:17:32 +00:00
v0.26.1
A frame that is not a parseable IPv4 or IPv6 packet is exactly what the kernel refuses. Measured on a real up tun device: the version nibble is the only thing it inspects, and anything but 4 or 6 comes back EINVAL at any length -- 1421, 1500 and 2000-byte frames with a valid header all go through untouched. That error left fromSpoke, unwound Handle, and took a 54-minute peer stream down with it. The spoke has always refused these frames before its device write, which is why a phone logs "unknown packet, discarded" all day and never dies while the hub had no equivalent. destinationOf returning !ok is exactly the kernel's reject condition, so that branch now drops and counts the frame instead of handing it to the device. This stops the malformed frame from killing the service; it does not fix what put one on the wire. The candidate cause is concurrent serveEdge writers racing on one local conn with no send lock on streamConn.Write, which is still unproven. Silently accepted sub-MTU spliced frames also remain -- the kernel does not validate TotalLen either.
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%