update handler options

This commit is contained in:
ginuerzh 2022-01-04 21:56:58 +08:00
parent 566e930010
commit c428b37a36
36 changed files with 468 additions and 524 deletions

View File

@ -7,7 +7,6 @@ import (
"os" "os"
"strings" "strings"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass" "github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/config" "github.com/go-gost/gost/pkg/config"
@ -71,7 +70,7 @@ func buildService(cfg *config.Config) (services []*service.Service) {
}) })
ln := registry.GetListener(svc.Listener.Type)( ln := registry.GetListener(svc.Listener.Type)(
listener.AddrOption(svc.Addr), listener.AddrOption(svc.Addr),
listener.AuthenticatorOption(authFromConfig(svc.Listener.Auths...)), listener.AuthsOption(authsFromConfig(svc.Listener.Auths...)...),
listener.LoggerOption(listenerLogger), listener.LoggerOption(listenerLogger),
) )
@ -91,15 +90,13 @@ func buildService(cfg *config.Config) (services []*service.Service) {
}) })
h := registry.GetHandler(svc.Handler.Type)( h := registry.GetHandler(svc.Handler.Type)(
handler.LoggerOption(handlerLogger), handler.RetriesOption(svc.Handler.Retries),
handler.ChainOption(chains[svc.Handler.Chain]),
handler.ResolverOption(resolvers[svc.Handler.Resolver]),
handler.HostsOption(hosts[svc.Handler.Hosts]),
handler.BypassOption(bypasses[svc.Handler.Bypass]), handler.BypassOption(bypasses[svc.Handler.Bypass]),
handler.AuthenticatorOption(authFromConfig(svc.Handler.Auths...)), handler.AuthsOption(authsFromConfig(svc.Handler.Auths...)...),
handler.RouterOption(&chain.Router{ handler.LoggerOption(handlerLogger),
Chain: chains[svc.Handler.Chain],
Resolver: resolvers[svc.Handler.Resolver],
Hosts: hosts[svc.Handler.Hosts],
Logger: handlerLogger,
}),
) )
if forwarder, ok := h.(handler.Forwarder); ok { if forwarder, ok := h.(handler.Forwarder); ok {
@ -331,17 +328,15 @@ func hostsFromConfig(cfg *config.HostsConfig) hostspkg.HostMapper {
return hosts return hosts
} }
func authFromConfig(cfgs ...config.AuthConfig) auth.Authenticator { func authsFromConfig(cfgs ...config.AuthConfig) []*url.Userinfo {
auths := make(map[string]string) var auths []*url.Userinfo
for _, cfg := range cfgs { for _, cfg := range cfgs {
if cfg.Username == "" { if cfg.Username == "" {
continue continue
} }
auths[cfg.Username] = cfg.Password auths = append(auths, url.UserPassword(cfg.Username, cfg.Password))
}
if len(auths) > 0 {
return auth.NewMapAuthenticator(auths)
} }
return nil return auths
} }

View File

@ -11,10 +11,7 @@ type MapAuthenticator struct {
} }
// NewMapAuthenticator creates an Authenticator that authenticates client by local infos. // NewMapAuthenticator creates an Authenticator that authenticates client by local infos.
func NewMapAuthenticator(kvs map[string]string) *MapAuthenticator { func NewMapAuthenticator(kvs map[string]string) Authenticator {
if kvs == nil {
kvs = make(map[string]string)
}
return &MapAuthenticator{ return &MapAuthenticator{
kvs: kvs, kvs: kvs,
} }
@ -22,11 +19,7 @@ func NewMapAuthenticator(kvs map[string]string) *MapAuthenticator {
// Authenticate checks the validity of the provided user-password pair. // Authenticate checks the validity of the provided user-password pair.
func (au *MapAuthenticator) Authenticate(user, password string) bool { func (au *MapAuthenticator) Authenticate(user, password string) bool {
if au == nil { if au == nil || len(au.kvs) == 0 {
return true
}
if len(au.kvs) == 0 {
return true return true
} }

View File

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

View File

@ -88,6 +88,7 @@ type ListenerConfig struct {
type HandlerConfig struct { type HandlerConfig struct {
Type string Type string
Retries int `yaml:",omitempty"`
Chain string `yaml:",omitempty"` Chain string `yaml:",omitempty"`
Bypass string `yaml:",omitempty"` Bypass string `yaml:",omitempty"`
Resolver string `yaml:",omitempty"` Resolver string `yaml:",omitempty"`

View File

@ -15,7 +15,6 @@ type metadata struct {
func (c *httpConnector) parseMetadata(md mdata.Metadata) (err error) { func (c *httpConnector) parseMetadata(md mdata.Metadata) (err error) {
const ( const (
connectTimeout = "timeout" connectTimeout = "timeout"
user = "user"
header = "header" header = "header"
) )

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/url"
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
@ -24,20 +23,19 @@ func init() {
type socks5Connector struct { type socks5Connector struct {
selector gosocks5.Selector selector gosocks5.Selector
user *url.Userinfo
logger logger.Logger logger logger.Logger
md metadata md metadata
options connector.Options
} }
func NewConnector(opts ...connector.Option) connector.Connector { func NewConnector(opts ...connector.Option) connector.Connector {
options := &connector.Options{} options := connector.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &socks5Connector{ return &socks5Connector{
user: options.User, options: options,
logger: options.Logger,
} }
} }
@ -46,13 +44,15 @@ func (c *socks5Connector) Init(md md.Metadata) (err error) {
return return
} }
c.logger = c.options.Logger
selector := &clientSelector{ selector := &clientSelector{
methods: []uint8{ methods: []uint8{
gosocks5.MethodNoAuth, gosocks5.MethodNoAuth,
gosocks5.MethodUserPass, gosocks5.MethodUserPass,
}, },
logger: c.logger, logger: c.logger,
User: c.user, User: c.options.User,
TLSConfig: c.md.tlsConfig, TLSConfig: c.md.tlsConfig,
} }
if !c.md.noTLS { if !c.md.noTLS {

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"net" "net"
"net/url"
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
@ -22,20 +21,20 @@ func init() {
} }
type ssConnector struct { type ssConnector struct {
user *url.Userinfo
cipher core.Cipher cipher core.Cipher
md metadata md metadata
logger logger.Logger logger logger.Logger
options connector.Options
} }
func NewConnector(opts ...connector.Option) connector.Connector { func NewConnector(opts ...connector.Option) connector.Connector {
options := &connector.Options{} options := connector.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &ssConnector{ return &ssConnector{
user: options.User, options: options,
logger: options.Logger, logger: options.Logger,
} }
} }
@ -45,9 +44,9 @@ func (c *ssConnector) Init(md md.Metadata) (err error) {
return return
} }
if c.user != nil { if c.options.User != nil {
method := c.user.Username() method := c.options.User.Username()
password, _ := c.user.Password() password, _ := c.options.User.Password()
c.cipher, err = ss.ShadowCipher(method, password, c.md.key) c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
} }

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"net" "net"
"net/url"
"time" "time"
"github.com/go-gost/gost/pkg/common/util/socks" "github.com/go-gost/gost/pkg/common/util/socks"
@ -21,20 +20,20 @@ func init() {
} }
type ssuConnector struct { type ssuConnector struct {
user *url.Userinfo
cipher core.Cipher cipher core.Cipher
md metadata md metadata
logger logger.Logger logger logger.Logger
options connector.Options
} }
func NewConnector(opts ...connector.Option) connector.Connector { func NewConnector(opts ...connector.Option) connector.Connector {
options := &connector.Options{} options := connector.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &ssuConnector{ return &ssuConnector{
user: options.User, options: options,
logger: options.Logger, logger: options.Logger,
} }
} }
@ -44,9 +43,9 @@ func (c *ssuConnector) Init(md md.Metadata) (err error) {
return return
} }
if c.user != nil { if c.options.User != nil {
method := c.user.Username() method := c.options.User.Username()
password, _ := c.user.Password() password, _ := c.options.User.Password()
c.cipher, err = ss.ShadowCipher(method, password, c.md.key) c.cipher, err = ss.ShadowCipher(method, password, c.md.key)
} }

View File

@ -9,7 +9,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/common/bufpool" "github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
@ -30,27 +29,22 @@ func init() {
} }
type dnsHandler struct { type dnsHandler struct {
bypass bypass.Bypass
router *chain.Router
exchangers []exchanger.Exchanger exchangers []exchanger.Exchanger
cache *resolver_util.Cache cache *resolver_util.Cache
router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
cache := resolver_util.NewCache().WithLogger(options.Logger)
return &dnsHandler{ return &dnsHandler{
bypass: options.Bypass, options: options,
router: options.Router,
cache: cache,
logger: options.Logger,
} }
} }
@ -59,6 +53,16 @@ func (h *dnsHandler) Init(md md.Metadata) (err error) {
return return
} }
h.cache = resolver_util.NewCache().WithLogger(h.options.Logger)
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
for _, server := range h.md.servers { for _, server := range h.md.servers {
server = strings.TrimSpace(server) server = strings.TrimSpace(server)
if server == "" { if server == "" {
@ -89,6 +93,7 @@ func (h *dnsHandler) Init(md md.Metadata) (err error) {
} }
h.exchangers = append(h.exchangers, ex) h.exchangers = append(h.exchangers, ex)
} }
return return
} }

View File

@ -6,7 +6,6 @@ import (
"net" "net"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -22,22 +21,20 @@ func init() {
type forwardHandler struct { type forwardHandler struct {
group *chain.NodeGroup group *chain.NodeGroup
bypass bypass.Bypass
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &forwardHandler{ return &forwardHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
@ -51,7 +48,16 @@ func (h *forwardHandler) Init(md md.Metadata) (err error) {
h.group = chain.NewNodeGroup(chain.NewNode("dummy", ":0")) h.group = chain.NewNodeGroup(chain.NewNode("dummy", ":0"))
} }
return nil h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return
} }
// Forward implements handler.Forwarder. // Forward implements handler.Forwarder.

View File

@ -6,7 +6,6 @@ import (
"net" "net"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -21,26 +20,20 @@ func init() {
type forwardHandler struct { type forwardHandler struct {
group *chain.NodeGroup group *chain.NodeGroup
bypass bypass.Bypass
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &forwardHandler{ return &forwardHandler{
bypass: options.Bypass, options: options,
router: &chain.Router{
Retries: options.Router.Retries,
Resolver: options.Resolver,
Logger: options.Logger,
},
logger: options.Logger,
} }
} }
@ -48,6 +41,16 @@ func (h *forwardHandler) Init(md md.Metadata) (err error) {
if err = h.parseMetadata(md); err != nil { if err = h.parseMetadata(md); err != nil {
return return
} }
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return return
} }

View File

@ -8,9 +8,8 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh" ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -32,24 +31,21 @@ func init() {
} }
type forwardHandler struct { type forwardHandler struct {
bypass bypass.Bypass
config *ssh.ServerConfig config *ssh.ServerConfig
router *chain.Router router *chain.Router
authenticator auth.Authenticator
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &forwardHandler{ return &forwardHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
@ -58,18 +54,28 @@ func (h *forwardHandler) Init(md md.Metadata) (err error) {
return return
} }
authenticator := auth_util.AuthFromUsers(h.options.Auths...)
config := &ssh.ServerConfig{ config := &ssh.ServerConfig{
PasswordCallback: ssh_util.PasswordCallback(h.authenticator), PasswordCallback: ssh_util.PasswordCallback(authenticator),
PublicKeyCallback: ssh_util.PublicKeyCallback(h.md.authorizedKeys), PublicKeyCallback: ssh_util.PublicKeyCallback(h.md.authorizedKeys),
} }
config.AddHostKey(h.md.signer) config.AddHostKey(h.md.signer)
if h.authenticator == nil && len(h.md.authorizedKeys) == 0 { if authenticator == nil && len(h.md.authorizedKeys) == 0 {
config.NoClientAuth = true config.NoClientAuth = true
} }
h.config = config h.config = config
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return nil return nil
} }
@ -161,7 +167,7 @@ func (h *forwardHandler) directPortForwardChannel(ctx context.Context, channel s
} }
*/ */
if h.bypass != nil && h.bypass.Contains(raddr) { if h.options.Bypass != nil && h.options.Bypass.Contains(raddr) {
h.logger.Infof("bypass %s", raddr) h.logger.Infof("bypass %s", raddr)
return return
} }

View File

@ -17,8 +17,8 @@ import (
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/go-gost/gost/pkg/auth" "github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
@ -30,23 +30,21 @@ func init() {
} }
type httpHandler struct { type httpHandler struct {
bypass bypass.Bypass
router *chain.Router router *chain.Router
authenticator auth.Authenticator authenticator auth.Authenticator
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &httpHandler{ return &httpHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
@ -55,6 +53,16 @@ func (h *httpHandler) Init(md md.Metadata) error {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return nil return nil
} }
@ -141,7 +149,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
resp.Header = http.Header{} resp.Header = http.Header{}
} }
if h.bypass != nil && h.bypass.Contains(addr) { if h.options.Bypass != nil && h.options.Bypass.Contains(addr) {
resp.StatusCode = http.StatusForbidden resp.StatusCode = http.StatusForbidden
if h.logger.IsLevelEnabled(logger.DebugLevel) { if h.logger.IsLevelEnabled(logger.DebugLevel) {

View File

@ -64,7 +64,7 @@ func (h *httpHandler) handleUDP(ctx context.Context, conn net.Conn, network, add
} }
relay := handler.NewUDPRelay(socks.UDPTunServerConn(conn), pc). relay := handler.NewUDPRelay(socks.UDPTunServerConn(conn), pc).
WithBypass(h.bypass). WithBypass(h.options.Bypass).
WithLogger(h.logger) WithLogger(h.logger)
t := time.Now() t := time.Now()

View File

@ -14,10 +14,9 @@ import (
"strings" "strings"
"time" "time"
"github.com/asaskevich/govalidator"
"github.com/go-gost/gost/pkg/auth" "github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
http2_util "github.com/go-gost/gost/pkg/internal/util/http2" http2_util "github.com/go-gost/gost/pkg/internal/util/http2"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -30,23 +29,21 @@ func init() {
} }
type http2Handler struct { type http2Handler struct {
bypass bypass.Bypass
router *chain.Router router *chain.Router
authenticator auth.Authenticator authenticator auth.Authenticator
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &http2Handler{ return &http2Handler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
@ -55,6 +52,15 @@ func (h *http2Handler) Init(md md.Metadata) error {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return nil return nil
} }
@ -133,7 +139,7 @@ func (h *http2Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req
} }
*/ */
if h.bypass != nil && h.bypass.Contains(addr) { if h.options.Bypass != nil && h.options.Bypass.Contains(addr) {
w.WriteHeader(http.StatusForbidden) w.WriteHeader(http.StatusForbidden)
h.logger.Info("bypass: ", addr) h.logger.Info("bypass: ", addr)
return return
@ -203,156 +209,6 @@ func (h *http2Handler) roundTrip(ctx context.Context, w http.ResponseWriter, req
} }
} }
func (h *http2Handler) handleRequest(ctx context.Context, conn net.Conn, req *http.Request) {
if req == nil {
return
}
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]interface{}{
"dst": addr,
}
if u, _, _ := h.basicProxyAuth(req.Header.Get("Proxy-Authorization")); u != "" {
fields["user"] = u
}
h.logger = h.logger.WithFields(fields)
if h.logger.IsLevelEnabled(logger.DebugLevel) {
dump, _ := httputil.DumpRequest(req, false)
h.logger.Debug(string(dump))
}
h.logger.Infof("%s >> %s", conn.RemoteAddr(), addr)
resp := &http.Response{
ProtoMajor: 1,
ProtoMinor: 1,
Header: http.Header{},
}
if h.md.proxyAgent != "" {
resp.Header.Add("Proxy-Agent", h.md.proxyAgent)
}
/*
if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) {
log.Logf("[http] %s - %s : Unauthorized to tcp connect to %s",
conn.RemoteAddr(), conn.LocalAddr(), host)
resp.StatusCode = http.StatusForbidden
if Debug {
dump, _ := httputil.DumpResponse(resp, false)
log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(dump))
}
resp.Write(conn)
return
}
*/
if h.bypass != nil && h.bypass.Contains(addr) {
resp.StatusCode = http.StatusForbidden
if h.logger.IsLevelEnabled(logger.DebugLevel) {
dump, _ := httputil.DumpResponse(resp, false)
h.logger.Debug(string(dump))
}
h.logger.Info("bypass: ", addr)
resp.Write(conn)
return
}
if !h.authenticate(conn, req, resp) {
return
}
if req.Method == "PRI" ||
(req.Method != http.MethodConnect && req.URL.Scheme != "http") {
resp.StatusCode = http.StatusBadRequest
resp.Write(conn)
if h.logger.IsLevelEnabled(logger.DebugLevel) {
dump, _ := httputil.DumpResponse(resp, false)
h.logger.Debug(string(dump))
}
return
}
req.Header.Del("Proxy-Authorization")
cc, err := h.router.Dial(ctx, network, addr)
if err != nil {
resp.StatusCode = http.StatusServiceUnavailable
resp.Write(conn)
if h.logger.IsLevelEnabled(logger.DebugLevel) {
dump, _ := httputil.DumpResponse(resp, false)
h.logger.Debug(string(dump))
}
return
}
defer cc.Close()
if req.Method == http.MethodConnect {
resp.StatusCode = http.StatusOK
resp.Status = "200 Connection established"
if h.logger.IsLevelEnabled(logger.DebugLevel) {
dump, _ := httputil.DumpResponse(resp, false)
h.logger.Debug(string(dump))
}
if err = resp.Write(conn); err != nil {
h.logger.Error(err)
return
}
} else {
req.Header.Del("Proxy-Connection")
if err = req.Write(cc); err != nil {
h.logger.Error(err)
return
}
}
start := time.Now()
h.logger.Infof("%s <-> %s", conn.RemoteAddr(), addr)
handler.Transport(conn, cc)
h.logger.
WithFields(map[string]interface{}{
"duration": time.Since(start),
}).
Infof("%s >-< %s", conn.RemoteAddr(), addr)
}
func (h *http2Handler) decodeServerName(s string) (string, error) { func (h *http2Handler) decodeServerName(s string) (string, error) {
b, err := base64.RawURLEncoding.DecodeString(s) b, err := base64.RawURLEncoding.DecodeString(s)
if err != nil { if err != nil {

View File

@ -1,26 +1,48 @@
package handler package handler
import ( import (
"github.com/go-gost/gost/pkg/auth" "net/url"
"github.com/go-gost/gost/pkg/bypass" "github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/hosts"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
"github.com/go-gost/gost/pkg/resolver" "github.com/go-gost/gost/pkg/resolver"
) )
type Options struct { type Options struct {
Router *chain.Router Retries int
Bypass bypass.Bypass Chain *chain.Chain
Resolver resolver.Resolver Resolver resolver.Resolver
Authenticator auth.Authenticator Hosts hosts.HostMapper
Bypass bypass.Bypass
Auths []*url.Userinfo
Logger logger.Logger Logger logger.Logger
} }
type Option func(opts *Options) type Option func(opts *Options)
func RouterOption(router *chain.Router) Option { func RetriesOption(retries int) Option {
return func(opts *Options) { return func(opts *Options) {
opts.Router = router opts.Retries = retries
}
}
func ChainOption(chain *chain.Chain) Option {
return func(opts *Options) {
opts.Chain = chain
}
}
func ResolverOption(resolver resolver.Resolver) Option {
return func(opts *Options) {
opts.Resolver = resolver
}
}
func HostsOption(hosts hosts.HostMapper) Option {
return func(opts *Options) {
opts.Hosts = hosts
} }
} }
@ -30,9 +52,9 @@ func BypassOption(bypass bypass.Bypass) Option {
} }
} }
func AuthenticatorOption(auth auth.Authenticator) Option { func AuthsOption(auths ...*url.Userinfo) Option {
return func(opts *Options) { return func(opts *Options) {
opts.Authenticator = auth opts.Auths = auths
} }
} }

View File

@ -6,7 +6,6 @@ import (
"net" "net"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -22,27 +21,38 @@ func init() {
} }
type redirectHandler struct { type redirectHandler struct {
bypass bypass.Bypass
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &redirectHandler{ return &redirectHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
func (h *redirectHandler) Init(md md.Metadata) (err error) { func (h *redirectHandler) Init(md md.Metadata) (err error) {
return h.parseMetadata(md) if err = h.parseMetadata(md); err != nil {
return
}
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return
} }
func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn) { func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn) {
@ -84,7 +94,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn) {
h.logger.Infof("%s >> %s", conn.RemoteAddr(), dstAddr) h.logger.Infof("%s >> %s", conn.RemoteAddr(), dstAddr)
if h.bypass != nil && h.bypass.Contains(dstAddr.String()) { if h.options.Bypass != nil && h.options.Bypass.Contains(dstAddr.String()) {
h.logger.Info("bypass: ", dstAddr) h.logger.Info("bypass: ", dstAddr)
return return
} }

View File

@ -201,7 +201,7 @@ func (h *relayHandler) tunnelServerUDP(tunnel, c net.PacketConn) (err error) {
return err return err
} }
if h.bypass != nil && h.bypass.Contains(raddr.String()) { if h.options.Bypass != nil && h.options.Bypass.Contains(raddr.String()) {
h.logger.Warn("bypass: ", raddr) h.logger.Warn("bypass: ", raddr)
return nil return nil
} }
@ -234,7 +234,7 @@ func (h *relayHandler) tunnelServerUDP(tunnel, c net.PacketConn) (err error) {
return err return err
} }
if h.bypass != nil && h.bypass.Contains(raddr.String()) { if h.options.Bypass != nil && h.options.Bypass.Contains(raddr.String()) {
h.logger.Warn("bypass: ", raddr) h.logger.Warn("bypass: ", raddr)
return nil return nil
} }

View File

@ -30,7 +30,7 @@ func (h *relayHandler) handleConnect(ctx context.Context, conn net.Conn, network
return return
} }
if h.bypass != nil && h.bypass.Contains(address) { if h.options.Bypass != nil && h.options.Bypass.Contains(address) {
h.logger.Info("bypass: ", address) h.logger.Info("bypass: ", address)
resp.Status = relay.StatusForbidden resp.Status = relay.StatusForbidden
resp.WriteTo(conn) resp.WriteTo(conn)

View File

@ -7,8 +7,8 @@ import (
"time" "time"
"github.com/go-gost/gost/pkg/auth" "github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
@ -22,23 +22,21 @@ func init() {
type relayHandler struct { type relayHandler struct {
group *chain.NodeGroup group *chain.NodeGroup
bypass bypass.Bypass
router *chain.Router router *chain.Router
authenticator auth.Authenticator authenticator auth.Authenticator
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &relayHandler{ return &relayHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
@ -47,6 +45,15 @@ func (h *relayHandler) Init(md md.Metadata) (err error) {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return nil return nil
} }

View File

@ -11,7 +11,6 @@ import (
"net" "net"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/common/bufpool" "github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
@ -27,16 +26,16 @@ func init() {
type sniHandler struct { type sniHandler struct {
httpHandler handler.Handler httpHandler handler.Handler
bypass bypass.Bypass
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
log := options.Logger log := options.Logger
@ -45,8 +44,7 @@ func NewHandler(opts ...handler.Option) handler.Handler {
} }
h := &sniHandler{ h := &sniHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: log, logger: log,
} }
@ -72,6 +70,14 @@ func (h *sniHandler) Init(md md.Metadata) (err error) {
} }
} }
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
return nil return nil
} }
@ -132,7 +138,7 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn) {
}) })
h.logger.Infof("%s >> %s", conn.RemoteAddr(), target) h.logger.Infof("%s >> %s", conn.RemoteAddr(), target)
if h.bypass != nil && h.bypass.Contains(target) { if h.options.Bypass != nil && h.options.Bypass.Contains(target) {
h.logger.Info("bypass: ", target) h.logger.Info("bypass: ", target)
return return
} }

View File

@ -7,8 +7,8 @@ import (
"github.com/go-gost/gosocks4" "github.com/go-gost/gosocks4"
"github.com/go-gost/gost/pkg/auth" "github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
@ -21,23 +21,21 @@ func init() {
} }
type socks4Handler struct { type socks4Handler struct {
bypass bypass.Bypass
router *chain.Router router *chain.Router
authenticator auth.Authenticator authenticator auth.Authenticator
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &socks4Handler{ return &socks4Handler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
@ -46,6 +44,16 @@ func (h *socks4Handler) Init(md md.Metadata) (err error) {
return err return err
} }
h.authenticator = auth_util.AuthFromUsers(h.options.Auths...)
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return nil return nil
} }
@ -105,7 +113,7 @@ func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *g
}) })
h.logger.Infof("%s >> %s", conn.RemoteAddr(), addr) h.logger.Infof("%s >> %s", conn.RemoteAddr(), addr)
if h.bypass != nil && h.bypass.Contains(addr) { if h.options.Bypass != nil && h.options.Bypass.Contains(addr) {
resp := gosocks4.NewReply(gosocks4.Rejected, nil) resp := gosocks4.NewReply(gosocks4.Rejected, nil)
resp.Write(conn) resp.Write(conn)
h.logger.Debug(resp) h.logger.Debug(resp)

View File

@ -17,7 +17,7 @@ func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, networ
}) })
h.logger.Infof("%s >> %s", conn.RemoteAddr(), address) h.logger.Infof("%s >> %s", conn.RemoteAddr(), address)
if h.bypass != nil && h.bypass.Contains(address) { if h.options.Bypass != nil && h.options.Bypass.Contains(address) {
resp := gosocks5.NewReply(gosocks5.NotAllowed, nil) resp := gosocks5.NewReply(gosocks5.NotAllowed, nil)
resp.Write(conn) resp.Write(conn)
h.logger.Debug(resp) h.logger.Debug(resp)

View File

@ -6,9 +6,8 @@ import (
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
auth_util "github.com/go-gost/gost/pkg/common/util/auth"
"github.com/go-gost/gost/pkg/common/util/socks" "github.com/go-gost/gost/pkg/common/util/socks"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -23,23 +22,20 @@ func init() {
type socks5Handler struct { type socks5Handler struct {
selector gosocks5.Selector selector gosocks5.Selector
bypass bypass.Bypass
router *chain.Router router *chain.Router
authenticator auth.Authenticator
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &socks5Handler{ return &socks5Handler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
@ -48,8 +44,17 @@ func (h *socks5Handler) Init(md md.Metadata) (err error) {
return return
} }
h.logger = h.options.Logger
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.selector = &serverSelector{ h.selector = &serverSelector{
Authenticator: h.authenticator, Authenticator: auth_util.AuthFromUsers(h.options.Auths...),
TLSConfig: h.md.tlsConfig, TLSConfig: h.md.tlsConfig,
logger: h.logger, logger: h.logger,
noTLS: h.md.noTLS, noTLS: h.md.noTLS,

View File

@ -67,7 +67,7 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn) {
} }
relay := handler.NewUDPRelay(socks.UDPConn(cc, h.md.udpBufferSize), pc). relay := handler.NewUDPRelay(socks.UDPConn(cc, h.md.udpBufferSize), pc).
WithBypass(h.bypass). WithBypass(h.options.Bypass).
WithLogger(h.logger) WithLogger(h.logger)
relay.SetBufferSize(h.md.udpBufferSize) relay.SetBufferSize(h.md.udpBufferSize)

View File

@ -46,7 +46,7 @@ func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, network
} }
relay := handler.NewUDPRelay(socks.UDPTunServerConn(conn), pc). relay := handler.NewUDPRelay(socks.UDPTunServerConn(conn), pc).
WithBypass(h.bypass). WithBypass(h.options.Bypass).
WithLogger(h.logger) WithLogger(h.logger)
relay.SetBufferSize(h.md.udpBufferSize) relay.SetBufferSize(h.md.udpBufferSize)

View File

@ -8,13 +8,13 @@ import (
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/common/util/ss" "github.com/go-gost/gost/pkg/common/util/ss"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry" "github.com/go-gost/gost/pkg/registry"
"github.com/shadowsocks/go-shadowsocks2/core"
) )
func init() { func init() {
@ -22,31 +22,47 @@ func init() {
} }
type ssHandler struct { type ssHandler struct {
bypass bypass.Bypass cipher core.Cipher
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &ssHandler{ return &ssHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
func (h *ssHandler) Init(md md.Metadata) (err error) { func (h *ssHandler) Init(md md.Metadata) (err error) {
if err := h.parseMetadata(md); err != nil { if err = h.parseMetadata(md); err != nil {
return err return
}
if len(h.options.Auths) > 0 {
method := h.options.Auths[0].Username()
password, _ := h.options.Auths[0].Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil {
return
}
} }
return nil h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return
} }
func (h *ssHandler) Handle(ctx context.Context, conn net.Conn) { func (h *ssHandler) Handle(ctx context.Context, conn net.Conn) {
@ -65,8 +81,8 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn) {
}).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr()) }).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr())
}() }()
if h.md.cipher != nil { if h.cipher != nil {
conn = ss.ShadowConn(h.md.cipher.StreamConn(conn), nil) conn = ss.ShadowConn(h.cipher.StreamConn(conn), nil)
} }
if h.md.readTimeout > 0 { if h.md.readTimeout > 0 {
@ -86,7 +102,7 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn) {
h.logger.Infof("%s >> %s", conn.RemoteAddr(), addr) h.logger.Infof("%s >> %s", conn.RemoteAddr(), addr)
if h.bypass != nil && h.bypass.Contains(addr.String()) { if h.options.Bypass != nil && h.options.Bypass.Contains(addr.String()) {
h.logger.Info("bypass: ", addr.String()) h.logger.Info("bypass: ", addr.String())
return return
} }

View File

@ -1,41 +1,23 @@
package ss package ss
import ( import (
"strings"
"time" "time"
"github.com/go-gost/gost/pkg/common/util/ss"
mdata "github.com/go-gost/gost/pkg/metadata" mdata "github.com/go-gost/gost/pkg/metadata"
"github.com/shadowsocks/go-shadowsocks2/core"
) )
type metadata struct { type metadata struct {
cipher core.Cipher key string
readTimeout time.Duration readTimeout time.Duration
} }
func (h *ssHandler) parseMetadata(md mdata.Metadata) (err error) { func (h *ssHandler) parseMetadata(md mdata.Metadata) (err error) {
const ( const (
users = "users"
key = "key" key = "key"
readTimeout = "readTimeout" readTimeout = "readTimeout"
) )
var method, password string h.md.key = mdata.GetString(md, key)
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
auth := auths[0]
ss := strings.SplitN(auth, ":", 2)
if len(ss) == 1 {
method = ss[0]
} else {
method, password = ss[0], ss[1]
}
}
h.md.cipher, err = ss.ShadowCipher(method, password, mdata.GetString(md, key))
if err != nil {
return
}
h.md.readTimeout = mdata.GetDuration(md, readTimeout) h.md.readTimeout = mdata.GetDuration(md, readTimeout)
return return

View File

@ -5,7 +5,6 @@ import (
"net" "net"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/common/bufpool" "github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/pkg/common/util/socks" "github.com/go-gost/gost/pkg/common/util/socks"
@ -14,6 +13,7 @@ import (
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry" "github.com/go-gost/gost/pkg/registry"
"github.com/shadowsocks/go-shadowsocks2/core"
) )
func init() { func init() {
@ -21,31 +21,48 @@ func init() {
} }
type ssuHandler struct { type ssuHandler struct {
bypass bypass.Bypass cipher core.Cipher
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &ssuHandler{ return &ssuHandler{
bypass: options.Bypass, options: options,
router: options.Router,
logger: options.Logger,
} }
} }
func (h *ssuHandler) Init(md md.Metadata) (err error) { func (h *ssuHandler) Init(md md.Metadata) (err error) {
if err := h.parseMetadata(md); err != nil { if err = h.parseMetadata(md); err != nil {
return err return
} }
return nil if len(h.options.Auths) > 0 {
method := h.options.Auths[0].Username()
password, _ := h.options.Auths[0].Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil {
return
}
}
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return
} }
func (h *ssuHandler) Handle(ctx context.Context, conn net.Conn) { func (h *ssuHandler) Handle(ctx context.Context, conn net.Conn) {
@ -66,14 +83,14 @@ func (h *ssuHandler) Handle(ctx context.Context, conn net.Conn) {
pc, ok := conn.(net.PacketConn) pc, ok := conn.(net.PacketConn)
if ok { if ok {
if h.md.cipher != nil { if h.cipher != nil {
pc = h.md.cipher.PacketConn(pc) pc = h.cipher.PacketConn(pc)
} }
// standard UDP relay. // standard UDP relay.
pc = ss.UDPServerConn(pc, conn.RemoteAddr(), h.md.bufferSize) pc = ss.UDPServerConn(pc, conn.RemoteAddr(), h.md.bufferSize)
} else { } else {
if h.md.cipher != nil { if h.cipher != nil {
conn = ss.ShadowConn(h.md.cipher.StreamConn(conn), nil) conn = ss.ShadowConn(h.cipher.StreamConn(conn), nil)
} }
// UDP over TCP // UDP over TCP
pc = socks.UDPTunServerConn(conn) pc = socks.UDPTunServerConn(conn)
@ -116,7 +133,7 @@ func (h *ssuHandler) relayPacket(pc1, pc2 net.PacketConn) (err error) {
return err return err
} }
if h.bypass != nil && h.bypass.Contains(addr.String()) { if h.options.Bypass != nil && h.options.Bypass.Contains(addr.String()) {
h.logger.Warn("bypass: ", addr) h.logger.Warn("bypass: ", addr)
return nil return nil
} }
@ -148,7 +165,7 @@ func (h *ssuHandler) relayPacket(pc1, pc2 net.PacketConn) (err error) {
return err return err
} }
if h.bypass != nil && h.bypass.Contains(raddr.String()) { if h.options.Bypass != nil && h.options.Bypass.Contains(raddr.String()) {
h.logger.Warn("bypass: ", raddr) h.logger.Warn("bypass: ", raddr)
return nil return nil
} }

View File

@ -2,43 +2,25 @@ package ss
import ( import (
"math" "math"
"strings"
"time" "time"
"github.com/go-gost/gost/pkg/common/util/ss"
mdata "github.com/go-gost/gost/pkg/metadata" mdata "github.com/go-gost/gost/pkg/metadata"
"github.com/shadowsocks/go-shadowsocks2/core"
) )
type metadata struct { type metadata struct {
cipher core.Cipher key string
readTimeout time.Duration readTimeout time.Duration
bufferSize int bufferSize int
} }
func (h *ssuHandler) parseMetadata(md mdata.Metadata) (err error) { func (h *ssuHandler) parseMetadata(md mdata.Metadata) (err error) {
const ( const (
users = "users"
key = "key" key = "key"
readTimeout = "readTimeout" readTimeout = "readTimeout"
bufferSize = "bufferSize" bufferSize = "bufferSize"
) )
var method, password string h.md.key = mdata.GetString(md, key)
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
auth := auths[0]
ss := strings.SplitN(auth, ":", 2)
if len(ss) == 1 {
method = ss[0]
} else {
method, password = ss[0], ss[1]
}
}
h.md.cipher, err = ss.ShadowCipher(method, password, mdata.GetString(md, key))
if err != nil {
return
}
h.md.readTimeout = mdata.GetDuration(md, readTimeout) h.md.readTimeout = mdata.GetDuration(md, readTimeout)
if bs := mdata.GetInt(md, bufferSize); bs > 0 { if bs := mdata.GetInt(md, bufferSize); bs > 0 {

View File

@ -10,14 +10,15 @@ import (
"sync" "sync"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/common/bufpool" "github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/pkg/common/util/ss"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
tap_util "github.com/go-gost/gost/pkg/internal/util/tap" tap_util "github.com/go-gost/gost/pkg/internal/util/tap"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry" "github.com/go-gost/gost/pkg/registry"
"github.com/shadowsocks/go-shadowsocks2/core"
"github.com/shadowsocks/go-shadowsocks2/shadowaead" "github.com/shadowsocks/go-shadowsocks2/shadowaead"
"github.com/songgao/water/waterutil" "github.com/songgao/water/waterutil"
) )
@ -28,34 +29,51 @@ func init() {
type tapHandler struct { type tapHandler struct {
group *chain.NodeGroup group *chain.NodeGroup
bypass bypass.Bypass
routes sync.Map routes sync.Map
exit chan struct{} exit chan struct{}
cipher core.Cipher
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &tapHandler{ return &tapHandler{
bypass: options.Bypass,
router: options.Router,
logger: options.Logger,
exit: make(chan struct{}, 1), exit: make(chan struct{}, 1),
options: options,
} }
} }
func (h *tapHandler) Init(md md.Metadata) (err error) { func (h *tapHandler) Init(md md.Metadata) (err error) {
if err := h.parseMetadata(md); err != nil { if err = h.parseMetadata(md); err != nil {
return err return
} }
return nil if len(h.options.Auths) > 0 {
method := h.options.Auths[0].Username()
password, _ := h.options.Auths[0].Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil {
return
}
}
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return
} }
// Forward implements handler.Forwarder. // Forward implements handler.Forwarder.
@ -132,8 +150,8 @@ func (h *tapHandler) handleLoop(ctx context.Context, conn net.Conn, addr net.Add
return err return err
} }
if h.md.cipher != nil { if h.cipher != nil {
pc = h.md.cipher.PacketConn(pc) pc = h.cipher.PacketConn(pc)
} }
return h.transport(conn, pc, addr) return h.transport(conn, pc, addr)

View File

@ -1,42 +1,21 @@
package tap package tap
import ( import (
"strings"
"github.com/go-gost/gost/pkg/common/util/ss"
mdata "github.com/go-gost/gost/pkg/metadata" mdata "github.com/go-gost/gost/pkg/metadata"
"github.com/shadowsocks/go-shadowsocks2/core"
) )
type metadata struct { type metadata struct {
cipher core.Cipher key string
retryCount int
bufferSize int bufferSize int
} }
func (h *tapHandler) parseMetadata(md mdata.Metadata) (err error) { func (h *tapHandler) parseMetadata(md mdata.Metadata) (err error) {
const ( const (
users = "users"
key = "key" key = "key"
readTimeout = "readTimeout"
bufferSize = "bufferSize" bufferSize = "bufferSize"
) )
var method, password string h.md.key = mdata.GetString(md, key)
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
auth := auths[0]
ss := strings.SplitN(auth, ":", 2)
if len(ss) == 1 {
method = ss[0]
} else {
method, password = ss[0], ss[1]
}
}
h.md.cipher, err = ss.ShadowCipher(method, password, mdata.GetString(md, key))
if err != nil {
return
}
h.md.bufferSize = mdata.GetInt(md, bufferSize) h.md.bufferSize = mdata.GetInt(md, bufferSize)
if h.md.bufferSize <= 0 { if h.md.bufferSize <= 0 {
h.md.bufferSize = 1024 h.md.bufferSize = 1024

View File

@ -10,14 +10,15 @@ import (
"sync" "sync"
"time" "time"
"github.com/go-gost/gost/pkg/bypass"
"github.com/go-gost/gost/pkg/chain" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/common/bufpool" "github.com/go-gost/gost/pkg/common/bufpool"
"github.com/go-gost/gost/pkg/common/util/ss"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
tun_util "github.com/go-gost/gost/pkg/internal/util/tun" tun_util "github.com/go-gost/gost/pkg/internal/util/tun"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata" md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry" "github.com/go-gost/gost/pkg/registry"
"github.com/shadowsocks/go-shadowsocks2/core"
"github.com/shadowsocks/go-shadowsocks2/shadowaead" "github.com/shadowsocks/go-shadowsocks2/shadowaead"
"github.com/songgao/water/waterutil" "github.com/songgao/water/waterutil"
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
@ -30,34 +31,51 @@ func init() {
type tunHandler struct { type tunHandler struct {
group *chain.NodeGroup group *chain.NodeGroup
bypass bypass.Bypass
routes sync.Map routes sync.Map
exit chan struct{} exit chan struct{}
cipher core.Cipher
router *chain.Router router *chain.Router
logger logger.Logger logger logger.Logger
md metadata md metadata
options handler.Options
} }
func NewHandler(opts ...handler.Option) handler.Handler { func NewHandler(opts ...handler.Option) handler.Handler {
options := &handler.Options{} options := handler.Options{}
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(&options)
} }
return &tunHandler{ return &tunHandler{
bypass: options.Bypass,
router: options.Router,
logger: options.Logger,
exit: make(chan struct{}, 1), exit: make(chan struct{}, 1),
options: options,
} }
} }
func (h *tunHandler) Init(md md.Metadata) (err error) { func (h *tunHandler) Init(md md.Metadata) (err error) {
if err := h.parseMetadata(md); err != nil { if err = h.parseMetadata(md); err != nil {
return err return
} }
return nil if len(h.options.Auths) > 0 {
method := h.options.Auths[0].Username()
password, _ := h.options.Auths[0].Password()
h.cipher, err = ss.ShadowCipher(method, password, h.md.key)
if err != nil {
return
}
}
h.router = &chain.Router{
Retries: h.options.Retries,
Chain: h.options.Chain,
Resolver: h.options.Resolver,
Hosts: h.options.Hosts,
Logger: h.options.Logger,
}
h.logger = h.options.Logger
return
} }
// Forward implements handler.Forwarder. // Forward implements handler.Forwarder.
@ -133,8 +151,8 @@ func (h *tunHandler) handleLoop(ctx context.Context, conn net.Conn, addr net.Add
return err return err
} }
if h.md.cipher != nil { if h.cipher != nil {
pc = h.md.cipher.PacketConn(pc) pc = h.cipher.PacketConn(pc)
} }
return h.transport(conn, pc, addr) return h.transport(conn, pc, addr)

View File

@ -1,41 +1,21 @@
package tun package tun
import ( import (
"strings"
"github.com/go-gost/gost/pkg/common/util/ss"
mdata "github.com/go-gost/gost/pkg/metadata" mdata "github.com/go-gost/gost/pkg/metadata"
"github.com/shadowsocks/go-shadowsocks2/core"
) )
type metadata struct { type metadata struct {
cipher core.Cipher key string
bufferSize int bufferSize int
} }
func (h *tunHandler) parseMetadata(md mdata.Metadata) (err error) { func (h *tunHandler) parseMetadata(md mdata.Metadata) (err error) {
const ( const (
users = "users"
key = "key" key = "key"
readTimeout = "readTimeout"
bufferSize = "bufferSize" bufferSize = "bufferSize"
) )
var method, password string h.md.key = mdata.GetString(md, key)
if auths := mdata.GetStrings(md, users); len(auths) > 0 {
auth := auths[0]
ss := strings.SplitN(auth, ":", 2)
if len(ss) == 1 {
method = ss[0]
} else {
method, password = ss[0], ss[1]
}
}
h.md.cipher, err = ss.ShadowCipher(method, password, mdata.GetString(md, key))
if err != nil {
return
}
h.md.bufferSize = mdata.GetInt(md, bufferSize) h.md.bufferSize = mdata.GetInt(md, bufferSize)
if h.md.bufferSize <= 0 { if h.md.bufferSize <= 0 {
h.md.bufferSize = 1024 h.md.bufferSize = 1024

View File

@ -1,13 +1,14 @@
package listener package listener
import ( import (
"github.com/go-gost/gost/pkg/auth" "net/url"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
) )
type Options struct { type Options struct {
Addr string Addr string
Authenticator auth.Authenticator Auths []*url.Userinfo
Logger logger.Logger Logger logger.Logger
} }
@ -19,9 +20,9 @@ func AddrOption(addr string) Option {
} }
} }
func AuthenticatorOption(auth auth.Authenticator) Option { func AuthsOption(auths ...*url.Userinfo) Option {
return func(opts *Options) { return func(opts *Options) {
opts.Authenticator = auth opts.Auths = auths
} }
} }

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"net" "net"
"github.com/go-gost/gost/pkg/auth" auth_util "github.com/go-gost/gost/pkg/common/util/auth"
ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh" ssh_util "github.com/go-gost/gost/pkg/internal/util/ssh"
"github.com/go-gost/gost/pkg/listener" "github.com/go-gost/gost/pkg/listener"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
@ -21,11 +21,11 @@ type sshListener struct {
addr string addr string
net.Listener net.Listener
config *ssh.ServerConfig config *ssh.ServerConfig
authenticator auth.Authenticator
cqueue chan net.Conn cqueue chan net.Conn
errChan chan error errChan chan error
logger logger.Logger logger logger.Logger
md metadata md metadata
options listener.Options
} }
func NewListener(opts ...listener.Option) listener.Listener { func NewListener(opts ...listener.Option) listener.Listener {
@ -51,14 +51,13 @@ func (l *sshListener) Init(md md.Metadata) (err error) {
l.Listener = ln l.Listener = ln
authenticator := auth_util.AuthFromUsers(l.options.Auths...)
config := &ssh.ServerConfig{ config := &ssh.ServerConfig{
PasswordCallback: ssh_util.PasswordCallback(l.authenticator), PasswordCallback: ssh_util.PasswordCallback(authenticator),
PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys), PublicKeyCallback: ssh_util.PublicKeyCallback(l.md.authorizedKeys),
} }
config.AddHostKey(l.md.signer) config.AddHostKey(l.md.signer)
if authenticator == nil && len(l.md.authorizedKeys) == 0 {
if l.authenticator == nil && len(l.md.authorizedKeys) == 0 {
config.NoClientAuth = true config.NoClientAuth = true
} }