add network field to admission request, add CLAUDE.md and README.md

This commit is contained in:
ginuerzh
2026-05-21 22:22:12 +08:00
parent 146c8ff22e
commit e1226236da
4 changed files with 226 additions and 12 deletions
+76
View File
@@ -0,0 +1,76 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Code Generation
```bash
# Build the module
go build ./...
# Regenerate protobuf code (run from a service proto directory)
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
admission.proto
```
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](https://github.com/go-gost/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 (12 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` |
| `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). Every request carries proxy context fields (`network`, `addr`, `host`, `client`, `service`) relevant to the intercepted connection.
### 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*Server` struct. 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:
1. Create `<name>/proto/<name>.proto` with the service, RPCs, and messages. Set `go_package` to `github.com/go-gost/plugin/<name>/proto`.
2. Run `protoc` to generate `.pb.go` and `_grpc.pb.go`.
3. Add at minimum a gRPC example under `<name>/example/grpc/main.go`.
4. 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
```bash
# Build check from plugin/ directory
go build ./...
# Vet
go vet ./...
```
There are no tests in this module. Building is the primary verification.
+127
View File
@@ -0,0 +1,127 @@
# GOST Plugin SDK
[![Go Reference](https://pkg.go.dev/badge/github.com/go-gost/plugin.svg)](https://pkg.go.dev/github.com/go-gost/plugin)
gRPC-based plugin protocol definitions for [GOST](https://github.com/go-gost/gost). This module defines the service contracts that external plugin processes implement to extend GOST with custom authentication, admission control, traffic limiting, DNS resolution, and more.
## Available plugins
| Plugin | Service | Description |
|--------|---------|-------------|
| [admission](admission/) | `Admission` | Allow/deny connections by address |
| [auth](auth/) | `Authenticator` | Authenticate users and clients |
| [bypass](bypass/) | `Bypass` | Bypass the proxy chain for specific hosts |
| [hop](hop/) | `Hop` | Custom node selection for proxy chains |
| [hosts](hosts/) | `HostMapper` | Static or dynamic host-to-IP mapping |
| [ingress](ingress/) | `Ingress` | Ingress rule management |
| [limiter/traffic](limiter/traffic/) | `Limiter` | Per-connection bandwidth limits |
| [observer](observer/) | `Observer` | Receive connection and traffic events |
| [recorder](recorder/) | `Recorder` | Record proxied traffic |
| [resolver](resolver/) | `Resolver` | Custom DNS resolution |
| [router](router/) | `Router` | Custom route selection |
| [sd](sd/) | `SD` | Service discovery (register/deregister/get) |
## Usage
### gRPC plugin server
```go
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"github.com/go-gost/plugin/admission/proto"
"google.golang.org/grpc"
)
var port = flag.Int("port", 8000, "Server port")
type server struct {
proto.UnimplementedAdmissionServer
}
func (s *server) Admit(ctx context.Context, req *proto.AdmissionRequest) (*proto.AdmissionReply, error) {
reply := &proto.AdmissionReply{}
if req.GetAddr() == "127.0.0.1:80" {
reply.Ok = true
}
return reply, nil
}
func main() {
flag.Parse()
lis, _ := net.Listen("tcp", fmt.Sprintf(":%d", *port))
s := grpc.NewServer()
proto.RegisterAdmissionServer(s, &server{})
log.Fatal(s.Serve(lis))
}
```
### HTTP plugin server
GOST also supports HTTP/JSON transport. The endpoint path matches the plugin type:
```go
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"net"
"net/http"
)
var port = flag.Int("port", 8000, "Server port")
func main() {
flag.Parse()
lis, _ := net.Listen("tcp", fmt.Sprintf(":%d", *port))
http.HandleFunc("/admission", func(w http.ResponseWriter, r *http.Request) {
var req struct {
Addr string `json:"addr"`
Service string `json:"service"`
}
json.NewDecoder(r.Body).Decode(&req)
json.NewEncoder(w).Encode(map[string]bool{"ok": req.Addr == "127.0.0.1:80"})
})
log.Fatal(http.Serve(lis, nil))
}
```
### Configuration
Point GOST at your plugin server via the `plugin` block in config:
```yaml
services:
- name: service-0
addr: ":8080"
handler:
type: http
listener:
type: tcp
plugin:
type: admission
addr: 127.0.0.1:8000
```
## Code generation
Generated protobuf code was produced with `protoc-gen-go v1.28.1` and `protoc-gen-go-grpc v1.2.0`. To regenerate:
```bash
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
admission.proto
```
## License
MIT
+22 -12
View File
@@ -31,6 +31,7 @@ type AdmissionRequest struct {
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
Service string `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"`
Network string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"`
}
func (x *AdmissionRequest) Reset() {
@@ -79,6 +80,13 @@ func (x *AdmissionRequest) GetService() string {
return ""
}
func (x *AdmissionRequest) GetNetwork() string {
if x != nil {
return x.Network
}
return ""
}
type AdmissionReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -130,21 +138,23 @@ var File_admission_proto protoreflect.FileDescriptor
var file_admission_proto_rawDesc = []byte{
0x0a, 0x0f, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x40, 0x0a, 0x10, 0x41, 0x64, 0x6d, 0x69,
0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5a, 0x0a, 0x10, 0x41, 0x64, 0x6d, 0x69,
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72,
0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x20, 0x0a, 0x0e, 0x41, 0x64,
0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x0e, 0x0a, 0x02,
0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x32, 0x44, 0x0a, 0x09,
0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x05, 0x41, 0x64, 0x6d,
0x69, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73,
0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70,
0x6c, 0x79, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x67, 0x6f, 0x2d, 0x67, 0x6f, 0x73, 0x74, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f,
0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65,
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74,
0x77, 0x6f, 0x72, 0x6b, 0x22, 0x20, 0x0a, 0x0e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01,
0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x32, 0x44, 0x0a, 0x09, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73,
0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x05, 0x41, 0x64, 0x6d, 0x69, 0x74, 0x12, 0x17, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64,
0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x42, 0x2b, 0x5a, 0x29,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x67, 0x6f,
0x73, 0x74, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73,
0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
+1
View File
@@ -9,6 +9,7 @@ option go_package = "github.com/go-gost/plugin/admission/proto";
message AdmissionRequest {
string addr = 1;
string service = 2;
string network = 3;
}
message AdmissionReply {