add auther config

This commit is contained in:
ginuerzh 2022-02-12 00:33:20 +08:00
parent c1bf501734
commit a8a6bbc3a3
37 changed files with 261 additions and 183 deletions

View File

@ -107,7 +107,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
} }
resolverCfg.Nameservers = append( resolverCfg.Nameservers = append(
resolverCfg.Nameservers, resolverCfg.Nameservers,
config.NameserverConfig{ &config.NameserverConfig{
Addr: rs, Addr: rs,
}, },
) )
@ -127,7 +127,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
} }
hostsCfg.Mappings = append( hostsCfg.Mappings = append(
hostsCfg.Mappings, hostsCfg.Mappings,
config.HostMappingConfig{ &config.HostMappingConfig{
Hostname: ss[0], Hostname: ss[0],
IP: ss[1], IP: ss[1],
}, },
@ -194,7 +194,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
} }
resolverCfg.Nameservers = append( resolverCfg.Nameservers = append(
resolverCfg.Nameservers, resolverCfg.Nameservers,
config.NameserverConfig{ &config.NameserverConfig{
Addr: rs, Addr: rs,
}, },
) )
@ -214,7 +214,7 @@ func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
} }
hostsCfg.Mappings = append( hostsCfg.Mappings = append(
hostsCfg.Mappings, hostsCfg.Mappings,
config.HostMappingConfig{ &config.HostMappingConfig{
Hostname: ss[0], Hostname: ss[0],
IP: ss[1], IP: ss[1],
}, },
@ -271,13 +271,12 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
} }
} }
var auths []*config.AuthConfig var auth *config.AuthConfig
if url.User != nil { if url.User != nil {
auth := &config.AuthConfig{ auth = &config.AuthConfig{
Username: url.User.Username(), Username: url.User.Username(),
} }
auth.Password, _ = url.User.Password() auth.Password, _ = url.User.Password()
auths = append(auths, auth)
} }
md := metadata.MapMetadata{} md := metadata.MapMetadata{}
@ -292,7 +291,7 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
auths = append(auths, au) auth = au
} }
md.Del("auth") md.Del("auth")
@ -319,7 +318,7 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
svc.Handler = &config.HandlerConfig{ svc.Handler = &config.HandlerConfig{
Type: handler, Type: handler,
Auths: auths, Auth: auth,
Metadata: md, Metadata: md,
} }
svc.Listener = &config.ListenerConfig{ svc.Listener = &config.ListenerConfig{
@ -329,10 +328,10 @@ func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
} }
if svc.Handler.Type == "sshd" { if svc.Handler.Type == "sshd" {
svc.Handler.Auths = nil svc.Handler.Auth = nil
} }
if svc.Listener.Type == "sshd" { if svc.Listener.Type == "sshd" {
svc.Listener.Auths = auths svc.Listener.Auth = auth
} }
return svc, nil return svc, nil

View File

