mirror of
https://github.com/go-gost/plugin.git
synced 2026-10-19 16:16:19 +00:00
add network field to admission request, add CLAUDE.md and README.md
This commit is contained in:
@@ -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.
|
||||
@@ -0,0 +1,127 @@
|
||||
# GOST Plugin SDK
|
||||
|
||||
[](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
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user