add plugin system
This commit is contained in:
@ -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 {
|
||||
|
@ -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...)
|
||||
}
|
||||
|
Reference in New Issue
Block a user