This commit is contained in:
ginuerzh 2021-11-15 12:55:05 +08:00
parent 3fe5084629
commit ce3d62759a
38 changed files with 788 additions and 291 deletions

View File

@ -47,6 +47,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.ChainOption(chains[svc.Listener.Chain]),
listener.LoggerOption(listenerLogger), listener.LoggerOption(listenerLogger),
) )
if err := ln.Init(metadata.MapMetadata(svc.Listener.Metadata)); err != nil { if err := ln.Init(metadata.MapMetadata(svc.Listener.Metadata)); err != nil {
@ -59,8 +60,8 @@ func buildService(cfg *config.Config) (services []*service.Service) {
}) })
h := registry.GetHandler(svc.Handler.Type)( h := registry.GetHandler(svc.Handler.Type)(
handler.ChainOption(chains[svc.Chain]), handler.ChainOption(chains[svc.Handler.Chain]),
handler.BypassOption(bypasses[svc.Bypass]), handler.BypassOption(bypasses[svc.Handler.Bypass]),
handler.LoggerOption(handlerLogger), handler.LoggerOption(handlerLogger),
) )

View File

@ -13,6 +13,8 @@ services:
addr: ":28000" addr: ":28000"
handler: handler:
type: http type: http
chain: chain01
# bypass: bypass01
metadata: metadata:
proxyAgent: "gost/3.0" proxyAgent: "gost/3.0"
retry: 3 retry: 3
@ -25,13 +27,13 @@ services:
type: tcp type: tcp
metadata: metadata:
keepAlive: 15s keepAlive: 15s
chain: chain01
# bypass: bypass01
- name: ss - name: ss
url: "ss://chacha20:gost@:8000" url: "ss://chacha20:gost@:8000"
addr: ":28338" addr: ":28338"
handler: handler:
type: ss type: ss
# chain: chain01
# bypass: bypass01
metadata: metadata:
method: chacha20-ietf method: chacha20-ietf
password: gost password: gost
@ -43,26 +45,26 @@ services:
type: tcp type: tcp
metadata: metadata:
keepAlive: 15s keepAlive: 15s
# chain: chain01
# bypass: bypass01
- name: socks5 - name: socks5
url: "socks5://gost:gost@:1080" url: "socks5://gost:gost@:1080"
addr: ":21080" addr: ":21080"
handler: handler:
type: socks5 type: socks5
# chain: chain-ss
# bypass: bypass01
metadata: metadata:
auths: auths:
- gost:gost - gost:gost
readTimeout: 5s readTimeout: 5s
retry: 3 retry: 3
notls: true notls: true
bind: true
udp: true
# udpBufferSize: 4096 # range [512, 66560] # udpBufferSize: 4096 # range [512, 66560]
listener: listener:
type: tcp type: tcp
metadata: metadata:
keepAlive: 15s keepAlive: 15s
chain: chain-ss
# bypass: bypass01
- name: socks5+tcp - name: socks5+tcp
url: "socks5://gost:gost@:1080" url: "socks5://gost:gost@:1080"
addr: ":21081" addr: ":21081"
@ -93,6 +95,7 @@ services:
failTimeout: 30s failTimeout: 30s
handler: handler:
type: forward type: forward
chain: chain-ss
metadata: metadata:
readTimeout: 5s readTimeout: 5s
retry: 3 retry: 3
@ -100,7 +103,38 @@ services:
type: udp type: udp
metadata: metadata:
keepAlive: 15s keepAlive: 15s
chain: chain-ss
- name: kcp-forward-tunnel
addr: ":8388"
forwarder:
targets:
- 127.0.0.1:28338
handler:
type: forward
metadata:
readTimeout: 5s
retry: 3
listener:
type: kcp
metadata:
keepAlive: 15s
- name: rtcp
addr: ":28100"
forwarder:
targets:
- 192.168.8.8:80
handler:
type: forward
metadata:
readTimeout: 5s
retry: 3
listener:
type: rtcp
chain: chain-socks5
metadata:
keepAlive: 15s
mux: true
chains: chains:
- name: chain01 - name: chain01
@ -179,7 +213,7 @@ chains:
- name: hop01 - name: hop01
nodes: nodes:
- name: node01 - name: node01
addr: ":11080" addr: ":21080"
url: "http://gost:gost@:8081" url: "http://gost:gost@:8081"
# bypass: bypass01 # bypass: bypass01
connector: connector:

View File

