add plugin system

This commit is contained in:
ginuerzh
2023-04-18 20:52:56 +08:00
parent 7576651a67
commit 32c8188351
48 changed files with 761 additions and 115 deletions

View File

@ -109,13 +109,19 @@ type TLSConfig struct {
Organization string `yaml:",omitempty" json:"organization,omitempty"`
}
type PluginConfig struct {
Addr string `json:"addr"`
TLS *TLSConfig `json:"tls"`
}
type AutherConfig struct {
Name string `json:"name"`
Auths []*AuthConfig `yaml:",omitempty" json:"auths"`
Auths []*AuthConfig `yaml:",omitempty" json:"auths,omitempty"`
Reload time.Duration `yaml:",omitempty" json:"reload,omitempty"`
File *FileLoader `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisLoader `yaml:",omitempty" json:"redis,omitempty"`
HTTP *HTTPLoader `yaml:"http,omitempty" json:"http,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
}
type AuthConfig struct {
@ -134,11 +140,12 @@ type AdmissionConfig struct {
// DEPRECATED by whitelist since beta.4
Reverse bool `yaml:",omitempty" json:"reverse,omitempty"`
Whitelist bool `yaml:",omitempty" json:"whitelist,omitempty"`
Matchers []string `json:"matchers"`
Matchers []string `yaml:",omitempty" json:"matchers,omitempty"`
Reload time.Duration `yaml:",omitempty" json:"reload,omitempty"`
File *FileLoader `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisLoader `yaml:",omitempty" json:"redis,omitempty"`
HTTP *HTTPLoader `yaml:"http,omitempty" json:"http,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
}
type BypassConfig struct {
@ -146,11 +153,12 @@ type BypassConfig struct {
// DEPRECATED by whitelist since beta.4
Reverse bool `yaml:",omitempty" json:"reverse,omitempty"`
Whitelist bool `yaml:",omitempty" json:"whitelist,omitempty"`
Matchers []string `json:"matchers"`
Matchers []string `yaml:",omitempty" json:"matchers,omitempty"`
Reload time.Duration `yaml:",omitempty" json:"reload,omitempty"`
File *FileLoader `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisLoader `yaml:",omitempty" json:"redis,omitempty"`
HTTP *HTTPLoader `yaml:"http,omitempty" json:"http,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
}
type FileLoader struct {
@ -182,7 +190,8 @@ type NameserverConfig struct {
type ResolverConfig struct {
Name string `json:"name"`
Nameservers []*NameserverConfig `json:"nameservers"`
Nameservers []*NameserverConfig `yaml:",omitempty" json:"nameservers,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
}
type HostMappingConfig struct {
@ -193,11 +202,12 @@ type HostMappingConfig struct {
type HostsConfig struct {
Name string `json:"name"`
Mappings []*HostMappingConfig `json:"mappings"`
Mappings []*HostMappingConfig `yaml:",omitempty" json:"mappings,omitempty"`
Reload time.Duration `yaml:",omitempty" json:"reload,omitempty"`
File *FileLoader `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisLoader `yaml:",omitempty" json:"redis,omitempty"`
HTTP *HTTPLoader `yaml:"http,omitempty" json:"http,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
}
type IngressRuleConfig struct {
@ -212,12 +222,14 @@ type IngressConfig struct {
File *FileLoader `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisLoader `yaml:",omitempty" json:"redis,omitempty"`
HTTP *HTTPLoader `yaml:"http,omitempty" json:"http,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
}
type RecorderConfig struct {
Name string `json:"name"`
File *FileRecorder `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisRecorder `yaml:",omitempty" json:"redis,omitempty"`
Name string `json:"name"`
File *FileRecorder `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisRecorder `yaml:",omitempty" json:"redis,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
}
type FileRecorder struct {

View File

@ -1,6 +1,7 @@
package parsing
import (
"crypto/tls"
"net"
"net/url"
@ -31,6 +32,10 @@ import (
"github.com/go-gost/x/registry"
resolver_impl "github.com/go-gost/x/resolver"
xs "github.com/go-gost/x/selector"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)
const (
@ -50,6 +55,20 @@ func ParseAuther(cfg *config.AutherConfig) auth.Authenticator {
return nil
}
if cfg.Plugin != nil {
c, err := newPluginConn(cfg.Plugin)
if err != nil {
logger.Default().Error(err)
}
return auth_impl.NewPluginAuthenticator(
auth_impl.PluginConnOption(c),
auth_impl.LoggerOption(logger.Default().WithFields(map[string]any{
"kind": "auther",
"auther": cfg.Name,
})),
)
}
m := make(map[string]string)
for _, user := range cfg.Auths {
@ -84,7 +103,6 @@ func ParseAuther(cfg *config.AutherConfig) auth.Authenticator {
loader.TimeoutHTTPLoaderOption(cfg.HTTP.Timeout),
)))
}
return auth_impl.NewAuthenticator(opts...)
}
@ -170,6 +188,21 @@ func ParseAdmission(cfg *config.AdmissionConfig) admission.Admission {
if cfg == nil {
return nil
}
if cfg.Plugin != nil {
c, err := newPluginConn(cfg.Plugin)
if err != nil {
logger.Default().Error(err)
}
return admission_impl.NewPluginAdmission(
admission_impl.PluginConnOption(c),
admission_impl.LoggerOption(logger.Default().WithFields(map[string]any{
"kind": "admission",
"admission": cfg.Name,
})),
)
}
opts := []admission_impl.Option{
admission_impl.MatchersOption(cfg.Matchers),
admission_impl.WhitelistOption(cfg.Reverse || cfg.Whitelist),
@ -205,6 +238,20 @@ func ParseBypass(cfg *config.BypassConfig) bypass.Bypass {
return nil
}
if cfg.Plugin != nil {
c, err := newPluginConn(cfg.Plugin)
if err != nil {
logger.Default().Error(err)
}
return bypass_impl.NewPluginBypass(
bypass_impl.PluginConnOption(c),
bypass_impl.LoggerOption(logger.Default().WithFields(map[string]any{
"kind": "bypass",
"bypass": cfg.Name,
})),
)
}
opts := []bypass_impl.Option{
bypass_impl.MatchersOption(cfg.Matchers),
bypass_impl.WhitelistOption(cfg.Reverse || cfg.Whitelist),
@ -239,6 +286,22 @@ func ParseResolver(cfg *config.ResolverConfig) (resolver.Resolver, error) {
if cfg == nil {
return nil, nil
}
if cfg.Plugin != nil {
c, err := newPluginConn(cfg.Plugin)
if err != nil {
logger.Default().Error(err)
return nil, err
}
return resolver_impl.NewPluginResolver(
resolver_impl.PluginConnOption(c),
resolver_impl.LoggerOption(logger.Default().WithFields(map[string]any{
"kind": "resolver",
"resolver": cfg.Name,
})),
)
}
var nameservers []resolver_impl.NameServer
for _, server := range cfg.Nameservers {
nameservers = append(nameservers, resolver_impl.NameServer{
@ -254,7 +317,7 @@ func ParseResolver(cfg *config.ResolverConfig) (resolver.Resolver, error) {
return resolver_impl.NewResolver(
nameservers,
resolver_impl.LoggerResolverOption(
resolver_impl.LoggerOption(
logger.Default().WithFields(map[string]any{
"kind": "resolver",
"resolver": cfg.Name,
@ -268,6 +331,20 @@ func ParseHosts(cfg *config.HostsConfig) hosts.HostMapper {
return nil
}
if cfg.Plugin != nil {
c, err := newPluginConn(cfg.Plugin)
if err != nil {
logger.Default().Error(err)
}
return xhosts.NewPluginHostMapper(
xhosts.PluginConnOption(c),
xhosts.LoggerOption(logger.Default().WithFields(map[string]any{
"kind": "hosts",
"hosts": cfg.Name,
})),
)
}
var mappings []xhosts.Mapping
for _, mapping := range cfg.Mappings {
if mapping.IP == "" || mapping.Hostname == "" {
@ -326,6 +403,20 @@ func ParseIngress(cfg *config.IngressConfig) ingress.Ingress {
return nil
}
if cfg.Plugin != nil {
c, err := newPluginConn(cfg.Plugin)
if err != nil {
logger.Default().Error(err)
}
return xingress.NewPluginIngress(
xingress.PluginConnOption(c),
xingress.LoggerOption(logger.Default().WithFields(map[string]any{
"kind": "ingress",
"ingress": cfg.Name,
})),
)
}
var rules []xingress.Rule
for _, rule := range cfg.Rules {
if rule.Hostname == "" || rule.Endpoint == "" {
@ -380,9 +471,24 @@ func ParseRecorder(cfg *config.RecorderConfig) (r recorder.Recorder) {
return nil
}
if cfg.Plugin != nil {
c, err := newPluginConn(cfg.Plugin)
if err != nil {
logger.Default().Error(err)
}
return xrecorder.NewPluginRecorder(
xrecorder.PluginConnOption(c),
xrecorder.LoggerOption(logger.Default().WithFields(map[string]any{
"kind": "recorder",
"recorder": cfg.Name,
})),
)
}
if cfg.File != nil && cfg.File.Path != "" {
return xrecorder.FileRecorder(cfg.File.Path,
xrecorder.SepRecorderOption(cfg.File.Sep))
xrecorder.SepRecorderOption(cfg.File.Sep),
)
}
if cfg.Redis != nil &&
@ -566,3 +672,24 @@ func ParseRateLimiter(cfg *config.LimiterConfig) (lim rate.RateLimiter) {
return xrate.NewRateLimiter(opts...)
}
func newPluginConn(cfg *config.PluginConfig) (*grpc.ClientConn, error) {
grpcOpts := []grpc.DialOption{
// grpc.WithBlock(),
grpc.WithConnectParams(grpc.ConnectParams{
Backoff: backoff.DefaultConfig,
}),
grpc.FailOnNonTempDialError(true),
}
if tlsCfg := cfg.TLS; tlsCfg != nil && tlsCfg.Secure {
grpcOpts = append(grpcOpts,
grpc.WithAuthority(tlsCfg.ServerName),
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
ServerName: tlsCfg.ServerName,
InsecureSkipVerify: !tlsCfg.Secure,
})))
} else {
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
return grpc.Dial(cfg.Addr, grpcOpts...)
}