OpenTunnel now only authorizes the tunnel and returns a random single-use id (the stream credential); the reserved endpoint field and CloseTunnel are removed. Tunnel is a bidi stream whose lifetime is the tunnel's lifetime, bound to the OpenTunnel id via the "id" metadata key. Breaking change; regenerated with the pinned toolchain.
5.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Build & Code Generation
# Build the module
go build ./...
# Regenerate protobuf code (always from the module root, passing the full
# relative path — never from inside a proto directory)
protoc --proto_path=. --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
admission/proto/admission.proto
The full path becomes the proto file's registered name (e.g. admission/proto/admission.proto), which is required: protobuf registers file descriptors in a process-global registry, and bare names like auth.proto collide with other libraries and panic at init (proto: file "auth.proto" is already registered, see go-gost/plugin#3). Regenerating from inside a service directory reintroduces the bare names — don't.
Generated code was produced with protoc-gen-go v1.28.1, protoc-gen-go-grpc v1.2.0, protoc v3.15.8. The go_package option in each .proto sets the output path (e.g. github.com/go-gost/plugin/admission/proto).
Architecture
This module defines the gRPC plugin protocol for GOST. External plugin processes implement these gRPC services to extend GOST's behavior (authentication, rate limiting, DNS resolution, etc.). The core GOST binary communicates with plugins either via gRPC or HTTP/JSON — examples for both transports are provided.
Service catalog (13 plugin types)
Each subdirectory follows the same structure: proto/<name>.proto + generated .pb.go/_grpc.pb.go, and example/ with reference implementations (gRPC and optionally HTTP).
| Directory | Service | RPC(s) | In config plugin: block |
|---|---|---|---|
admission/ |
Admission |
Admit(req) → (ok) |
type: admission |
auth/ |
Authenticator |
Authenticate(req) → (ok, id) |
type: auth |
bypass/ |
Bypass |
Bypass(req) → (ok) |
type: bypass |
hop/ |
Hop |
Select(req) → (node bytes) |
type: hop |
hosts/ |
HostMapper |
Lookup(req) → (ips[], ok) |
type: hosts |
ingress/ |
Ingress |
GetRule(req) → (endpoint), SetRule(req) → (ok) |
type: ingress |
limiter/traffic/ |
Limiter |
Limit(req) → (in, out) |
type: limiter |
observer/ |
Observer |
Observe(events[]) → (ok) |
type: observer |
p2p/ |
P2P |
OpenTunnel(req) → (ok, id), Tunnel(stream) → (stream), Status |
top-level p2ps: section (plugin.type: grpc) |
recorder/ |
Recorder |
Record(data, metadata) → (ok) |
type: recorder |
resolver/ |
Resolver |
Resolve(req) → (ips[], ok) |
type: resolver |
router/ |
Router |
GetRoute(req) → (dst, gateway) |
type: router |
sd/ |
SD |
Register, Deregister, Renew, Get |
type: sd |
All RPCs are unary (no streaming), with one deliberate exception: the p2p service's Tunnel is a bidirectional stream carrying the tunnel's data (its lifetime is the tunnel's lifetime). Every request carries proxy context fields (network, addr, host, client, service) relevant to the intercepted connection. The p2p service deviates further: peer is an opaque string (the plugin defines its semantics), there is no example/ for it in this module (the standalone p2p/ host repo is the reference implementation), and only the gRPC transport exists.
Dual transport: gRPC + HTTP
GOST supports two transports for plugin communication. Examples for both exist under example/grpc/ and example/http/.
- gRPC examples: Standard gRPC server embedding the
Unimplemented*Serverstruct. Auth example shows how to extract credentials from gRPC metadata. - HTTP examples: Plain HTTP/JSON servers. The endpoint path matches the service name (e.g.,
/admission,/auth,/bypass). Request/response structs mirror the proto messages as JSON.
Adding a new plugin type
The pattern is consistent across all 12 services:
- Create
<name>/proto/<name>.protowith the service, RPCs, and messages. Setgo_packagetogithub.com/go-gost/plugin/<name>/proto. - Run
protocto generate.pb.goand_grpc.pb.go. - Add at minimum a gRPC example under
<name>/example/grpc/main.go. - If the plugin type supports HTTP transport, add
<name>/example/http/main.go.
The corresponding implementation in x/ (e.g., x/admission/) contains a gRPC client that calls these services and an HTTP client that hits the JSON endpoints — the dual transport logic lives there, not in this module.
Known issue: recorder go_package
recorder/proto/recorder.proto declares go_package = "github.com/go-gost/plugin/ingress/proto", which places it in the same Go package as the ingress service. This means recorder/ and ingress/ share a proto package namespace. If you add new message types to either, ensure no symbol collisions occur.
Verification
# Build check from plugin/ directory
go build ./...
# Vet
go vet ./...
There are no tests in this module. Building is the primary verification.