@ -26,6 +26,7 @@ import (
_ "github.com/go-gost/gost/pkg/listener/obfs/http" _ "github.com/go-gost/gost/pkg/listener/obfs/http"
_ "github.com/go-gost/gost/pkg/listener/obfs/tls" _ "github.com/go-gost/gost/pkg/listener/obfs/tls"
_ "github.com/go-gost/gost/pkg/listener/quic" _ "github.com/go-gost/gost/pkg/listener/quic"
_ "github.com/go-gost/gost/pkg/listener/rtcp"
_ "github.com/go-gost/gost/pkg/listener/tcp" _ "github.com/go-gost/gost/pkg/listener/tcp"
_ "github.com/go-gost/gost/pkg/listener/tls" _ "github.com/go-gost/gost/pkg/listener/tls"
_ "github.com/go-gost/gost/pkg/listener/tls/mux" _ "github.com/go-gost/gost/pkg/listener/tls/mux"

View File

@ -1,4 +1,4 @@
package handler package chain
import ( import (
"bytes" "bytes"
@ -6,17 +6,16 @@ import (
"fmt" "fmt"
"net" "net"
"github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
) )
type Router struct { type Router struct {
chain *chain.Chain chain *Chain
retries int retries int
logger logger.Logger logger logger.Logger
} }
func (r *Router) WithChain(chain *chain.Chain) *Router { func (r *Router) WithChain(chain *Chain) *Router {
r.chain = chain r.chain = chain
return r return r
} }

View File

@ -42,11 +42,14 @@ type BypassConfig struct {
} }
type ListenerConfig struct { type ListenerConfig struct {
Type string Type string
Chain string
Metadata map[string]interface{} Metadata map[string]interface{}
} }
type HandlerConfig struct { type HandlerConfig struct {
Type string Type string
Chain string
Bypass string
Metadata map[string]interface{} Metadata map[string]interface{}
} }
@ -72,8 +75,6 @@ type ServiceConfig struct {
Listener *ListenerConfig Listener *ListenerConfig
Handler *HandlerConfig Handler *HandlerConfig
Forwarder *ForwarderConfig Forwarder *ForwarderConfig
Chain string
Bypass string
} }
type ChainConfig struct { type ChainConfig struct {

View File

@ -9,7 +9,6 @@ import (
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"strings"
"time" "time"
"github.com/go-gost/gost/pkg/connector" "github.com/go-gost/gost/pkg/connector"
@ -111,22 +110,3 @@ func (c *httpConnector) Connect(ctx context.Context, conn net.Conn, network, add
return conn, nil return conn, nil
} }
func (c *httpConnector) parseMetadata(md md.Metadata) (err error) {
c.md.connectTimeout = md.GetDuration(connectTimeout)
c.md.UserAgent, _ = md.Get(userAgent).(string)
if c.md.UserAgent == "" {
c.md.UserAgent = defaultUserAgent
}
if v := md.GetString(auth); v != "" {
ss := strings.SplitN(v, ":", 2)
if len(ss) == 1 {
c.md.User = url.User(ss[0])
} else {
c.md.User = url.UserPassword(ss[0], ss[1])
}
}
return
}

View File

@ -2,13 +2,10 @@ package http
import ( import (
"net/url" "net/url"
"strings"
"time" "time"
)
const ( md "github.com/go-gost/gost/pkg/metadata"
connectTimeout = "timeout"
userAgent = "userAgent"
auth = "auth"
) )
const ( const (
@ -20,3 +17,28 @@ type metadata struct {
UserAgent string UserAgent string
User *url.Userinfo User *url.Userinfo
} }
func (c *httpConnector) parseMetadata(md md.Metadata) (err error) {
const (
connectTimeout = "timeout"
userAgent = "userAgent"
auth = "auth"
)
c.md.connectTimeout = md.GetDuration(connectTimeout)
c.md.UserAgent, _ = md.Get(userAgent).(string)
if c.md.UserAgent == "" {
c.md.UserAgent = defaultUserAgent
}
if v := md.GetString(auth); v != "" {
ss := strings.SplitN(v, ":", 2)
if len(ss) == 1 {
c.md.User = url.User(ss[0])
} else {
c.md.User = url.UserPassword(ss[0], ss[1])
}
}
return
}

View File

@ -5,7 +5,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/url"
"strconv" "strconv"
"time" "time"
@ -114,13 +113,3 @@ func (c *socks4Connector) Connect(ctx context.Context, conn net.Conn, network, a
return conn, nil return conn, nil
} }
func (c *socks4Connector) parseMetadata(md md.Metadata) (err error) {
if v := md.GetString(auth); v != "" {
c.md.User = url.User(v)
}
c.md.connectTimeout = md.GetDuration(connectTimeout)
c.md.disable4a = md.GetBool(disable4a)
return
}

View File

@ -3,12 +3,8 @@ package v4
import ( import (
"net/url" "net/url"
"time" "time"
)
const ( md "github.com/go-gost/gost/pkg/metadata"
connectTimeout = "timeout"
auth = "auth"
disable4a = "disable4a"
) )
type metadata struct { type metadata struct {
@ -16,3 +12,19 @@ type metadata struct {
User *url.Userinfo User *url.Userinfo
disable4a bool disable4a bool
} }
func (c *socks4Connector) parseMetadata(md md.Metadata) (err error) {
const (
connectTimeout = "timeout"
auth = "auth"
disable4a = "disable4a"
)
if v := md.GetString(auth); v != "" {
c.md.User = url.User(v)
}
c.md.connectTimeout = md.GetDuration(connectTimeout)
c.md.disable4a = md.GetBool(disable4a)
return
}

View File

@ -6,8 +6,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/url"
"strings"
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
@ -172,19 +170,3 @@ func (c *socks5Connector) connectUDP(ctx context.Context, conn net.Conn, network
return socks.UDPTunClientConn(conn, addr), nil return socks.UDPTunClientConn(conn, addr), nil
} }
func (c *socks5Connector) parseMetadata(md md.Metadata) (err error) {
if v := md.GetString(auth); v != "" {
ss := strings.SplitN(v, ":", 2)
if len(ss) == 1 {
c.md.User = url.User(ss[0])
} else {
c.md.User = url.UserPassword(ss[0], ss[1])
}
}
c.md.connectTimeout = md.GetDuration(connectTimeout)
c.md.noTLS = md.GetBool(noTLS)
return
}

View File

@ -3,13 +3,10 @@ package v5
import ( import (
"crypto/tls" "crypto/tls"
"net/url" "net/url"
"strings"
"time" "time"
)
const ( md "github.com/go-gost/gost/pkg/metadata"
connectTimeout = "timeout"
auth = "auth"
noTLS = "notls"
) )
type metadata struct { type metadata struct {
@ -18,3 +15,25 @@ type metadata struct {
tlsConfig *tls.Config tlsConfig *tls.Config
noTLS bool noTLS bool
} }
func (c *socks5Connector) parseMetadata(md md.Metadata) (err error) {
const (
connectTimeout = "timeout"
auth = "auth"
noTLS = "notls"
)
if v := md.GetString(auth); v != "" {
ss := strings.SplitN(v, ":", 2)
if len(ss) == 1 {
c.md.User = url.User(ss[0])
} else {
c.md.User = url.UserPassword(ss[0], ss[1])
}
}
c.md.connectTimeout = md.GetDuration(connectTimeout)
c.md.noTLS = md.GetBool(noTLS)
return
}

View File

@ -75,7 +75,7 @@ func (h *localForwardHandler) Handle(ctx context.Context, conn net.Conn) {
h.logger.Infof("%s >> %s", conn.RemoteAddr(), target.Addr()) h.logger.Infof("%s >> %s", conn.RemoteAddr(), target.Addr())
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)
@ -105,9 +105,3 @@ func (h *localForwardHandler) Handle(ctx context.Context, conn net.Conn) {
}). }).
Infof("%s >-< %s", conn.RemoteAddr(), target.Addr()) Infof("%s >-< %s", conn.RemoteAddr(), target.Addr())
} }
func (h *localForwardHandler) parseMetadata(md md.Metadata) (err error) {
h.md.readTimeout = md.GetDuration(readTimeout)
h.md.retryCount = md.GetInt(retryCount)
return
}

