From 04f6ed470873c4072695ba9c304e4bbf3762f006 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Mon, 4 Apr 2022 11:30:31 +0800 Subject: [PATCH] remove pkgs to github.com/go-gost/x --- admission/admission.go | 84 ------- auth/auth.go | 22 -- bypass/bypass.go | 83 ------- common/matcher/matcher.go | 99 --------- common/util/resolver/cache.go | 88 -------- common/util/resolver/resolver.go | 30 --- common/util/tls/tls.go | 178 --------------- connector/forward/connector.go | 45 ---- connector/http/connector.go | 129 ----------- connector/http/metadata.go | 32 --- connector/socks/v4/connector.go | 123 ----------- connector/socks/v4/metadata.go | 24 -- connector/socks/v5/bind.go | 133 ------------ connector/socks/v5/conn.go | 17 -- connector/socks/v5/connector.go | 173 --------------- connector/socks/v5/listener.go | 102 --------- connector/socks/v5/metadata.go | 24 -- connector/socks/v5/selector.go | 73 ------- dialer/tcp/dialer.go | 48 ---- dialer/tcp/metadata.go | 23 -- dialer/tls/dialer.go | 68 ------ dialer/tls/metadata.go | 21 -- dialer/udp/conn.go | 17 -- dialer/udp/dialer.go | 50 ----- dialer/udp/metadata.go | 23 -- go.mod | 15 +- go.sum | 41 +--- handler/auto/handler.go | 115 ---------- handler/forward/local/handler.go | 117 ---------- handler/forward/local/metadata.go | 20 -- handler/forward/remote/handler.go | 111 ---------- handler/forward/remote/metadata.go | 20 -- handler/http/handler.go | 337 ----------------------------- handler/http/metadata.go | 53 ----- handler/http/udp.go | 80 ------- handler/socks/v4/handler.go | 152 ------------- handler/socks/v4/metadata.go | 20 -- handler/socks/v5/bind.go | 149 ------------- handler/socks/v5/connect.go | 53 ----- handler/socks/v5/handler.go | 115 ---------- handler/socks/v5/mbind.go | 133 ------------ handler/socks/v5/metadata.go | 43 ---- handler/socks/v5/selector.go | 90 -------- handler/socks/v5/udp.go | 85 -------- handler/socks/v5/udp_tun.go | 72 ------ hosts/hosts.go | 122 ----------- internal/util/mux/mux.go | 85 -------- internal/util/socks/conn.go | 172 --------------- internal/util/socks/socks.go | 18 -- internal/util/tcp.go | 32 --- listener/rtcp/listener.go | 102 --------- listener/rtcp/metadata.go | 11 - listener/rudp/listener.go | 109 ---------- listener/rudp/metadata.go | 51 ----- listener/tcp/listener.go | 60 ----- listener/tcp/metadata.go | 12 - listener/tls/listener.go | 64 ------ listener/tls/metadata.go | 12 - listener/udp/listener.go | 74 ------- listener/udp/metadata.go | 54 ----- logger/gost_logger.go | 155 ------------- logger/logger.go | 34 +-- logger/nop_logger.go | 53 ----- registry/admission.go | 40 ---- registry/auther.go | 40 ---- registry/bypass.go | 40 ---- registry/chain.go | 40 ---- registry/connector.go | 26 --- registry/dialer.go | 26 --- registry/handler.go | 26 --- registry/hosts.go | 42 ---- registry/listener.go | 26 --- registry/registry.go | 116 ---------- registry/resolver.go | 43 ---- registry/service.go | 20 -- resolver/exchanger/exchanger.go | 223 ------------------- resolver/impl/resolver.go | 178 --------------- resolver/resolver.go | 2 +- 78 files changed, 11 insertions(+), 5627 deletions(-) delete mode 100644 common/matcher/matcher.go delete mode 100644 common/util/resolver/cache.go delete mode 100644 common/util/resolver/resolver.go delete mode 100644 common/util/tls/tls.go delete mode 100644 connector/forward/connector.go delete mode 100644 connector/http/connector.go delete mode 100644 connector/http/metadata.go delete mode 100644 connector/socks/v4/connector.go delete mode 100644 connector/socks/v4/metadata.go delete mode 100644 connector/socks/v5/bind.go delete mode 100644 connector/socks/v5/conn.go delete mode 100644 connector/socks/v5/connector.go delete mode 100644 connector/socks/v5/listener.go delete mode 100644 connector/socks/v5/metadata.go delete mode 100644 connector/socks/v5/selector.go delete mode 100644 dialer/tcp/dialer.go delete mode 100644 dialer/tcp/metadata.go delete mode 100644 dialer/tls/dialer.go delete mode 100644 dialer/tls/metadata.go delete mode 100644 dialer/udp/conn.go delete mode 100644 dialer/udp/dialer.go delete mode 100644 dialer/udp/metadata.go delete mode 100644 handler/auto/handler.go delete mode 100644 handler/forward/local/handler.go delete mode 100644 handler/forward/local/metadata.go delete mode 100644 handler/forward/remote/handler.go delete mode 100644 handler/forward/remote/metadata.go delete mode 100644 handler/http/handler.go delete mode 100644 handler/http/metadata.go delete mode 100644 handler/http/udp.go delete mode 100644 handler/socks/v4/handler.go delete mode 100644 handler/socks/v4/metadata.go delete mode 100644 handler/socks/v5/bind.go delete mode 100644 handler/socks/v5/connect.go delete mode 100644 handler/socks/v5/handler.go delete mode 100644 handler/socks/v5/mbind.go delete mode 100644 handler/socks/v5/metadata.go delete mode 100644 handler/socks/v5/selector.go delete mode 100644 handler/socks/v5/udp.go delete mode 100644 handler/socks/v5/udp_tun.go delete mode 100644 internal/util/mux/mux.go delete mode 100644 internal/util/socks/conn.go delete mode 100644 internal/util/socks/socks.go delete mode 100644 internal/util/tcp.go delete mode 100644 listener/rtcp/listener.go delete mode 100644 listener/rtcp/metadata.go delete mode 100644 listener/rudp/listener.go delete mode 100644 listener/rudp/metadata.go delete mode 100644 listener/tcp/listener.go delete mode 100644 listener/tcp/metadata.go delete mode 100644 listener/tls/listener.go delete mode 100644 listener/tls/metadata.go delete mode 100644 listener/udp/listener.go delete mode 100644 listener/udp/metadata.go delete mode 100644 logger/gost_logger.go delete mode 100644 logger/nop_logger.go delete mode 100644 registry/admission.go delete mode 100644 registry/auther.go delete mode 100644 registry/bypass.go delete mode 100644 registry/chain.go delete mode 100644 registry/connector.go delete mode 100644 registry/dialer.go delete mode 100644 registry/handler.go delete mode 100644 registry/hosts.go delete mode 100644 registry/listener.go delete mode 100644 registry/registry.go delete mode 100644 registry/resolver.go delete mode 100644 registry/service.go delete mode 100644 resolver/exchanger/exchanger.go delete mode 100644 resolver/impl/resolver.go diff --git a/admission/admission.go b/admission/admission.go index ab3e71e..ab36f02 100644 --- a/admission/admission.go +++ b/admission/admission.go @@ -1,89 +1,5 @@ package admission -import ( - "net" - "strconv" - - "github.com/go-gost/core/common/matcher" - "github.com/go-gost/core/logger" -) - type Admission interface { Admit(addr string) bool } - -type options struct { - logger logger.Logger -} - -type Option func(opts *options) - -func LoggerOption(logger logger.Logger) Option { - return func(opts *options) { - opts.logger = logger - } -} - -type admission struct { - matchers []matcher.Matcher - reversed bool - options options -} - -// NewAdmission creates and initializes a new Admission using matchers as its match rules. -// The rules will be reversed if the reversed is true. -func NewAdmission(reversed bool, matchers []matcher.Matcher, opts ...Option) Admission { - options := options{} - for _, opt := range opts { - opt(&options) - } - return &admission{ - matchers: matchers, - reversed: reversed, - options: options, - } -} - -// NewAdmissionPatterns creates and initializes a new Admission using matcher patterns as its match rules. -// The rules will be reversed if the reverse is true. -func NewAdmissionPatterns(reversed bool, patterns []string, opts ...Option) Admission { - var matchers []matcher.Matcher - for _, pattern := range patterns { - if m := matcher.NewMatcher(pattern); m != nil { - matchers = append(matchers, m) - } - } - return NewAdmission(reversed, matchers, opts...) -} - -func (p *admission) Admit(addr string) bool { - if addr == "" || p == nil || len(p.matchers) == 0 { - p.options.logger.Debugf("admission: %v is denied", addr) - return false - } - - // try to strip the port - if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" { - if p, _ := strconv.Atoi(port); p > 0 { // port is valid - addr = host - } - } - - var matched bool - for _, matcher := range p.matchers { - if matcher == nil { - continue - } - if matcher.Match(addr) { - matched = true - break - } - } - - b := !p.reversed && matched || - p.reversed && !matched - if !b { - p.options.logger.Debugf("admission: %v is denied", addr) - } - return b -} diff --git a/auth/auth.go b/auth/auth.go index 6bdf54d..8becea0 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -4,25 +4,3 @@ package auth type Authenticator interface { Authenticate(user, password string) bool } - -// authenticator is an Authenticator that authenticates client by key-value pairs. -type authenticator struct { - kvs map[string]string -} - -// NewAuthenticator creates an Authenticator that authenticates client by pre-defined user mapping. -func NewAuthenticator(kvs map[string]string) Authenticator { - return &authenticator{ - kvs: kvs, - } -} - -// Authenticate checks the validity of the provided user-password pair. -func (au *authenticator) Authenticate(user, password string) bool { - if au == nil || len(au.kvs) == 0 { - return true - } - - v, ok := au.kvs[user] - return ok && (v == "" || password == v) -} diff --git a/bypass/bypass.go b/bypass/bypass.go index a3cd3ee..698dbd7 100644 --- a/bypass/bypass.go +++ b/bypass/bypass.go @@ -1,90 +1,7 @@ package bypass -import ( - "net" - "strconv" - - "github.com/go-gost/core/common/matcher" - "github.com/go-gost/core/logger" -) - // Bypass is a filter of address (IP or domain). type Bypass interface { // Contains reports whether the bypass includes addr. Contains(addr string) bool } - -type options struct { - logger logger.Logger -} - -type Option func(opts *options) - -func LoggerOption(logger logger.Logger) Option { - return func(opts *options) { - opts.logger = logger - } -} - -type bypass struct { - matchers []matcher.Matcher - reversed bool - options options -} - -// NewBypass creates and initializes a new Bypass using matchers as its match rules. -// The rules will be reversed if the reversed is true. -func NewBypass(reversed bool, matchers []matcher.Matcher, opts ...Option) Bypass { - options := options{} - for _, opt := range opts { - opt(&options) - } - return &bypass{ - matchers: matchers, - reversed: reversed, - options: options, - } -} - -// NewBypassPatterns creates and initializes a new Bypass using matcher patterns as its match rules. -// The rules will be reversed if the reverse is true. -func NewBypassPatterns(reversed bool, patterns []string, opts ...Option) Bypass { - var matchers []matcher.Matcher - for _, pattern := range patterns { - if m := matcher.NewMatcher(pattern); m != nil { - matchers = append(matchers, m) - } - } - return NewBypass(reversed, matchers, opts...) -} - -func (bp *bypass) Contains(addr string) bool { - if addr == "" || bp == nil || len(bp.matchers) == 0 { - return false - } - - // try to strip the port - if host, port, _ := net.SplitHostPort(addr); host != "" && port != "" { - if p, _ := strconv.Atoi(port); p > 0 { // port is valid - addr = host - } - } - - var matched bool - for _, matcher := range bp.matchers { - if matcher == nil { - continue - } - if matcher.Match(addr) { - matched = true - break - } - } - - b := !bp.reversed && matched || - bp.reversed && !matched - if b { - bp.options.logger.Debugf("bypass: %s", addr) - } - return b -} diff --git a/common/matcher/matcher.go b/common/matcher/matcher.go deleted file mode 100644 index 81442d3..0000000 --- a/common/matcher/matcher.go +++ /dev/null @@ -1,99 +0,0 @@ -package matcher - -import ( - "net" - "strings" - - "github.com/gobwas/glob" -) - -// Matcher is a generic pattern matcher, -// it gives the match result of the given pattern for specific v. -type Matcher interface { - Match(v string) bool -} - -// NewMatcher creates a Matcher for the given pattern. -// The acutal Matcher depends on the pattern: -// IP Matcher if pattern is a valid IP address. -// CIDR Matcher if pattern is a valid CIDR address. -// Domain Matcher if both of the above are not. -func NewMatcher(pattern string) Matcher { - if pattern == "" { - return nil - } - if ip := net.ParseIP(pattern); ip != nil { - return IPMatcher(ip) - } - if _, inet, err := net.ParseCIDR(pattern); err == nil { - return CIDRMatcher(inet) - } - return DomainMatcher(pattern) -} - -type ipMatcher struct { - ip net.IP -} - -// IPMatcher creates a Matcher for a specific IP address. -func IPMatcher(ip net.IP) Matcher { - return &ipMatcher{ - ip: ip, - } -} - -func (m *ipMatcher) Match(ip string) bool { - if m == nil { - return false - } - return m.ip.Equal(net.ParseIP(ip)) -} - -type cidrMatcher struct { - ipNet *net.IPNet -} - -// CIDRMatcher creates a Matcher for a specific CIDR notation IP address. -func CIDRMatcher(inet *net.IPNet) Matcher { - return &cidrMatcher{ - ipNet: inet, - } -} - -func (m *cidrMatcher) Match(ip string) bool { - if m == nil || m.ipNet == nil { - return false - } - return m.ipNet.Contains(net.ParseIP(ip)) -} - -type domainMatcher struct { - pattern string - glob glob.Glob -} - -// DomainMatcher creates a Matcher for a specific domain pattern, -// the pattern can be a plain domain such as 'example.com', -// a wildcard such as '*.exmaple.com' or a special wildcard '.example.com'. -func DomainMatcher(pattern string) Matcher { - p := pattern - if strings.HasPrefix(pattern, ".") { - p = pattern[1:] // trim the prefix '.' - pattern = "*" + p - } - return &domainMatcher{ - pattern: p, - glob: glob.MustCompile(pattern), - } -} - -func (m *domainMatcher) Match(domain string) bool { - if m == nil || m.glob == nil { - return false - } - - if domain == m.pattern { - return true - } - return m.glob.Match(domain) -} diff --git a/common/util/resolver/cache.go b/common/util/resolver/cache.go deleted file mode 100644 index 177fe2f..0000000 --- a/common/util/resolver/cache.go +++ /dev/null @@ -1,88 +0,0 @@ -package resolver - -import ( - "fmt" - "sync" - "time" - - "github.com/go-gost/core/logger" - "github.com/miekg/dns" -) - -type CacheKey string - -// NewCacheKey generates resolver cache key from question of dns query. -func NewCacheKey(q *dns.Question) CacheKey { - if q == nil { - return "" - } - key := fmt.Sprintf("%s%s.%s", q.Name, dns.Class(q.Qclass).String(), dns.Type(q.Qtype).String()) - return CacheKey(key) -} - -type cacheItem struct { - msg *dns.Msg - ts time.Time - ttl time.Duration -} - -type Cache struct { - m sync.Map - logger logger.Logger -} - -func NewCache() *Cache { - return &Cache{} -} - -func (c *Cache) WithLogger(logger logger.Logger) *Cache { - c.logger = logger - return c -} - -func (c *Cache) Load(key CacheKey) *dns.Msg { - v, ok := c.m.Load(key) - if !ok { - return nil - } - - item, ok := v.(*cacheItem) - if !ok { - return nil - } - - if time.Since(item.ts) > item.ttl { - c.m.Delete(key) - return nil - } - - c.logger.Debugf("hit resolver cache: %s", key) - - return item.msg.Copy() -} - -func (c *Cache) Store(key CacheKey, mr *dns.Msg, ttl time.Duration) { - if key == "" || mr == nil || ttl < 0 { - return - } - - if ttl == 0 { - for _, answer := range mr.Answer { - v := time.Duration(answer.Header().Ttl) * time.Second - if ttl == 0 || ttl > v { - ttl = v - } - } - } - if ttl == 0 { - ttl = 30 * time.Second - } - - c.m.Store(key, &cacheItem{ - msg: mr.Copy(), - ts: time.Now(), - ttl: ttl, - }) - - c.logger.Debugf("resolver cache store: %s, ttl: %v", key, ttl) -} diff --git a/common/util/resolver/resolver.go b/common/util/resolver/resolver.go deleted file mode 100644 index 74ec536..0000000 --- a/common/util/resolver/resolver.go +++ /dev/null @@ -1,30 +0,0 @@ -package resolver - -import ( - "net" - - "github.com/miekg/dns" -) - -func AddSubnetOpt(m *dns.Msg, ip net.IP) { - if m == nil || ip == nil { - return - } - - opt := new(dns.OPT) - opt.Hdr.Name = "." - opt.Hdr.Rrtype = dns.TypeOPT - e := new(dns.EDNS0_SUBNET) - e.Code = dns.EDNS0SUBNET - if ip := ip.To4(); ip != nil { - e.Family = 1 - e.SourceNetmask = 24 - e.Address = ip - } else { - e.Family = 2 - e.SourceNetmask = 128 - e.Address = ip.To16() - } - opt.Option = append(opt.Option, e) - m.Extra = append(m.Extra, opt) -} diff --git a/common/util/tls/tls.go b/common/util/tls/tls.go deleted file mode 100644 index 8fa5e3e..0000000 --- a/common/util/tls/tls.go +++ /dev/null @@ -1,178 +0,0 @@ -package tls - -import ( - "crypto/tls" - "crypto/x509" - "errors" - "io/ioutil" - "net" - "time" -) - -var ( - // DefaultConfig is a default TLS config for global use. - DefaultConfig *tls.Config -) - -// LoadServerConfig loads the certificate from cert & key files and optional client CA file. -func LoadServerConfig(certFile, keyFile, caFile string) (*tls.Config, error) { - if certFile == "" && keyFile == "" { - return DefaultConfig.Clone(), nil - } - - cert, err := tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { - return nil, err - } - - cfg := &tls.Config{Certificates: []tls.Certificate{cert}} - - pool, err := loadCA(caFile) - if err != nil { - return nil, err - } - if pool != nil { - cfg.ClientCAs = pool - cfg.ClientAuth = tls.RequireAndVerifyClientCert - } - - return cfg, nil -} - -// LoadClientConfig loads the certificate from cert & key files and optional CA file. -func LoadClientConfig(certFile, keyFile, caFile string, verify bool, serverName string) (*tls.Config, error) { - var cfg *tls.Config - - if certFile == "" && keyFile == "" { - cfg = &tls.Config{} - } else { - cert, err := tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { - return nil, err - } - - cfg = &tls.Config{ - Certificates: []tls.Certificate{cert}, - } - } - - rootCAs, err := loadCA(caFile) - if err != nil { - return nil, err - } - - cfg.RootCAs = rootCAs - cfg.ServerName = serverName - cfg.InsecureSkipVerify = !verify - - // If the root ca is given, but skip verify, we verify the certificate manually. - if cfg.RootCAs != nil && !verify { - cfg.VerifyConnection = func(state tls.ConnectionState) error { - opts := x509.VerifyOptions{ - Roots: cfg.RootCAs, - CurrentTime: time.Now(), - DNSName: "", - Intermediates: x509.NewCertPool(), - } - - certs := state.PeerCertificates - for i, cert := range certs { - if i == 0 { - continue - } - opts.Intermediates.AddCert(cert) - } - - _, err := certs[0].Verify(opts) - return err - } - } - - return cfg, nil -} - -func loadCA(caFile string) (cp *x509.CertPool, err error) { - if caFile == "" { - return - } - cp = x509.NewCertPool() - data, err := ioutil.ReadFile(caFile) - if err != nil { - return nil, err - } - if !cp.AppendCertsFromPEM(data) { - return nil, errors.New("AppendCertsFromPEM failed") - } - return -} - -// Wrap a net.Conn into a client tls connection, performing any -// additional verification as needed. -// -// As of go 1.3, crypto/tls only supports either doing no certificate -// verification, or doing full verification including of the peer's -// DNS name. For consul, we want to validate that the certificate is -// signed by a known CA, but because consul doesn't use DNS names for -// node names, we don't verify the certificate DNS names. Since go 1.3 -// no longer supports this mode of operation, we have to do it -// manually. -// -// This code is taken from consul: -// https://github.com/hashicorp/consul/blob/master/tlsutil/config.go -func WrapTLSClient(conn net.Conn, tlsConfig *tls.Config, timeout time.Duration) (net.Conn, error) { - var err error - var tlsConn *tls.Conn - - if timeout > 0 { - conn.SetDeadline(time.Now().Add(timeout)) - defer conn.SetDeadline(time.Time{}) - } - - tlsConn = tls.Client(conn, tlsConfig) - - // Otherwise perform handshake, but don't verify the domain - // - // The following is lightly-modified from the doFullHandshake - // method in https://golang.org/src/crypto/tls/handshake_client.go - if err = tlsConn.Handshake(); err != nil { - tlsConn.Close() - return nil, err - } - - // We can do this in `tls.Config.VerifyConnection`, which effective for - // other TLS protocols such as WebSocket. See `route.go:parseChainNode` - /* - // If crypto/tls is doing verification, there's no need to do our own. - if tlsConfig.InsecureSkipVerify == false { - return tlsConn, nil - } - - // Similarly if we use host's CA, we can do full handshake - if tlsConfig.RootCAs == nil { - return tlsConn, nil - } - - opts := x509.VerifyOptions{ - Roots: tlsConfig.RootCAs, - CurrentTime: time.Now(), - DNSName: "", - Intermediates: x509.NewCertPool(), - } - - certs := tlsConn.ConnectionState().PeerCertificates - for i, cert := range certs { - if i == 0 { - continue - } - opts.Intermediates.AddCert(cert) - } - - _, err = certs[0].Verify(opts) - if err != nil { - tlsConn.Close() - return nil, err - } - */ - - return tlsConn, err -} diff --git a/connector/forward/connector.go b/connector/forward/connector.go deleted file mode 100644 index 220ca6f..0000000 --- a/connector/forward/connector.go +++ /dev/null @@ -1,45 +0,0 @@ -package forward - -import ( - "context" - "net" - - "github.com/go-gost/core/connector" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.ConnectorRegistry().Register("forward", NewConnector) -} - -type forwardConnector struct { - options connector.Options -} - -func NewConnector(opts ...connector.Option) connector.Connector { - options := connector.Options{} - for _, opt := range opts { - opt(&options) - } - - return &forwardConnector{ - options: options, - } -} - -func (c *forwardConnector) Init(md md.Metadata) (err error) { - return nil -} - -func (c *forwardConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) { - log := c.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - "network": network, - "address": address, - }) - log.Infof("connect %s/%s", address, network) - - return conn, nil -} diff --git a/connector/http/connector.go b/connector/http/connector.go deleted file mode 100644 index 5b6120e..0000000 --- a/connector/http/connector.go +++ /dev/null @@ -1,129 +0,0 @@ -package http - -import ( - "bufio" - "context" - "encoding/base64" - "fmt" - "net" - "net/http" - "net/http/httputil" - "net/url" - "time" - - "github.com/go-gost/core/connector" - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.ConnectorRegistry().Register("http", NewConnector) -} - -type httpConnector struct { - md metadata - options connector.Options -} - -func NewConnector(opts ...connector.Option) connector.Connector { - options := connector.Options{} - for _, opt := range opts { - opt(&options) - } - - return &httpConnector{ - options: options, - } -} - -func (c *httpConnector) Init(md md.Metadata) (err error) { - return c.parseMetadata(md) -} - -func (c *httpConnector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) { - log := c.options.Logger.WithFields(map[string]any{ - "local": conn.LocalAddr().String(), - "remote": conn.RemoteAddr().String(), - "network": network, - "address": address, - }) - log.Infof("connect %s/%s", address, network) - - req := &http.Request{ - Method: http.MethodConnect, - URL: &url.URL{Host: address}, - Host: address, - ProtoMajor: 1, - ProtoMinor: 1, - Header: c.md.header, - } - - if req.Header == nil { - req.Header = http.Header{} - } - req.Header.Set("Proxy-Connection", "keep-alive") - - if user := c.options.Auth; user != nil { - u := user.Username() - p, _ := user.Password() - req.Header.Set("Proxy-Authorization", - "Basic "+base64.StdEncoding.EncodeToString([]byte(u+":"+p))) - } - - switch network { - case "tcp", "tcp4", "tcp6": - if _, ok := conn.(net.PacketConn); ok { - err := fmt.Errorf("tcp over udp is unsupported") - log.Error(err) - return nil, err - } - case "udp", "udp4", "udp6": - req.Header.Set("X-Gost-Protocol", "udp") - default: - err := fmt.Errorf("network %s is unsupported", network) - log.Error(err) - return nil, err - } - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpRequest(req, false) - log.Debug(string(dump)) - } - - if c.md.connectTimeout > 0 { - conn.SetDeadline(time.Now().Add(c.md.connectTimeout)) - defer conn.SetDeadline(time.Time{}) - } - - req = req.WithContext(ctx) - if err := req.Write(conn); err != nil { - return nil, err - } - - resp, err := http.ReadResponse(bufio.NewReader(conn), req) - if err != nil { - return nil, err - } - // NOTE: the server may return `Transfer-Encoding: chunked` header, - // then the Content-Length of response will be unknown (-1), - // in this case, close body will be blocked, so we leave it untouched. - // defer resp.Body.Close() - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%s", resp.Status) - } - - if network == "udp" { - addr, _ := net.ResolveUDPAddr(network, address) - return socks.UDPTunClientConn(conn, addr), nil - } - - return conn, nil -} diff --git a/connector/http/metadata.go b/connector/http/metadata.go deleted file mode 100644 index 16db7e9..0000000 --- a/connector/http/metadata.go +++ /dev/null @@ -1,32 +0,0 @@ -package http - -import ( - "net/http" - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - connectTimeout time.Duration - header http.Header -} - -func (c *httpConnector) parseMetadata(md mdata.Metadata) (err error) { - const ( - connectTimeout = "timeout" - header = "header" - ) - - c.md.connectTimeout = mdata.GetDuration(md, connectTimeout) - - if mm := mdata.GetStringMapString(md, header); len(mm) > 0 { - hd := http.Header{} - for k, v := range mm { - hd.Add(k, v) - } - c.md.header = hd - } - - return -} diff --git a/connector/socks/v4/connector.go b/connector/socks/v4/connector.go deleted file mode 100644 index f18427c..0000000 --- a/connector/socks/v4/connector.go +++ /dev/null @@ -1,123 +0,0 @@ -package v4 - -import ( - "context" - "errors" - "fmt" - "net" - "strconv" - "time" - - "github.com/go-gost/core/connector" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" - "github.com/go-gost/gosocks4" -) - -func init() { - registry.ConnectorRegistry().Register("socks4", NewConnector) - registry.ConnectorRegistry().Register("socks4a", NewConnector) -} - -type socks4Connector struct { - md metadata - options connector.Options -} - -func NewConnector(opts ...connector.Option) connector.Connector { - options := connector.Options{} - for _, opt := range opts { - opt(&options) - } - - return &socks4Connector{ - options: options, - } -} - -func (c *socks4Connector) Init(md md.Metadata) (err error) { - return c.parseMetadata(md) -} - -func (c *socks4Connector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) { - log := c.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - "network": network, - "address": address, - }) - log.Infof("connect %s/%s", address, network) - - switch network { - case "tcp", "tcp4", "tcp6": - if _, ok := conn.(net.PacketConn); ok { - err := fmt.Errorf("tcp over udp is unsupported") - log.Error(err) - return nil, err - } - default: - err := fmt.Errorf("network %s is unsupported", network) - log.Error(err) - return nil, err - } - - var addr *gosocks4.Addr - - if c.md.disable4a { - taddr, err := net.ResolveTCPAddr("tcp4", address) - if err != nil { - log.Error("resolve: ", err) - return nil, err - } - if len(taddr.IP) == 0 { - taddr.IP = net.IPv4zero - } - addr = &gosocks4.Addr{ - Type: gosocks4.AddrIPv4, - Host: taddr.IP.String(), - Port: uint16(taddr.Port), - } - } else { - host, port, err := net.SplitHostPort(address) - if err != nil { - return nil, err - } - p, _ := strconv.Atoi(port) - addr = &gosocks4.Addr{ - Type: gosocks4.AddrDomain, - Host: host, - Port: uint16(p), - } - } - - if c.md.connectTimeout > 0 { - conn.SetDeadline(time.Now().Add(c.md.connectTimeout)) - defer conn.SetDeadline(time.Time{}) - } - - var userid []byte - if c.options.Auth != nil { - userid = []byte(c.options.Auth.Username()) - } - req := gosocks4.NewRequest(gosocks4.CmdConnect, addr, userid) - if err := req.Write(conn); err != nil { - log.Error(err) - return nil, err - } - log.Debug(req) - - reply, err := gosocks4.ReadReply(conn) - if err != nil { - log.Error(err) - return nil, err - } - log.Debug(reply) - - if reply.Code != gosocks4.Granted { - err = errors.New("host unreachable") - log.Error(err) - return nil, err - } - - return conn, nil -} diff --git a/connector/socks/v4/metadata.go b/connector/socks/v4/metadata.go deleted file mode 100644 index da17e76..0000000 --- a/connector/socks/v4/metadata.go +++ /dev/null @@ -1,24 +0,0 @@ -package v4 - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - connectTimeout time.Duration - disable4a bool -} - -func (c *socks4Connector) parseMetadata(md mdata.Metadata) (err error) { - const ( - connectTimeout = "timeout" - disable4a = "disable4a" - ) - - c.md.connectTimeout = mdata.GetDuration(md, connectTimeout) - c.md.disable4a = mdata.GetBool(md, disable4a) - - return -} diff --git a/connector/socks/v5/bind.go b/connector/socks/v5/bind.go deleted file mode 100644 index ba419c7..0000000 --- a/connector/socks/v5/bind.go +++ /dev/null @@ -1,133 +0,0 @@ -package v5 - -import ( - "context" - "fmt" - "net" - - "github.com/go-gost/core/common/net/udp" - "github.com/go-gost/core/connector" - "github.com/go-gost/core/internal/util/mux" - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -// Bind implements connector.Binder. -func (c *socks5Connector) Bind(ctx context.Context, conn net.Conn, network, address string, opts ...connector.BindOption) (net.Listener, error) { - log := c.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - "network": network, - "address": address, - }) - log.Infof("bind on %s/%s", address, network) - - options := connector.BindOptions{} - for _, opt := range opts { - opt(&options) - } - - switch network { - case "tcp", "tcp4", "tcp6": - if options.Mux { - return c.muxBindTCP(ctx, conn, network, address, log) - } - return c.bindTCP(ctx, conn, network, address, log) - case "udp", "udp4", "udp6": - return c.bindUDP(ctx, conn, network, address, &options, log) - default: - err := fmt.Errorf("network %s is unsupported", network) - log.Error(err) - return nil, err - } -} - -func (c *socks5Connector) bindTCP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Listener, error) { - laddr, err := c.bind(conn, gosocks5.CmdBind, network, address, log) - if err != nil { - return nil, err - } - - return &tcpListener{ - addr: laddr, - conn: conn, - logger: log, - }, nil -} - -func (c *socks5Connector) muxBindTCP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Listener, error) { - laddr, err := c.bind(conn, socks.CmdMuxBind, network, address, log) - if err != nil { - return nil, err - } - - session, err := mux.ServerSession(conn) - if err != nil { - return nil, err - } - - return &tcpMuxListener{ - addr: laddr, - session: session, - logger: log, - }, nil -} - -func (c *socks5Connector) bindUDP(ctx context.Context, conn net.Conn, network, address string, opts *connector.BindOptions, log logger.Logger) (net.Listener, error) { - laddr, err := c.bind(conn, socks.CmdUDPTun, network, address, log) - if err != nil { - return nil, err - } - - ln := udp.NewListener(socks.UDPTunClientPacketConn(conn), - &udp.ListenConfig{ - Addr: laddr, - Backlog: opts.Backlog, - ReadQueueSize: opts.UDPDataQueueSize, - ReadBufferSize: opts.UDPDataBufferSize, - TTL: opts.UDPConnTTL, - KeepAlive: true, - Logger: log, - }) - - return ln, nil -} - -func (l *socks5Connector) bind(conn net.Conn, cmd uint8, network, address string, log logger.Logger) (net.Addr, error) { - addr := gosocks5.Addr{} - addr.ParseFrom(address) - req := gosocks5.NewRequest(cmd, &addr) - if err := req.Write(conn); err != nil { - return nil, err - } - log.Debug(req) - - // first reply, bind status - reply, err := gosocks5.ReadReply(conn) - if err != nil { - return nil, err - } - - log.Debug(reply) - - if reply.Rep != gosocks5.Succeeded { - return nil, fmt.Errorf("bind on %s/%s failed", address, network) - } - - var baddr net.Addr - switch network { - case "tcp", "tcp4", "tcp6": - baddr, err = net.ResolveTCPAddr(network, reply.Addr.String()) - case "udp", "udp4", "udp6": - baddr, err = net.ResolveUDPAddr(network, reply.Addr.String()) - default: - err = fmt.Errorf("unknown network %s", network) - } - if err != nil { - return nil, err - } - log.Debugf("bind on %s/%s OK", baddr, baddr.Network()) - - return baddr, nil -} diff --git a/connector/socks/v5/conn.go b/connector/socks/v5/conn.go deleted file mode 100644 index d11f3b5..0000000 --- a/connector/socks/v5/conn.go +++ /dev/null @@ -1,17 +0,0 @@ -package v5 - -import "net" - -type bindConn struct { - net.Conn - localAddr net.Addr - remoteAddr net.Addr -} - -func (c *bindConn) LocalAddr() net.Addr { - return c.localAddr -} - -func (c *bindConn) RemoteAddr() net.Addr { - return c.remoteAddr -} diff --git a/connector/socks/v5/connector.go b/connector/socks/v5/connector.go deleted file mode 100644 index ab06af4..0000000 --- a/connector/socks/v5/connector.go +++ /dev/null @@ -1,173 +0,0 @@ -package v5 - -import ( - "context" - "crypto/tls" - "errors" - "fmt" - "net" - "time" - - "github.com/go-gost/core/connector" - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" - "github.com/go-gost/gosocks5" -) - -func init() { - registry.ConnectorRegistry().Register("socks5", NewConnector) - registry.ConnectorRegistry().Register("socks", NewConnector) -} - -type socks5Connector struct { - selector gosocks5.Selector - md metadata - options connector.Options -} - -func NewConnector(opts ...connector.Option) connector.Connector { - options := connector.Options{} - for _, opt := range opts { - opt(&options) - } - - return &socks5Connector{ - options: options, - } -} - -func (c *socks5Connector) Init(md md.Metadata) (err error) { - if err = c.parseMetadata(md); err != nil { - return - } - - selector := &clientSelector{ - methods: []uint8{ - gosocks5.MethodNoAuth, - gosocks5.MethodUserPass, - }, - User: c.options.Auth, - TLSConfig: c.options.TLSConfig, - logger: c.options.Logger, - } - if !c.md.noTLS { - selector.methods = append(selector.methods, socks.MethodTLS) - if selector.TLSConfig == nil { - selector.TLSConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } - } - c.selector = selector - - return -} - -// Handshake implements connector.Handshaker. -func (c *socks5Connector) Handshake(ctx context.Context, conn net.Conn) (net.Conn, error) { - log := c.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - }) - - if c.md.connectTimeout > 0 { - conn.SetDeadline(time.Now().Add(c.md.connectTimeout)) - defer conn.SetDeadline(time.Time{}) - } - - cc := gosocks5.ClientConn(conn, c.selector) - if err := cc.Handleshake(); err != nil { - log.Error(err) - return nil, err - } - - return cc, nil -} - -func (c *socks5Connector) Connect(ctx context.Context, conn net.Conn, network, address string, opts ...connector.ConnectOption) (net.Conn, error) { - log := c.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - "network": network, - "address": address, - }) - log.Infof("connect %s/%s", address, network) - - if c.md.connectTimeout > 0 { - conn.SetDeadline(time.Now().Add(c.md.connectTimeout)) - defer conn.SetDeadline(time.Time{}) - } - - switch network { - case "udp", "udp4", "udp6": - return c.connectUDP(ctx, conn, network, address, log) - case "tcp", "tcp4", "tcp6": - if _, ok := conn.(net.PacketConn); ok { - err := fmt.Errorf("tcp over udp is unsupported") - log.Error(err) - return nil, err - } - default: - err := fmt.Errorf("network %s is unsupported", network) - log.Error(err) - return nil, err - } - - addr := gosocks5.Addr{} - if err := addr.ParseFrom(address); err != nil { - log.Error(err) - return nil, err - } - - req := gosocks5.NewRequest(gosocks5.CmdConnect, &addr) - if err := req.Write(conn); err != nil { - log.Error(err) - return nil, err - } - log.Debug(req) - - reply, err := gosocks5.ReadReply(conn) - if err != nil { - log.Error(err) - return nil, err - } - log.Debug(reply) - - if reply.Rep != gosocks5.Succeeded { - err = errors.New("host unreachable") - log.Error(err) - return nil, err - } - - return conn, nil -} - -func (c *socks5Connector) connectUDP(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) (net.Conn, error) { - addr, err := net.ResolveUDPAddr(network, address) - if err != nil { - log.Error(err) - return nil, err - } - - req := gosocks5.NewRequest(socks.CmdUDPTun, nil) - if err := req.Write(conn); err != nil { - log.Error(err) - return nil, err - } - log.Debug(req) - - reply, err := gosocks5.ReadReply(conn) - if err != nil { - log.Error(err) - return nil, err - } - log.Debug(reply) - - if reply.Rep != gosocks5.Succeeded { - return nil, errors.New("get socks5 UDP tunnel failure") - } - - return socks.UDPTunClientConn(conn, addr), nil -} diff --git a/connector/socks/v5/listener.go b/connector/socks/v5/listener.go deleted file mode 100644 index 000dc88..0000000 --- a/connector/socks/v5/listener.go +++ /dev/null @@ -1,102 +0,0 @@ -package v5 - -import ( - "fmt" - "net" - - "github.com/go-gost/core/internal/util/mux" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -type tcpListener struct { - addr net.Addr - conn net.Conn - logger logger.Logger -} - -func (p *tcpListener) Accept() (net.Conn, error) { - // second reply, peer connected - rep, err := gosocks5.ReadReply(p.conn) - if err != nil { - return nil, err - } - p.logger.Debug(rep) - - if rep.Rep != gosocks5.Succeeded { - return nil, fmt.Errorf("peer connect failed") - } - - raddr, err := net.ResolveTCPAddr("tcp", rep.Addr.String()) - if err != nil { - return nil, err - } - - return &bindConn{ - Conn: p.conn, - localAddr: p.addr, - remoteAddr: raddr, - }, nil -} - -func (p *tcpListener) Addr() net.Addr { - return p.addr -} - -func (p *tcpListener) Close() error { - return p.conn.Close() -} - -type tcpMuxListener struct { - addr net.Addr - session *mux.Session - logger logger.Logger -} - -func (p *tcpMuxListener) Accept() (net.Conn, error) { - cc, err := p.session.Accept() - if err != nil { - return nil, err - } - - conn, err := p.getPeerConn(cc) - if err != nil { - cc.Close() - return nil, err - } - - return conn, nil -} - -func (p *tcpMuxListener) getPeerConn(conn net.Conn) (net.Conn, error) { - // second reply, peer connected - rep, err := gosocks5.ReadReply(conn) - if err != nil { - return nil, err - } - p.logger.Debug(rep) - - if rep.Rep != gosocks5.Succeeded { - err = fmt.Errorf("peer connect failed") - return nil, err - } - - raddr, err := net.ResolveTCPAddr("tcp", rep.Addr.String()) - if err != nil { - return nil, err - } - - return &bindConn{ - Conn: conn, - localAddr: p.addr, - remoteAddr: raddr, - }, nil -} - -func (p *tcpMuxListener) Addr() net.Addr { - return p.addr -} - -func (p *tcpMuxListener) Close() error { - return p.session.Close() -} diff --git a/connector/socks/v5/metadata.go b/connector/socks/v5/metadata.go deleted file mode 100644 index 59cd528..0000000 --- a/connector/socks/v5/metadata.go +++ /dev/null @@ -1,24 +0,0 @@ -package v5 - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - connectTimeout time.Duration - noTLS bool -} - -func (c *socks5Connector) parseMetadata(md mdata.Metadata) (err error) { - const ( - connectTimeout = "timeout" - noTLS = "notls" - ) - - c.md.connectTimeout = mdata.GetDuration(md, connectTimeout) - c.md.noTLS = mdata.GetBool(md, noTLS) - - return -} diff --git a/connector/socks/v5/selector.go b/connector/socks/v5/selector.go deleted file mode 100644 index a51eb98..0000000 --- a/connector/socks/v5/selector.go +++ /dev/null @@ -1,73 +0,0 @@ -package v5 - -import ( - "crypto/tls" - "net" - "net/url" - - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -type clientSelector struct { - methods []uint8 - User *url.Userinfo - TLSConfig *tls.Config - logger logger.Logger -} - -func (s *clientSelector) Methods() []uint8 { - s.logger.Debug("methods: ", s.methods) - return s.methods -} - -func (s *clientSelector) AddMethod(methods ...uint8) { - s.methods = append(s.methods, methods...) -} - -func (s *clientSelector) Select(methods ...uint8) (method uint8) { - return -} - -func (s *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) { - s.logger.Debug("method selected: ", method) - - switch method { - case socks.MethodTLS: - conn = tls.Client(conn, s.TLSConfig) - - case gosocks5.MethodUserPass, socks.MethodTLSAuth: - if method == socks.MethodTLSAuth { - conn = tls.Client(conn, s.TLSConfig) - } - - var username, password string - if s.User != nil { - username = s.User.Username() - password, _ = s.User.Password() - } - - req := gosocks5.NewUserPassRequest(gosocks5.UserPassVer, username, password) - if err := req.Write(conn); err != nil { - s.logger.Error(err) - return nil, err - } - s.logger.Debug(req) - - resp, err := gosocks5.ReadUserPassResponse(conn) - if err != nil { - s.logger.Error(err) - return nil, err - } - s.logger.Debug(resp) - - if resp.Status != gosocks5.Succeeded { - return nil, gosocks5.ErrAuthFailure - } - case gosocks5.MethodNoAcceptable: - return nil, gosocks5.ErrBadMethod - } - - return conn, nil -} diff --git a/dialer/tcp/dialer.go b/dialer/tcp/dialer.go deleted file mode 100644 index fff87b1..0000000 --- a/dialer/tcp/dialer.go +++ /dev/null @@ -1,48 +0,0 @@ -package tcp - -import ( - "context" - "net" - - "github.com/go-gost/core/dialer" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.DialerRegistry().Register("tcp", NewDialer) -} - -type tcpDialer struct { - md metadata - logger logger.Logger -} - -func NewDialer(opts ...dialer.Option) dialer.Dialer { - options := &dialer.Options{} - for _, opt := range opts { - opt(options) - } - - return &tcpDialer{ - logger: options.Logger, - } -} - -func (d *tcpDialer) Init(md md.Metadata) (err error) { - return d.parseMetadata(md) -} - -func (d *tcpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) { - var options dialer.DialOptions - for _, opt := range opts { - opt(&options) - } - - conn, err := options.NetDialer.Dial(ctx, "tcp", addr) - if err != nil { - d.logger.Error(err) - } - return conn, err -} diff --git a/dialer/tcp/metadata.go b/dialer/tcp/metadata.go deleted file mode 100644 index 34e3789..0000000 --- a/dialer/tcp/metadata.go +++ /dev/null @@ -1,23 +0,0 @@ -package tcp - -import ( - "time" - - md "github.com/go-gost/core/metadata" -) - -const ( - dialTimeout = "dialTimeout" -) - -const ( - defaultDialTimeout = 5 * time.Second -) - -type metadata struct { - dialTimeout time.Duration -} - -func (d *tcpDialer) parseMetadata(md md.Metadata) (err error) { - return -} diff --git a/dialer/tls/dialer.go b/dialer/tls/dialer.go deleted file mode 100644 index 8d29e96..0000000 --- a/dialer/tls/dialer.go +++ /dev/null @@ -1,68 +0,0 @@ -package tls - -import ( - "context" - "crypto/tls" - "net" - "time" - - "github.com/go-gost/core/dialer" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.DialerRegistry().Register("tls", NewDialer) -} - -type tlsDialer struct { - md metadata - logger logger.Logger - options dialer.Options -} - -func NewDialer(opts ...dialer.Option) dialer.Dialer { - options := dialer.Options{} - for _, opt := range opts { - opt(&options) - } - - return &tlsDialer{ - logger: options.Logger, - options: options, - } -} - -func (d *tlsDialer) Init(md md.Metadata) (err error) { - return d.parseMetadata(md) -} - -func (d *tlsDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) { - var options dialer.DialOptions - for _, opt := range opts { - opt(&options) - } - - conn, err := options.NetDialer.Dial(ctx, "tcp", addr) - if err != nil { - d.logger.Error(err) - } - return conn, err -} - -// Handshake implements dialer.Handshaker -func (d *tlsDialer) Handshake(ctx context.Context, conn net.Conn, options ...dialer.HandshakeOption) (net.Conn, error) { - if d.md.handshakeTimeout > 0 { - conn.SetDeadline(time.Now().Add(d.md.handshakeTimeout)) - defer conn.SetDeadline(time.Time{}) - } - - tlsConn := tls.Client(conn, d.options.TLSConfig) - if err := tlsConn.HandshakeContext(ctx); err != nil { - conn.Close() - return nil, err - } - - return tlsConn, nil -} diff --git a/dialer/tls/metadata.go b/dialer/tls/metadata.go deleted file mode 100644 index e75c270..0000000 --- a/dialer/tls/metadata.go +++ /dev/null @@ -1,21 +0,0 @@ -package tls - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - handshakeTimeout time.Duration -} - -func (d *tlsDialer) parseMetadata(md mdata.Metadata) (err error) { - const ( - handshakeTimeout = "handshakeTimeout" - ) - - d.md.handshakeTimeout = mdata.GetDuration(md, handshakeTimeout) - - return -} diff --git a/dialer/udp/conn.go b/dialer/udp/conn.go deleted file mode 100644 index 33e962d..0000000 --- a/dialer/udp/conn.go +++ /dev/null @@ -1,17 +0,0 @@ -package udp - -import "net" - -type conn struct { - *net.UDPConn -} - -func (c *conn) WriteTo(b []byte, addr net.Addr) (int, error) { - return c.UDPConn.Write(b) -} - -func (c *conn) ReadFrom(b []byte) (n int, addr net.Addr, err error) { - n, err = c.UDPConn.Read(b) - addr = c.RemoteAddr() - return -} diff --git a/dialer/udp/dialer.go b/dialer/udp/dialer.go deleted file mode 100644 index 1bae731..0000000 --- a/dialer/udp/dialer.go +++ /dev/null @@ -1,50 +0,0 @@ -package udp - -import ( - "context" - "net" - - "github.com/go-gost/core/dialer" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.DialerRegistry().Register("udp", NewDialer) -} - -type udpDialer struct { - md metadata - logger logger.Logger -} - -func NewDialer(opts ...dialer.Option) dialer.Dialer { - options := &dialer.Options{} - for _, opt := range opts { - opt(options) - } - - return &udpDialer{ - logger: options.Logger, - } -} - -func (d *udpDialer) Init(md md.Metadata) (err error) { - return d.parseMetadata(md) -} - -func (d *udpDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialOption) (net.Conn, error) { - var options dialer.DialOptions - for _, opt := range opts { - opt(&options) - } - - c, err := options.NetDialer.Dial(ctx, "udp", addr) - if err != nil { - return nil, err - } - return &conn{ - UDPConn: c.(*net.UDPConn), - }, nil -} diff --git a/dialer/udp/metadata.go b/dialer/udp/metadata.go deleted file mode 100644 index 23bd5e2..0000000 --- a/dialer/udp/metadata.go +++ /dev/null @@ -1,23 +0,0 @@ -package udp - -import ( - "time" - - md "github.com/go-gost/core/metadata" -) - -const ( - dialTimeout = "dialTimeout" -) - -const ( - defaultDialTimeout = 5 * time.Second -) - -type metadata struct { - dialTimeout time.Duration -} - -func (d *udpDialer) parseMetadata(md md.Metadata) (err error) { - return -} diff --git a/go.mod b/go.mod index 8db320a..4bb3109 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,8 @@ module github.com/go-gost/core go 1.18 require ( - github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d - github.com/go-gost/gosocks4 v0.0.1 - github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 - github.com/gobwas/glob v0.2.3 - github.com/miekg/dns v1.1.47 github.com/prometheus/client_golang v1.12.1 - github.com/sirupsen/logrus v1.8.1 - github.com/xtaci/smux v1.5.16 - golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 ) require ( @@ -23,11 +16,5 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/stretchr/testify v1.7.0 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/tools v0.1.10 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 067e0cb..3df39b5 100644 --- a/go.sum +++ b/go.sum @@ -38,8 +38,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -54,7 +52,6 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -63,10 +60,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 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/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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -74,8 +67,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -152,8 +143,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.1.47 h1:J9bWiXbqMbnZPcY8Qi2E3EWIBsIm6MZzzJB9VRg5gL8= -github.com/miekg/dns v1.1.47/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -164,7 +153,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -192,21 +180,14 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/xtaci/smux v1.5.16 h1:FBPYOkW8ZTjLKUM4LI4xnnuuDC8CQ/dB04HD519WoEk= -github.com/xtaci/smux v1.5.16/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -248,9 +229,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/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.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= 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= @@ -279,11 +257,7 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 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= @@ -299,8 +273,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -314,7 +286,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -335,14 +306,10 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc= -golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= @@ -393,9 +360,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= 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= @@ -489,9 +453,6 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/handler/auto/handler.go b/handler/auto/handler.go deleted file mode 100644 index 597531d..0000000 --- a/handler/auto/handler.go +++ /dev/null @@ -1,115 +0,0 @@ -package auto - -import ( - "bufio" - "context" - "net" - "time" - - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/handler" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" - "github.com/go-gost/gosocks4" - "github.com/go-gost/gosocks5" -) - -func init() { - registry.HandlerRegistry().Register("auto", NewHandler) -} - -type autoHandler struct { - httpHandler handler.Handler - socks4Handler handler.Handler - socks5Handler handler.Handler - options handler.Options -} - -func NewHandler(opts ...handler.Option) handler.Handler { - options := handler.Options{} - for _, opt := range opts { - opt(&options) - } - - h := &autoHandler{ - options: options, - } - - if f := registry.HandlerRegistry().Get("http"); f != nil { - v := append(opts, - handler.LoggerOption(options.Logger.WithFields(map[string]any{"type": "http"}))) - h.httpHandler = f(v...) - } - if f := registry.HandlerRegistry().Get("socks4"); f != nil { - v := append(opts, - handler.LoggerOption(options.Logger.WithFields(map[string]any{"type": "socks4"}))) - h.socks4Handler = f(v...) - } - if f := registry.HandlerRegistry().Get("socks5"); f != nil { - v := append(opts, - handler.LoggerOption(options.Logger.WithFields(map[string]any{"type": "socks5"}))) - h.socks5Handler = f(v...) - } - - return h -} - -func (h *autoHandler) Init(md md.Metadata) error { - if h.httpHandler != nil { - if err := h.httpHandler.Init(md); err != nil { - return err - } - } - if h.socks4Handler != nil { - if err := h.socks4Handler.Init(md); err != nil { - return err - } - } - if h.socks5Handler != nil { - if err := h.socks5Handler.Init(md); err != nil { - return err - } - } - - return nil -} - -func (h *autoHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error { - log := h.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - }) - - start := time.Now() - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) - defer func() { - log.WithFields(map[string]any{ - "duration": time.Since(start), - }).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr()) - }() - - br := bufio.NewReader(conn) - b, err := br.Peek(1) - if err != nil { - log.Error(err) - conn.Close() - return err - } - - conn = netpkg.NewBufferReaderConn(conn, br) - switch b[0] { - case gosocks4.Ver4: // socks4 - if h.socks4Handler != nil { - return h.socks4Handler.Handle(ctx, conn) - } - case gosocks5.Ver5: // socks5 - if h.socks5Handler != nil { - return h.socks5Handler.Handle(ctx, conn) - } - default: // http - if h.httpHandler != nil { - return h.httpHandler.Handle(ctx, conn) - } - } - return nil -} diff --git a/handler/forward/local/handler.go b/handler/forward/local/handler.go deleted file mode 100644 index e281864..0000000 --- a/handler/forward/local/handler.go +++ /dev/null @@ -1,117 +0,0 @@ -package local - -import ( - "context" - "errors" - "fmt" - "net" - "time" - - "github.com/go-gost/core/chain" - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/handler" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.HandlerRegistry().Register("tcp", NewHandler) - registry.HandlerRegistry().Register("udp", NewHandler) - registry.HandlerRegistry().Register("forward", NewHandler) -} - -type forwardHandler struct { - group *chain.NodeGroup - router *chain.Router - md metadata - options handler.Options -} - -func NewHandler(opts ...handler.Option) handler.Handler { - options := handler.Options{} - for _, opt := range opts { - opt(&options) - } - - return &forwardHandler{ - options: options, - } -} - -func (h *forwardHandler) Init(md md.Metadata) (err error) { - if err = h.parseMetadata(md); err != nil { - return - } - - if h.group == nil { - // dummy node used by relay connector. - h.group = chain.NewNodeGroup(&chain.Node{Name: "dummy", Addr: ":0"}) - } - - h.router = h.options.Router - if h.router == nil { - h.router = (&chain.Router{}).WithLogger(h.options.Logger) - } - - return -} - -// Forward implements handler.Forwarder. -func (h *forwardHandler) Forward(group *chain.NodeGroup) { - h.group = group -} - -func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error { - defer conn.Close() - - start := time.Now() - log := h.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - }) - - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) - defer func() { - log.WithFields(map[string]any{ - "duration": time.Since(start), - }).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr()) - }() - - target := h.group.Next() - if target == nil { - err := errors.New("target not available") - log.Error(err) - return err - } - - network := "tcp" - if _, ok := conn.(net.PacketConn); ok { - network = "udp" - } - - log = log.WithFields(map[string]any{ - "dst": fmt.Sprintf("%s/%s", target.Addr, network), - }) - - log.Infof("%s >> %s", conn.RemoteAddr(), target.Addr) - - cc, err := h.router.Dial(ctx, network, target.Addr) - if err != nil { - log.Error(err) - // TODO: the router itself may be failed due to the failed node in the router, - // the dead marker may be a wrong operation. - target.Marker.Mark() - return err - } - defer cc.Close() - target.Marker.Reset() - - t := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), target.Addr) - netpkg.Transport(conn, cc) - log.WithFields(map[string]any{ - "duration": time.Since(t), - }).Infof("%s >-< %s", conn.RemoteAddr(), target.Addr) - - return nil -} diff --git a/handler/forward/local/metadata.go b/handler/forward/local/metadata.go deleted file mode 100644 index e9598dd..0000000 --- a/handler/forward/local/metadata.go +++ /dev/null @@ -1,20 +0,0 @@ -package local - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - readTimeout time.Duration -} - -func (h *forwardHandler) parseMetadata(md mdata.Metadata) (err error) { - const ( - readTimeout = "readTimeout" - ) - - h.md.readTimeout = mdata.GetDuration(md, readTimeout) - return -} diff --git a/handler/forward/remote/handler.go b/handler/forward/remote/handler.go deleted file mode 100644 index 3f31e12..0000000 --- a/handler/forward/remote/handler.go +++ /dev/null @@ -1,111 +0,0 @@ -package remote - -import ( - "context" - "errors" - "fmt" - "net" - "time" - - "github.com/go-gost/core/chain" - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/handler" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.HandlerRegistry().Register("rtcp", NewHandler) - registry.HandlerRegistry().Register("rudp", NewHandler) -} - -type forwardHandler struct { - group *chain.NodeGroup - router *chain.Router - md metadata - options handler.Options -} - -func NewHandler(opts ...handler.Option) handler.Handler { - options := handler.Options{} - for _, opt := range opts { - opt(&options) - } - - return &forwardHandler{ - options: options, - } -} - -func (h *forwardHandler) Init(md md.Metadata) (err error) { - if err = h.parseMetadata(md); err != nil { - return - } - - h.router = h.options.Router - if h.router == nil { - h.router = (&chain.Router{}).WithLogger(h.options.Logger) - } - - return -} - -// Forward implements handler.Forwarder. -func (h *forwardHandler) Forward(group *chain.NodeGroup) { - h.group = group -} - -func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error { - defer conn.Close() - - start := time.Now() - log := h.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - }) - - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) - defer func() { - log.WithFields(map[string]any{ - "duration": time.Since(start), - }).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr()) - }() - - target := h.group.Next() - if target == nil { - err := errors.New("target not available") - log.Error(err) - return err - } - - network := "tcp" - if _, ok := conn.(net.PacketConn); ok { - network = "udp" - } - - log = log.WithFields(map[string]any{ - "dst": fmt.Sprintf("%s/%s", target.Addr, network), - }) - - log.Infof("%s >> %s", conn.RemoteAddr(), target.Addr) - - cc, err := h.router.Dial(ctx, network, target.Addr) - if err != nil { - log.Error(err) - // TODO: the router itself may be failed due to the failed node in the router, - // the dead marker may be a wrong operation. - target.Marker.Mark() - return err - } - defer cc.Close() - target.Marker.Reset() - - t := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), target.Addr) - netpkg.Transport(conn, cc) - log.WithFields(map[string]any{ - "duration": time.Since(t), - }).Infof("%s >-< %s", conn.RemoteAddr(), target.Addr) - - return nil -} diff --git a/handler/forward/remote/metadata.go b/handler/forward/remote/metadata.go deleted file mode 100644 index 474f6d2..0000000 --- a/handler/forward/remote/metadata.go +++ /dev/null @@ -1,20 +0,0 @@ -package remote - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - readTimeout time.Duration -} - -func (h *forwardHandler) parseMetadata(md mdata.Metadata) (err error) { - const ( - readTimeout = "readTimeout" - ) - - h.md.readTimeout = mdata.GetDuration(md, readTimeout) - return -} diff --git a/handler/http/handler.go b/handler/http/handler.go deleted file mode 100644 index a45fd72..0000000 --- a/handler/http/handler.go +++ /dev/null @@ -1,337 +0,0 @@ -package http - -import ( - "bufio" - "context" - "encoding/base64" - "encoding/binary" - "errors" - "hash/crc32" - "net" - "net/http" - "net/http/httputil" - "os" - "strconv" - "strings" - "time" - - "github.com/asaskevich/govalidator" - "github.com/go-gost/core/chain" - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/handler" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" -) - -func init() { - registry.HandlerRegistry().Register("http", NewHandler) -} - -type httpHandler struct { - router *chain.Router - md metadata - options handler.Options -} - -func NewHandler(opts ...handler.Option) handler.Handler { - options := handler.Options{} - for _, opt := range opts { - opt(&options) - } - - return &httpHandler{ - options: options, - } -} - -func (h *httpHandler) Init(md md.Metadata) error { - if err := h.parseMetadata(md); err != nil { - return err - } - - h.router = h.options.Router - if h.router == nil { - h.router = (&chain.Router{}).WithLogger(h.options.Logger) - } - - return nil -} - -func (h *httpHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error { - defer conn.Close() - - start := time.Now() - log := h.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - }) - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) - defer func() { - log.WithFields(map[string]any{ - "duration": time.Since(start), - }).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr()) - }() - - req, err := http.ReadRequest(bufio.NewReader(conn)) - if err != nil { - log.Error(err) - return err - } - defer req.Body.Close() - - return h.handleRequest(ctx, conn, req, log) -} - -func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *http.Request, log logger.Logger) error { - if h.md.sni && !req.URL.IsAbs() && govalidator.IsDNSName(req.Host) { - req.URL.Scheme = "http" - } - - network := req.Header.Get("X-Gost-Protocol") - if network != "udp" { - network = "tcp" - } - - // Try to get the actual host. - // Compatible with GOST 2.x. - if v := req.Header.Get("Gost-Target"); v != "" { - if h, err := h.decodeServerName(v); err == nil { - req.Host = h - } - } - req.Header.Del("Gost-Target") - - if v := req.Header.Get("X-Gost-Target"); v != "" { - if h, err := h.decodeServerName(v); err == nil { - req.Host = h - } - } - req.Header.Del("X-Gost-Target") - - addr := req.Host - if _, port, _ := net.SplitHostPort(addr); port == "" { - addr = net.JoinHostPort(addr, "80") - } - - fields := map[string]any{ - "dst": addr, - } - if u, _, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"), log); u != "" { - fields["user"] = u - } - log = log.WithFields(fields) - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpRequest(req, false) - log.Debug(string(dump)) - } - log.Infof("%s >> %s", conn.RemoteAddr(), addr) - - resp := &http.Response{ - ProtoMajor: 1, - ProtoMinor: 1, - Header: h.md.header, - } - if resp.Header == nil { - resp.Header = http.Header{} - } - - if h.options.Bypass != nil && h.options.Bypass.Contains(addr) { - resp.StatusCode = http.StatusForbidden - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - log.Info("bypass: ", addr) - - return resp.Write(conn) - } - - if !h.authenticate(conn, req, resp, log) { - return nil - } - - if network == "udp" { - return h.handleUDP(ctx, conn, log) - } - - if req.Method == "PRI" || - (req.Method != http.MethodConnect && req.URL.Scheme != "http") { - resp.StatusCode = http.StatusBadRequest - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - - return resp.Write(conn) - } - - req.Header.Del("Proxy-Authorization") - - cc, err := h.router.Dial(ctx, network, addr) - if err != nil { - resp.StatusCode = http.StatusServiceUnavailable - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - resp.Write(conn) - return err - } - defer cc.Close() - - if req.Method == http.MethodConnect { - resp.StatusCode = http.StatusOK - resp.Status = "200 Connection established" - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - if err = resp.Write(conn); err != nil { - log.Error(err) - return err - } - } else { - req.Header.Del("Proxy-Connection") - if err = req.Write(cc); err != nil { - log.Error(err) - return err - } - } - - start := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), addr) - netpkg.Transport(conn, cc) - log.WithFields(map[string]any{ - "duration": time.Since(start), - }).Infof("%s >-< %s", conn.RemoteAddr(), addr) - - return nil -} - -func (h *httpHandler) decodeServerName(s string) (string, error) { - b, err := base64.RawURLEncoding.DecodeString(s) - if err != nil { - return "", err - } - if len(b) < 4 { - return "", errors.New("invalid name") - } - v, err := base64.RawURLEncoding.DecodeString(string(b[4:])) - if err != nil { - return "", err - } - if crc32.ChecksumIEEE(v) != binary.BigEndian.Uint32(b[:4]) { - return "", errors.New("invalid name") - } - return string(v), nil -} - -func (h *httpHandler) basicProxyAuth(proxyAuth string, log logger.Logger) (username, password string, ok bool) { - if proxyAuth == "" { - return - } - - if !strings.HasPrefix(proxyAuth, "Basic ") { - return - } - c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(proxyAuth, "Basic ")) - if err != nil { - return - } - cs := string(c) - s := strings.IndexByte(cs, ':') - if s < 0 { - return - } - - 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) { - u, p, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization"), log) - if h.options.Auther == nil || h.options.Auther.Authenticate(u, p) { - return true - } - - pr := h.md.probeResistance - // probing resistance is enabled, and knocking host is mismatch. - if pr != nil && (pr.Knock == "" || !strings.EqualFold(req.URL.Hostname(), pr.Knock)) { - resp.StatusCode = http.StatusServiceUnavailable // default status code - - switch pr.Type { - case "code": - resp.StatusCode, _ = strconv.Atoi(pr.Value) - case "web": - url := pr.Value - if !strings.HasPrefix(url, "http") { - url = "http://" + url - } - r, err := http.Get(url) - if err != nil { - log.Error(err) - break - } - resp = r - defer resp.Body.Close() - case "host": - cc, err := net.Dial("tcp", pr.Value) - if err != nil { - log.Error(err) - break - } - defer cc.Close() - - req.Write(cc) - netpkg.Transport(conn, cc) - return - case "file": - f, _ := os.Open(pr.Value) - if f != nil { - defer f.Close() - - resp.StatusCode = http.StatusOK - if finfo, _ := f.Stat(); finfo != nil { - resp.ContentLength = finfo.Size() - } - resp.Header.Set("Content-Type", "text/html") - resp.Body = f - } - } - } - - if resp.Header == nil { - resp.Header = http.Header{} - } - if resp.StatusCode == 0 { - resp.StatusCode = http.StatusProxyAuthRequired - resp.Header.Add("Proxy-Authenticate", "Basic realm=\"gost\"") - if strings.ToLower(req.Header.Get("Proxy-Connection")) == "keep-alive" { - // XXX libcurl will keep sending auth request in same conn - // which we don't supported yet. - resp.Header.Add("Connection", "close") - resp.Header.Add("Proxy-Connection", "close") - } - - log.Info("proxy authentication required") - } else { - resp.Header.Set("Server", "nginx/1.20.1") - resp.Header.Set("Date", time.Now().Format(http.TimeFormat)) - if resp.StatusCode == http.StatusOK { - resp.Header.Set("Connection", "keep-alive") - } - } - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - - resp.Write(conn) - return -} diff --git a/handler/http/metadata.go b/handler/http/metadata.go deleted file mode 100644 index b20b4ba..0000000 --- a/handler/http/metadata.go +++ /dev/null @@ -1,53 +0,0 @@ -package http - -import ( - "net/http" - "strings" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - probeResistance *probeResistance - sni bool - enableUDP bool - header http.Header -} - -func (h *httpHandler) parseMetadata(md mdata.Metadata) error { - const ( - header = "header" - probeResistKey = "probeResistance" - knock = "knock" - sni = "sni" - enableUDP = "udp" - ) - - if m := mdata.GetStringMapString(md, header); len(m) > 0 { - hd := http.Header{} - for k, v := range m { - hd.Add(k, v) - } - h.md.header = hd - } - - if v := mdata.GetString(md, probeResistKey); v != "" { - if ss := strings.SplitN(v, ":", 2); len(ss) == 2 { - h.md.probeResistance = &probeResistance{ - Type: ss[0], - Value: ss[1], - Knock: mdata.GetString(md, knock), - } - } - } - h.md.sni = mdata.GetBool(md, sni) - h.md.enableUDP = mdata.GetBool(md, enableUDP) - - return nil -} - -type probeResistance struct { - Type string - Value string - Knock string -} diff --git a/handler/http/udp.go b/handler/http/udp.go deleted file mode 100644 index dba9db5..0000000 --- a/handler/http/udp.go +++ /dev/null @@ -1,80 +0,0 @@ -package http - -import ( - "context" - "errors" - "net" - "net/http" - "net/http/httputil" - "time" - - "github.com/go-gost/core/common/net/relay" - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" -) - -func (h *httpHandler) handleUDP(ctx context.Context, conn net.Conn, log logger.Logger) error { - log = log.WithFields(map[string]any{ - "cmd": "udp", - }) - - resp := &http.Response{ - ProtoMajor: 1, - ProtoMinor: 1, - Header: h.md.header, - } - if resp.Header == nil { - resp.Header = http.Header{} - } - - if !h.md.enableUDP { - resp.StatusCode = http.StatusForbidden - - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - - log.Error("http: UDP relay is disabled") - - return resp.Write(conn) - } - - resp.StatusCode = http.StatusOK - if log.IsLevelEnabled(logger.DebugLevel) { - dump, _ := httputil.DumpResponse(resp, false) - log.Debug(string(dump)) - } - if err := resp.Write(conn); err != nil { - log.Error(err) - return err - } - - // obtain a udp connection - c, err := h.router.Dial(ctx, "udp", "") // UDP association - if err != nil { - log.Error(err) - return err - } - defer c.Close() - - pc, ok := c.(net.PacketConn) - if !ok { - err = errors.New("wrong connection type") - log.Error(err) - return err - } - - relay := relay.NewUDPRelay(socks.UDPTunServerConn(conn), pc). - WithBypass(h.options.Bypass). - WithLogger(log) - - t := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), pc.LocalAddr()) - relay.Run() - log.WithFields(map[string]any{ - "duration": time.Since(t), - }).Infof("%s >-< %s", conn.RemoteAddr(), pc.LocalAddr()) - - return nil -} diff --git a/handler/socks/v4/handler.go b/handler/socks/v4/handler.go deleted file mode 100644 index 3d0c9ce..0000000 --- a/handler/socks/v4/handler.go +++ /dev/null @@ -1,152 +0,0 @@ -package v4 - -import ( - "context" - "errors" - "net" - "time" - - "github.com/go-gost/core/chain" - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/handler" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" - "github.com/go-gost/gosocks4" -) - -var ( - ErrUnknownCmd = errors.New("socks4: unknown command") - ErrUnimplemented = errors.New("socks4: unimplemented") -) - -func init() { - registry.HandlerRegistry().Register("socks4", NewHandler) - registry.HandlerRegistry().Register("socks4a", NewHandler) -} - -type socks4Handler struct { - router *chain.Router - md metadata - options handler.Options -} - -func NewHandler(opts ...handler.Option) handler.Handler { - options := handler.Options{} - for _, opt := range opts { - opt(&options) - } - - return &socks4Handler{ - options: options, - } -} - -func (h *socks4Handler) Init(md md.Metadata) (err error) { - if err := h.parseMetadata(md); err != nil { - return err - } - - h.router = h.options.Router - if h.router == nil { - h.router = (&chain.Router{}).WithLogger(h.options.Logger) - } - - return nil -} - -func (h *socks4Handler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error { - defer conn.Close() - - start := time.Now() - - log := h.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - }) - - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) - defer func() { - log.WithFields(map[string]any{ - "duration": time.Since(start), - }).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr()) - }() - - if h.md.readTimeout > 0 { - conn.SetReadDeadline(time.Now().Add(h.md.readTimeout)) - } - - req, err := gosocks4.ReadRequest(conn) - if err != nil { - log.Error(err) - return err - } - log.Debug(req) - - conn.SetReadDeadline(time.Time{}) - - if h.options.Auther != nil && - !h.options.Auther.Authenticate(string(req.Userid), "") { - resp := gosocks4.NewReply(gosocks4.RejectedUserid, nil) - log.Debug(resp) - return resp.Write(conn) - } - - switch req.Cmd { - case gosocks4.CmdConnect: - return h.handleConnect(ctx, conn, req, log) - case gosocks4.CmdBind: - return h.handleBind(ctx, conn, req) - default: - err = ErrUnknownCmd - log.Error(err) - return err - } -} - -func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *gosocks4.Request, log logger.Logger) error { - addr := req.Addr.String() - - log = log.WithFields(map[string]any{ - "dst": addr, - }) - log.Infof("%s >> %s", conn.RemoteAddr(), addr) - - if h.options.Bypass != nil && h.options.Bypass.Contains(addr) { - resp := gosocks4.NewReply(gosocks4.Rejected, nil) - log.Debug(resp) - log.Info("bypass: ", addr) - return resp.Write(conn) - } - - cc, err := h.router.Dial(ctx, "tcp", addr) - if err != nil { - resp := gosocks4.NewReply(gosocks4.Failed, nil) - resp.Write(conn) - log.Debug(resp) - return err - } - - defer cc.Close() - - resp := gosocks4.NewReply(gosocks4.Granted, nil) - if err := resp.Write(conn); err != nil { - log.Error(err) - return err - } - log.Debug(resp) - - t := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), addr) - netpkg.Transport(conn, cc) - log.WithFields(map[string]any{ - "duration": time.Since(t), - }).Infof("%s >-< %s", conn.RemoteAddr(), addr) - - return nil -} - -func (h *socks4Handler) handleBind(ctx context.Context, conn net.Conn, req *gosocks4.Request) error { - // TODO: bind - return ErrUnimplemented -} diff --git a/handler/socks/v4/metadata.go b/handler/socks/v4/metadata.go deleted file mode 100644 index 99d4395..0000000 --- a/handler/socks/v4/metadata.go +++ /dev/null @@ -1,20 +0,0 @@ -package v4 - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - readTimeout time.Duration -} - -func (h *socks4Handler) parseMetadata(md mdata.Metadata) (err error) { - const ( - readTimeout = "readTimeout" - ) - - h.md.readTimeout = mdata.GetDuration(md, readTimeout) - return -} diff --git a/handler/socks/v5/bind.go b/handler/socks/v5/bind.go deleted file mode 100644 index 89299fc..0000000 --- a/handler/socks/v5/bind.go +++ /dev/null @@ -1,149 +0,0 @@ -package v5 - -import ( - "context" - "fmt" - "net" - "time" - - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -func (h *socks5Handler) handleBind(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error { - log = log.WithFields(map[string]any{ - "dst": fmt.Sprintf("%s/%s", address, network), - "cmd": "bind", - }) - - log.Infof("%s >> %s", conn.RemoteAddr(), address) - - if !h.md.enableBind { - reply := gosocks5.NewReply(gosocks5.NotAllowed, nil) - log.Debug(reply) - log.Error("socks5: BIND is disabled") - return reply.Write(conn) - } - - // BIND does not support chain. - return h.bindLocal(ctx, conn, network, address, log) -} - -func (h *socks5Handler) bindLocal(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error { - ln, err := net.Listen(network, address) // strict mode: if the port already in use, it will return error - if err != nil { - log.Error(err) - reply := gosocks5.NewReply(gosocks5.Failure, nil) - if err := reply.Write(conn); err != nil { - log.Error(err) - } - log.Debug(reply) - return err - } - - socksAddr := gosocks5.Addr{} - if err := socksAddr.ParseFrom(ln.Addr().String()); err != nil { - log.Warn(err) - } - - // Issue: may not reachable when host has multi-interface - socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) - socksAddr.Type = 0 - reply := gosocks5.NewReply(gosocks5.Succeeded, &socksAddr) - if err := reply.Write(conn); err != nil { - log.Error(err) - ln.Close() - return err - } - log.Debug(reply) - - log = log.WithFields(map[string]any{ - "bind": fmt.Sprintf("%s/%s", ln.Addr(), ln.Addr().Network()), - }) - - log.Debugf("bind on %s OK", ln.Addr()) - - h.serveBind(ctx, conn, ln, log) - return nil -} - -func (h *socks5Handler) serveBind(ctx context.Context, conn net.Conn, ln net.Listener, log logger.Logger) { - var rc net.Conn - accept := func() <-chan error { - errc := make(chan error, 1) - - go func() { - defer close(errc) - defer ln.Close() - - c, err := ln.Accept() - if err != nil { - errc <- err - } - rc = c - }() - - return errc - } - - pc1, pc2 := net.Pipe() - pipe := func() <-chan error { - errc := make(chan error, 1) - - go func() { - defer close(errc) - defer pc1.Close() - - errc <- netpkg.Transport(conn, pc1) - }() - - return errc - } - - defer pc2.Close() - - select { - case err := <-accept(): - if err != nil { - log.Error(err) - - reply := gosocks5.NewReply(gosocks5.Failure, nil) - if err := reply.Write(pc2); err != nil { - log.Error(err) - } - log.Debug(reply) - - return - } - defer rc.Close() - - log.Debugf("peer %s accepted", rc.RemoteAddr()) - - log = log.WithFields(map[string]any{ - "local": rc.LocalAddr().String(), - "remote": rc.RemoteAddr().String(), - }) - - raddr := gosocks5.Addr{} - raddr.ParseFrom(rc.RemoteAddr().String()) - reply := gosocks5.NewReply(gosocks5.Succeeded, &raddr) - if err := reply.Write(pc2); err != nil { - log.Error(err) - } - log.Debug(reply) - - start := time.Now() - log.Infof("%s <-> %s", rc.LocalAddr(), rc.RemoteAddr()) - netpkg.Transport(pc2, rc) - log.WithFields(map[string]any{"duration": time.Since(start)}). - Infof("%s >-< %s", rc.LocalAddr(), rc.RemoteAddr()) - - case err := <-pipe(): - if err != nil { - log.Error(err) - } - ln.Close() - return - } -} diff --git a/handler/socks/v5/connect.go b/handler/socks/v5/connect.go deleted file mode 100644 index 88a8deb..0000000 --- a/handler/socks/v5/connect.go +++ /dev/null @@ -1,53 +0,0 @@ -package v5 - -import ( - "context" - "fmt" - "net" - "time" - - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error { - log = log.WithFields(map[string]any{ - "dst": fmt.Sprintf("%s/%s", address, network), - "cmd": "connect", - }) - log.Infof("%s >> %s", conn.RemoteAddr(), address) - - if h.options.Bypass != nil && h.options.Bypass.Contains(address) { - resp := gosocks5.NewReply(gosocks5.NotAllowed, nil) - log.Debug(resp) - log.Info("bypass: ", address) - return resp.Write(conn) - } - - cc, err := h.router.Dial(ctx, network, address) - if err != nil { - resp := gosocks5.NewReply(gosocks5.NetUnreachable, nil) - log.Debug(resp) - resp.Write(conn) - return err - } - - defer cc.Close() - - resp := gosocks5.NewReply(gosocks5.Succeeded, nil) - if err := resp.Write(conn); err != nil { - log.Error(err) - return err - } - log.Debug(resp) - - t := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), address) - netpkg.Transport(conn, cc) - log.WithFields(map[string]any{ - "duration": time.Since(t), - }).Infof("%s >-< %s", conn.RemoteAddr(), address) - - return nil -} diff --git a/handler/socks/v5/handler.go b/handler/socks/v5/handler.go deleted file mode 100644 index ccc55c6..0000000 --- a/handler/socks/v5/handler.go +++ /dev/null @@ -1,115 +0,0 @@ -package v5 - -import ( - "context" - "errors" - "net" - "time" - - "github.com/go-gost/core/chain" - "github.com/go-gost/core/handler" - "github.com/go-gost/core/internal/util/socks" - md "github.com/go-gost/core/metadata" - "github.com/go-gost/core/registry" - "github.com/go-gost/gosocks5" -) - -var ( - ErrUnknownCmd = errors.New("socks5: unknown command") -) - -func init() { - registry.HandlerRegistry().Register("socks5", NewHandler) - registry.HandlerRegistry().Register("socks", NewHandler) -} - -type socks5Handler struct { - selector gosocks5.Selector - router *chain.Router - md metadata - options handler.Options -} - -func NewHandler(opts ...handler.Option) handler.Handler { - options := handler.Options{} - for _, opt := range opts { - opt(&options) - } - - return &socks5Handler{ - options: options, - } -} - -func (h *socks5Handler) Init(md md.Metadata) (err error) { - if err = h.parseMetadata(md); err != nil { - return - } - - h.router = h.options.Router - if h.router == nil { - h.router = (&chain.Router{}).WithLogger(h.options.Logger) - } - - h.selector = &serverSelector{ - Authenticator: h.options.Auther, - TLSConfig: h.options.TLSConfig, - logger: h.options.Logger, - noTLS: h.md.noTLS, - } - - return -} - -func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error { - defer conn.Close() - - start := time.Now() - - log := h.options.Logger.WithFields(map[string]any{ - "remote": conn.RemoteAddr().String(), - "local": conn.LocalAddr().String(), - }) - - log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr()) - defer func() { - log.WithFields(map[string]any{ - "duration": time.Since(start), - }).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr()) - }() - - if h.md.readTimeout > 0 { - conn.SetReadDeadline(time.Now().Add(h.md.readTimeout)) - } - - conn = gosocks5.ServerConn(conn, h.selector) - req, err := gosocks5.ReadRequest(conn) - if err != nil { - log.Error(err) - return err - } - log.Debug(req) - conn.SetReadDeadline(time.Time{}) - - address := req.Addr.String() - - switch req.Cmd { - case gosocks5.CmdConnect: - return h.handleConnect(ctx, conn, "tcp", address, log) - case gosocks5.CmdBind: - return h.handleBind(ctx, conn, "tcp", address, log) - case socks.CmdMuxBind: - return h.handleMuxBind(ctx, conn, "tcp", address, log) - case gosocks5.CmdUdp: - return h.handleUDP(ctx, conn, log) - case socks.CmdUDPTun: - return h.handleUDPTun(ctx, conn, "udp", address, log) - default: - err = ErrUnknownCmd - log.Error(err) - resp := gosocks5.NewReply(gosocks5.CmdUnsupported, nil) - resp.Write(conn) - log.Debug(resp) - return err - } -} diff --git a/handler/socks/v5/mbind.go b/handler/socks/v5/mbind.go deleted file mode 100644 index 8164a54..0000000 --- a/handler/socks/v5/mbind.go +++ /dev/null @@ -1,133 +0,0 @@ -package v5 - -import ( - "context" - "fmt" - "net" - "time" - - netpkg "github.com/go-gost/core/common/net" - "github.com/go-gost/core/internal/util/mux" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -func (h *socks5Handler) handleMuxBind(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error { - log = log.WithFields(map[string]any{ - "dst": fmt.Sprintf("%s/%s", address, network), - "cmd": "mbind", - }) - - log.Infof("%s >> %s", conn.RemoteAddr(), address) - - if !h.md.enableBind { - reply := gosocks5.NewReply(gosocks5.NotAllowed, nil) - log.Debug(reply) - log.Error("socks5: BIND is disabled") - return reply.Write(conn) - } - - return h.muxBindLocal(ctx, conn, network, address, log) -} - -func (h *socks5Handler) muxBindLocal(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error { - ln, err := net.Listen(network, address) // strict mode: if the port already in use, it will return error - if err != nil { - log.Error(err) - reply := gosocks5.NewReply(gosocks5.Failure, nil) - if err := reply.Write(conn); err != nil { - log.Error(err) - } - log.Debug(reply) - return err - } - - socksAddr := gosocks5.Addr{} - err = socksAddr.ParseFrom(ln.Addr().String()) - if err != nil { - log.Warn(err) - } - - // Issue: may not reachable when host has multi-interface - socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) - socksAddr.Type = 0 - reply := gosocks5.NewReply(gosocks5.Succeeded, &socksAddr) - if err := reply.Write(conn); err != nil { - log.Error(err) - ln.Close() - return err - } - log.Debug(reply) - - log = log.WithFields(map[string]any{ - "bind": fmt.Sprintf("%s/%s", ln.Addr(), ln.Addr().Network()), - }) - - log.Debugf("bind on %s OK", ln.Addr()) - - return h.serveMuxBind(ctx, conn, ln, log) -} - -func (h *socks5Handler) serveMuxBind(ctx context.Context, conn net.Conn, ln net.Listener, log logger.Logger) error { - // Upgrade connection to multiplex stream. - session, err := mux.ClientSession(conn) - if err != nil { - log.Error(err) - return err - } - defer session.Close() - - go func() { - defer ln.Close() - for { - conn, err := session.Accept() - if err != nil { - log.Error(err) - return - } - conn.Close() // we do not handle incoming connections. - } - }() - - for { - rc, err := ln.Accept() - if err != nil { - log.Error(err) - return err - } - log.Debugf("peer %s accepted", rc.RemoteAddr()) - - go func(c net.Conn) { - defer c.Close() - - log = log.WithFields(map[string]any{ - "local": rc.LocalAddr().String(), - "remote": rc.RemoteAddr().String(), - }) - sc, err := session.GetConn() - if err != nil { - log.Error(err) - return - } - defer sc.Close() - - // incompatible with GOST v2.x - if !h.md.compatibilityMode { - addr := gosocks5.Addr{} - addr.ParseFrom(c.RemoteAddr().String()) - reply := gosocks5.NewReply(gosocks5.Succeeded, &addr) - if err := reply.Write(sc); err != nil { - log.Error(err) - return - } - log.Debug(reply) - } - - t := time.Now() - log.Infof("%s <-> %s", c.LocalAddr(), c.RemoteAddr()) - netpkg.Transport(sc, c) - log.WithFields(map[string]any{"duration": time.Since(t)}). - Infof("%s >-< %s", c.LocalAddr(), c.RemoteAddr()) - }(rc) - } -} diff --git a/handler/socks/v5/metadata.go b/handler/socks/v5/metadata.go deleted file mode 100644 index 283133e..0000000 --- a/handler/socks/v5/metadata.go +++ /dev/null @@ -1,43 +0,0 @@ -package v5 - -import ( - "math" - "time" - - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { - readTimeout time.Duration - noTLS bool - enableBind bool - enableUDP bool - udpBufferSize int - compatibilityMode bool -} - -func (h *socks5Handler) parseMetadata(md mdata.Metadata) (err error) { - const ( - readTimeout = "readTimeout" - noTLS = "notls" - enableBind = "bind" - enableUDP = "udp" - udpBufferSize = "udpBufferSize" - compatibilityMode = "comp" - ) - - h.md.readTimeout = mdata.GetDuration(md, readTimeout) - h.md.noTLS = mdata.GetBool(md, noTLS) - h.md.enableBind = mdata.GetBool(md, enableBind) - h.md.enableUDP = mdata.GetBool(md, enableUDP) - - if bs := mdata.GetInt(md, udpBufferSize); bs > 0 { - h.md.udpBufferSize = int(math.Min(math.Max(float64(bs), 512), 64*1024)) - } else { - h.md.udpBufferSize = 1500 - } - - h.md.compatibilityMode = mdata.GetBool(md, compatibilityMode) - - return nil -} diff --git a/handler/socks/v5/selector.go b/handler/socks/v5/selector.go deleted file mode 100644 index 9c10ca1..0000000 --- a/handler/socks/v5/selector.go +++ /dev/null @@ -1,90 +0,0 @@ -package v5 - -import ( - "crypto/tls" - "net" - - "github.com/go-gost/core/auth" - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -type serverSelector struct { - methods []uint8 - Authenticator auth.Authenticator - TLSConfig *tls.Config - logger logger.Logger - noTLS bool -} - -func (selector *serverSelector) Methods() []uint8 { - return selector.methods -} - -func (s *serverSelector) Select(methods ...uint8) (method uint8) { - s.logger.Debugf("%d %d %v", gosocks5.Ver5, len(methods), methods) - method = gosocks5.MethodNoAuth - for _, m := range methods { - if m == socks.MethodTLS && !s.noTLS { - method = m - break - } - } - - // when Authenticator is set, auth is mandatory - if s.Authenticator != nil { - if method == gosocks5.MethodNoAuth { - method = gosocks5.MethodUserPass - } - if method == socks.MethodTLS && !s.noTLS { - method = socks.MethodTLSAuth - } - } - - return -} - -func (s *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) { - s.logger.Debugf("%d %d", gosocks5.Ver5, method) - switch method { - case socks.MethodTLS: - conn = tls.Server(conn, s.TLSConfig) - - case gosocks5.MethodUserPass, socks.MethodTLSAuth: - if method == socks.MethodTLSAuth { - conn = tls.Server(conn, s.TLSConfig) - } - - req, err := gosocks5.ReadUserPassRequest(conn) - if err != nil { - s.logger.Error(err) - return nil, err - } - s.logger.Debug(req) - - if s.Authenticator != nil && - !s.Authenticator.Authenticate(req.Username, req.Password) { - resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure) - if err := resp.Write(conn); err != nil { - s.logger.Error(err) - return nil, err - } - s.logger.Info(resp) - - return nil, gosocks5.ErrAuthFailure - } - - resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded) - if err := resp.Write(conn); err != nil { - s.logger.Error(err) - return nil, err - } - s.logger.Debug(resp) - - case gosocks5.MethodNoAcceptable: - return nil, gosocks5.ErrBadMethod - } - - return conn, nil -} diff --git a/handler/socks/v5/udp.go b/handler/socks/v5/udp.go deleted file mode 100644 index c192256..0000000 --- a/handler/socks/v5/udp.go +++ /dev/null @@ -1,85 +0,0 @@ -package v5 - -import ( - "context" - "errors" - "fmt" - "io" - "io/ioutil" - "net" - "time" - - "github.com/go-gost/core/common/net/relay" - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, log logger.Logger) error { - log = log.WithFields(map[string]any{ - "cmd": "udp", - }) - - if !h.md.enableUDP { - reply := gosocks5.NewReply(gosocks5.NotAllowed, nil) - log.Debug(reply) - log.Error("socks5: UDP relay is disabled") - return reply.Write(conn) - } - - cc, err := net.ListenUDP("udp", nil) - if err != nil { - log.Error(err) - reply := gosocks5.NewReply(gosocks5.Failure, nil) - reply.Write(conn) - log.Debug(reply) - return err - } - defer cc.Close() - - saddr := gosocks5.Addr{} - saddr.ParseFrom(cc.LocalAddr().String()) - saddr.Type = 0 - saddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) // replace the IP to the out-going interface's - reply := gosocks5.NewReply(gosocks5.Succeeded, &saddr) - if err := reply.Write(conn); err != nil { - log.Error(err) - return err - } - log.Debug(reply) - - log = log.WithFields(map[string]any{ - "bind": fmt.Sprintf("%s/%s", cc.LocalAddr(), cc.LocalAddr().Network()), - }) - log.Debugf("bind on %s OK", cc.LocalAddr()) - - // obtain a udp connection - c, err := h.router.Dial(ctx, "udp", "") // UDP association - if err != nil { - log.Error(err) - return err - } - defer c.Close() - - pc, ok := c.(net.PacketConn) - if !ok { - err := errors.New("socks5: wrong connection type") - log.Error(err) - return err - } - - r := relay.NewUDPRelay(socks.UDPConn(cc, h.md.udpBufferSize), pc). - WithBypass(h.options.Bypass). - WithLogger(log) - r.SetBufferSize(h.md.udpBufferSize) - - go r.Run() - - t := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), cc.LocalAddr()) - io.Copy(ioutil.Discard, conn) - log.WithFields(map[string]any{"duration": time.Since(t)}). - Infof("%s >-< %s", conn.RemoteAddr(), cc.LocalAddr()) - - return nil -} diff --git a/handler/socks/v5/udp_tun.go b/handler/socks/v5/udp_tun.go deleted file mode 100644 index edfd379..0000000 --- a/handler/socks/v5/udp_tun.go +++ /dev/null @@ -1,72 +0,0 @@ -package v5 - -import ( - "context" - "net" - "time" - - "github.com/go-gost/core/common/net/relay" - "github.com/go-gost/core/internal/util/socks" - "github.com/go-gost/core/logger" - "github.com/go-gost/gosocks5" -) - -func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network, address string, log logger.Logger) error { - log = log.WithFields(map[string]any{ - "cmd": "udp-tun", - }) - - bindAddr, _ := net.ResolveUDPAddr(network, address) - if bindAddr == nil { - bindAddr = &net.UDPAddr{} - } - - if bindAddr.Port == 0 { - // relay mode - if !h.md.enableUDP { - reply := gosocks5.NewReply(gosocks5.NotAllowed, nil) - log.Debug(reply) - log.Error("socks5: UDP relay is disabled") - return reply.Write(conn) - } - } else { - // BIND mode - if !h.md.enableBind { - reply := gosocks5.NewReply(gosocks5.NotAllowed, nil) - log.Debug(reply) - log.Error("socks5: BIND is disabled") - return reply.Write(conn) - } - } - - pc, err := net.ListenUDP(network, bindAddr) - if err != nil { - log.Error(err) - return err - } - defer pc.Close() - - saddr := gosocks5.Addr{} - saddr.ParseFrom(pc.LocalAddr().String()) - reply := gosocks5.NewReply(gosocks5.Succeeded, &saddr) - if err := reply.Write(conn); err != nil { - log.Error(err) - return err - } - log.Debug(reply) - log.Debugf("bind on %s OK", pc.LocalAddr()) - - r := relay.NewUDPRelay(socks.UDPTunServerConn(conn), pc). - WithBypass(h.options.Bypass). - WithLogger(log) - r.SetBufferSize(h.md.udpBufferSize) - - t := time.Now() - log.Infof("%s <-> %s", conn.RemoteAddr(), pc.LocalAddr()) - r.Run() - log.WithFields(map[string]any{ - "duration": time.Since(t), - }).Infof("%s >-< %s", conn.RemoteAddr(), pc.LocalAddr()) - - return nil -} diff --git a/hosts/hosts.go b/hosts/hosts.go index 0b51c5e..35590cb 100644 --- a/hosts/hosts.go +++ b/hosts/hosts.go @@ -2,131 +2,9 @@ package hosts import ( "net" - "strings" - "sync" - - "github.com/go-gost/core/logger" ) // HostMapper is a mapping from hostname to IP. type HostMapper interface { Lookup(network, host string) ([]net.IP, bool) } - -type hostMapping struct { - IPs []net.IP - Hostname string -} - -// Hosts is a static table lookup for hostnames. -// For each host a single line should be present with the following information: -// IP_address canonical_hostname [aliases...] -// Fields of the entry are separated by any number of blanks and/or tab characters. -// Text from a "#" character until the end of the line is a comment, and is ignored. -type Hosts struct { - mappings sync.Map - Logger logger.Logger -} - -func NewHosts() *Hosts { - return &Hosts{} -} - -// Map maps ip to hostname or aliases. -func (h *Hosts) Map(ip net.IP, hostname string, aliases ...string) { - if hostname == "" { - return - } - - v, _ := h.mappings.Load(hostname) - m, _ := v.(*hostMapping) - if m == nil { - m = &hostMapping{ - IPs: []net.IP{ip}, - Hostname: hostname, - } - } else { - m.IPs = append(m.IPs, ip) - } - h.mappings.Store(hostname, m) - - for _, alias := range aliases { - // indirect mapping from alias to hostname - if alias != "" { - h.mappings.Store(alias, &hostMapping{ - Hostname: hostname, - }) - } - } -} - -// 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 *Hosts) Lookup(network, host string) (ips []net.IP, ok bool) { - m := h.lookup(host) - if m == nil { - m = h.lookup("." + host) - } - if m == nil { - s := host - for { - if index := strings.IndexByte(s, '.'); index > 0 { - m = h.lookup(s[index:]) - s = s[index+1:] - if m == nil { - continue - } - } - break - } - } - - if m == nil { - return - } - - // hostname alias - if !strings.HasPrefix(m.Hostname, ".") && host != m.Hostname { - m = h.lookup(m.Hostname) - if m == nil { - return - } - } - - switch network { - case "ip4": - for _, ip := range m.IPs { - if ip = ip.To4(); ip != nil { - ips = append(ips, ip) - } - } - case "ip6": - for _, ip := range m.IPs { - if ip.To4() == nil { - ips = append(ips, ip) - } - } - default: - ips = m.IPs - } - - if len(ips) > 0 { - h.Logger.Debugf("host mapper: %s -> %s", host, ips) - } - - return -} - -func (h *Hosts) lookup(host string) *hostMapping { - if h == nil || host == "" { - return nil - } - - v, ok := h.mappings.Load(host) - if !ok { - return nil - } - m, _ := v.(*hostMapping) - return m -} diff --git a/internal/util/mux/mux.go b/internal/util/mux/mux.go deleted file mode 100644 index 4fae020..0000000 --- a/internal/util/mux/mux.go +++ /dev/null @@ -1,85 +0,0 @@ -package mux - -import ( - "net" - - smux "github.com/xtaci/smux" -) - -type Session struct { - conn net.Conn - session *smux.Session -} - -func ClientSession(conn net.Conn) (*Session, error) { - s, err := smux.Client(conn, smux.DefaultConfig()) - if err != nil { - return nil, err - } - return &Session{ - conn: conn, - session: s, - }, nil -} - -func ServerSession(conn net.Conn) (*Session, error) { - s, err := smux.Server(conn, smux.DefaultConfig()) - if err != nil { - return nil, err - } - return &Session{ - conn: conn, - session: s, - }, nil -} - -func (session *Session) GetConn() (net.Conn, error) { - stream, err := session.session.OpenStream() - if err != nil { - return nil, err - } - return &streamConn{Conn: session.conn, stream: stream}, nil -} - -func (session *Session) Accept() (net.Conn, error) { - stream, err := session.session.AcceptStream() - if err != nil { - return nil, err - } - return &streamConn{Conn: session.conn, stream: stream}, nil -} - -func (session *Session) Close() error { - if session.session == nil { - return nil - } - return session.session.Close() -} - -func (session *Session) IsClosed() bool { - if session.session == nil { - return true - } - return session.session.IsClosed() -} - -func (session *Session) NumStreams() int { - return session.session.NumStreams() -} - -type streamConn struct { - net.Conn - stream *smux.Stream -} - -func (c *streamConn) Read(b []byte) (n int, err error) { - return c.stream.Read(b) -} - -func (c *streamConn) Write(b []byte) (n int, err error) { - return c.stream.Write(b) -} - -func (c *streamConn) Close() error { - return c.stream.Close() -} diff --git a/internal/util/socks/conn.go b/internal/util/socks/conn.go deleted file mode 100644 index 69316e8..0000000 --- a/internal/util/socks/conn.go +++ /dev/null @@ -1,172 +0,0 @@ -package socks - -import ( - "bytes" - "net" - - "github.com/go-gost/core/common/bufpool" - "github.com/go-gost/gosocks5" -) - -type udpTunConn struct { - net.Conn - taddr net.Addr -} - -func UDPTunClientConn(c net.Conn, targetAddr net.Addr) net.Conn { - return &udpTunConn{ - Conn: c, - taddr: targetAddr, - } -} - -func UDPTunClientPacketConn(c net.Conn) net.PacketConn { - return &udpTunConn{ - Conn: c, - } -} - -func UDPTunServerConn(c net.Conn) net.PacketConn { - return &udpTunConn{ - Conn: c, - } -} - -func (c *udpTunConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) { - socksAddr := gosocks5.Addr{} - header := gosocks5.UDPHeader{ - Addr: &socksAddr, - } - dgram := gosocks5.UDPDatagram{ - Header: &header, - Data: b, - } - _, err = dgram.ReadFrom(c.Conn) - if err != nil { - return - } - - n = len(dgram.Data) - if n > len(b) { - n = copy(b, dgram.Data) - } - addr, err = net.ResolveUDPAddr("udp", socksAddr.String()) - - return -} - -func (c *udpTunConn) Read(b []byte) (n int, err error) { - n, _, err = c.ReadFrom(b) - return -} - -func (c *udpTunConn) WriteTo(b []byte, addr net.Addr) (n int, err error) { - socksAddr := gosocks5.Addr{} - if err = socksAddr.ParseFrom(addr.String()); err != nil { - return - } - - header := gosocks5.UDPHeader{ - Addr: &socksAddr, - } - dgram := gosocks5.UDPDatagram{ - Header: &header, - Data: b, - } - dgram.Header.Rsv = uint16(len(dgram.Data)) - dgram.Header.Frag = 0xff // UDP tun relay flag, used by shadowsocks - _, err = dgram.WriteTo(c.Conn) - n = len(b) - - return -} - -func (c *udpTunConn) Write(b []byte) (n int, err error) { - return c.WriteTo(b, c.taddr) -} - -var ( - DefaultBufferSize = 4096 -) - -type udpConn struct { - net.PacketConn - raddr net.Addr - taddr net.Addr - bufferSize int -} - -func UDPConn(c net.PacketConn, bufferSize int) net.PacketConn { - return &udpConn{ - PacketConn: c, - bufferSize: bufferSize, - } -} - -// ReadFrom reads an UDP datagram. -// NOTE: for server side, -// the returned addr is the target address the client want to relay to. -func (c *udpConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) { - rbuf := bufpool.Get(c.bufferSize) - defer bufpool.Put(rbuf) - - n, c.raddr, err = c.PacketConn.ReadFrom(*rbuf) - if err != nil { - return - } - - socksAddr := gosocks5.Addr{} - header := gosocks5.UDPHeader{ - Addr: &socksAddr, - } - hlen, err := header.ReadFrom(bytes.NewReader((*rbuf)[:n])) - if err != nil { - return - } - n = copy(b, (*rbuf)[hlen:n]) - - addr, err = net.ResolveUDPAddr("udp", socksAddr.String()) - return -} - -func (c *udpConn) Read(b []byte) (n int, err error) { - n, _, err = c.ReadFrom(b) - return -} - -func (c *udpConn) WriteTo(b []byte, addr net.Addr) (n int, err error) { - wbuf := bufpool.Get(c.bufferSize) - defer bufpool.Put(wbuf) - - socksAddr := gosocks5.Addr{} - if err = socksAddr.ParseFrom(addr.String()); err != nil { - return - } - - header := gosocks5.UDPHeader{ - Addr: &socksAddr, - } - dgram := gosocks5.UDPDatagram{ - Header: &header, - Data: b, - } - - buf := bytes.NewBuffer((*wbuf)[:0]) - _, err = dgram.WriteTo(buf) - if err != nil { - return - } - - _, err = c.PacketConn.WriteTo(buf.Bytes(), c.raddr) - n = len(b) - - return -} - -func (c *udpConn) Write(b []byte) (n int, err error) { - return c.WriteTo(b, c.taddr) -} - -func (c *udpConn) RemoteAddr() net.Addr { - return c.raddr -} diff --git a/internal/util/socks/socks.go b/internal/util/socks/socks.go deleted file mode 100644 index 91d241d..0000000 --- a/internal/util/socks/socks.go +++ /dev/null @@ -1,18 +0,0 @@ -package socks - -const ( - // MethodTLS is an extended SOCKS5 method with tls encryption support. - MethodTLS uint8 = 0x80 - // MethodTLSAuth is an extended SOCKS5 method with tls encryption and authentication support. - MethodTLSAuth uint8 = 0x82 - // MethodMux is an extended SOCKS5 method for stream multiplexing. - MethodMux = 0x88 -) - -const ( - // CmdMuxBind is an extended SOCKS5 request CMD for - // multiplexing transport with the binding server. - CmdMuxBind uint8 = 0xF2 - // CmdUDPTun is an extended SOCKS5 request CMD for UDP over TCP. - CmdUDPTun uint8 = 0xF3 -) diff --git a/internal/util/tcp.go b/internal/util/tcp.go deleted file mode 100644 index b2298fb..0000000 --- a/internal/util/tcp.go +++ /dev/null @@ -1,32 +0,0 @@ -package util - -import ( - "net" - "time" -) - -const ( - defaultKeepAlivePeriod = 180 * time.Second -) - -// TCPKeepAliveListener is a TCP listener with keep alive enabled. -type TCPKeepAliveListener struct { - KeepAlivePeriod time.Duration - *net.TCPListener -} - -func (l *TCPKeepAliveListener) Accept() (c net.Conn, err error) { - tc, err := l.AcceptTCP() - if err != nil { - return - } - - tc.SetKeepAlive(true) - period := l.KeepAlivePeriod - if period <= 0 { - period = defaultKeepAlivePeriod - } - tc.SetKeepAlivePeriod(period) - - return tc, nil -} diff --git a/listener/rtcp/listener.go b/listener/rtcp/listener.go deleted file mode 100644 index c7e3847..0000000 --- a/listener/rtcp/listener.go +++ /dev/null @@ -1,102 +0,0 @@ -package rtcp - -import ( - "context" - "net" - - "github.com/go-gost/core/chain" - "github.com/go-gost/core/connector" - "github.com/go-gost/core/listener" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - metrics "github.com/go-gost/core/metrics/wrapper" - "github.com/go-gost/core/registry" -) - -func init() { - registry.ListenerRegistry().Register("rtcp", NewListener) -} - -type rtcpListener struct { - laddr net.Addr - ln net.Listener - md metadata - router *chain.Router - logger logger.Logger - closed chan struct{} - options listener.Options -} - -func NewListener(opts ...listener.Option) listener.Listener { - options := listener.Options{} - for _, opt := range opts { - opt(&options) - } - return &rtcpListener{ - closed: make(chan struct{}), - logger: options.Logger, - options: options, - } -} - -func (l *rtcpListener) Init(md md.Metadata) (err error) { - if err = l.parseMetadata(md); err != nil { - return - } - - laddr, err := net.ResolveTCPAddr("tcp", l.options.Addr) - if err != nil { - return - } - - l.laddr = laddr - l.router = (&chain.Router{}). - WithChain(l.options.Chain). - WithLogger(l.logger) - - return -} - -func (l *rtcpListener) Accept() (conn net.Conn, err error) { - select { - case <-l.closed: - return nil, net.ErrClosed - default: - } - - if l.ln == nil { - l.ln, err = l.router.Bind( - context.Background(), "tcp", l.laddr.String(), - connector.MuxBindOption(true), - ) - if err != nil { - return nil, listener.NewAcceptError(err) - } - l.ln = metrics.WrapListener(l.options.Service, l.ln) - } - conn, err = l.ln.Accept() - if err != nil { - l.ln.Close() - l.ln = nil - return nil, listener.NewAcceptError(err) - } - return -} - -func (l *rtcpListener) Addr() net.Addr { - return l.laddr -} - -func (l *rtcpListener) Close() error { - select { - case <-l.closed: - default: - close(l.closed) - if l.ln != nil { - l.ln.Close() - l.ln = nil - } - } - - return nil -} diff --git a/listener/rtcp/metadata.go b/listener/rtcp/metadata.go deleted file mode 100644 index 42d52d5..0000000 --- a/listener/rtcp/metadata.go +++ /dev/null @@ -1,11 +0,0 @@ -package rtcp - -import ( - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct{} - -func (l *rtcpListener) parseMetadata(md mdata.Metadata) (err error) { - return -} diff --git a/listener/rudp/listener.go b/listener/rudp/listener.go deleted file mode 100644 index 0a6a598..0000000 --- a/listener/rudp/listener.go +++ /dev/null @@ -1,109 +0,0 @@ -package rudp - -import ( - "context" - "net" - - "github.com/go-gost/core/chain" - "github.com/go-gost/core/connector" - "github.com/go-gost/core/listener" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - metrics "github.com/go-gost/core/metrics/wrapper" - "github.com/go-gost/core/registry" -) - -func init() { - registry.ListenerRegistry().Register("rudp", NewListener) -} - -type rudpListener struct { - laddr net.Addr - ln net.Listener - router *chain.Router - closed chan struct{} - logger logger.Logger - md metadata - options listener.Options -} - -func NewListener(opts ...listener.Option) listener.Listener { - options := listener.Options{} - for _, opt := range opts { - opt(&options) - } - return &rudpListener{ - closed: make(chan struct{}), - logger: options.Logger, - options: options, - } -} - -func (l *rudpListener) Init(md md.Metadata) (err error) { - if err = l.parseMetadata(md); err != nil { - return - } - - laddr, err := net.ResolveUDPAddr("udp", l.options.Addr) - if err != nil { - return - } - - l.laddr = laddr - l.router = (&chain.Router{}). - WithChain(l.options.Chain). - WithLogger(l.logger) - - return -} - -func (l *rudpListener) Accept() (conn net.Conn, err error) { - select { - case <-l.closed: - return nil, net.ErrClosed - default: - } - - if l.ln == nil { - l.ln, err = l.router.Bind( - context.Background(), "udp", l.laddr.String(), - connector.BacklogBindOption(l.md.backlog), - connector.UDPConnTTLBindOption(l.md.ttl), - connector.UDPDataBufferSizeBindOption(l.md.readBufferSize), - connector.UDPDataQueueSizeBindOption(l.md.readQueueSize), - ) - if err != nil { - return nil, listener.NewAcceptError(err) - } - } - conn, err = l.ln.Accept() - if err != nil { - l.ln.Close() - l.ln = nil - return nil, listener.NewAcceptError(err) - } - - if pc, ok := conn.(net.PacketConn); ok { - conn = metrics.WrapUDPConn(l.options.Service, pc) - } - - return -} - -func (l *rudpListener) Addr() net.Addr { - return l.laddr -} - -func (l *rudpListener) Close() error { - select { - case <-l.closed: - default: - close(l.closed) - if l.ln != nil { - l.ln.Close() - l.ln = nil - } - } - - return nil -} diff --git a/listener/rudp/metadata.go b/listener/rudp/metadata.go deleted file mode 100644 index 53e0e41..0000000 --- a/listener/rudp/metadata.go +++ /dev/null @@ -1,51 +0,0 @@ -package rudp - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -const ( - defaultTTL = 5 * time.Second - defaultReadBufferSize = 1500 - defaultReadQueueSize = 128 - defaultBacklog = 128 -) - -type metadata struct { - ttl time.Duration - readBufferSize int - readQueueSize int - backlog int -} - -func (l *rudpListener) parseMetadata(md mdata.Metadata) (err error) { - const ( - ttl = "ttl" - readBufferSize = "readBufferSize" - readQueueSize = "readQueueSize" - backlog = "backlog" - ) - - l.md.ttl = mdata.GetDuration(md, ttl) - if l.md.ttl <= 0 { - l.md.ttl = defaultTTL - } - l.md.readBufferSize = mdata.GetInt(md, readBufferSize) - if l.md.readBufferSize <= 0 { - l.md.readBufferSize = defaultReadBufferSize - } - - l.md.readQueueSize = mdata.GetInt(md, readQueueSize) - if l.md.readQueueSize <= 0 { - l.md.readQueueSize = defaultReadQueueSize - } - - l.md.backlog = mdata.GetInt(md, backlog) - if l.md.backlog <= 0 { - l.md.backlog = defaultBacklog - } - - return -} diff --git a/listener/tcp/listener.go b/listener/tcp/listener.go deleted file mode 100644 index 1396349..0000000 --- a/listener/tcp/listener.go +++ /dev/null @@ -1,60 +0,0 @@ -package tcp - -import ( - "net" - - "github.com/go-gost/core/listener" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - metrics "github.com/go-gost/core/metrics/wrapper" - "github.com/go-gost/core/registry" -) - -func init() { - registry.ListenerRegistry().Register("tcp", NewListener) -} - -type tcpListener struct { - ln net.Listener - logger logger.Logger - md metadata - options listener.Options -} - -func NewListener(opts ...listener.Option) listener.Listener { - options := listener.Options{} - for _, opt := range opts { - opt(&options) - } - return &tcpListener{ - logger: options.Logger, - options: options, - } -} - -func (l *tcpListener) Init(md md.Metadata) (err error) { - if err = l.parseMetadata(md); err != nil { - return - } - - ln, err := net.Listen("tcp", l.options.Addr) - if err != nil { - return - } - - l.ln = metrics.WrapListener(l.options.Service, ln) - - return -} - -func (l *tcpListener) Accept() (conn net.Conn, err error) { - return l.ln.Accept() -} - -func (l *tcpListener) Addr() net.Addr { - return l.ln.Addr() -} - -func (l *tcpListener) Close() error { - return l.ln.Close() -} diff --git a/listener/tcp/metadata.go b/listener/tcp/metadata.go deleted file mode 100644 index e1d286a..0000000 --- a/listener/tcp/metadata.go +++ /dev/null @@ -1,12 +0,0 @@ -package tcp - -import ( - md "github.com/go-gost/core/metadata" -) - -type metadata struct { -} - -func (l *tcpListener) parseMetadata(md md.Metadata) (err error) { - return -} diff --git a/listener/tls/listener.go b/listener/tls/listener.go deleted file mode 100644 index bfe22f3..0000000 --- a/listener/tls/listener.go +++ /dev/null @@ -1,64 +0,0 @@ -package tls - -import ( - "crypto/tls" - "net" - - admission "github.com/go-gost/core/admission/wrapper" - "github.com/go-gost/core/listener" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - metrics "github.com/go-gost/core/metrics/wrapper" - "github.com/go-gost/core/registry" -) - -func init() { - registry.ListenerRegistry().Register("tls", NewListener) -} - -type tlsListener struct { - ln net.Listener - logger logger.Logger - md metadata - options listener.Options -} - -func NewListener(opts ...listener.Option) listener.Listener { - options := listener.Options{} - for _, opt := range opts { - opt(&options) - } - return &tlsListener{ - logger: options.Logger, - options: options, - } -} - -func (l *tlsListener) Init(md md.Metadata) (err error) { - if err = l.parseMetadata(md); err != nil { - return - } - - ln, err := net.Listen("tcp", l.options.Addr) - if err != nil { - return - } - ln = metrics.WrapListener(l.options.Service, ln) - ln = admission.WrapListener(l.options.Admission, ln) - - l.ln = tls.NewListener(ln, l.options.TLSConfig) - - return -} - -func (l *tlsListener) Accept() (conn net.Conn, err error) { - return l.ln.Accept() -} - -func (l *tlsListener) Addr() net.Addr { - return l.ln.Addr() -} - -func (l *tlsListener) Close() error { - return l.ln.Close() -} diff --git a/listener/tls/metadata.go b/listener/tls/metadata.go deleted file mode 100644 index d515844..0000000 --- a/listener/tls/metadata.go +++ /dev/null @@ -1,12 +0,0 @@ -package tls - -import ( - mdata "github.com/go-gost/core/metadata" -) - -type metadata struct { -} - -func (l *tlsListener) parseMetadata(md mdata.Metadata) (err error) { - return -} diff --git a/listener/udp/listener.go b/listener/udp/listener.go deleted file mode 100644 index 2858107..0000000 --- a/listener/udp/listener.go +++ /dev/null @@ -1,74 +0,0 @@ -package udp - -import ( - "net" - - "github.com/go-gost/core/common/net/udp" - "github.com/go-gost/core/listener" - "github.com/go-gost/core/logger" - md "github.com/go-gost/core/metadata" - metrics "github.com/go-gost/core/metrics/wrapper" - "github.com/go-gost/core/registry" -) - -func init() { - registry.ListenerRegistry().Register("udp", NewListener) -} - -type udpListener struct { - ln net.Listener - logger logger.Logger - md metadata - options listener.Options -} - -func NewListener(opts ...listener.Option) listener.Listener { - options := listener.Options{} - for _, opt := range opts { - opt(&options) - } - return &udpListener{ - logger: options.Logger, - options: options, - } -} - -func (l *udpListener) Init(md md.Metadata) (err error) { - if err = l.parseMetadata(md); err != nil { - return - } - - laddr, err := net.ResolveUDPAddr("udp", l.options.Addr) - if err != nil { - return - } - - var conn net.PacketConn - conn, err = net.ListenUDP("udp", laddr) - if err != nil { - return - } - conn = metrics.WrapPacketConn(l.options.Service, conn) - - l.ln = udp.NewListener(conn, &udp.ListenConfig{ - Backlog: l.md.backlog, - ReadQueueSize: l.md.readQueueSize, - ReadBufferSize: l.md.readBufferSize, - KeepAlive: l.md.keepalive, - TTL: l.md.ttl, - Logger: l.logger, - }) - return -} - -func (l *udpListener) Accept() (conn net.Conn, err error) { - return l.ln.Accept() -} - -func (l *udpListener) Addr() net.Addr { - return l.ln.Addr() -} - -func (l *udpListener) Close() error { - return l.ln.Close() -} diff --git a/listener/udp/metadata.go b/listener/udp/metadata.go deleted file mode 100644 index a82add3..0000000 --- a/listener/udp/metadata.go +++ /dev/null @@ -1,54 +0,0 @@ -package udp - -import ( - "time" - - mdata "github.com/go-gost/core/metadata" -) - -const ( - defaultTTL = 5 * time.Second - defaultReadBufferSize = 1500 - defaultReadQueueSize = 128 - defaultBacklog = 128 -) - -type metadata struct { - readBufferSize int - readQueueSize int - backlog int - keepalive bool - ttl time.Duration -} - -func (l *udpListener) parseMetadata(md mdata.Metadata) (err error) { - const ( - readBufferSize = "readBufferSize" - readQueueSize = "readQueueSize" - backlog = "backlog" - keepAlive = "keepAlive" - ttl = "ttl" - ) - - l.md.ttl = mdata.GetDuration(md, ttl) - if l.md.ttl <= 0 { - l.md.ttl = defaultTTL - } - l.md.readBufferSize = mdata.GetInt(md, readBufferSize) - if l.md.readBufferSize <= 0 { - l.md.readBufferSize = defaultReadBufferSize - } - - l.md.readQueueSize = mdata.GetInt(md, readQueueSize) - if l.md.readQueueSize <= 0 { - l.md.readQueueSize = defaultReadQueueSize - } - - l.md.backlog = mdata.GetInt(md, backlog) - if l.md.backlog <= 0 { - l.md.backlog = defaultBacklog - } - l.md.keepalive = mdata.GetBool(md, keepAlive) - - return -} diff --git a/logger/gost_logger.go b/logger/gost_logger.go deleted file mode 100644 index 7395fb8..0000000 --- a/logger/gost_logger.go +++ /dev/null @@ -1,155 +0,0 @@ -package logger - -import ( - "fmt" - "path/filepath" - "runtime" - - "github.com/sirupsen/logrus" -) - -var ( - defaultLogger = NewLogger() -) - -func Default() Logger { - return defaultLogger -} - -func SetDefault(logger Logger) { - defaultLogger = logger -} - -type logger struct { - logger *logrus.Entry -} - -func NewLogger(opts ...LoggerOption) Logger { - var options LoggerOptions - for _, opt := range opts { - opt(&options) - } - - log := logrus.New() - if options.Output != nil { - log.SetOutput(options.Output) - } - - switch options.Format { - case TextFormat: - log.SetFormatter(&logrus.TextFormatter{ - FullTimestamp: true, - }) - default: - log.SetFormatter(&logrus.JSONFormatter{ - DisableHTMLEscape: true, - // PrettyPrint: true, - }) - } - - switch options.Level { - case DebugLevel, InfoLevel, WarnLevel, ErrorLevel, FatalLevel: - lvl, _ := logrus.ParseLevel(string(options.Level)) - log.SetLevel(lvl) - default: - log.SetLevel(logrus.InfoLevel) - } - - return &logger{ - logger: logrus.NewEntry(log), - } -} - -// WithFields adds new fields to log. -func (l *logger) WithFields(fields map[string]any) Logger { - return &logger{ - logger: l.logger.WithFields(logrus.Fields(fields)), - } -} - -// Debug logs a message at level Debug. -func (l *logger) Debug(args ...any) { - l.log(logrus.DebugLevel, args...) -} - -// Debugf logs a message at level Debug. -func (l *logger) Debugf(format string, args ...any) { - l.logf(logrus.DebugLevel, format, args...) -} - -// Info logs a message at level Info. -func (l *logger) Info(args ...any) { - l.log(logrus.InfoLevel, args...) -} - -// Infof logs a message at level Info. -func (l *logger) Infof(format string, args ...any) { - l.logf(logrus.InfoLevel, format, args...) -} - -// Warn logs a message at level Warn. -func (l *logger) Warn(args ...any) { - l.log(logrus.WarnLevel, args...) -} - -// Warnf logs a message at level Warn. -func (l *logger) Warnf(format string, args ...any) { - l.logf(logrus.WarnLevel, format, args...) -} - -// Error logs a message at level Error. -func (l *logger) Error(args ...any) { - l.log(logrus.ErrorLevel, args...) -} - -// Errorf logs a message at level Error. -func (l *logger) Errorf(format string, args ...any) { - l.logf(logrus.ErrorLevel, format, args...) -} - -// Fatal logs a message at level Fatal then the process will exit with status set to 1. -func (l *logger) Fatal(args ...any) { - l.log(logrus.FatalLevel, args...) - l.logger.Logger.Exit(1) -} - -// Fatalf logs a message at level Fatal then the process will exit with status set to 1. -func (l *logger) Fatalf(format string, args ...any) { - l.logf(logrus.FatalLevel, format, args...) - l.logger.Logger.Exit(1) -} - -func (l *logger) GetLevel() LogLevel { - return LogLevel(l.logger.Logger.GetLevel().String()) -} - -func (l *logger) IsLevelEnabled(level LogLevel) bool { - lvl, _ := logrus.ParseLevel(string(level)) - return l.logger.Logger.IsLevelEnabled(lvl) -} - -func (l *logger) log(level logrus.Level, args ...any) { - lg := l.logger - if l.logger.Logger.IsLevelEnabled(logrus.DebugLevel) { - lg = lg.WithField("caller", l.caller(3)) - } - lg.Log(level, args...) -} - -func (l *logger) logf(level logrus.Level, format string, args ...any) { - lg := l.logger - if l.logger.Logger.IsLevelEnabled(logrus.DebugLevel) { - lg = lg.WithField("caller", l.caller(3)) - } - lg.Logf(level, format, args...) -} - -func (l *logger) caller(skip int) string { - _, file, line, ok := runtime.Caller(skip) - if !ok { - file = "" - } else { - file = filepath.Join(filepath.Base(filepath.Dir(file)), filepath.Base(file)) - } - return fmt.Sprintf("%s:%d", file, line) -} diff --git a/logger/logger.go b/logger/logger.go index 6aa1e99..18c676d 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,9 +1,5 @@ package logger -import ( - "io" -) - // LogFormat is format type type LogFormat string @@ -44,28 +40,14 @@ type Logger interface { IsLevelEnabled(level LogLevel) bool } -type LoggerOptions struct { - Output io.Writer - Format LogFormat - Level LogLevel +var ( + defaultLogger Logger +) + +func Default() Logger { + return defaultLogger } -type LoggerOption func(opts *LoggerOptions) - -func OutputLoggerOption(out io.Writer) LoggerOption { - return func(opts *LoggerOptions) { - opts.Output = out - } -} - -func FormatLoggerOption(format LogFormat) LoggerOption { - return func(opts *LoggerOptions) { - opts.Format = format - } -} - -func LevelLoggerOption(level LogLevel) LoggerOption { - return func(opts *LoggerOptions) { - opts.Level = level - } +func SetDefault(logger Logger) { + defaultLogger = logger } diff --git a/logger/nop_logger.go b/logger/nop_logger.go deleted file mode 100644 index 5a131fe..0000000 --- a/logger/nop_logger.go +++ /dev/null @@ -1,53 +0,0 @@ -package logger - -var ( - nop = &nopLogger{} -) - -func Nop() Logger { - return nop -} - -type nopLogger struct{} - -func (l *nopLogger) WithFields(fields map[string]any) Logger { - return l -} - -func (l *nopLogger) Debug(args ...any) { -} - -func (l *nopLogger) Debugf(format string, args ...any) { -} - -func (l *nopLogger) Info(args ...any) { -} - -func (l *nopLogger) Infof(format string, args ...any) { -} - -func (l *nopLogger) Warn(args ...any) { -} - -func (l *nopLogger) Warnf(format string, args ...any) { -} - -func (l *nopLogger) Error(args ...any) { -} - -func (l *nopLogger) Errorf(format string, args ...any) { -} - -func (l *nopLogger) Fatal(args ...any) { -} - -func (l *nopLogger) Fatalf(format string, args ...any) { -} - -func (l *nopLogger) GetLevel() LogLevel { - return "" -} - -func (l *nopLogger) IsLevelEnabled(level LogLevel) bool { - return false -} diff --git a/registry/admission.go b/registry/admission.go deleted file mode 100644 index 3fffb28..0000000 --- a/registry/admission.go +++ /dev/null @@ -1,40 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/admission" -) - -type admissionRegistry struct { - registry -} - -func (r *admissionRegistry) Register(name string, v admission.Admission) error { - return r.registry.Register(name, v) -} - -func (r *admissionRegistry) Get(name string) admission.Admission { - if name != "" { - return &admissionWrapper{name: name, r: r} - } - return nil -} - -func (r *admissionRegistry) get(name string) admission.Admission { - if v := r.registry.Get(name); v != nil { - return v.(admission.Admission) - } - return nil -} - -type admissionWrapper struct { - name string - r *admissionRegistry -} - -func (w *admissionWrapper) Admit(addr string) bool { - p := w.r.get(w.name) - if p == nil { - return false - } - return p.Admit(addr) -} diff --git a/registry/auther.go b/registry/auther.go deleted file mode 100644 index ecc2d36..0000000 --- a/registry/auther.go +++ /dev/null @@ -1,40 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/auth" -) - -type autherRegistry struct { - registry -} - -func (r *autherRegistry) Register(name string, v auth.Authenticator) error { - return r.registry.Register(name, v) -} - -func (r *autherRegistry) Get(name string) auth.Authenticator { - if name != "" { - return &autherWrapper{name: name, r: r} - } - return nil -} - -func (r *autherRegistry) get(name string) auth.Authenticator { - if v := r.registry.Get(name); v != nil { - return v.(auth.Authenticator) - } - return nil -} - -type autherWrapper struct { - name string - r *autherRegistry -} - -func (w *autherWrapper) Authenticate(user, password string) bool { - v := w.r.get(w.name) - if v == nil { - return true - } - return v.Authenticate(user, password) -} diff --git a/registry/bypass.go b/registry/bypass.go deleted file mode 100644 index 8a77c67..0000000 --- a/registry/bypass.go +++ /dev/null @@ -1,40 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/bypass" -) - -type bypassRegistry struct { - registry -} - -func (r *bypassRegistry) Register(name string, v bypass.Bypass) error { - return r.registry.Register(name, v) -} - -func (r *bypassRegistry) Get(name string) bypass.Bypass { - if name != "" { - return &bypassWrapper{name: name, r: r} - } - return nil -} - -func (r *bypassRegistry) get(name string) bypass.Bypass { - if v := r.registry.Get(name); v != nil { - return v.(bypass.Bypass) - } - return nil -} - -type bypassWrapper struct { - name string - r *bypassRegistry -} - -func (w *bypassWrapper) Contains(addr string) bool { - bp := w.r.get(w.name) - if bp == nil { - return false - } - return bp.Contains(addr) -} diff --git a/registry/chain.go b/registry/chain.go deleted file mode 100644 index 36d2465..0000000 --- a/registry/chain.go +++ /dev/null @@ -1,40 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/chain" -) - -type chainRegistry struct { - registry -} - -func (r *chainRegistry) Register(name string, v chain.Chainer) error { - return r.registry.Register(name, v) -} - -func (r *chainRegistry) Get(name string) chain.Chainer { - if name != "" { - return &chainWrapper{name: name, r: r} - } - return nil -} - -func (r *chainRegistry) get(name string) chain.Chainer { - if v := r.registry.Get(name); v != nil { - return v.(chain.Chainer) - } - return nil -} - -type chainWrapper struct { - name string - r *chainRegistry -} - -func (w *chainWrapper) Route(network, address string) *chain.Route { - v := w.r.get(w.name) - if v == nil { - return nil - } - return v.Route(network, address) -} diff --git a/registry/connector.go b/registry/connector.go deleted file mode 100644 index 955b49b..0000000 --- a/registry/connector.go +++ /dev/null @@ -1,26 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/connector" - "github.com/go-gost/core/logger" -) - -type NewConnector func(opts ...connector.Option) connector.Connector - -type connectorRegistry struct { - registry -} - -func (r *connectorRegistry) Register(name string, v NewConnector) error { - if err := r.registry.Register(name, v); err != nil { - logger.Default().Fatal(err) - } - return nil -} - -func (r *connectorRegistry) Get(name string) NewConnector { - if v := r.registry.Get(name); v != nil { - return v.(NewConnector) - } - return nil -} diff --git a/registry/dialer.go b/registry/dialer.go deleted file mode 100644 index 2db3b5a..0000000 --- a/registry/dialer.go +++ /dev/null @@ -1,26 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/dialer" - "github.com/go-gost/core/logger" -) - -type NewDialer func(opts ...dialer.Option) dialer.Dialer - -type dialerRegistry struct { - registry -} - -func (r *dialerRegistry) Register(name string, v NewDialer) error { - if err := r.registry.Register(name, v); err != nil { - logger.Default().Fatal(err) - } - return nil -} - -func (r *dialerRegistry) Get(name string) NewDialer { - if v := r.registry.Get(name); v != nil { - return v.(NewDialer) - } - return nil -} diff --git a/registry/handler.go b/registry/handler.go deleted file mode 100644 index c063206..0000000 --- a/registry/handler.go +++ /dev/null @@ -1,26 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/handler" - "github.com/go-gost/core/logger" -) - -type NewHandler func(opts ...handler.Option) handler.Handler - -type handlerRegistry struct { - registry -} - -func (r *handlerRegistry) Register(name string, v NewHandler) error { - if err := r.registry.Register(name, v); err != nil { - logger.Default().Fatal(err) - } - return nil -} - -func (r *handlerRegistry) Get(name string) NewHandler { - if v := r.registry.Get(name); v != nil { - return v.(NewHandler) - } - return nil -} diff --git a/registry/hosts.go b/registry/hosts.go deleted file mode 100644 index 16dacad..0000000 --- a/registry/hosts.go +++ /dev/null @@ -1,42 +0,0 @@ -package registry - -import ( - "net" - - "github.com/go-gost/core/hosts" -) - -type hostsRegistry struct { - registry -} - -func (r *hostsRegistry) Register(name string, v hosts.HostMapper) error { - return r.registry.Register(name, v) -} - -func (r *hostsRegistry) Get(name string) hosts.HostMapper { - if name != "" { - return &hostsWrapper{name: name, r: r} - } - return nil -} - -func (r *hostsRegistry) get(name string) hosts.HostMapper { - if v := r.registry.Get(name); v != nil { - return v.(hosts.HostMapper) - } - return nil -} - -type hostsWrapper struct { - name string - r *hostsRegistry -} - -func (w *hostsWrapper) Lookup(network, host string) ([]net.IP, bool) { - v := w.r.get(w.name) - if v == nil { - return nil, false - } - return v.Lookup(network, host) -} diff --git a/registry/listener.go b/registry/listener.go deleted file mode 100644 index 8d55ce3..0000000 --- a/registry/listener.go +++ /dev/null @@ -1,26 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/listener" - "github.com/go-gost/core/logger" -) - -type NewListener func(opts ...listener.Option) listener.Listener - -type listenerRegistry struct { - registry -} - -func (r *listenerRegistry) Register(name string, v NewListener) error { - if err := r.registry.Register(name, v); err != nil { - logger.Default().Fatal(err) - } - return nil -} - -func (r *listenerRegistry) Get(name string) NewListener { - if v := r.registry.Get(name); v != nil { - return v.(NewListener) - } - return nil -} diff --git a/registry/registry.go b/registry/registry.go deleted file mode 100644 index affd3d2..0000000 --- a/registry/registry.go +++ /dev/null @@ -1,116 +0,0 @@ -package registry - -import ( - "errors" - "sync" - - "github.com/go-gost/core/admission" - "github.com/go-gost/core/auth" - "github.com/go-gost/core/bypass" - "github.com/go-gost/core/chain" - "github.com/go-gost/core/hosts" - "github.com/go-gost/core/resolver" - "github.com/go-gost/core/service" -) - -var ( - ErrDup = errors.New("registry: duplicate object") -) - -var ( - listenerReg Registry[NewListener] = &listenerRegistry{} - handlerReg Registry[NewHandler] = &handlerRegistry{} - dialerReg Registry[NewDialer] = &dialerRegistry{} - connectorReg Registry[NewConnector] = &connectorRegistry{} - - serviceReg Registry[service.Service] = &serviceRegistry{} - chainReg Registry[chain.Chainer] = &chainRegistry{} - autherReg Registry[auth.Authenticator] = &autherRegistry{} - admissionReg Registry[admission.Admission] = &admissionRegistry{} - bypassReg Registry[bypass.Bypass] = &bypassRegistry{} - resolverReg Registry[resolver.Resolver] = &resolverRegistry{} - hostsReg Registry[hosts.HostMapper] = &hostsRegistry{} -) - -type Registry[T any] interface { - Register(name string, v T) error - Unregister(name string) - IsRegistered(name string) bool - Get(name string) T -} - -type registry struct { - m sync.Map -} - -func (r *registry) Register(name string, v any) error { - if name == "" || v == nil { - return nil - } - if _, loaded := r.m.LoadOrStore(name, v); loaded { - return ErrDup - } - - return nil -} - -func (r *registry) Unregister(name string) { - r.m.Delete(name) -} - -func (r *registry) IsRegistered(name string) bool { - _, ok := r.m.Load(name) - return ok -} - -func (r *registry) Get(name string) any { - if name == "" { - return nil - } - v, _ := r.m.Load(name) - return v -} - -func ListenerRegistry() Registry[NewListener] { - return listenerReg -} - -func HandlerRegistry() Registry[NewHandler] { - return handlerReg -} - -func DialerRegistry() Registry[NewDialer] { - return dialerReg -} - -func ConnectorRegistry() Registry[NewConnector] { - return connectorReg -} - -func ServiceRegistry() Registry[service.Service] { - return serviceReg -} - -func ChainRegistry() Registry[chain.Chainer] { - return chainReg -} - -func AutherRegistry() Registry[auth.Authenticator] { - return autherReg -} - -func AdmissionRegistry() Registry[admission.Admission] { - return admissionReg -} - -func BypassRegistry() Registry[bypass.Bypass] { - return bypassReg -} - -func ResolverRegistry() Registry[resolver.Resolver] { - return resolverReg -} - -func HostsRegistry() Registry[hosts.HostMapper] { - return hostsReg -} diff --git a/registry/resolver.go b/registry/resolver.go deleted file mode 100644 index bd950fa..0000000 --- a/registry/resolver.go +++ /dev/null @@ -1,43 +0,0 @@ -package registry - -import ( - "context" - "net" - - "github.com/go-gost/core/resolver" -) - -type resolverRegistry struct { - registry -} - -func (r *resolverRegistry) Register(name string, v resolver.Resolver) error { - return r.registry.Register(name, v) -} - -func (r *resolverRegistry) Get(name string) resolver.Resolver { - if name != "" { - return &resolverWrapper{name: name, r: r} - } - return nil -} - -func (r *resolverRegistry) get(name string) resolver.Resolver { - if v := r.registry.Get(name); v != nil { - return v.(resolver.Resolver) - } - return nil -} - -type resolverWrapper struct { - name string - r *resolverRegistry -} - -func (w *resolverWrapper) Resolve(ctx context.Context, network, host string) ([]net.IP, error) { - r := w.r.get(w.name) - if r == nil { - return nil, resolver.ErrInvalid - } - return r.Resolve(ctx, network, host) -} diff --git a/registry/service.go b/registry/service.go deleted file mode 100644 index 97bc25a..0000000 --- a/registry/service.go +++ /dev/null @@ -1,20 +0,0 @@ -package registry - -import ( - "github.com/go-gost/core/service" -) - -type serviceRegistry struct { - registry -} - -func (r *serviceRegistry) Register(name string, v service.Service) error { - return r.registry.Register(name, v) -} - -func (r *serviceRegistry) Get(name string) service.Service { - if v := r.registry.Get(name); v != nil { - return v.(service.Service) - } - return nil -} diff --git a/resolver/exchanger/exchanger.go b/resolver/exchanger/exchanger.go deleted file mode 100644 index 2d66d28..0000000 --- a/resolver/exchanger/exchanger.go +++ /dev/null @@ -1,223 +0,0 @@ -package exchanger - -import ( - "bytes" - "context" - "crypto/tls" - "fmt" - "io/ioutil" - "net" - "net/http" - "net/url" - "strings" - "time" - - "github.com/go-gost/core/chain" - "github.com/go-gost/core/logger" - "github.com/miekg/dns" -) - -type Options struct { - router *chain.Router - tlsConfig *tls.Config - timeout time.Duration - logger logger.Logger -} - -// Option allows a common way to set Exchanger options. -type Option func(opts *Options) - -// RouterOption sets the router for Exchanger. -func RouterOption(router *chain.Router) Option { - return func(opts *Options) { - opts.router = router - } -} - -// TLSConfigOption sets the TLS config for Exchanger. -func TLSConfigOption(cfg *tls.Config) Option { - return func(opts *Options) { - opts.tlsConfig = cfg - } -} - -// LoggerOption sets the logger for Exchanger. -func LoggerOption(logger logger.Logger) Option { - return func(opts *Options) { - opts.logger = logger - } -} - -// TimeoutOption sets the timeout for Exchanger. -func TimeoutOption(timeout time.Duration) Option { - return func(opts *Options) { - opts.timeout = timeout - } -} - -// Exchanger is an interface for DNS synchronous query. -type Exchanger interface { - Exchange(ctx context.Context, msg []byte) ([]byte, error) - String() string -} - -type exchanger struct { - network string - addr string - rawAddr string - router *chain.Router - client *http.Client - options Options -} - -// NewExchanger create an Exchanger. -// The addr should be URL-like format, -// e.g. udp://1.1.1.1:53, tls://1.1.1.1:853, https://1.0.0.1/dns-query -func NewExchanger(addr string, opts ...Option) (Exchanger, error) { - var options Options - for _, opt := range opts { - opt(&options) - } - - if !strings.Contains(addr, "://") { - addr = "udp://" + addr - } - u, err := url.Parse(addr) - if err != nil { - return nil, err - } - - if options.timeout <= 0 { - options.timeout = 5 * time.Second - } - - ex := &exchanger{ - network: u.Scheme, - addr: u.Host, - rawAddr: addr, - router: options.router, - options: options, - } - if _, port, _ := net.SplitHostPort(ex.addr); port == "" { - ex.addr = net.JoinHostPort(ex.addr, "53") - } - if ex.router == nil { - ex.router = (&chain.Router{}).WithLogger(options.logger) - } - - switch ex.network { - case "tcp": - case "dot", "tls": - if ex.options.tlsConfig == nil { - ex.options.tlsConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } - ex.network = "tcp" - case "https": - ex.addr = addr - if ex.options.tlsConfig == nil { - ex.options.tlsConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } - ex.client = &http.Client{ - Timeout: options.timeout, - Transport: &http.Transport{ - TLSClientConfig: options.tlsConfig, - ForceAttemptHTTP2: true, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: options.timeout, - ExpectContinueTimeout: 1 * time.Second, - DialContext: ex.dial, - }, - } - default: - ex.network = "udp" - } - - return ex, nil -} - -func (ex *exchanger) Exchange(ctx context.Context, msg []byte) ([]byte, error) { - if ex.network == "https" { - return ex.dohExchange(ctx, msg) - } - return ex.exchange(ctx, msg) -} - -func (ex *exchanger) dohExchange(ctx context.Context, msg []byte) ([]byte, error) { - req, err := http.NewRequestWithContext(ctx, "POST", ex.addr, bytes.NewBuffer(msg)) - if err != nil { - return nil, fmt.Errorf("failed to create an HTTPS request: %w", err) - } - - // req.Header.Add("Content-Type", "application/dns-udpwireformat") - req.Header.Add("Content-Type", "application/dns-message") - - client := ex.client - if client == nil { - client = http.DefaultClient - } - resp, err := client.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to perform an HTTPS request: %w", err) - } - - // Check response status code - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("returned status code %d", resp.StatusCode) - } - - // Read wireformat response from the body - buf, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to read the response body: %w", err) - } - - return buf, nil -} - -func (ex *exchanger) exchange(ctx context.Context, msg []byte) ([]byte, error) { - if ex.options.timeout > 0 { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, ex.options.timeout) - defer cancel() - } - - c, err := ex.dial(ctx, ex.network, ex.addr) - if err != nil { - return nil, err - } - defer c.Close() - - if ex.options.tlsConfig != nil { - c = tls.Client(c, ex.options.tlsConfig) - } - - conn := &dns.Conn{ - UDPSize: 1024, - Conn: c, - } - - if _, err = conn.Write(msg); err != nil { - return nil, err - } - - mr, err := conn.ReadMsg() - if err != nil { - return nil, err - } - - return mr.Pack() -} - -func (ex *exchanger) dial(ctx context.Context, network, address string) (net.Conn, error) { - return ex.router.Dial(ctx, network, address) -} - -func (ex *exchanger) String() string { - return ex.rawAddr -} diff --git a/resolver/impl/resolver.go b/resolver/impl/resolver.go deleted file mode 100644 index fd813d9..0000000 --- a/resolver/impl/resolver.go +++ /dev/null @@ -1,178 +0,0 @@ -package impl - -import ( - "context" - "net" - "strings" - "time" - - "github.com/go-gost/core/chain" - resolver_util "github.com/go-gost/core/common/util/resolver" - "github.com/go-gost/core/logger" - resolverpkg "github.com/go-gost/core/resolver" - "github.com/go-gost/core/resolver/exchanger" - "github.com/miekg/dns" -) - -type NameServer struct { - Addr string - Chain chain.Chainer - TTL time.Duration - Timeout time.Duration - ClientIP net.IP - Prefer string - Hostname string // for TLS handshake verification - exchanger exchanger.Exchanger -} - -type resolverOptions struct { - domain string - logger logger.Logger -} - -type ResolverOption func(opts *resolverOptions) - -func DomainResolverOption(domain string) ResolverOption { - return func(opts *resolverOptions) { - opts.domain = domain - } -} - -func LoggerResolverOption(logger logger.Logger) ResolverOption { - return func(opts *resolverOptions) { - opts.logger = logger - } -} - -type resolver struct { - servers []NameServer - cache *resolver_util.Cache - options resolverOptions -} - -func NewResolver(nameservers []NameServer, opts ...ResolverOption) (resolverpkg.Resolver, error) { - options := resolverOptions{} - for _, opt := range opts { - opt(&options) - } - - var servers []NameServer - for _, server := range nameservers { - addr := strings.TrimSpace(server.Addr) - if addr == "" { - continue - } - ex, err := exchanger.NewExchanger( - addr, - exchanger.RouterOption( - (&chain.Router{}). - WithChain(server.Chain). - WithLogger(options.logger), - ), - exchanger.TimeoutOption(server.Timeout), - exchanger.LoggerOption(options.logger), - ) - if err != nil { - options.logger.Warnf("parse %s: %v", server, err) - continue - } - - server.exchanger = ex - servers = append(servers, server) - } - cache := resolver_util.NewCache(). - WithLogger(options.logger) - - return &resolver{ - servers: servers, - cache: cache, - options: options, - }, nil -} - -func (r *resolver) Resolve(ctx context.Context, network, host string) (ips []net.IP, err error) { - if ip := net.ParseIP(host); ip != nil { - return []net.IP{ip}, nil - } - - if r.options.domain != "" && - !strings.Contains(host, ".") { - host = host + "." + r.options.domain - } - - for _, server := range r.servers { - ips, err = r.resolve(ctx, &server, host) - if err != nil { - r.options.logger.Error(err) - continue - } - - r.options.logger.Debugf("resolve %s via %s: %v", host, server.exchanger.String(), ips) - - if len(ips) > 0 { - break - } - } - - return -} - -func (r *resolver) resolve(ctx context.Context, server *NameServer, host string) (ips []net.IP, err error) { - if server == nil { - return - } - - if server.Prefer == "ipv6" { // prefer ipv6 - mq := dns.Msg{} - mq.SetQuestion(dns.Fqdn(host), dns.TypeAAAA) - ips, err = r.resolveIPs(ctx, server, &mq) - if err != nil || len(ips) > 0 { - return - } - } - - // fallback to ipv4 - mq := dns.Msg{} - mq.SetQuestion(dns.Fqdn(host), dns.TypeA) - return r.resolveIPs(ctx, server, &mq) -} - -func (r *resolver) resolveIPs(ctx context.Context, server *NameServer, mq *dns.Msg) (ips []net.IP, err error) { - key := resolver_util.NewCacheKey(&mq.Question[0]) - mr := r.cache.Load(key) - if mr == nil { - resolver_util.AddSubnetOpt(mq, server.ClientIP) - mr, err = r.exchange(ctx, server.exchanger, mq) - if err != nil { - return - } - r.cache.Store(key, mr, server.TTL) - } - - for _, ans := range mr.Answer { - if ar, _ := ans.(*dns.AAAA); ar != nil { - ips = append(ips, ar.AAAA) - } - if ar, _ := ans.(*dns.A); ar != nil { - ips = append(ips, ar.A) - } - } - - return -} - -func (r *resolver) exchange(ctx context.Context, ex exchanger.Exchanger, mq *dns.Msg) (mr *dns.Msg, err error) { - query, err := mq.Pack() - if err != nil { - return - } - reply, err := ex.Exchange(ctx, query) - if err != nil { - return - } - - mr = &dns.Msg{} - err = mr.Unpack(reply) - - return -} diff --git a/resolver/resolver.go b/resolver/resolver.go index ad0435c..b8a7354 100644 --- a/resolver/resolver.go +++ b/resolver/resolver.go @@ -7,7 +7,7 @@ import ( ) var ( - ErrInvalid = errors.New("resolver is invalid") + ErrInvalid = errors.New("invalid resolver") ) type Resolver interface {