@ -16,6 +16,14 @@ func buildService(cfg *config.Config) (services []*service.Service) {
return return
} }
for _, autherCfg := range cfg.Authers {
if auther := parsing.ParseAuther(autherCfg); auther != nil {
if err := registry.Auther().Register(autherCfg.Name, auther); err != nil {
log.Fatal(err)
}
}
}
for _, bypassCfg := range cfg.Bypasses { for _, bypassCfg := range cfg.Bypasses {
if bp := parsing.ParseBypass(bypassCfg); bp != nil { if bp := parsing.ParseBypass(bypassCfg); bp != nil {
if err := registry.Bypass().Register(bypassCfg.Name, bp); err != nil { if err := registry.Bypass().Register(bypassCfg.Name, bp); err != nil {

View File

@ -1,24 +0,0 @@
package auth
import (
"net/url"
"github.com/go-gost/gost/pkg/auth"
)
func AuthFromUsers(users ...*url.Userinfo) auth.Authenticator {
kvs := make(map[string]string)
for _, v := range users {
if v == nil || v.Username() == "" {
continue
}
kvs[v.Username()], _ = v.Password()
}
var authenticator auth.Authenticator
if len(kvs) > 0 {
authenticator = auth.NewMapAuthenticator(kvs)
}
return authenticator
}

View File

@ -67,6 +67,14 @@ type TLSConfig struct {
ServerName string `yaml:"serverName,omitempty" json:"serverName,omitempty"` ServerName string `yaml:"serverName,omitempty" json:"serverName,omitempty"`
} }
type AutherConfig struct {
Name string `json:"name"`
// inline, file, redis, etc.
Type string `yaml:",omitempty" json:"type,omitempty"`
Auths []*AuthConfig `yaml:",omitempty" json:"auths"`
// File string `yaml:",omitempty" json:"file"`
}
type AuthConfig struct { type AuthConfig struct {
Username string `json:"username"` Username string `json:"username"`
Password string `yaml:",omitempty" json:"password,omitempty"` Password string `yaml:",omitempty" json:"password,omitempty"`
@ -79,7 +87,9 @@ type SelectorConfig struct {
} }
type BypassConfig struct { type BypassConfig struct {
Name string `json:"name"` Name string `json:"name"`
// inline, file, etc.
Type string `yaml:",omitempty" json:"type,omitempty"`
Reverse bool `yaml:",omitempty" json:"reverse,omitempty"` Reverse bool `yaml:",omitempty" json:"reverse,omitempty"`
Matchers []string `json:"matchers"` Matchers []string `json:"matchers"`
} }
@ -95,8 +105,10 @@ type NameserverConfig struct {
} }
type ResolverConfig struct { type ResolverConfig struct {
Name string `json:"name"` Name string `json:"name"`
Nameservers []NameserverConfig `json:"nameservers"` // inline, file, etc.
Type string `yaml:",omitempty" json:"type,omitempty"`
Nameservers []*NameserverConfig `json:"nameservers"`
} }
type HostMappingConfig struct { type HostMappingConfig struct {
@ -106,14 +118,17 @@ type HostMappingConfig struct {
} }
type HostsConfig struct { type HostsConfig struct {
Name string `json:"name"` Name string `json:"name"`
Mappings []HostMappingConfig `json:"mappings"` // inline, file, etc.
Type string `yaml:",omitempty" json:"type,omitempty"`
Mappings []*HostMappingConfig `json:"mappings"`
} }
type ListenerConfig struct { type ListenerConfig struct {
Type string `json:"type"` Type string `json:"type"`
Chain string `yaml:",omitempty" json:"chain,omitempty"` Chain string `yaml:",omitempty" json:"chain,omitempty"`
Auths []*AuthConfig `yaml:",omitempty" json:"auths,omitempty"` Auther string `yaml:",omitempty" json:"auther,omitempty"`
Auth *AuthConfig `yaml:",omitempty" json:"auth,omitempty"`
TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"` TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"`
Metadata map[string]interface{} `yaml:",omitempty" json:"metadata,omitempty"` Metadata map[string]interface{} `yaml:",omitempty" json:"metadata,omitempty"`
} }
@ -122,7 +137,8 @@ type HandlerConfig struct {
Type string `json:"type"` Type string `json:"type"`
Retries int `yaml:",omitempty" json:"retries,omitempty"` Retries int `yaml:",omitempty" json:"retries,omitempty"`
Chain string `yaml:",omitempty" json:"chain,omitempty"` Chain string `yaml:",omitempty" json:"chain,omitempty"`
Auths []*AuthConfig `yaml:",omitempty" json:"auths,omitempty"` Auther string `yaml:",omitempty" json:"auther,omitempty"`
Auth *AuthConfig `yaml:",omitempty" json:"auth,omitempty"`
TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"` TLS *TLSConfig `yaml:",omitempty" json:"tls,omitempty"`
Metadata map[string]interface{} `yaml:",omitempty" json:"metadata,omitempty"` Metadata map[string]interface{} `yaml:",omitempty" json:"metadata,omitempty"`
} }
@ -185,6 +201,7 @@ type NodeConfig struct {
type Config struct { type Config struct {
Services []*ServiceConfig `json:"services"` Services []*ServiceConfig `json:"services"`
Chains []*ChainConfig `yaml:",omitempty" json:"chains,omitempty"` Chains []*ChainConfig `yaml:",omitempty" json:"chains,omitempty"`
Authers []*AutherConfig `yaml:",omitempty" json:"authers,omitempty"`
Bypasses []*BypassConfig `yaml:",omitempty" json:"bypasses,omitempty"` Bypasses []*BypassConfig `yaml:",omitempty" json:"bypasses,omitempty"`
Resolvers []*ResolverConfig `yaml:",omitempty" json:"resolvers,omitempty"` Resolvers []*ResolverConfig `yaml:",omitempty" json:"resolvers,omitempty"`
Hosts []*HostsConfig `yaml:",omitempty" json:"hosts,omitempty"` Hosts []*HostsConfig `yaml:",omitempty" json:"hosts,omitempty"`

View File

@ -1,8 +1,6 @@
package parsing package parsing
import ( import (
"net/url"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
tls_util "github.com/go-gost/gost/pkg/common/util/tls" tls_util "github.com/go-gost/gost/pkg/common/util/tls"
"github.com/go-gost/gost/pkg/config" "github.com/go-gost/gost/pkg/config"
@ -39,15 +37,6 @@ func ParseChain(cfg *config.ChainConfig) (chain.Chainer, error) {
"kind": "connector", "kind": "connector",
}) })
var user *url.Userinfo
if auth := v.Connector.Auth; auth != nil && auth.Username != "" {
if auth.Password == "" {
user = url.User(auth.Username)
} else {
user = url.UserPassword(auth.Username, auth.Password)
}
}
tlsCfg := v.Connector.TLS tlsCfg := v.Connector.TLS
if tlsCfg == nil { if tlsCfg == nil {
tlsCfg = &config.TLSConfig{} tlsCfg = &config.TLSConfig{}
@ -61,7 +50,7 @@ func ParseChain(cfg *config.ChainConfig) (chain.Chainer, error) {
} }
cr := registry.GetConnector(v.Connector.Type)( cr := registry.GetConnector(v.Connector.Type)(
connector.UserOption(user), connector.AuthOption(parseAuth(v.Connector.Auth)),
connector.TLSConfigOption(tlsConfig), connector.TLSConfigOption(tlsConfig),
connector.LoggerOption(connectorLogger), connector.LoggerOption(connectorLogger),
) )
@ -78,15 +67,6 @@ func ParseChain(cfg *config.ChainConfig) (chain.Chainer, error) {
"kind": "dialer", "kind": "dialer",
}) })
user = nil
if auth := v.Dialer.Auth; auth != nil && auth.Username != "" {
if auth.Password == "" {
user = url.User(auth.Username)
} else {
user = url.UserPassword(auth.Username, auth.Password)
}
}
tlsCfg = v.Dialer.TLS tlsCfg = v.Dialer.TLS
if tlsCfg == nil { if tlsCfg == nil {
tlsCfg = &config.TLSConfig{} tlsCfg = &config.TLSConfig{}
@ -100,7 +80,7 @@ func ParseChain(cfg *config.ChainConfig) (chain.Chainer, error) {
} }
d := registry.GetDialer(v.Dialer.Type)( d := registry.GetDialer(v.Dialer.Type)(
dialer.UserOption(user), dialer.AuthOption(parseAuth(v.Dialer.Auth)),
dialer.TLSConfigOption(tlsConfig), dialer.TLSConfigOption(tlsConfig),
dialer.LoggerOption(dialerLogger), dialer.LoggerOption(dialerLogger),
) )

View File

@ -2,16 +2,59 @@ package parsing
import ( import (
"net" "net"
"net/url"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass" "github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/config" "github.com/go-gost/gost/pkg/config"
hostspkg "github.com/go-gost/gost/pkg/hosts" hostspkg "github.com/go-gost/gost/pkg/hosts"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/pkg/registry"
"github.com/go-gost/gost/pkg/resolver" "github.com/go-gost/gost/pkg/resolver"
resolver_impl "github.com/go-gost/gost/pkg/resolver/impl" resolver_impl "github.com/go-gost/gost/pkg/resolver/impl"
) )
func ParseAuther(cfg *config.AutherConfig) auth.Authenticator {
if cfg == nil {
return nil
}
m := make(map[string]string)
for _, user := range cfg.Auths {
if user.Username == "" {
continue
}
m[user.Username] = user.Password
}
if len(m) == 0 {
return nil
}
return auth.NewMapAuthenticator(m)
}
func autherFromAuth(au *config.AuthConfig) auth.Authenticator {
if au == nil || au.Username == "" {
return nil
}
return auth.NewMapAuthenticator(map[string]string{
au.Username: au.Password,
})
}
func parseAuth(cfg *config.AuthConfig) *url.Userinfo {
if cfg == nil || cfg.Username == "" {
return nil
}
if cfg.Password == "" {
return url.User(cfg.Username)
}
return url.UserPassword(cfg.Username, cfg.Password)
}
func parseSelector(cfg *config.SelectorConfig) chain.Selector { func parseSelector(cfg *config.SelectorConfig) chain.Selector {
if cfg == nil { if cfg == nil {
return nil return nil
@ -57,8 +100,8 @@ func ParseResolver(cfg *config.ResolverConfig) (resolver.Resolver, error) {
var nameservers []resolver_impl.NameServer var nameservers []resolver_impl.NameServer
for _, server := range cfg.Nameservers { for _, server := range cfg.Nameservers {
nameservers = append(nameservers, resolver_impl.NameServer{ nameservers = append(nameservers, resolver_impl.NameServer{
Addr: server.Addr, Addr: server.Addr,
// Chain: chains[server.Chain], Chain: registry.Chain().Get(server.Chain),
TTL: server.TTL, TTL: server.TTL,
Timeout: server.Timeout, Timeout: server.Timeout,
ClientIP: net.ParseIP(server.ClientIP), ClientIP: net.ParseIP(server.ClientIP),

View File

@ -1,7 +1,6 @@
package parsing package parsing
import ( import (
"net/url"
"strings" "strings"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
@ -48,10 +47,16 @@ func ParseService(cfg *config.ServiceConfig) (*service.Service, error) {
return nil, err return nil, err
} }
auther := autherFromAuth(cfg.Listener.Auth)
if cfg.Listener.Auther != "" {
auther = registry.Auther().Get(cfg.Listener.Auther)
}
ln := registry.GetListener(cfg.Listener.Type)( ln := registry.GetListener(cfg.Listener.Type)(
listener.AddrOption(cfg.Addr), listener.AddrOption(cfg.Addr),
listener.ChainOption(registry.Chain().Get(cfg.Listener.Chain)), listener.ChainOption(registry.Chain().Get(cfg.Listener.Chain)),
listener.AuthsOption(parseAuths(cfg.Listener.Auths...)...), listener.AutherOption(auther),
listener.AuthOption(parseAuth(cfg.Listener.Auth)),
listener.TLSConfigOption(tlsConfig), listener.TLSConfigOption(tlsConfig),
listener.LoggerOption(listenerLogger), listener.LoggerOption(listenerLogger),
) )
@ -79,8 +84,13 @@ func ParseService(cfg *config.ServiceConfig) (*service.Service, error) {
return nil, err return nil, err
} }
auther = autherFromAuth(cfg.Handler.Auth)
if cfg.Handler.Auther != "" {
auther = registry.Auther().Get(cfg.Handler.Auther)
}
h := registry.GetHandler(cfg.Handler.Type)( h := registry.GetHandler(cfg.Handler.Type)(
handler.AuthsOption(parseAuths(cfg.Handler.Auths...)...), handler.AutherOption(auther),
handler.AuthOption(parseAuth(cfg.Handler.Auth)),
handler.RetriesOption(cfg.Handler.Retries), handler.RetriesOption(cfg.Handler.Retries),
handler.ChainOption(registry.Chain().Get(cfg.Handler.Chain)), handler.ChainOption(registry.Chain().Get(cfg.Handler.Chain)),
handler.BypassOption(registry.Bypass().Get(cfg.Bypass)), handler.BypassOption(registry.Bypass().Get(cfg.Bypass)),
@ -111,19 +121,6 @@ func ParseService(cfg *config.ServiceConfig) (*service.Service, error) {
return s, nil return s, nil
} }
func parseAuths(cfgs ...*config.AuthConfig) []*url.Userinfo {
var auths []*url.Userinfo
for _, cfg := range cfgs {
if cfg == nil || cfg.Username == "" {
continue
}
auths = append(auths, url.UserPassword(cfg.Username, cfg.Password))
}
return auths
}
func parseForwarder(cfg *config.ForwarderConfig) *chain.NodeGroup { func parseForwarder(cfg *config.ForwarderConfig) *chain.NodeGroup {
if cfg == nil || len(cfg.Targets) == 0 { if cfg == nil || len(cfg.Targets) == 0 {
return nil return nil

View File

@ -23,7 +23,6 @@ func init() {
} }
type httpConnector struct { type httpConnector struct {
user *url.Userinfo
md metadata md metadata
options connector.Options options connector.Options
} }
@ -35,7 +34,6 @@ func NewConnector(opts ...connector.Option) connector.Connector {
} }
return &httpConnector{ return &httpConnector{
user: options.User,
options: options, options: options,
} }
} }
@ -67,7 +65,7 @@ func (c *httpConnector) Connect(ctx context.Context, conn net.Conn, network, add
} }
req.Header.Set("Proxy-Connection", "keep-alive") req.Header.Set("Proxy-Connection", "keep-alive")
if user := c.user; user != nil { if user := c.options.Auth; user != nil {
u := user.Username() u := user.Username()
p, _ := user.Password() p, _ := user.Password()
req.Header.Set("Proxy-Authorization", req.Header.Set("Proxy-Authorization",

View File

@ -24,7 +24,6 @@ func init() {
} }
type http2Connector struct { type http2Connector struct {
user *url.Userinfo
md metadata md metadata
options connector.Options options connector.Options
} }
@ -36,7 +35,6 @@ func NewConnector(opts ...connector.Option) connector.Connector {
} }
return &http2Connector{ return &http2Connector{
user: options.User,
options: options, options: options,
} }
} }
@ -76,7 +74,7 @@ func (c *http2Connector) Connect(ctx context.Context, conn net.Conn, network, ad
req.Header.Set("User-Agent", c.md.UserAgent) req.Header.Set("User-Agent", c.md.UserAgent)
} }
if user := c.user; user != nil { if user := c.options.Auth; user != nil {
u := user.Username() u := user.Username()
p, _ := user.Password() p, _ := user.Password()
req.Header.Set("Proxy-Authorization", req.Header.Set("Proxy-Authorization",

View File

@ -9,16 +9,16 @@ import (
) )
type Options struct { type Options struct {
User *url.Userinfo Auth *url.Userinfo
TLSConfig *tls.Config TLSConfig *tls.Config
Logger logger.Logger Logger logger.Logger
} }
type Option func(opts *Options) type Option func(opts *Options)
func UserOption(user *url.Userinfo) Option { func AuthOption(auth *url.Userinfo) Option {
return func(opts *Options) { return func(opts *Options) {
opts.User = user opts.Auth = auth
} }
} }

View File

@ -82,10 +82,10 @@ func (c *relayConnector) bind(conn net.Conn, cmd uint8, network, address string)
Flags: cmd, Flags: cmd,
} }
if c.user != nil { if c.options.Auth != nil {
pwd, _ := c.user.Password() pwd, _ := c.options.Auth.Password()
req.Features = append(req.Features, &relay.UserAuthFeature{ req.Features = append(req.Features, &relay.UserAuthFeature{
Username: c.user.Username(), Username: c.options.Auth.Username(),
Password: pwd, Password: pwd,
}) })
} }

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"net" "net"
"net/url"
"time" "time"
"github.com/go-gost/gost/pkg/common/util/socks" "github.com/go-gost/gost/pkg/common/util/socks"
@ -19,7 +18,6 @@ func init() {
} }
type relayConnector struct { type relayConnector struct {
user *url.Userinfo
md metadata md metadata
options connector.Options options connector.Options
} }
@ -31,7 +29,6 @@ func NewConnector(opts ...connector.Option) connector.Connector {
} }
return &relayConnector{ return &relayConnector{
user: options.User,
options: options, options: options,
} }
} }
@ -73,10 +70,10 @@ func (c *relayConnector) Connect(ctx context.Context, conn net.Conn, network, ad
} }
} }
if c.user != nil { if c.options.Auth != nil {
pwd, _ := c.user.Password() pwd, _ := c.options.Auth.Password()
req.Features = append(req.Features, &relay.UserAuthFeature{ req.Features = append(req.Features, &relay.UserAuthFeature{
Username: c.user.Username(), Username: c.options.Auth.Username(),
Password: pwd, Password: pwd,
}) })
} }

View File

@ -5,7 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/url"
"strconv" "strconv"
"time" "time"
@ -21,7 +20,6 @@ func init() {
} }
type socks4Connector struct { type socks4Connector struct {
user *url.Userinfo
md metadata md metadata
options connector.Options options connector.Options
} }
@ -33,7 +31,6 @@ func NewConnector(opts ...connector.Option) connector.Connector {
} }
return &socks4Connector{ return &socks4Connector{
user: options.User,
options: options, options: options,
} }
} }
@ -99,8 +96,8 @@ func (c *socks4Connector) Connect(ctx context.Context, conn net.Conn, network, a
} }
var userid []byte var userid []byte
if c.user != nil && c.user.Username() != "" { if c.options.Auth != nil {
userid = []byte(c.user.Username()) userid = []byte(c.options.Auth.Username())
} }
req := gosocks4.NewRequest(gosocks4.CmdConnect, addr, userid) req := gosocks4.NewRequest(gosocks4.CmdConnect, addr, userid)
if err := req.Write(conn); err != nil { if err := req.Write(conn); err != nil {

View File

@ -48,7 +48,7 @@ func (c *socks5Connector) Init(md md.Metadata) (err error) {
gosocks5.MethodNoAuth, gosocks5.MethodNoAuth,
gosocks5.MethodUserPass, gosocks5.MethodUserPass,
}, },
User: c.options.User, User: c.options.Auth,
TLSConfig: c.options.TLSConfig, TLSConfig: c.options.TLSConfig,
logger: c.options.Logger, logger: c.options.Logger,
} }

View File

@ -41,9 +41,9 @@ func (c *ssConnector) Init(md md.Metadata) (err error) {
return return
} }
if c.options.User != nil { if c.options.Auth != nil {
method := c.options.User.Username() method := c.options.Auth.Username()
password, _ := c.options.User.Password() password, _ := c.options.Auth.Password()
c.cipher, err = ss.ShadowCipher(method, password, c.md.key) c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
} }

View File

@ -40,9 +40,9 @@ func (c *ssuConnector) Init(md md.Metadata) (err error) {
return return
} }
if c.options.User != nil { if c.options.Auth != nil {
method := c.options.User.Username() method := c.options.Auth.Username()
password, _ := c.options.User.Password() password, _ := c.options.Auth.Password()
c.cipher, err = ss.ShadowCipher(method, password, c.md.key) c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
} }

View File

@ -10,16 +10,16 @@ import (
) )
type Options struct { type Options struct {
User *url.Userinfo Auth *url.Userinfo
TLSConfig *tls.Config TLSConfig *tls.Config
Logger logger.Logger Logger logger.Logger
} }
type Option func(opts *Options) type Option func(opts *Options)
func UserOption(user *url.Userinfo) Option { func AuthOption(auth *url.Userinfo) Option {
return func(opts *Options) { return func(opts *Options) {
opts.User = user opts.Auth = auth
} }
} }

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"net" "net"
"net/url"
"sync" "sync"
"time" "time"
@ -20,7 +19,6 @@ func init() {
} }
type sshdDialer struct { type sshdDialer struct {
user *url.Userinfo
sessions map[string]*sshSession sessions map[string]*sshSession
sessionMutex sync.Mutex sessionMutex sync.Mutex
md metadata md metadata
@ -34,7 +32,6 @@ func NewDialer(opts ...dialer.Option) dialer.Dialer {
} }
return &sshdDialer{ return &sshdDialer{
user: options.User,
sessions: make(map[string]*sshSession), sessions: make(map[string]*sshSession),
options: options, options: options,
} }
@ -167,9 +164,9 @@ func (d *sshdDialer) initSession(ctx context.Context, addr string, conn net.Conn
// Timeout: timeout, // Timeout: timeout,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), HostKeyCallback: ssh.InsecureIgnoreHostKey(),
} }
if d.user != nil { if d.options.Auth != nil {
config.User = d.user.Username() config.User = d.options.Auth.Username()
if password, _ := d.user.Password(); password != "" { if password, _ := d.options.Auth.Password(); password != "" {
config.Auth = []ssh.AuthMethod{ config.Auth = []ssh.AuthMethod{
ssh.Password(password), ssh.Password(password),
} }

View File

@ -16,9 +16,7 @@ import (
"time" "time"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
@ -30,10 +28,9 @@ func init() {
} }
type httpHandler struct { type httpHandler struct {
router *chain.Router router *chain.Router
authenticator auth.Authenticator md metadata
md metadata options handler.Options
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
@ -52,7 +49,6 @@ func (h *httpHandler) Init(md md.Metadata) error {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{ h.router = &chain.Router{
Retries: h.options.Retries, Retries: h.options.Retries,
Chain: h.options.Chain, Chain: h.options.Chain,
@ -266,7 +262,7 @@ func (h *httpHandler) basicProxyAuth(proxyAuth string, log logger.Logger) (usern
func (h *httpHandler) authenticate(conn net.Conn, req *http.Request, resp *http.Response, log logger.Logger) (ok bool) { func (h *httpHandler) authenticate(conn net.Conn, req *http.Request, resp *http.Response, log logger.Logger) (ok bool) {
u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"), log) u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"), log)
if h.authenticator == nil || h.authenticator.Authenticate(u, p) { if h.options.Auther == nil || h.options.Auther.Authenticate(u, p) {
return true return true
} }

View File

@ -18,9 +18,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
http2_util "github.com/go-gost/gost/pkg/internal/util/http2" http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -33,10 +31,9 @@ func init() {
} }
type http2Handler struct { type http2Handler struct {
router *chain.Router router *chain.Router
authenticator auth.Authenticator md metadata
md metadata options handler.Options
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
@ -55,7 +52,6 @@ func (h *http2Handler) Init(md md.Metadata) error {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{ h.router = &chain.Router{
Retries: h.options.Retries, Retries: h.options.Retries,
Chain: h.options.Chain, Chain: h.options.Chain,
@ -239,7 +235,7 @@ func (h *http2Handler) basicProxyAuth(proxyAuth string) (username, password stri
func (h *http2Handler) authenticate(w http.ResponseWriter, r *http.Request, resp *http.Response, log logger.Logger) (ok bool) { func (h *http2Handler) authenticate(w http.ResponseWriter, r *http.Request, resp *http.Response, log logger.Logger) (ok bool) {
u, p, _ := h.basicProxyAuth(r.Header.Get("Proxy-Authorization")) u, p, _ := h.basicProxyAuth(r.Header.Get("Proxy-Authorization"))
if h.authenticator == nil || h.authenticator.Authenticate(u, p) { if h.options.Auther == nil || h.options.Auther.Authenticate(u, p) {
return true return true
} }

View File

@ -4,6 +4,7 @@ import (
"crypto/tls" "crypto/tls"
"net/url" "net/url"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass" "github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/hosts" "github.com/go-gost/gost/pkg/hosts"
@ -17,7 +18,8 @@ type Options struct {
Resolver resolver.Resolver Resolver resolver.Resolver
Hosts hosts.HostMapper Hosts hosts.HostMapper
Bypass bypass.Bypass Bypass bypass.Bypass
Auths []*url.Userinfo Auth *url.Userinfo
Auther auth.Authenticator
TLSConfig *tls.Config TLSConfig *tls.Config
Logger logger.Logger Logger logger.Logger
} }
@ -54,9 +56,14 @@ func BypassOption(bypass bypass.Bypass) Option {
} }
} }
func AuthsOption(auths ...*url.Userinfo) Option { func AuthOption(auth *url.Userinfo) Option {
return func(opts *Options) { return func(opts *Options) {
opts.Auths = auths opts.Auth = auth
}
}
func AutherOption(auther auth.Authenticator) Option {
return func(opts *Options) {
opts.Auther = auther
} }
} }

View File

@ -6,9 +6,7 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry" "github.com/go-gost/gost/pkg/registry"
@ -20,11 +18,10 @@ func init() {
} }
type relayHandler struct { type relayHandler struct {
group *chain.NodeGroup group *chain.NodeGroup
router *chain.Router router *chain.Router
authenticator auth.Authenticator md metadata
md metadata options handler.Options
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
@ -43,7 +40,6 @@ func (h *relayHandler) Init(md md.Metadata) (err error) {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{ h.router = &chain.Router{
Retries: h.options.Retries, Retries: h.options.Retries,
Chain: h.options.Chain, Chain: h.options.Chain,
@ -113,7 +109,7 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn) {
Version: relay.Version1, Version: relay.Version1,
Status: relay.StatusOK, Status: relay.StatusOK,
} }
if h.authenticator != nil && !h.authenticator.Authenticate(user, pass) { if h.options.Auther != nil && !h.options.Auther.Authenticate(user, pass) {
resp.Status = relay.StatusUnauthorized resp.Status = relay.StatusUnauthorized
resp.WriteTo(conn) resp.WriteTo(conn)
log.Error("unauthorized") log.Error("unauthorized")

View File

@ -6,9 +6,7 @@ import (
"time" "time"
"github.com/go-gost/gosocks4" "github.com/go-gost/gosocks4"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
@ -21,10 +19,9 @@ func init() {
} }
type socks4Handler struct { type socks4Handler struct {
router *chain.Router router *chain.Router
authenticator auth.Authenticator md metadata
md metadata options handler.Options
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
@ -43,7 +40,6 @@ func (h *socks4Handler) Init(md md.Metadata) (err error) {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{ h.router = &chain.Router{
Retries: h.options.Retries, Retries: h.options.Retries,
Chain: h.options.Chain, Chain: h.options.Chain,
@ -85,8 +81,8 @@ func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn) {
conn.SetReadDeadline(time.Time{}) conn.SetReadDeadline(time.Time{})
if h.authenticator != nil && if h.options.Auther != nil &&
!h.authenticator.Authenticate(string(req.Userid), "") { !h.options.Auther.Authenticate(string(req.Userid), "") {
resp := gosocks4.NewReply(gosocks4.RejectedUserid, nil) resp := gosocks4.NewReply(gosocks4.RejectedUserid, nil)
resp.Write(conn) resp.Write(conn)
log.Debug(resp) log.Debug(resp)

View File

@ -7,7 +7,6 @@ import (
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/common/util/socks" "github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
@ -51,7 +50,7 @@ func (h *socks5Handler) Init(md md.Metadata) (err error) {
} }
h.selector = &serverSelector{ h.selector = &serverSelector{
Authenticator: auth_util.AuthFromUsers(h.options.Auths...), Authenticator: h.options.Auther,
TLSConfig: h.options.TLSConfig, TLSConfig: h.options.TLSConfig,
logger: h.options.Logger, logger: h.options.Logger,
noTLS: h.md.noTLS, noTLS: h.md.noTLS,

View File

@ -42,9 +42,9 @@ func (h *ssHandler) Init(md md.Metadata) (err error) {
if err = h.parseMetadata(md); err != nil { if err = h.parseMetadata(md); err != nil {
return return
} }
if len(h.options.Auths) > 0 { if h.options.Auth != nil {
method := h.options.Auths[0].Username() method := h.options.Auth.Username()
password, _ := h.options.Auths[0].Password() password, _ := h.options.Auth.Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key) h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil { if err != nil {
return return

View File

@ -43,9 +43,9 @@ func (h *ssuHandler) Init(md md.Metadata) (err error) {
return return
} }
if len(h.options.Auths) > 0 { if h.options.Auth != nil {
method := h.options.Auths[0].Username() method := h.options.Auth.Username()
password, _ := h.options.Auths[0].Password() password, _ := h.options.Auth.Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key) h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil { if err != nil {
return return

View File

@ -54,9 +54,9 @@ func (h *tapHandler) Init(md md.Metadata) (err error) {
return return
} }
if len(h.options.Auths) > 0 { if h.options.Auth != nil {
method := h.options.Auths[0].Username() method := h.options.Auth.Username()
password, _ := h.options.Auths[0].Password() password, _ := h.options.Auth.Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key) h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil { if err != nil {
return return

View File

@ -56,9 +56,9 @@ func (h *tunHandler) Init(md md.Metadata) (err error) {
return return
} }
if len(h.options.Auths) > 0 { if h.options.Auth != nil {
method := h.options.Auths[0].Username() method := h.options.Auth.Username()
password, _ := h.options.Auths[0].Password() password, _ := h.options.Auth.Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key) h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil { if err != nil {
return return

View File

@ -4,13 +4,15 @@ import (
"crypto/tls" "crypto/tls"
"net/url" "net/url"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
) )
type Options struct { type Options struct {
Addr string Addr string
Auths []*url.Userinfo Auther auth.Authenticator
Auth *url.Userinfo
TLSConfig *tls.Config TLSConfig *tls.Config
Chain chain.Chainer Chain chain.Chainer
Logger logger.Logger Logger logger.Logger
@ -24,9 +26,15 @@ func AddrOption(addr string) Option {
} }
} }
func AuthsOption(auths ...*url.Userinfo) Option { func AutherOption(auther auth.Authenticator) Option {
return func(opts *Options) { return func(opts *Options) {
opts.Auths = auths opts.Auther = auther
}
}
func AuthOption(auth *url.Userinfo) Option {
return func(opts *Options) {
opts.Auth = auth
} }
} }

View File

@ -5,7 +5,6 @@ import (
"net" "net"
"time" "time"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh" ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
"github.com/go-gost/gost/pkg/listener" "github.com/go-gost/gost/pkg/listener"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -53,13 +52,12 @@ func (l *sshListener) Init(md md.Metadata) (err error) {
l.Listener = ln l.Listener = ln
authenticator := auth_util.AuthFromUsers(l.options.Auths...)
config := &ssh.ServerConfig{ config := &ssh.ServerConfig{
PasswordCallback: ssh_util.PasswordCallback(authenticator), PasswordCallback: ssh_util.PasswordCallback(l.options.Auther),
PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys), PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys),
} }
config.AddHostKey(l.md.signer) config.AddHostKey(l.md.signer)
if authenticator == nil && len(l.md.authorizedKeys) == 0 { if l.options.Auther == nil && len(l.md.authorizedKeys) == 0 {
config.NoClientAuth = true config.NoClientAuth = true
} }

View File

@ -7,7 +7,6 @@ import (
"strconv" "strconv"
"time" "time"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh" ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
sshd_util "github.com/go-gost/gost/pkg/internal/util/sshd" sshd_util "github.com/go-gost/gost/pkg/internal/util/sshd"
"github.com/go-gost/gost/pkg/listener" "github.com/go-gost/gost/pkg/listener"
@ -62,13 +61,12 @@ func (l *sshdListener) Init(md md.Metadata) (err error) {
l.Listener = ln l.Listener = ln
authenticator := auth_util.AuthFromUsers(l.options.Auths...)
config := &ssh.ServerConfig{ config := &ssh.ServerConfig{
PasswordCallback: ssh_util.PasswordCallback(authenticator), PasswordCallback: ssh_util.PasswordCallback(l.options.Auther),
PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys), PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys),
} }
config.AddHostKey(l.md.signer) config.AddHostKey(l.md.signer)
if authenticator == nil && len(l.md.authorizedKeys) == 0 { if l.options.Auther == nil && len(l.md.authorizedKeys) == 0 {
config.NoClientAuth = true config.NoClientAuth = true
} }

62
pkg/registry/auther.go Normal file
View File

@ -0,0 +1,62 @@
package registry
import (
"sync"
"github.com/go-gost/gost/pkg/auth"
)
var (
autherReg = &autherRegistry{}
)
func Auther() *autherRegistry {
return autherReg
}
type autherRegistry struct {
m sync.Map
}
func (r *autherRegistry) Register(name string, auth auth.Authenticator) error {
if _, loaded := r.m.LoadOrStore(name, auth); loaded {
return ErrDup
}
return nil
}
func (r *autherRegistry) Unregister(name string) {
r.m.Delete(name)
}
func (r *autherRegistry) IsRegistered(name string) bool {
_, ok := r.m.Load(name)
return ok
}
func (r *autherRegistry) Get(name string) auth.Authenticator {
if name == "" {
return nil
}
return &autherWrapper{name: name}
}
func (r *autherRegistry) get(name string) auth.Authenticator {
if v, ok := r.m.Load(name); ok {
return v.(auth.Authenticator)
}
return nil
}
type autherWrapper struct {
name string
}
func (w *autherWrapper) Authenticate(user, password string) bool {
v := autherReg.get(w.name)
if v == nil {
return true
}
return v.Authenticate(user, password)
}

View File

@ -36,6 +36,9 @@ func (r *bypassRegistry) IsRegistered(name string) bool {
} }
func (r *bypassRegistry) Get(name string) bypass.Bypass { func (r *bypassRegistry) Get(name string) bypass.Bypass {
if name == "" {
return nil
}
return &bypassWrapper{name: name} return &bypassWrapper{name: name}
} }

View File

@ -36,6 +36,9 @@ func (r *chainRegistry) IsRegistered(name string) bool {
} }
func (r *chainRegistry) Get(name string) chain.Chainer { func (r *chainRegistry) Get(name string) chain.Chainer {
if name == "" {
return nil
}
return &chainWrapper{name: name} return &chainWrapper{name: name}
} }

View File

@ -37,6 +37,9 @@ func (r *hostsRegistry) IsRegistered(name string) bool {
} }
func (r *hostsRegistry) Get(name string) hosts.HostMapper { func (r *hostsRegistry) Get(name string) hosts.HostMapper {
if name == "" {
return nil
}
return &hostsWrapper{name: name} return &hostsWrapper{name: name}
} }

View File

@ -38,6 +38,9 @@ func (r *resolverRegistry) IsRegistered(name string) bool {
} }
func (r *resolverRegistry) Get(name string) resolver.Resolver { func (r *resolverRegistry) Get(name string) resolver.Resolver {
if name == "" {
return nil
}
return &resolverWrapper{name: name} return &resolverWrapper{name: name}
} }

View File

@ -36,6 +36,9 @@ func (r *serviceRegistry) IsRegistered(name string) bool {
} }
func (r *serviceRegistry) Get(name string) *service.Service { func (r *serviceRegistry) Get(name string) *service.Service {
if name == "" {
return nil
}
v, ok := r.m.Load(name) v, ok := r.m.Load(name)
if !ok { if !ok {
return nil return nil