View File

@ -2,14 +2,22 @@ package local
import ( import (
"time" "time"
)
const ( md "github.com/go-gost/gost/pkg/metadata"
readTimeout = "readTimeout"
retryCount = "retry"
) )
type metadata struct { type metadata struct {
readTimeout time.Duration readTimeout time.Duration
retryCount int retryCount int
} }
func (h *localForwardHandler) parseMetadata(md md.Metadata) (err error) {
const (
readTimeout = "readTimeout"
retryCount = "retry"
)
h.md.readTimeout = md.GetDuration(readTimeout)
h.md.retryCount = md.GetInt(retryCount)
return
}

View File

@ -15,7 +15,6 @@ import (
"strings" "strings"
"time" "time"
"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/handler" "github.com/go-gost/gost/pkg/handler"
@ -52,38 +51,6 @@ func (h *httpHandler) Init(md md.Metadata) error {
return h.parseMetadata(md) return h.parseMetadata(md)
} }
func (h *httpHandler) parseMetadata(md md.Metadata) error {
h.md.proxyAgent = md.GetString(proxyAgentKey)
if v, _ := md.Get(authsKey).([]interface{}); len(v) > 0 {
authenticator := auth.NewLocalAuthenticator(nil)
for _, auth := range v {
if s, _ := auth.(string); s != "" {
ss := strings.SplitN(s, ":", 2)
if len(ss) == 1 {
authenticator.Add(ss[0], "")
} else {
authenticator.Add(ss[0], ss[1])
}
}
}
h.md.authenticator = authenticator
}
if v := md.GetString(probeResistKey); v != "" {
if ss := strings.SplitN(v, ":", 2); len(ss) == 2 {
h.md.probeResist = &probeResist{
Type: ss[0],
Value: ss[1],
Knock: md.GetString(knockKey),
}
}
}
h.md.retryCount = md.GetInt(retryCount)
return nil
}
func (h *httpHandler) Handle(ctx context.Context, conn net.Conn) { func (h *httpHandler) Handle(ctx context.Context, conn net.Conn) {
defer conn.Close() defer conn.Close()
@ -209,7 +176,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
req.Header.Del("Proxy-Authorization") req.Header.Del("Proxy-Authorization")
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)

View File

@ -1,13 +1,10 @@
package http package http
import "github.com/go-gost/gost/pkg/auth" import (
"strings"
const ( "github.com/go-gost/gost/pkg/auth"
proxyAgentKey = "proxyAgent" md "github.com/go-gost/gost/pkg/metadata"
authsKey = "auths"
probeResistKey = "probeResist"
knockKey = "knock"
retryCount = "retry"
) )
type metadata struct { type metadata struct {
@ -17,6 +14,46 @@ type metadata struct {
probeResist *probeResist probeResist *probeResist
} }
func (h *httpHandler) parseMetadata(md md.Metadata) error {
const (
proxyAgentKey = "proxyAgent"
authsKey = "auths"
probeResistKey = "probeResist"
knockKey = "knock"
retryCount = "retry"
)
h.md.proxyAgent = md.GetString(proxyAgentKey)
if v, _ := md.Get(authsKey).([]interface{}); len(v) > 0 {
authenticator := auth.NewLocalAuthenticator(nil)
for _, auth := range v {
if s, _ := auth.(string); s != "" {
ss := strings.SplitN(s, ":", 2)
if len(ss) == 1 {
authenticator.Add(ss[0], "")
} else {
authenticator.Add(ss[0], ss[1])
}
}
}
h.md.authenticator = authenticator
}
if v := md.GetString(probeResistKey); v != "" {
if ss := strings.SplitN(v, ":", 2); len(ss) == 2 {
h.md.probeResist = &probeResist{
Type: ss[0],
Value: ss[1],
Knock: md.GetString(knockKey),
}
}
}
h.md.retryCount = md.GetInt(retryCount)
return nil
}
type probeResist struct { type probeResist struct {
Type string Type string
Value string Value string

View File

@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/go-gost/gosocks4" "github.com/go-gost/gosocks4"
"github.com/go-gost/gost/pkg/auth"
"github.com/go-gost/gost/pkg/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/handler" "github.com/go-gost/gost/pkg/handler"
@ -108,7 +107,7 @@ func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *g
return return
} }
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)
@ -142,19 +141,3 @@ func (h *socks4Handler) handleConnect(ctx context.Context, conn net.Conn, req *g
func (h *socks4Handler) handleBind(ctx context.Context, conn net.Conn, req *gosocks4.Request) { func (h *socks4Handler) handleBind(ctx context.Context, conn net.Conn, req *gosocks4.Request) {
// TODO: bind // TODO: bind
} }
func (h *socks4Handler) parseMetadata(md md.Metadata) (err error) {
if v, _ := md.Get(authsKey).([]interface{}); len(v) > 0 {
authenticator := auth.NewLocalAuthenticator(nil)
for _, auth := range v {
if v, _ := auth.(string); v != "" {
authenticator.Add(v, "")
}
}
h.md.authenticator = authenticator
}
h.md.readTimeout = md.GetDuration(readTimeout)
h.md.retryCount = md.GetInt(retryCount)
return
}

View File

@ -4,12 +4,7 @@ import (
"time" "time"
"github.com/go-gost/gost/pkg/auth" "github.com/go-gost/gost/pkg/auth"
) md "github.com/go-gost/gost/pkg/metadata"
const (
authsKey = "auths"
readTimeout = "readTimeout"
retryCount = "retry"
) )
type metadata struct { type metadata struct {
@ -17,3 +12,25 @@ type metadata struct {
readTimeout time.Duration readTimeout time.Duration
retryCount int retryCount int
} }
func (h *socks4Handler) parseMetadata(md md.Metadata) (err error) {
const (
authsKey = "auths"
readTimeout = "readTimeout"
retryCount = "retry"
)
if v, _ := md.Get(authsKey).([]interface{}); len(v) > 0 {
authenticator := auth.NewLocalAuthenticator(nil)
for _, auth := range v {
if v, _ := auth.(string); v != "" {
authenticator.Add(v, "")
}
}
h.md.authenticator = authenticator
}
h.md.readTimeout = md.GetDuration(readTimeout)
h.md.retryCount = md.GetInt(retryCount)
return
}

View File

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
) )
@ -19,12 +20,20 @@ func (h *socks5Handler) handleBind(ctx context.Context, conn net.Conn, req *goso
h.logger.Infof("%s >> %s", conn.RemoteAddr(), addr) h.logger.Infof("%s >> %s", conn.RemoteAddr(), addr)
if !h.md.enableBind {
reply := gosocks5.NewReply(gosocks5.NotAllowed, nil)
reply.Write(conn)
h.logger.Debug(reply)
h.logger.Error("BIND is diabled")
return
}
if h.chain.IsEmpty() { if h.chain.IsEmpty() {
h.bindLocal(ctx, conn, addr) h.bindLocal(ctx, conn, addr)
return return
} }
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)
@ -83,7 +92,7 @@ func (h *socks5Handler) bindLocal(ctx context.Context, conn net.Conn, addr strin
h.logger = h.logger.WithFields(map[string]interface{}{ h.logger = h.logger.WithFields(map[string]interface{}{
"bind": socksAddr.String(), "bind": socksAddr.String(),
}) })
h.logger.Infof("bind on %s OK", socksAddr.String()) h.logger.Debugf("bind on %s OK", &socksAddr)
h.serveBind(ctx, conn, ln) h.serveBind(ctx, conn, ln)
} }
@ -127,10 +136,19 @@ func (h *socks5Handler) serveBind(ctx context.Context, conn net.Conn, ln net.Lis
case err := <-accept(): case err := <-accept():
if err != nil { if err != nil {
h.logger.Error(err) h.logger.Error(err)
reply := gosocks5.NewReply(gosocks5.Failure, nil)
if err := reply.Write(pc2); err != nil {
h.logger.Error(err)
}
h.logger.Debug(reply)
return return
} }
defer rc.Close() defer rc.Close()
h.logger.Debugf("peer %s accepted", rc.RemoteAddr())
raddr := gosocks5.Addr{} raddr := gosocks5.Addr{}
raddr.ParseFrom(rc.RemoteAddr().String()) raddr.ParseFrom(rc.RemoteAddr().String())
reply := gosocks5.NewReply(gosocks5.Succeeded, &raddr) reply := gosocks5.NewReply(gosocks5.Succeeded, &raddr)
@ -138,7 +156,6 @@ func (h *socks5Handler) serveBind(ctx context.Context, conn net.Conn, ln net.Lis
h.logger.Error(err) h.logger.Error(err)
} }
h.logger.Debug(reply) h.logger.Debug(reply)
h.logger.Infof("peer accepted: %s", raddr.String())
start := time.Now() start := time.Now()
h.logger.Infof("%s <-> %s", conn.RemoteAddr(), raddr.String()) h.logger.Infof("%s <-> %s", conn.RemoteAddr(), raddr.String())

