diff --git a/admission/admission.go b/admission/admission.go index 8d7e278..9088214 100644 --- a/admission/admission.go +++ b/admission/admission.go @@ -13,6 +13,7 @@ import ( "github.com/go-gost/core/logger" "github.com/go-gost/x/internal/loader" "github.com/go-gost/x/internal/matcher" + "google.golang.org/grpc" ) type options struct { @@ -21,6 +22,7 @@ type options struct { fileLoader loader.Loader redisLoader loader.Loader httpLoader loader.Loader + client *grpc.ClientConn period time.Duration logger logger.Logger } @@ -63,6 +65,12 @@ func HTTPLoaderOption(httpLoader loader.Loader) Option { } } +func PluginConnOption(c *grpc.ClientConn) Option { + return func(opts *options) { + opts.client = c + } +} + func LoggerOption(logger logger.Logger) Option { return func(opts *options) { opts.logger = logger @@ -101,7 +109,7 @@ func NewAdmission(opts ...Option) admission_pkg.Admission { return p } -func (p *admission) Admit(addr string) bool { +func (p *admission) Admit(ctx context.Context, addr string) bool { if addr == "" || p == nil { return true } diff --git a/admission/plugin.go b/admission/plugin.go new file mode 100644 index 0000000..e99d492 --- /dev/null +++ b/admission/plugin.go @@ -0,0 +1,56 @@ +package admission + +import ( + "context" + + admission_pkg "github.com/go-gost/core/admission" + "github.com/go-gost/plugin/admission/proto" + xlogger "github.com/go-gost/x/logger" +) + +type pluginAdmission struct { + client proto.AdmissionClient + options options +} + +// NewPluginAdmission creates a plugin admission. +func NewPluginAdmission(opts ...Option) admission_pkg.Admission { + var options options + for _, opt := range opts { + opt(&options) + } + if options.logger == nil { + options.logger = xlogger.Nop() + } + + p := &pluginAdmission{ + options: options, + } + if options.client != nil { + p.client = proto.NewAdmissionClient(options.client) + } + return p +} + +func (p *pluginAdmission) Admit(ctx context.Context, addr string) bool { + if p.client == nil { + return false + } + + r, err := p.client.Admit(ctx, + &proto.AdmissionRequest{ + Addr: addr, + }) + if err != nil { + p.options.logger.Error(err) + return false + } + return r.Ok +} + +func (p *pluginAdmission) Close() error { + if p.options.client != nil { + return p.options.client.Close() + } + return nil +} diff --git a/admission/wrapper/conn.go b/admission/wrapper/conn.go index 7d35bb3..1990d6f 100644 --- a/admission/wrapper/conn.go +++ b/admission/wrapper/conn.go @@ -1,6 +1,7 @@ package wrapper import ( + "context" "errors" "io" "net" @@ -33,7 +34,7 @@ func WrapConn(admission admission.Admission, c net.Conn) net.Conn { func (c *serverConn) Read(b []byte) (n int, err error) { if c.admission != nil && - !c.admission.Admit(c.RemoteAddr().String()) { + !c.admission.Admit(context.Background(), c.RemoteAddr().String()) { err = io.EOF return } @@ -79,7 +80,7 @@ func (c *packetConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { } if c.admission != nil && - !c.admission.Admit(addr.String()) { + !c.admission.Admit(context.Background(), addr.String()) { continue } @@ -143,7 +144,7 @@ func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { return } if c.admission != nil && - !c.admission.Admit(addr.String()) { + !c.admission.Admit(context.Background(), addr.String()) { continue } return @@ -158,7 +159,7 @@ func (c *udpConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) { return } if c.admission != nil && - !c.admission.Admit(addr.String()) { + !c.admission.Admit(context.Background(), addr.String()) { continue } return @@ -176,7 +177,7 @@ func (c *udpConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAd return } if c.admission != nil && - !c.admission.Admit(addr.String()) { + !c.admission.Admit(context.Background(), addr.String()) { continue } return diff --git a/admission/wrapper/listener.go b/admission/wrapper/listener.go index 05d4dee..1c2d7b1 100644 --- a/admission/wrapper/listener.go +++ b/admission/wrapper/listener.go @@ -1,6 +1,7 @@ package wrapper import ( + "context" "net" "github.com/go-gost/core/admission" @@ -28,7 +29,7 @@ func (ln *listener) Accept() (net.Conn, error) { return nil, err } if ln.admission != nil && - !ln.admission.Admit(c.RemoteAddr().String()) { + !ln.admission.Admit(context.Background(), c.RemoteAddr().String()) { c.Close() continue } diff --git a/api/middleware.go b/api/middleware.go index efd84e3..924a614 100644 --- a/api/middleware.go +++ b/api/middleware.go @@ -35,7 +35,7 @@ func mwBasicAuth(auther auth.Authenticator) gin.HandlerFunc { return } u, p, _ := c.Request.BasicAuth() - if !auther.Authenticate(u, p) { + if !auther.Authenticate(c, u, p) { c.AbortWithStatus(http.StatusUnauthorized) } } diff --git a/auth/auth.go b/auth/auth.go index 9209642..d6ba5d6 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -12,6 +12,7 @@ import ( "github.com/go-gost/core/logger" "github.com/go-gost/x/internal/loader" xlogger "github.com/go-gost/x/logger" + "google.golang.org/grpc" ) type options struct { @@ -20,6 +21,7 @@ type options struct { redisLoader loader.Loader httpLoader loader.Loader period time.Duration + client *grpc.ClientConn logger logger.Logger } @@ -55,6 +57,12 @@ func HTTPLoaderOption(httpLoader loader.Loader) Option { } } +func PluginConnOption(c *grpc.ClientConn) Option { + return func(opts *options) { + opts.client = c + } +} + func LoggerOption(logger logger.Logger) Option { return func(opts *options) { opts.logger = logger @@ -97,14 +105,18 @@ func NewAuthenticator(opts ...Option) auth.Authenticator { } // Authenticate checks the validity of the provided user-password pair. -func (p *authenticator) Authenticate(user, password string) bool { - if p == nil || len(p.kvs) == 0 { +func (p *authenticator) Authenticate(ctx context.Context, user, password string) bool { + if p == nil { return true } p.mu.RLock() defer p.mu.RUnlock() + if len(p.kvs) == 0 { + return true + } + v, ok := p.kvs[user] return ok && (v == "" || password == v) } diff --git a/auth/plugin.go b/auth/plugin.go new file mode 100644 index 0000000..77070cd --- /dev/null +++ b/auth/plugin.go @@ -0,0 +1,58 @@ +package auth + +import ( + "context" + + "github.com/go-gost/core/auth" + "github.com/go-gost/plugin/auth/proto" + xlogger "github.com/go-gost/x/logger" +) + +type pluginAuthenticator struct { + client proto.AuthenticatorClient + options options +} + +// NewPluginAuthenticator creates an Authenticator that authenticates client by plugin. +func NewPluginAuthenticator(opts ...Option) auth.Authenticator { + var options options + for _, opt := range opts { + opt(&options) + } + if options.logger == nil { + options.logger = xlogger.Nop() + } + + p := &pluginAuthenticator{ + options: options, + } + if options.client != nil { + p.client = proto.NewAuthenticatorClient(options.client) + } + return p +} + +// Authenticate checks the validity of the provided user-password pair. +func (p *pluginAuthenticator) Authenticate(ctx context.Context, user, password string) bool { + if p.client == nil { + return false + } + + r, err := p.client.Authenticate(ctx, + &proto.AuthenticateRequest{ + Username: user, + Password: password, + }) + if err != nil { + p.options.logger.Error(err) + return false + } + return r.Ok +} + +func (p *pluginAuthenticator) Close() error { + if p.options.client != nil { + return p.options.client.Close() + } + return nil +} diff --git a/bypass/bypass.go b/bypass/bypass.go index 6c7fd59..fe7d06d 100644 --- a/bypass/bypass.go +++ b/bypass/bypass.go @@ -13,6 +13,7 @@ import ( "github.com/go-gost/core/logger" "github.com/go-gost/x/internal/loader" "github.com/go-gost/x/internal/matcher" + "google.golang.org/grpc" ) type options struct { @@ -21,6 +22,7 @@ type options struct { fileLoader loader.Loader redisLoader loader.Loader httpLoader loader.Loader + client *grpc.ClientConn period time.Duration logger logger.Logger } @@ -63,6 +65,12 @@ func HTTPLoaderOption(httpLoader loader.Loader) Option { } } +func PluginConnOption(c *grpc.ClientConn) Option { + return func(opts *options) { + opts.client = c + } +} + func LoggerOption(logger logger.Logger) Option { return func(opts *options) { opts.logger = logger @@ -232,7 +240,7 @@ func (bp *bypass) parsePatterns(r io.Reader) (patterns []string, err error) { return } -func (bp *bypass) Contains(addr string) bool { +func (bp *bypass) Contains(ctx context.Context, addr string) bool { if addr == "" || bp == nil { return false } diff --git a/bypass/plugin.go b/bypass/plugin.go new file mode 100644 index 0000000..8393410 --- /dev/null +++ b/bypass/plugin.go @@ -0,0 +1,56 @@ +package bypass + +import ( + "context" + + bypass_pkg "github.com/go-gost/core/bypass" + "github.com/go-gost/plugin/bypass/proto" + xlogger "github.com/go-gost/x/logger" +) + +type pluginBypass struct { + client proto.BypassClient + options options +} + +// NewPluginBypass creates a plugin bypass. +func NewPluginBypass(opts ...Option) bypass_pkg.Bypass { + var options options + for _, opt := range opts { + opt(&options) + } + if options.logger == nil { + options.logger = xlogger.Nop() + } + + p := &pluginBypass{ + options: options, + } + if options.client != nil { + p.client = proto.NewBypassClient(options.client) + } + return p +} + +func (p *pluginBypass) Contains(ctx context.Context, addr string) bool { + if p.client == nil { + return false + } + + r, err := p.client.Bypass(ctx, + &proto.BypassRequest{ + Addr: addr, + }) + if err != nil { + p.options.logger.Error(err) + return false + } + return r.Ok +} + +func (p *pluginBypass) Close() error { + if p.options.client != nil { + return p.options.client.Close() + } + return nil +} diff --git a/chain/hop.go b/chain/hop.go index ee908d2..4fe5185 100644 --- a/chain/hop.go +++ b/chain/hop.go @@ -74,7 +74,7 @@ func (p *chainHop) Select(ctx context.Context, opts ...chain.SelectOption) *chai // hop level bypass if p.options.bypass != nil && - p.options.bypass.Contains(options.Addr) { + p.options.bypass.Contains(ctx, options.Addr) { return nil } @@ -121,7 +121,7 @@ func (p *chainHop) Select(ctx context.Context, opts ...chain.SelectOption) *chai } // node level bypass if node.Options().Bypass != nil && - node.Options().Bypass.Contains(options.Addr) { + node.Options().Bypass.Contains(ctx, options.Addr) { continue } diff --git a/config/config.go b/config/config.go index c86eda9..269d51a 100644 --- a/config/config.go +++ b/config/config.go @@ -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 { diff --git a/config/parsing/parse.go b/config/parsing/parse.go index a3e07d2..a4a628d 100644 --- a/config/parsing/parse.go +++ b/config/parsing/parse.go @@ -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...) +} diff --git a/go.mod b/go.mod index 2accaca..36ffe72 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,10 @@ require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/gin-contrib/cors v1.3.1 github.com/gin-gonic/gin v1.8.2 - github.com/go-gost/core v0.0.0-20230131100536-f3482d7cd848 + github.com/go-gost/core v0.0.0-20230418124644-a2115a3d3876 github.com/go-gost/gosocks4 v0.0.1 github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 + github.com/go-gost/plugin v0.0.0-20230418123101-d221a4ec9a98 github.com/go-gost/relay v0.4.0 github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 github.com/go-redis/redis/v8 v8.11.5 @@ -35,19 +36,19 @@ require ( github.com/xtaci/tcpraw v1.2.25 github.com/yl2chen/cidranger v1.0.2 golang.org/x/crypto v0.6.0 - golang.org/x/net v0.7.0 - golang.org/x/sys v0.5.0 + golang.org/x/net v0.8.0 + golang.org/x/sys v0.6.0 golang.org/x/time v0.3.0 golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 - google.golang.org/grpc v1.51.0 - google.golang.org/protobuf v1.28.1 + google.golang.org/grpc v1.54.0 + google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/coreos/go-iptables v0.5.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect @@ -99,11 +100,11 @@ require ( github.com/ugorji/go/codec v1.2.7 // indirect github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/tools v0.4.0 // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/tools v0.6.0 // indirect golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect - google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index b0e2800..4e685db 100644 --- a/go.sum +++ b/go.sum @@ -55,8 +55,9 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -91,12 +92,14 @@ github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8n github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gost/core v0.0.0-20230131100536-f3482d7cd848 h1:jAack881fzd5s1jNC5w9SK1gL3bvnh4iK1lMFPnjUw8= -github.com/go-gost/core v0.0.0-20230131100536-f3482d7cd848/go.mod h1:R08B7BVdhWsYHX8s7wkEBpeKqc4+YFP6bLLFoao0J/A= +github.com/go-gost/core v0.0.0-20230418124644-a2115a3d3876 h1:SnrPPRt+IEHhxWmVwsiVu8yrfM8TS8ItYG3WRR5P/7c= +github.com/go-gost/core v0.0.0-20230418124644-a2115a3d3876/go.mod h1:pKIGDCHZSnxTUmBNMjVogJ+EjUdvaRdqMIJzQhEVOGQ= github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc= github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04= github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09/go.mod h1:1G6I7HP7VFVxveGkoK8mnprnJqSqJjdcASKsdUn4Pp4= +github.com/go-gost/plugin v0.0.0-20230418123101-d221a4ec9a98 h1:dOtNcxZbMDwtowa8b91nK2JcTL1lG0EIv0sXqSbvTc4= +github.com/go-gost/plugin v0.0.0-20230418123101-d221a4ec9a98/go.mod h1:IGQawP0E9B36VZ0AfDOpBK23bW4rOSiHtnU7mtafpAM= github.com/go-gost/relay v0.4.0 h1:zSOqJqnwV63oRiQ6fuurDYvehAVi3PizzFeE1gT+qo4= github.com/go-gost/relay v0.4.0/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8= github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 h1:xj8gUZGYO3nb5+6Bjw9+tsFkA9sYynrOvDvvC4uDV2I= @@ -464,8 +467,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -507,8 +510,9 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -591,14 +595,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -608,8 +613,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -667,8 +673,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -739,8 +745,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -757,8 +763,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -771,8 +777,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/handler/dns/handler.go b/handler/dns/handler.go index 2dd1bbd..a9189bf 100644 --- a/handler/dns/handler.go +++ b/handler/dns/handler.go @@ -194,7 +194,7 @@ func (h *dnsHandler) request(ctx context.Context, msg []byte, log logger.Logger) } if h.options.Bypass != nil && mq.Question[0].Qclass == dns.ClassINET { - if h.options.Bypass.Contains(strings.Trim(mq.Question[0].Name, ".")) { + if h.options.Bypass.Contains(context.Background(), strings.Trim(mq.Question[0].Name, ".")) { log.Debug("bypass: ", mq.Question[0].Name) mr = (&dns.Msg{}).SetReply(&mq) b := bufpool.Get(h.md.bufferSize) @@ -202,7 +202,7 @@ func (h *dnsHandler) request(ctx context.Context, msg []byte, log logger.Logger) } } - mr = h.lookupHosts(&mq, log) + mr = h.lookupHosts(ctx, &mq, log) if mr != nil { b := bufpool.Get(h.md.bufferSize) return mr.PackBuffer(*b) @@ -272,7 +272,7 @@ func (h *dnsHandler) exchange(ctx context.Context, mq *dns.Msg) ([]byte, error) } // lookup host mapper -func (h *dnsHandler) lookupHosts(r *dns.Msg, log logger.Logger) (m *dns.Msg) { +func (h *dnsHandler) lookupHosts(ctx context.Context, r *dns.Msg, log logger.Logger) (m *dns.Msg) { if h.hostMapper == nil || r.Question[0].Qclass != dns.ClassINET || (r.Question[0].Qtype != dns.TypeA && r.Question[0].Qtype != dns.TypeAAAA) { @@ -286,7 +286,7 @@ func (h *dnsHandler) lookupHosts(r *dns.Msg, log logger.Logger) (m *dns.Msg) { switch r.Question[0].Qtype { case dns.TypeA: - ips, _ := h.hostMapper.Lookup("ip4", host) + ips, _ := h.hostMapper.Lookup(ctx, "ip4", host) if len(ips) == 0 { return nil } @@ -302,7 +302,7 @@ func (h *dnsHandler) lookupHosts(r *dns.Msg, log logger.Logger) (m *dns.Msg) { } case dns.TypeAAAA: - ips, _ := h.hostMapper.Lookup("ip6", host) + ips, _ := h.hostMapper.Lookup(ctx, "ip6", host) if len(ips) == 0 { return nil } diff --git a/handler/forward/local/handler.go b/handler/forward/local/handler.go index e2d1b71..5ec1809 100644 --- a/handler/forward/local/handler.go +++ b/handler/forward/local/handler.go @@ -202,7 +202,7 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, log l if auther := target.Options().Auther; auther != nil { username, password, _ := req.BasicAuth() - if !auther.Authenticate(username, password) { + if !auther.Authenticate(ctx, username, password) { resp.StatusCode = http.StatusUnauthorized resp.Header.Set("WWW-Authenticate", "Basic") log.Warnf("node %s(%s) 401 unauthorized", target.Name, target.Addr) diff --git a/handler/forward/remote/handler.go b/handler/forward/remote/handler.go index 5eb577a..a8f8869 100644 --- a/handler/forward/remote/handler.go +++ b/handler/forward/remote/handler.go @@ -199,7 +199,7 @@ func (h *forwardHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, log l if auther := target.Options().Auther; auther != nil { username, password, _ := req.BasicAuth() - if !auther.Authenticate(username, password) { + if !auther.Authenticate(ctx, username, password) { resp.StatusCode = http.StatusUnauthorized resp.Header.Set("WWW-Authenticate", "Basic") log.Warnf("node %s(%s) 401 unauthorized", target.Name, target.Addr) diff --git a/handler/http/handler.go b/handler/http/handler.go index 5e88add..e5ea6ee 100644 --- a/handler/http/handler.go +++ b/handler/http/handler.go @@ -145,7 +145,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt resp.Header = http.Header{} } - if h.options.Bypass != nil && h.options.Bypass.Contains(addr) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, addr) { resp.StatusCode = http.StatusForbidden if log.IsLevelEnabled(logger.TraceLevel) { @@ -157,7 +157,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt return resp.Write(conn) } - if !h.authenticate(conn, req, resp, log) { + if !h.authenticate(ctx, conn, req, resp, log) { return nil } @@ -266,9 +266,9 @@ func (h *httpHandler) basicProxyAuth(proxyAuth string, log logger.Logger) (usern return cs[:s], cs[s+1:], true } -func (h *httpHandler) authenticate(conn net.Conn, req *http.Request, resp *http.Response, log logger.Logger) (ok bool) { +func (h *httpHandler) authenticate(ctx context.Context, conn net.Conn, req *http.Request, resp *http.Response, log logger.Logger) (ok bool) { u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"), log) - if h.options.Auther == nil || h.options.Auther.Authenticate(u, p) { + if h.options.Auther == nil || h.options.Auther.Authenticate(ctx, u, p) { return true } diff --git a/handler/http2/handler.go b/handler/http2/handler.go index d3d6013..6e4fafe 100644 --- a/handler/http2/handler.go +++ b/handler/http2/handler.go @@ -139,7 +139,7 @@ func (h *http2Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req w.Header().Set(k, h.md.header.Get(k)) } - if h.options.Bypass != nil && h.options.Bypass.Contains(addr) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, addr) { w.WriteHeader(http.StatusForbidden) log.Debug("bypass: ", addr) return nil @@ -152,7 +152,7 @@ func (h *http2Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req Body: ioutil.NopCloser(bytes.NewReader([]byte{})), } - if !h.authenticate(w, req, resp, log) { + if !h.authenticate(ctx, w, req, resp, log) { return nil } @@ -252,9 +252,9 @@ func (h *http2Handler) basicProxyAuth(proxyAuth string) (username, password stri return cs[:s], cs[s+1:], true } -func (h *http2Handler) authenticate(w http.ResponseWriter, r *http.Request, resp *http.Response, log logger.Logger) (ok bool) { +func (h *http2Handler) authenticate(ctx context.Context, w http.ResponseWriter, r *http.Request, resp *http.Response, log logger.Logger) (ok bool) { u, p, _ := h.basicProxyAuth(r.Header.Get("Proxy-Authorization")) - if h.options.Auther == nil || h.options.Auther.Authenticate(u, p) { + if h.options.Auther == nil || h.options.Auther.Authenticate(ctx, u, p) { return true } diff --git a/handler/http3/handler.go b/handler/http3/handler.go index 6169de7..90a11a5 100644 --- a/handler/http3/handler.go +++ b/handler/http3/handler.go @@ -105,7 +105,7 @@ func (h *http3Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req w.Header().Set(k, h.md.header.Get(k)) } - if h.options.Bypass != nil && h.options.Bypass.Contains(addr) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, addr) { w.WriteHeader(http.StatusForbidden) log.Debug("bypass: ", addr) return nil diff --git a/handler/redirect/tcp/handler.go b/handler/redirect/tcp/handler.go index 63d1063..604162e 100644 --- a/handler/redirect/tcp/handler.go +++ b/handler/redirect/tcp/handler.go @@ -116,7 +116,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han log.Debugf("%s >> %s", conn.RemoteAddr(), dstAddr) - if h.options.Bypass != nil && h.options.Bypass.Contains(dstAddr.String()) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, dstAddr.String()) { log.Debug("bypass: ", dstAddr) return nil } @@ -157,7 +157,7 @@ func (h *redirectHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, radd "host": host, }) - if h.options.Bypass != nil && h.options.Bypass.Contains(host) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, host) { log.Debug("bypass: ", host) return nil } @@ -226,7 +226,7 @@ func (h *redirectHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, rad "host": host, }) - if h.options.Bypass != nil && h.options.Bypass.Contains(host) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, host) { log.Debug("bypass: ", host) return nil } diff --git a/handler/redirect/udp/handler.go b/handler/redirect/udp/handler.go index 28e9911..2507d11 100644 --- a/handler/redirect/udp/handler.go +++ b/handler/redirect/udp/handler.go @@ -75,7 +75,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han log.Debugf("%s >> %s", conn.RemoteAddr(), dstAddr) - if h.options.Bypass != nil && h.options.Bypass.Contains(dstAddr.String()) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, dstAddr.String()) { log.Debug("bypass: ", dstAddr) return nil } diff --git a/handler/relay/connect.go b/handler/relay/connect.go index dd9ad84..4738dc5 100644 --- a/handler/relay/connect.go +++ b/handler/relay/connect.go @@ -35,7 +35,7 @@ func (h *relayHandler) handleConnect(ctx context.Context, conn net.Conn, network return err } - if h.options.Bypass != nil && h.options.Bypass.Contains(address) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, address) { log.Debug("bypass: ", address) resp.Status = relay.StatusForbidden _, err := resp.WriteTo(conn) @@ -112,7 +112,7 @@ func (h *relayHandler) handleConnectTunnel(ctx context.Context, conn net.Conn, n host, sp, _ := net.SplitHostPort(address) - if h.options.Bypass != nil && h.options.Bypass.Contains(address) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, address) { log.Debug("bypass: ", address) resp.Status = relay.StatusForbidden _, err := resp.WriteTo(conn) @@ -121,7 +121,7 @@ func (h *relayHandler) handleConnectTunnel(ctx context.Context, conn net.Conn, n var tid relay.TunnelID if ingress := h.md.ingress; ingress != nil { - tid = parseTunnelID(ingress.Get(host)) + tid = parseTunnelID(ingress.Get(ctx, host)) } if !tid.Equal(tunnelID) && !h.md.directTunnel { resp.Status = relay.StatusBadRequest diff --git a/handler/relay/entrypoint.go b/handler/relay/entrypoint.go index 93fd479..6e872cd 100644 --- a/handler/relay/entrypoint.go +++ b/handler/relay/entrypoint.go @@ -185,7 +185,7 @@ func (h *tunnelHandler) Handle(ctx context.Context, conn net.Conn, opts ...handl var tunnelID relay.TunnelID if h.ingress != nil { - tunnelID = parseTunnelID(h.ingress.Get(host)) + tunnelID = parseTunnelID(h.ingress.Get(ctx, host)) } if tunnelID.IsZero() { err := fmt.Errorf("no route to host %s", host) @@ -248,7 +248,7 @@ func (h *tunnelHandler) handleHTTP(ctx context.Context, raddr net.Addr, rw io.Re var tunnelID relay.TunnelID if h.ingress != nil { - tunnelID = parseTunnelID(h.ingress.Get(req.Host)) + tunnelID = parseTunnelID(h.ingress.Get(ctx, req.Host)) } if tunnelID.IsZero() { err := fmt.Errorf("no route to host %s", req.Host) diff --git a/handler/relay/handler.go b/handler/relay/handler.go index 081c42b..71e6f6e 100644 --- a/handler/relay/handler.go +++ b/handler/relay/handler.go @@ -196,7 +196,7 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn, opts ...handle } if h.options.Auther != nil && - !h.options.Auther.Authenticate(user, pass) { + !h.options.Auther.Authenticate(ctx, user, pass) { resp.Status = relay.StatusUnauthorized resp.WriteTo(conn) return ErrUnauthorized diff --git a/handler/sni/handler.go b/handler/sni/handler.go index e4865b9..4a8da2e 100644 --- a/handler/sni/handler.go +++ b/handler/sni/handler.go @@ -115,7 +115,7 @@ func (h *sniHandler) handleHTTP(ctx context.Context, rw io.ReadWriter, raddr net "host": host, }) - if h.options.Bypass != nil && h.options.Bypass.Contains(host) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, host) { log.Debug("bypass: ", host) return nil } @@ -183,7 +183,7 @@ func (h *sniHandler) handleHTTPS(ctx context.Context, rw io.ReadWriter, raddr ne }) log.Debugf("%s >> %s", raddr, host) - if h.options.Bypass != nil && h.options.Bypass.Contains(host) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, host) { log.Debug("bypass: ", host) return nil } diff --git a/handler/socks/v4/handler.go b/handler/socks/v4/handler.go index 67af4ba..8613d0f 100644 --- a/handler/socks/v4/handler.go +++ b/handler/socks/v4/handler.go @@ -91,7 +91,7 @@ func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn, opts ...handl conn.SetReadDeadline(time.Time{}) if h.options.Auther != nil && - !h.options.Auther.Authenticate(string(req.Userid), "") { + !h.options.Auther.Authenticate(ctx, string(req.Userid), "") { resp := gosocks4.NewReply(gosocks4.RejectedUserid, nil) log.Trace(resp) return resp.Write(conn) @@ -117,7 +117,7 @@ func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *g }) log.Debugf("%s >> %s", conn.RemoteAddr(), addr) - if h.options.Bypass != nil && h.options.Bypass.Contains(addr) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, addr) { resp := gosocks4.NewReply(gosocks4.Rejected, nil) log.Trace(resp) log.Debug("bypass: ", addr) diff --git a/handler/socks/v5/connect.go b/handler/socks/v5/connect.go index f3e8bc5..e22c89c 100644 --- a/handler/socks/v5/connect.go +++ b/handler/socks/v5/connect.go @@ -19,7 +19,7 @@ func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, networ }) log.Debugf("%s >> %s", conn.RemoteAddr(), address) - if h.options.Bypass != nil && h.options.Bypass.Contains(address) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, address) { resp := gosocks5.NewReply(gosocks5.NotAllowed, nil) log.Trace(resp) log.Debug("bypass: ", address) diff --git a/handler/socks/v5/selector.go b/handler/socks/v5/selector.go index 9373f88..9949e83 100644 --- a/handler/socks/v5/selector.go +++ b/handler/socks/v5/selector.go @@ -1,6 +1,7 @@ package v5 import ( + "context" "crypto/tls" "net" @@ -64,7 +65,7 @@ func (s *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, erro s.logger.Trace(req) if s.Authenticator != nil && - !s.Authenticator.Authenticate(req.Username, req.Password) { + !s.Authenticator.Authenticate(context.Background(), req.Username, req.Password) { resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure) if err := resp.Write(conn); err != nil { s.logger.Error(err) diff --git a/handler/ss/handler.go b/handler/ss/handler.go index 5b156da..61eab35 100644 --- a/handler/ss/handler.go +++ b/handler/ss/handler.go @@ -102,7 +102,7 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.H log.Debugf("%s >> %s", conn.RemoteAddr(), addr) - if h.options.Bypass != nil && h.options.Bypass.Contains(addr.String()) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, addr.String()) { log.Debug("bypass: ", addr.String()) return nil } diff --git a/handler/ss/udp/handler.go b/handler/ss/udp/handler.go index f043dea..aea90f5 100644 --- a/handler/ss/udp/handler.go +++ b/handler/ss/udp/handler.go @@ -135,7 +135,7 @@ func (h *ssuHandler) relayPacket(pc1, pc2 net.PacketConn, log logger.Logger) (er return err } - if h.options.Bypass != nil && h.options.Bypass.Contains(addr.String()) { + if h.options.Bypass != nil && h.options.Bypass.Contains(context.Background(), addr.String()) { log.Warn("bypass: ", addr) return nil } @@ -167,7 +167,7 @@ func (h *ssuHandler) relayPacket(pc1, pc2 net.PacketConn, log logger.Logger) (er return err } - if h.options.Bypass != nil && h.options.Bypass.Contains(raddr.String()) { + if h.options.Bypass != nil && h.options.Bypass.Contains(context.Background(), raddr.String()) { log.Warn("bypass: ", raddr) return nil } diff --git a/handler/sshd/handler.go b/handler/sshd/handler.go index 49ecf31..0e550cc 100644 --- a/handler/sshd/handler.go +++ b/handler/sshd/handler.go @@ -92,7 +92,7 @@ func (h *forwardHandler) handleDirectForward(ctx context.Context, conn *sshd_uti log.Debugf("%s >> %s", conn.RemoteAddr(), targetAddr) - if h.options.Bypass != nil && h.options.Bypass.Contains(targetAddr) { + if h.options.Bypass != nil && h.options.Bypass.Contains(ctx, targetAddr) { log.Debugf("bypass %s", targetAddr) return nil } diff --git a/handler/tun/server.go b/handler/tun/server.go index e158064..db22b16 100644 --- a/handler/tun/server.go +++ b/handler/tun/server.go @@ -25,7 +25,7 @@ func (h *tunHandler) handleServer(ctx context.Context, conn net.Conn, config *tu } defer pc.Close() - return h.transportServer(conn, pc, config, log) + return h.transportServer(ctx, conn, pc, config, log) }() if err == ErrTun { return err @@ -36,7 +36,7 @@ func (h *tunHandler) handleServer(ctx context.Context, conn net.Conn, config *tu } } -func (h *tunHandler) transportServer(tun io.ReadWriter, conn net.PacketConn, config *tun_util.Config, log logger.Logger) error { +func (h *tunHandler) transportServer(ctx context.Context, tun io.ReadWriter, conn net.PacketConn, config *tun_util.Config, log logger.Logger) error { errc := make(chan error, 1) go func() { @@ -135,7 +135,7 @@ func (h *tunHandler) transportServer(tun io.ReadWriter, conn net.PacketConn, con ok := true key := bytes.TrimRight((*b)[4:20], "\x00") for _, ip := range peerIPs { - if ok = auther.Authenticate(ip.String(), string(key)); !ok { + if ok = auther.Authenticate(ctx, ip.String(), string(key)); !ok { break } } diff --git a/hosts/hosts.go b/hosts/hosts.go index 99c8c17..66a648e 100644 --- a/hosts/hosts.go +++ b/hosts/hosts.go @@ -12,6 +12,7 @@ import ( "github.com/go-gost/core/hosts" "github.com/go-gost/core/logger" "github.com/go-gost/x/internal/loader" + "google.golang.org/grpc" ) type Mapping struct { @@ -24,6 +25,7 @@ type options struct { fileLoader loader.Loader redisLoader loader.Loader httpLoader loader.Loader + client *grpc.ClientConn period time.Duration logger logger.Logger } @@ -60,6 +62,12 @@ func HTTPLoaderOption(httpLoader loader.Loader) Option { } } +func PluginConnOption(c *grpc.ClientConn) Option { + return func(opts *options) { + opts.client = c + } +} + func LoggerOption(logger logger.Logger) Option { return func(opts *options) { opts.logger = logger @@ -104,7 +112,7 @@ func NewHostMapper(opts ...Option) hosts.HostMapper { // Lookup searches the IP address corresponds to the given network and host from the host table. // The network should be 'ip', 'ip4' or 'ip6', default network is 'ip'. // the host should be a hostname (example.org) or a hostname with dot prefix (.example.org). -func (h *hostMapper) Lookup(network, host string) (ips []net.IP, ok bool) { +func (h *hostMapper) Lookup(ctx context.Context, network, host string) (ips []net.IP, ok bool) { h.options.logger.Debugf("lookup %s/%s", host, network) ips = h.lookup(host) if ips == nil { diff --git a/hosts/plugin.go b/hosts/plugin.go new file mode 100644 index 0000000..56f2e21 --- /dev/null +++ b/hosts/plugin.go @@ -0,0 +1,66 @@ +package hosts + +import ( + "context" + "net" + + "github.com/go-gost/core/hosts" + "github.com/go-gost/plugin/hosts/proto" + xlogger "github.com/go-gost/x/logger" +) + +type pluginHostMapper struct { + client proto.HostMapperClient + options options +} + +// NewPluginHostMapper creates a plugin HostMapper. +func NewPluginHostMapper(opts ...Option) hosts.HostMapper { + var options options + for _, opt := range opts { + opt(&options) + } + if options.logger == nil { + options.logger = xlogger.Nop() + } + + p := &pluginHostMapper{ + options: options, + } + if options.client != nil { + p.client = proto.NewHostMapperClient(options.client) + } + return p +} + +func (p *pluginHostMapper) Lookup(ctx context.Context, network, host string) (ips []net.IP, ok bool) { + p.options.logger.Debugf("lookup %s/%s", host, network) + + if p.client == nil { + return + } + + r, err := p.client.Lookup(ctx, + &proto.LookupRequest{ + Network: network, + Host: host, + }) + if err != nil { + p.options.logger.Error(err) + return + } + for _, s := range r.Ips { + if ip := net.ParseIP(s); ip != nil { + ips = append(ips, ip) + } + } + ok = r.Ok + return +} + +func (p *pluginHostMapper) Close() error { + if p.options.client != nil { + return p.options.client.Close() + } + return nil +} diff --git a/ingress/ingress.go b/ingress/ingress.go index aa656dc..4d19759 100644 --- a/ingress/ingress.go +++ b/ingress/ingress.go @@ -12,6 +12,7 @@ import ( ingress_pkg "github.com/go-gost/core/ingress" "github.com/go-gost/core/logger" "github.com/go-gost/x/internal/loader" + "google.golang.org/grpc" ) type Rule struct { @@ -24,6 +25,7 @@ type options struct { fileLoader loader.Loader redisLoader loader.Loader httpLoader loader.Loader + client *grpc.ClientConn period time.Duration logger logger.Logger } @@ -60,6 +62,12 @@ func HTTPLoaderOption(httpLoader loader.Loader) Option { } } +func PluginConnOption(c *grpc.ClientConn) Option { + return func(opts *options) { + opts.client = c + } +} + func LoggerOption(logger logger.Logger) Option { return func(opts *options) { opts.logger = logger @@ -219,7 +227,7 @@ func (ing *ingress) parseRules(r io.Reader) (rules []Rule, err error) { return } -func (ing *ingress) Get(host string) string { +func (ing *ingress) Get(ctx context.Context, host string) string { if host == "" || ing == nil { return "" } diff --git a/ingress/plugin.go b/ingress/plugin.go new file mode 100644 index 0000000..4f86166 --- /dev/null +++ b/ingress/plugin.go @@ -0,0 +1,56 @@ +package ingress + +import ( + "context" + + ingress_pkg "github.com/go-gost/core/ingress" + "github.com/go-gost/plugin/ingress/proto" + xlogger "github.com/go-gost/x/logger" +) + +type pluginIngress struct { + client proto.IngressClient + options options +} + +// NewPluginIngress creates a plugin ingress. +func NewPluginIngress(opts ...Option) ingress_pkg.Ingress { + var options options + for _, opt := range opts { + opt(&options) + } + if options.logger == nil { + options.logger = xlogger.Nop() + } + + p := &pluginIngress{ + options: options, + } + if options.client != nil { + p.client = proto.NewIngressClient(options.client) + } + return p +} + +func (p *pluginIngress) Get(ctx context.Context, host string) string { + if p.client == nil { + return "" + } + + r, err := p.client.Get(ctx, + &proto.GetRequest{ + Host: host, + }) + if err != nil { + p.options.logger.Error(err) + return "" + } + return r.GetEndpoint() +} + +func (p *pluginIngress) Close() error { + if p.options.client != nil { + return p.options.client.Close() + } + return nil +} diff --git a/internal/net/udp/relay.go b/internal/net/udp/relay.go index 62b6e84..fc7bfee 100644 --- a/internal/net/udp/relay.go +++ b/internal/net/udp/relay.go @@ -1,6 +1,7 @@ package udp import ( + "context" "net" "github.com/go-gost/core/bypass" @@ -57,7 +58,7 @@ func (r *Relay) Run() (err error) { return err } - if r.bypass != nil && r.bypass.Contains(raddr.String()) { + if r.bypass != nil && r.bypass.Contains(context.Background(), raddr.String()) { if r.logger != nil { r.logger.Warn("bypass: ", raddr) } @@ -95,7 +96,7 @@ func (r *Relay) Run() (err error) { return err } - if r.bypass != nil && r.bypass.Contains(raddr.String()) { + if r.bypass != nil && r.bypass.Contains(context.Background(), raddr.String()) { if r.logger != nil { r.logger.Warn("bypass: ", raddr) } diff --git a/internal/util/ssh/ssh.go b/internal/util/ssh/ssh.go index 6290dbe..8671372 100644 --- a/internal/util/ssh/ssh.go +++ b/internal/util/ssh/ssh.go @@ -1,6 +1,7 @@ package ssh import ( + "context" "errors" "fmt" "io/ioutil" @@ -26,7 +27,7 @@ func PasswordCallback(au auth.Authenticator) PasswordCallbackFunc { return nil } return func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { - if au.Authenticate(conn.User(), string(password)) { + if au.Authenticate(context.Background(), conn.User(), string(password)) { return nil, nil } return nil, fmt.Errorf("password rejected for %s", conn.User()) diff --git a/recorder/plugin.go b/recorder/plugin.go new file mode 100644 index 0000000..0f1ab11 --- /dev/null +++ b/recorder/plugin.go @@ -0,0 +1,77 @@ +package recorder + +import ( + "context" + + "github.com/go-gost/core/logger" + "github.com/go-gost/core/recorder" + "github.com/go-gost/plugin/recorder/proto" + xlogger "github.com/go-gost/x/logger" + "google.golang.org/grpc" +) + +type pluginOptions struct { + client *grpc.ClientConn + logger logger.Logger +} + +type PluginOption func(opts *pluginOptions) + +func PluginConnOption(c *grpc.ClientConn) PluginOption { + return func(opts *pluginOptions) { + opts.client = c + } +} + +func LoggerOption(logger logger.Logger) PluginOption { + return func(opts *pluginOptions) { + opts.logger = logger + } +} + +type pluginRecorder struct { + client proto.RecorderClient + options pluginOptions +} + +// NewPluginRecorder creates a plugin recorder. +func NewPluginRecorder(opts ...PluginOption) recorder.Recorder { + var options pluginOptions + for _, opt := range opts { + opt(&options) + } + if options.logger == nil { + options.logger = xlogger.Nop() + } + + p := &pluginRecorder{ + options: options, + } + if options.client != nil { + p.client = proto.NewRecorderClient(options.client) + } + return p +} + +func (p *pluginRecorder) Record(ctx context.Context, b []byte) error { + if p.client == nil { + return nil + } + + _, err := p.client.Record(context.Background(), + &proto.RecordRequest{ + Data: b, + }) + if err != nil { + p.options.logger.Error(err) + return err + } + return nil +} + +func (p *pluginRecorder) Close() error { + if p.options.client != nil { + return p.options.client.Close() + } + return nil +} diff --git a/registry/admission.go b/registry/admission.go index 3c54eb4..10b96bf 100644 --- a/registry/admission.go +++ b/registry/admission.go @@ -1,6 +1,8 @@ package registry import ( + "context" + "github.com/go-gost/core/admission" ) @@ -28,10 +30,10 @@ type admissionWrapper struct { r *admissionRegistry } -func (w *admissionWrapper) Admit(addr string) bool { +func (w *admissionWrapper) Admit(ctx context.Context, addr string) bool { p := w.r.get(w.name) if p == nil { return false } - return p.Admit(addr) + return p.Admit(ctx, addr) } diff --git a/registry/auther.go b/registry/auther.go index 208e59f..79ad04e 100644 --- a/registry/auther.go +++ b/registry/auther.go @@ -1,6 +1,8 @@ package registry import ( + "context" + "github.com/go-gost/core/auth" ) @@ -28,10 +30,10 @@ type autherWrapper struct { r *autherRegistry } -func (w *autherWrapper) Authenticate(user, password string) bool { +func (w *autherWrapper) Authenticate(ctx context.Context, user, password string) bool { v := w.r.get(w.name) if v == nil { return true } - return v.Authenticate(user, password) + return v.Authenticate(ctx, user, password) } diff --git a/registry/bypass.go b/registry/bypass.go index 4f48aa4..be0bfee 100644 --- a/registry/bypass.go +++ b/registry/bypass.go @@ -1,6 +1,8 @@ package registry import ( + "context" + "github.com/go-gost/core/bypass" ) @@ -28,10 +30,10 @@ type bypassWrapper struct { r *bypassRegistry } -func (w *bypassWrapper) Contains(addr string) bool { +func (w *bypassWrapper) Contains(ctx context.Context, addr string) bool { bp := w.r.get(w.name) if bp == nil { return false } - return bp.Contains(addr) + return bp.Contains(ctx, addr) } diff --git a/registry/hosts.go b/registry/hosts.go index a4e7093..e678931 100644 --- a/registry/hosts.go +++ b/registry/hosts.go @@ -1,6 +1,7 @@ package registry import ( + "context" "net" "github.com/go-gost/core/hosts" @@ -30,10 +31,10 @@ type hostsWrapper struct { r *hostsRegistry } -func (w *hostsWrapper) Lookup(network, host string) ([]net.IP, bool) { +func (w *hostsWrapper) Lookup(ctx context.Context, network, host string) ([]net.IP, bool) { v := w.r.get(w.name) if v == nil { return nil, false } - return v.Lookup(network, host) + return v.Lookup(ctx, network, host) } diff --git a/registry/ingress.go b/registry/ingress.go index 0c039d0..358c579 100644 --- a/registry/ingress.go +++ b/registry/ingress.go @@ -1,6 +1,8 @@ package registry import ( + "context" + "github.com/go-gost/core/ingress" ) @@ -28,10 +30,10 @@ type ingressWrapper struct { r *ingressRegistry } -func (w *ingressWrapper) Get(host string) string { +func (w *ingressWrapper) Get(ctx context.Context, host string) string { v := w.r.get(w.name) if v == nil { return "" } - return v.Get(host) + return v.Get(ctx, host) } diff --git a/resolver/plugin.go b/resolver/plugin.go new file mode 100644 index 0000000..d77a744 --- /dev/null +++ b/resolver/plugin.go @@ -0,0 +1,65 @@ +package resolver + +import ( + "context" + "net" + + resolver_pkg "github.com/go-gost/core/resolver" + "github.com/go-gost/plugin/resolver/proto" + xlogger "github.com/go-gost/x/logger" +) + +type pluginResolver struct { + client proto.ResolverClient + options options +} + +// NewPluginResolver creates a plugin Resolver. +func NewPluginResolver(opts ...Option) (resolver_pkg.Resolver, error) { + var options options + for _, opt := range opts { + opt(&options) + } + if options.logger == nil { + options.logger = xlogger.Nop() + } + + p := &pluginResolver{ + options: options, + } + if options.client != nil { + p.client = proto.NewResolverClient(options.client) + } + return p, nil +} + +func (p *pluginResolver) Resolve(ctx context.Context, network, host string) (ips []net.IP, err error) { + p.options.logger.Debugf("resolve %s/%s", host, network) + + if p.client == nil { + return + } + + r, err := p.client.Resolve(context.Background(), + &proto.ResolveRequest{ + Network: network, + Host: host, + }) + if err != nil { + p.options.logger.Error(err) + return + } + for _, s := range r.Ips { + if ip := net.ParseIP(s); ip != nil { + ips = append(ips, ip) + } + } + return +} + +func (p *pluginResolver) Close() error { + if p.options.client != nil { + return p.options.client.Close() + } + return nil +} diff --git a/resolver/resolver.go b/resolver/resolver.go index 8d08cfc..548a1c0 100644 --- a/resolver/resolver.go +++ b/resolver/resolver.go @@ -12,6 +12,7 @@ import ( resolver_util "github.com/go-gost/x/internal/util/resolver" "github.com/go-gost/x/resolver/exchanger" "github.com/miekg/dns" + "google.golang.org/grpc" ) type NameServer struct { @@ -25,21 +26,28 @@ type NameServer struct { exchanger exchanger.Exchanger } -type resolverOptions struct { +type options struct { domain string + client *grpc.ClientConn logger logger.Logger } -type ResolverOption func(opts *resolverOptions) +type Option func(opts *options) -func DomainResolverOption(domain string) ResolverOption { - return func(opts *resolverOptions) { +func DomainOption(domain string) Option { + return func(opts *options) { opts.domain = domain } } -func LoggerResolverOption(logger logger.Logger) ResolverOption { - return func(opts *resolverOptions) { +func PluginConnOption(c *grpc.ClientConn) Option { + return func(opts *options) { + opts.client = c + } +} + +func LoggerOption(logger logger.Logger) Option { + return func(opts *options) { opts.logger = logger } } @@ -47,11 +55,11 @@ func LoggerResolverOption(logger logger.Logger) ResolverOption { type resolver struct { servers []NameServer cache *resolver_util.Cache - options resolverOptions + options options } -func NewResolver(nameservers []NameServer, opts ...ResolverOption) (resolverpkg.Resolver, error) { - options := resolverOptions{} +func NewResolver(nameservers []NameServer, opts ...Option) (resolverpkg.Resolver, error) { + options := options{} for _, opt := range opts { opt(&options) } diff --git a/service/service.go b/service/service.go index eec8316..11a0571 100644 --- a/service/service.go +++ b/service/service.go @@ -158,7 +158,7 @@ func (s *defaultService) Serve() error { } } if s.options.admission != nil && - !s.options.admission.Admit(conn.RemoteAddr().String()) { + !s.options.admission.Admit(context.Background(), conn.RemoteAddr().String()) { conn.Close() s.options.logger.Debugf("admission: %s is denied", conn.RemoteAddr()) continue