View File

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/handler"
) )
@ -24,7 +25,7 @@ func (h *socks5Handler) handleConnect(ctx context.Context, conn net.Conn, addr s
return return
} }
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)

View File

@ -90,29 +90,13 @@ func (h *socks5Handler) Handle(ctx context.Context, conn net.Conn) {
case gosocks5.CmdConnect: case gosocks5.CmdConnect:
h.handleConnect(ctx, conn, req.Addr.String()) h.handleConnect(ctx, conn, req.Addr.String())
case gosocks5.CmdBind: case gosocks5.CmdBind:
if h.md.enableBind { h.handleBind(ctx, conn, req)
h.handleBind(ctx, conn, req)
} else {
h.logger.Error("BIND is diabled")
}
case socks.CmdMuxBind: case socks.CmdMuxBind:
if h.md.enableBind { h.handleMuxBind(ctx, conn, req)
h.handleMuxBind(ctx, conn, req)
} else {
h.logger.Error("BIND is diabled")
}
case gosocks5.CmdUdp: case gosocks5.CmdUdp:
if h.md.enableUDP { h.handleUDP(ctx, conn, req)
h.handleUDP(ctx, conn, req)
} else {
h.logger.Error("UDP relay is diabled")
}
case socks.CmdUDPTun: case socks.CmdUDPTun:
if h.md.enableUDP { h.handleUDPTun(ctx, conn, req)
h.handleUDPTun(ctx, conn, req)
} else {
h.logger.Error("UDP relay is diabled")
}
default: default:
h.logger.Errorf("unknown cmd: %d", req.Cmd) h.logger.Errorf("unknown cmd: %d", req.Cmd)
resp := gosocks5.NewReply(gosocks5.CmdUnsupported, nil) resp := gosocks5.NewReply(gosocks5.CmdUnsupported, nil)

View File

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"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/internal/utils/mux" "github.com/go-gost/gost/pkg/internal/utils/mux"
) )
@ -20,12 +21,20 @@ func (h *socks5Handler) handleMuxBind(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.md.enableBind {
reply := gosocks5.NewReply(gosocks5.NotAllowed, nil)
reply.Write(conn)
h.logger.Debug(reply)
h.logger.Error("BIND is diabled")
return
}
if h.chain.IsEmpty() { if h.chain.IsEmpty() {
h.muxBindLocal(ctx, conn, addr) h.muxBindLocal(ctx, conn, addr)
return return
} }
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)
@ -90,14 +99,14 @@ func (h *socks5Handler) muxBindLocal(ctx context.Context, conn net.Conn, addr st
h.logger = h.logger.WithFields(map[string]interface{}{ h.logger = h.logger.WithFields(map[string]interface{}{
"bind": socksAddr.String(), "bind": socksAddr.String(),
}) })
h.logger.Infof("bind on: %s OK", socksAddr.String()) h.logger.Debugf("bind on %s OK", &socksAddr)
h.serveMuxBind(ctx, conn, ln) h.serveMuxBind(ctx, conn, ln)
} }
func (h *socks5Handler) serveMuxBind(ctx context.Context, conn net.Conn, ln net.Listener) { func (h *socks5Handler) serveMuxBind(ctx context.Context, conn net.Conn, ln net.Listener) {
// Upgrade connection to multiplex stream. // Upgrade connection to multiplex stream.
session, err := mux.NewMuxSession(conn) session, err := mux.ClientSession(conn)
if err != nil { if err != nil {
h.logger.Error(err) h.logger.Error(err)
return return
@ -122,7 +131,7 @@ func (h *socks5Handler) serveMuxBind(ctx context.Context, conn net.Conn, ln net.
h.logger.Error(err) h.logger.Error(err)
return return
} }
h.logger.Infof("peer accepted: %s", rc.RemoteAddr().String()) h.logger.Debugf("peer %s accepted", rc.RemoteAddr())
go func(c net.Conn) { go func(c net.Conn) {
defer c.Close() defer c.Close()
@ -134,6 +143,18 @@ func (h *socks5Handler) serveMuxBind(ctx context.Context, conn net.Conn, ln net.
} }
defer sc.Close() 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 {
h.logger.Error(err)
return
}
h.logger.Debug(reply)
}
t := time.Now() t := time.Now()
h.logger.Infof("%s <-> %s", conn.RemoteAddr(), c.RemoteAddr().String()) h.logger.Infof("%s <-> %s", conn.RemoteAddr(), c.RemoteAddr().String())
handler.Transport(sc, c) handler.Transport(sc, c)

View File

@ -11,30 +11,32 @@ import (
) )
type metadata struct { type metadata struct {
tlsConfig *tls.Config tlsConfig *tls.Config
authenticator auth.Authenticator authenticator auth.Authenticator
timeout time.Duration timeout time.Duration
readTimeout time.Duration readTimeout time.Duration
retryCount int retryCount int
noTLS bool noTLS bool
enableBind bool enableBind bool
enableUDP bool enableUDP bool
udpBufferSize int udpBufferSize int
compatibilityMode bool
} }
func (h *socks5Handler) parseMetadata(md md.Metadata) error { func (h *socks5Handler) parseMetadata(md md.Metadata) error {
const ( const (
certFile = "certFile" certFile = "certFile"
keyFile = "keyFile" keyFile = "keyFile"
caFile = "caFile" caFile = "caFile"
authsKey = "auths" authsKey = "auths"
readTimeout = "readTimeout" readTimeout = "readTimeout"
timeout = "timeout" timeout = "timeout"
retryCount = "retry" retryCount = "retry"
noTLS = "notls" noTLS = "notls"
enableBind = "bind" enableBind = "bind"
enableUDP = "udp" enableUDP = "udp"
udpBufferSize = "udpBufferSize" udpBufferSize = "udpBufferSize"
compatibilityMode = "comp"
) )
var err error var err error
@ -81,5 +83,7 @@ func (h *socks5Handler) parseMetadata(md md.Metadata) error {
h.md.udpBufferSize = 4096 // default buffer size h.md.udpBufferSize = 4096 // default buffer size
} }
h.md.compatibilityMode = md.GetBool(compatibilityMode)
return nil return nil
} }

View File

@ -9,7 +9,7 @@ import (
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/internal/bufpool" "github.com/go-gost/gost/pkg/internal/bufpool"
"github.com/go-gost/gost/pkg/internal/utils/socks" "github.com/go-gost/gost/pkg/internal/utils/socks"
) )
@ -19,6 +19,14 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, req *gosoc
"cmd": "udp", "cmd": "udp",
}) })
if !h.md.enableUDP {
reply := gosocks5.NewReply(gosocks5.NotAllowed, nil)
reply.Write(conn)
h.logger.Debug(reply)
h.logger.Error("UDP relay is diabled")
return
}
relay, err := net.ListenUDP("udp", nil) relay, err := net.ListenUDP("udp", nil)
if err != nil { if err != nil {
h.logger.Error(err) h.logger.Error(err)
@ -43,7 +51,7 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, req *gosoc
h.logger = h.logger.WithFields(map[string]interface{}{ h.logger = h.logger.WithFields(map[string]interface{}{
"bind": saddr.String(), "bind": saddr.String(),
}) })
h.logger.Infof("bind on %s OK", saddr.String()) h.logger.Debugf("bind on %s OK", &saddr)
if h.chain.IsEmpty() { if h.chain.IsEmpty() {
// serve as standard socks5 udp relay. // serve as standard socks5 udp relay.
@ -81,7 +89,7 @@ func (h *socks5Handler) handleUDP(ctx context.Context, conn net.Conn, req *gosoc
} }
func (h *socks5Handler) getUDPTun(ctx context.Context) (conn net.Conn, err error) { func (h *socks5Handler) getUDPTun(ctx context.Context) (conn net.Conn, err error) {
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)

View File

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/go-gost/gosocks5" "github.com/go-gost/gosocks5"
"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/internal/bufpool" "github.com/go-gost/gost/pkg/internal/bufpool"
"github.com/go-gost/gost/pkg/internal/utils/socks" "github.com/go-gost/gost/pkg/internal/utils/socks"
@ -16,6 +17,14 @@ func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, req *go
"cmd": "udp-tun", "cmd": "udp-tun",
}) })
if !h.md.enableUDP {
reply := gosocks5.NewReply(gosocks5.NotAllowed, nil)
reply.Write(conn)
h.logger.Debug(reply)
h.logger.Error("UDP relay is diabled")
return
}
if h.chain.IsEmpty() { if h.chain.IsEmpty() {
addr := req.Addr.String() addr := req.Addr.String()
@ -56,7 +65,7 @@ func (h *socks5Handler) handleUDPTun(ctx context.Context, conn net.Conn, req *go
return return
} }
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)

View File

@ -123,7 +123,7 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn) {
return return
} }
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)

View File

@ -5,7 +5,7 @@ import (
"net" "net"
"time" "time"
"github.com/go-gost/gost/pkg/handler" "github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/internal/bufpool" "github.com/go-gost/gost/pkg/internal/bufpool"
"github.com/go-gost/gost/pkg/internal/utils/socks" "github.com/go-gost/gost/pkg/internal/utils/socks"
"github.com/go-gost/gost/pkg/internal/utils/ss" "github.com/go-gost/gost/pkg/internal/utils/ss"
@ -17,7 +17,7 @@ func (h *ssHandler) handleUDP(ctx context.Context, raddr net.Addr, conn net.Pack
} }
// obtain a udp connection // obtain a udp connection
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)
@ -51,7 +51,7 @@ func (h *ssHandler) handleUDP(ctx context.Context, raddr net.Addr, conn net.Pack
func (h *ssHandler) handleUDPTun(ctx context.Context, conn net.Conn) { func (h *ssHandler) handleUDPTun(ctx context.Context, conn net.Conn) {
// obtain a udp connection // obtain a udp connection
r := (&handler.Router{}). r := (&chain.Router{}).
WithChain(h.chain). WithChain(h.chain).
WithRetry(h.md.retryCount). WithRetry(h.md.retryCount).
WithLogger(h.logger) WithLogger(h.logger)

View File

@ -6,70 +6,80 @@ import (
smux "github.com/xtaci/smux" smux "github.com/xtaci/smux"
) )
type MuxSession struct { type Session struct {
conn net.Conn conn net.Conn
session *smux.Session session *smux.Session
} }
func NewMuxSession(conn net.Conn) (*MuxSession, error) { func ClientSession(conn net.Conn) (*Session, error) {
// Upgrade connection to multiplex stream.
s, err := smux.Client(conn, smux.DefaultConfig()) s, err := smux.Client(conn, smux.DefaultConfig())
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &MuxSession{ return &Session{
conn: conn, conn: conn,
session: s, session: s,
}, nil }, nil
} }
func (session *MuxSession) GetConn() (net.Conn, error) { 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() stream, err := session.session.OpenStream()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &muxStreamConn{Conn: session.conn, stream: stream}, nil return &StreamConn{Conn: session.conn, stream: stream}, nil
} }
func (session *MuxSession) Accept() (net.Conn, error) { func (session *Session) Accept() (net.Conn, error) {
stream, err := session.session.AcceptStream() stream, err := session.session.AcceptStream()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &muxStreamConn{Conn: session.conn, stream: stream}, nil return &StreamConn{Conn: session.conn, stream: stream}, nil
} }
func (session *MuxSession) Close() error { func (session *Session) Close() error {
if session.session == nil { if session.session == nil {
return nil return nil
} }
return session.session.Close() return session.session.Close()
} }
func (session *MuxSession) IsClosed() bool { func (session *Session) IsClosed() bool {
if session.session == nil { if session.session == nil {
return true return true
} }
return session.session.IsClosed() return session.session.IsClosed()
} }
func (session *MuxSession) NumStreams() int { func (session *Session) NumStreams() int {
return session.session.NumStreams() return session.session.NumStreams()
} }
type muxStreamConn struct { type StreamConn struct {
net.Conn net.Conn
stream *smux.Stream stream *smux.Stream
} }
func (c *muxStreamConn) Read(b []byte) (n int, err error) { func (c *StreamConn) Read(b []byte) (n int, err error) {
return c.stream.Read(b) return c.stream.Read(b)
} }
func (c *muxStreamConn) Write(b []byte) (n int, err error) { func (c *StreamConn) Write(b []byte) (n int, err error) {
return c.stream.Write(b) return c.stream.Write(b)
} }
func (c *muxStreamConn) Close() error { func (c *StreamConn) Close() error {
return c.stream.Close() return c.stream.Close()
} }

View File

@ -48,6 +48,7 @@ func (l *kcpListener) Init(md md.Metadata) (err error) {
config = DefaultConfig config = DefaultConfig
} }
config.Init() config.Init()
l.md.config = config
var ln *kcp.Listener var ln *kcp.Listener
@ -168,7 +169,3 @@ func (l *kcpListener) mux(conn net.Conn) {
} }
} }
} }
func (l *kcpListener) parseMetadata(md md.Metadata) (err error) {
return
}

View File

@ -1,8 +1,6 @@
package kcp package kcp
const ( import md "github.com/go-gost/gost/pkg/metadata"
connQueueSize = "connQueueSize"
)
const ( const (
defaultQueueSize = 128 defaultQueueSize = 128
@ -13,3 +11,13 @@ type metadata struct {
connQueueSize int connQueueSize int
} }
func (l *kcpListener) parseMetadata(md md.Metadata) (err error) {
const (
connQueueSize = "connQueueSize"
)
l.md.connQueueSize = md.GetInt(connQueueSize)
return
}

View File

@ -1,11 +1,13 @@
package listener package listener
import ( import (
"github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/logger" "github.com/go-gost/gost/pkg/logger"
) )
type Options struct { type Options struct {
Addr string Addr string
Chain *chain.Chain
Logger logger.Logger Logger logger.Logger
} }
@ -17,6 +19,12 @@ func AddrOption(addr string) Option {
} }
} }
func ChainOption(chain *chain.Chain) Option {
return func(opts *Options) {
opts.Chain = chain
}
}
func LoggerOption(logger logger.Logger) Option { func LoggerOption(logger logger.Logger) Option {
return func(opts *Options) { return func(opts *Options) {
opts.Logger = logger opts.Logger = logger

17
pkg/listener/rtcp/conn.go Normal file
View File

@ -0,0 +1,17 @@
package rtcp
import "net"
type peerConn struct {
net.Conn
localAddr net.Addr
remoteAddr net.Addr
}
func (c *peerConn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *peerConn) RemoteAddr() net.Addr {
return c.remoteAddr
}

View File

@ -0,0 +1,214 @@
package rtcp
import (
"context"
"fmt"
"net"
"sync"
"time"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/internal/utils/mux"
"github.com/go-gost/gost/pkg/listener"
"github.com/go-gost/gost/pkg/logger"
md "github.com/go-gost/gost/pkg/metadata"
"github.com/go-gost/gost/pkg/registry"
)
func init() {
registry.RegisterListener("rtcp", NewListener)
}
type rtcpListener struct {
addr string
laddr net.Addr
chain *chain.Chain
md metadata
ln net.Listener
connChan chan net.Conn
session *mux.Session
sessionMux sync.Mutex
logger logger.Logger
closed chan struct{}
}
func NewListener(opts ...listener.Option) listener.Listener {
options := &listener.Options{}
for _, opt := range opts {
opt(options)
}
return &rtcpListener{
addr: options.Addr,
chain: options.Chain,
closed: make(chan struct{}),
logger: options.Logger,
}
}
func (l *rtcpListener) Init(md md.Metadata) (err error) {
if err = l.parseMetadata(md); err != nil {
return
}
laddr, err := net.ResolveTCPAddr("tcp", l.addr)
if err != nil {
return
}
l.laddr = laddr
l.connChan = make(chan net.Conn, l.md.connQueueSize)
if l.chain.IsEmpty() {
l.ln, err = net.ListenTCP("tcp", laddr)
return err
}
go l.listenLoop()
return
}
func (l *rtcpListener) Addr() net.Addr {
return l.laddr
}
func (l *rtcpListener) Close() error {
if l.ln != nil {
return l.ln.Close()
}
select {
case <-l.closed:
default:
close(l.closed)
}
return nil
}
func (l *rtcpListener) Accept() (conn net.Conn, err error) {
if l.ln != nil {
return l.ln.Accept()
}
select {
case conn = <-l.connChan:
case <-l.closed:
err = net.ErrClosed
}
return
}
func (l *rtcpListener) listenLoop() {
var tempDelay time.Duration
for {
select {
case <-l.closed:
return
default:
}
conn, err := l.accept()
if err != nil {
if tempDelay == 0 {
tempDelay = 1000 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 6 * time.Second; tempDelay > max {
tempDelay = max
}
l.logger.Warnf("accept: %v, retrying in %v", err, tempDelay)
time.Sleep(tempDelay)
continue
}
tempDelay = 0
select {
case l.connChan <- conn:
default:
conn.Close()
l.logger.Warnf("connection queue is full, client %s discarded", conn.RemoteAddr().String())
}
}
}
func (l *rtcpListener) accept() (net.Conn, error) {
if l.md.enableMux {
return l.muxAccept()
}
r := (&chain.Router{}).
WithChain(l.chain).
WithRetry(l.md.retryCount).
WithLogger(l.logger)
cc, err := r.Connect(context.Background())
if err != nil {
return nil, err
}
conn, err := l.waitPeer(cc)
if err != nil {
l.logger.Error(err)
cc.Close()
return nil, err
}
l.logger.Debugf("peer %s accepted", conn.RemoteAddr())
return conn, nil
}
func (l *rtcpListener) waitPeer(conn net.Conn) (net.Conn, error) {
addr := gosocks5.Addr{}
addr.ParseFrom(l.addr)
req := gosocks5.NewRequest(gosocks5.CmdBind, &addr)
if err := req.Write(conn); err != nil {
l.logger.Error(err)
return nil, err
}
// first reply, bind status
rep, err := gosocks5.ReadReply(conn)
if err != nil {
l.logger.Error(err)
return nil, err
}
l.logger.Debug(rep)
if rep.Rep != gosocks5.Succeeded {
err = fmt.Errorf("bind on %s failed", l.addr)
l.logger.Error(err)
return nil, err
}
l.logger.Debugf("bind on %s OK", rep.Addr)
// second reply, peer connected
rep, err = gosocks5.ReadReply(conn)
if err != nil {
l.logger.Error(err)
return nil, err
}
if rep.Rep != gosocks5.Succeeded {
err = fmt.Errorf("peer connect failed")
l.logger.Error(err)
return nil, err
}
raddr, err := net.ResolveTCPAddr("tcp", rep.Addr.String())
if err != nil {
return nil, err
}
return &peerConn{
Conn: conn,
localAddr: l.laddr,
remoteAddr: raddr,
}, nil
}

View File

@ -0,0 +1,35 @@
package rtcp
import (
"time"
md "github.com/go-gost/gost/pkg/metadata"
)
const (
defaultKeepAlivePeriod = 180 * time.Second
defaultConnQueueSize = 128
)
type metadata struct {
enableMux bool
connQueueSize int
retryCount int
}
func (l *rtcpListener) parseMetadata(md md.Metadata) (err error) {
const (
enableMux = "mux"
connQueueSize = "connQueueSize"
retryCount = "retry"
)
l.md.enableMux = md.GetBool(enableMux)
l.md.retryCount = md.GetInt(retryCount)
l.md.connQueueSize = md.GetInt(connQueueSize)
if l.md.connQueueSize <= 0 {
l.md.connQueueSize = defaultConnQueueSize
}
return
}

109
pkg/listener/rtcp/mux.go Normal file
View File

@ -0,0 +1,109 @@
package rtcp
import (
"context"
"fmt"
"net"
"github.com/go-gost/gosocks5"
"github.com/go-gost/gost/pkg/chain"
"github.com/go-gost/gost/pkg/internal/utils/mux"
"github.com/go-gost/gost/pkg/internal/utils/socks"
)
func (l *rtcpListener) muxAccept() (net.Conn, error) {
session, err := l.getSession()
if err != nil {
l.logger.Error(err)
return nil, err
}
cc, err := session.Accept()
if err != nil {
session.Close()
return nil, err
}
conn, err := l.getPeerConn(cc)
if err != nil {
l.logger.Error(err)
cc.Close()
return nil, err
}
l.logger.Debugf("peer %s accepted", conn.RemoteAddr())
return conn, nil
}
func (l *rtcpListener) getPeerConn(conn net.Conn) (net.Conn, error) {
// second reply, peer connected
rep, err := gosocks5.ReadReply(conn)
if err != nil {
return nil, err
}
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 &peerConn{
Conn: conn,
localAddr: l.laddr,
remoteAddr: raddr,
}, nil
}
func (l *rtcpListener) getSession() (s *mux.Session, err error) {
l.sessionMux.Lock()
defer l.sessionMux.Unlock()
if l.session != nil && !l.session.IsClosed() {
return l.session, nil
}
r := (&chain.Router{}).
WithChain(l.chain).
WithRetry(l.md.retryCount).
WithLogger(l.logger)
conn, err := r.Connect(context.Background())
if err != nil {
return nil, err
}
l.session, err = l.initSession(conn)
if err != nil {
conn.Close()
return
}
return l.session, nil
}
func (l *rtcpListener) initSession(conn net.Conn) (*mux.Session, error) {
addr := gosocks5.Addr{}
addr.ParseFrom(l.addr)
req := gosocks5.NewRequest(socks.CmdMuxBind, &addr)
if err := req.Write(conn); err != nil {
return nil, err
}
// first reply, bind status
rep, err := gosocks5.ReadReply(conn)
if err != nil {
return nil, err
}
if rep.Rep != gosocks5.Succeeded {
err = fmt.Errorf("bind on %s failed", l.addr)
return nil, err
}
l.logger.Debugf("bind on %s OK", rep.Addr)
return mux.ServerSession(conn)
}

View File

@ -57,10 +57,3 @@ func (l *tcpListener) Init(md md.Metadata) (err error) {
l.Listener = ln l.Listener = ln
return return
} }
func (l *tcpListener) parseMetadata(md md.Metadata) (err error) {
l.md.keepAlive = md.GetBool(keepAlive)
l.md.keepAlivePeriod = md.GetDuration(keepAlivePeriod)
return
}

View File

@ -1,10 +1,9 @@
package tcp package tcp
import "time" import (
"time"
const ( md "github.com/go-gost/gost/pkg/metadata"
keepAlive = "keepAlive"
keepAlivePeriod = "keepAlivePeriod"
) )
const ( const (
@ -15,3 +14,15 @@ type metadata struct {
keepAlive bool keepAlive bool
keepAlivePeriod time.Duration keepAlivePeriod time.Duration
} }
func (l *tcpListener) parseMetadata(md md.Metadata) (err error) {
const (
keepAlive = "keepAlive"
keepAlivePeriod = "keepAlivePeriod"
)
l.md.keepAlive = md.GetBool(keepAlive)
l.md.keepAlivePeriod = md.GetDuration(keepAlivePeriod)
return
}

View File

@ -15,14 +15,14 @@ func init() {
} }
type udpListener struct { type udpListener struct {
addr string addr string
md metadata md metadata
conn net.PacketConn conn net.PacketConn
connChan chan net.Conn connChan chan net.Conn
errChan chan error errChan chan error
closeChan chan struct{} closed chan struct{}
connPool *connPool connPool *connPool
logger logger.Logger logger logger.Logger
} }
func NewListener(opts ...listener.Option) listener.Listener { func NewListener(opts ...listener.Option) listener.Listener {
@ -31,10 +31,10 @@ func NewListener(opts ...listener.Option) listener.Listener {
opt(options) opt(options)
} }
return &udpListener{ return &udpListener{
addr: options.Addr, addr: options.Addr,
errChan: make(chan error, 1), errChan: make(chan error, 1),
closeChan: make(chan struct{}), closed: make(chan struct{}),
logger: options.Logger, logger: options.Logger,
} }
} }
@ -75,13 +75,14 @@ func (l *udpListener) Accept() (conn net.Conn, err error) {
func (l *udpListener) Close() error { func (l *udpListener) Close() error {
select { select {
case <-l.closeChan: case <-l.closed:
return nil
default: default:
close(l.closeChan) close(l.closed)
l.connPool.Close() l.connPool.Close()
return l.conn.Close() return l.conn.Close()
} }
return nil
} }
func (l *udpListener) Addr() net.Addr { func (l *udpListener) Addr() net.Addr {
@ -126,26 +127,3 @@ func (l *udpListener) getConn(addr net.Addr) *conn {
} }
return c return c
} }
func (l *udpListener) parseMetadata(md md.Metadata) (err error) {
l.md.ttl = md.GetDuration(ttl)
if l.md.ttl <= 0 {
l.md.ttl = defaultTTL
}
l.md.readBufferSize = md.GetInt(readBufferSize)
if l.md.readBufferSize <= 0 {
l.md.readBufferSize = defaultReadBufferSize
}
l.md.readQueueSize = md.GetInt(readQueueSize)
if l.md.readQueueSize <= 0 {
l.md.readQueueSize = defaultReadQueueSize
}
l.md.connQueueSize = md.GetInt(connQueueSize)
if l.md.connQueueSize <= 0 {
l.md.connQueueSize = defaultConnQueueSize
}
return
}

View File

@ -1,6 +1,10 @@
package udp package udp
import "time" import (
"time"
md "github.com/go-gost/gost/pkg/metadata"
)
const ( const (
defaultTTL = 60 * time.Second defaultTTL = 60 * time.Second
@ -9,13 +13,6 @@ const (
defaultConnQueueSize = 128 defaultConnQueueSize = 128
) )
const (
ttl = "ttl"
readBufferSize = "readBufferSize"
readQueueSize = "readQueueSize"
connQueueSize = "connQueueSize"
)
type metadata struct { type metadata struct {
ttl time.Duration ttl time.Duration
@ -23,3 +20,33 @@ type metadata struct {
readQueueSize int readQueueSize int
connQueueSize int connQueueSize int
} }
func (l *udpListener) parseMetadata(md md.Metadata) (err error) {
const (
ttl = "ttl"
readBufferSize = "readBufferSize"
readQueueSize = "readQueueSize"
connQueueSize = "connQueueSize"
)
l.md.ttl = md.GetDuration(ttl)
if l.md.ttl <= 0 {
l.md.ttl = defaultTTL
}
l.md.readBufferSize = md.GetInt(readBufferSize)
if l.md.readBufferSize <= 0 {
l.md.readBufferSize = defaultReadBufferSize
}
l.md.readQueueSize = md.GetInt(readQueueSize)
if l.md.readQueueSize <= 0 {
l.md.readQueueSize = defaultReadQueueSize
}
l.md.connQueueSize = md.GetInt(connQueueSize)
if l.md.connQueueSize <= 0 {
l.md.connQueueSize = defaultConnQueueSize
}
return
}