unknown 5 anos atrás
pai
commit
6771816be7

+ 75 - 0
core/plugin.go

@@ -0,0 +1,75 @@
+package core
+
+import (
+	"context"
+	"github.com/cnlh/nps/bridge"
+	"net"
+)
+
+// Plugin interface, all plugins must implement those functions.
+type Plugin interface {
+	GetConfigName() *NpsConfigs
+	GetConfigLevel() ConfigLevel
+	GetStage() Stage
+	Start(ctx context.Context, config map[string]string) (context.Context, error)
+	Run(ctx context.Context, config map[string]string) (context.Context, error)
+	End(ctx context.Context, config map[string]string) (context.Context, error)
+}
+
+type NpsPlugin struct {
+	Version string
+}
+
+func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs {
+	return nil
+}
+
+// describe the config level
+func (npsPlugin *NpsPlugin) GetConfigLevel() ConfigLevel {
+	return CONFIG_LEVEL_PLUGIN
+}
+
+// describe the stage of the plugin
+func (npsPlugin *NpsPlugin) GetStage() Stage {
+	return STAGE_RUN
+}
+
+func (npsPlugin *NpsPlugin) Start(ctx context.Context, config map[string]string) (context.Context, error) {
+	return ctx, nil
+}
+
+func (npsPlugin *NpsPlugin) Run(ctx context.Context, config map[string]string) (context.Context, error) {
+	return ctx, nil
+}
+
+func (npsPlugin *NpsPlugin) End(ctx context.Context, config map[string]string) (context.Context, error) {
+	return ctx, nil
+}
+
+func (npsPlugin *NpsPlugin) GetClientConn(ctx context.Context) net.Conn {
+	return ctx.Value(CLIENT_CONNECTION).(net.Conn)
+}
+
+func (npsPlugin *NpsPlugin) GetBridge(ctx context.Context) *bridge.Bridge {
+	return ctx.Value(BRIDGE).(*bridge.Bridge)
+}
+
+func (npsPlugin *NpsPlugin) GetClientId(ctx context.Context) int {
+	return ctx.Value(CLIENT_ID).(int)
+}
+
+type Plugins struct {
+	pgs []Plugin
+}
+
+func NewPlugins() *Plugins {
+	p := &Plugins{}
+	p.pgs = make([]Plugin, 0)
+	return p
+}
+
+func (pl *Plugins) Add(plugins ...Plugin) {
+	for _, plugin := range plugins {
+		pl.pgs = append(pl.pgs, plugin)
+	}
+}

+ 9 - 47
core/struct.go

@@ -1,10 +1,7 @@
 package core
 
 import (
-	"context"
 	"errors"
-	"github.com/cnlh/nps/bridge"
-	"net"
 )
 
 type Stage uint8
@@ -26,53 +23,18 @@ const (
 	CLIENT_ID             = "client_id"
 )
 
+type ConfigLevel uint8
+
+const (
+	CONFIG_LEVEL_CLIENT ConfigLevel = iota
+	CONFIG_LEVEL_PLUGIN
+	CONFIG_LEVEL_GLOBAL
+)
+
 var (
 	CLIENT_CONNECTION_NOT_EXIST = errors.New("the client connection is not exist")
 	BRIDGE_NOT_EXIST            = errors.New("the client connection is not exist")
 	REQUEST_EOF                 = errors.New("the request has finished")
-	CLIENT_ID_NOT_EXIST         = errors.New("the request has finished")
+	CLIENT_ID_NOT_EXIST         = errors.New("the client id is not exist")
 )
 
-// Plugin interface, all plugins must implement those functions.
-type Plugin interface {
-	GetConfigName() *NpsConfigs
-	GetStage() Stage
-	Start(ctx context.Context, config map[string]string) error
-	Run(ctx context.Context, config map[string]string) error
-	End(ctx context.Context, config map[string]string) error
-}
-
-type NpsPlugin struct {
-}
-
-func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs {
-	return nil
-}
-
-func (npsPlugin *NpsPlugin) GetStage() Stage {
-	return STAGE_RUN
-}
-
-func (npsPlugin *NpsPlugin) Start(ctx context.Context, config map[string]string) error {
-	return nil
-}
-
-func (npsPlugin *NpsPlugin) Run(ctx context.Context, config map[string]string) error {
-	return nil
-}
-
-func (npsPlugin *NpsPlugin) End(ctx context.Context, config map[string]string) error {
-	return nil
-}
-
-func (npsPlugin *NpsPlugin) GetClientConn(ctx context.Context) net.Conn {
-	return ctx.Value(CLIENT_CONNECTION).(net.Conn)
-}
-
-func (npsPlugin *NpsPlugin) GetBridge(ctx context.Context) *bridge.Bridge {
-	return ctx.Value(BRIDGE).(*bridge.Bridge)
-}
-
-func (npsPlugin *NpsPlugin) GetClientId(ctx context.Context) int {
-	return ctx.Value(CLIENT_ID).(int)
-}

+ 7 - 13
server/common/common_inet_proxy_handle.go

@@ -16,24 +16,18 @@ func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
 	return core.NewNpsConfigs("socks5_proxy", "proxy to inet")
 }
 
-func (proxy *Proxy) Run(ctx context.Context, config map[string]string) error {
-	proxy.clientConn = proxy.GetClientConn(ctx)
+func (proxy *Proxy) Run(ctx context.Context, config map[string]string) (context.Context, error) {
 	proxy.ctx = ctx
-
-	clientCtxConn := ctx.Value(core.CLIENT_CONNECTION)
-	if clientCtxConn == nil {
-		return core.CLIENT_CONNECTION_NOT_EXIST
-	}
-
+	proxy.clientConn = proxy.GetClientConn(ctx)
 	clientId := proxy.GetClientId(ctx)
-
 	brg := proxy.GetBridge(ctx)
+
 	severConn, err := brg.GetConnByClientId(clientId)
 	if err != nil {
-		return err
+		return ctx, err
 	}
 
-	go core.CopyBuffer(severConn, clientCtxConn.(net.Conn))
-	core.CopyBuffer(clientCtxConn.(net.Conn), severConn)
-	return nil
+	go core.CopyBuffer(severConn, proxy.clientConn)
+	core.CopyBuffer(proxy.clientConn, severConn)
+	return ctx, nil
 }

+ 2 - 2
server/socks5/socks5_check_access_handle.go

@@ -23,12 +23,12 @@ func (check *CheckAccess) GetConfigName() *core.NpsConfigs {
 	return c
 }
 
-func (check *CheckAccess) Run(ctx context.Context, config map[string]string) error {
+func (check *CheckAccess) Run(ctx context.Context, config map[string]string) (context.Context, error) {
 	check.clientConn = check.GetClientConn(ctx)
 	check.configUsername = config["socks5_access_username"]
 	check.configPassword = config["socks5_access_password"]
 
-	return nil
+	return ctx, nil
 }
 
 func (check *CheckAccess) checkAuth(configUserName, configPassword string) error {

+ 6 - 6
server/socks5/socks5_handshake_handle.go

@@ -12,25 +12,25 @@ type Handshake struct {
 	core.NpsPlugin
 }
 
-func (handshake *Handshake) Run(ctx context.Context, config map[string]string) error {
+func (handshake *Handshake) Run(ctx context.Context, config map[string]string) (context.Context, error) {
 	clientConn := handshake.GetClientConn(ctx)
 	buf := make([]byte, 2)
 	if _, err := io.ReadFull(clientConn, buf); err != nil {
-		return errors.New("negotiation err while read 2 bytes from client connection: " + err.Error())
+		return ctx, errors.New("negotiation err while read 2 bytes from client connection: " + err.Error())
 	}
 
 	if version := buf[0]; version != 5 {
-		return errors.New("only support socks5")
+		return ctx, errors.New("only support socks5")
 	}
 	nMethods := buf[1]
 
 	methods := make([]byte, nMethods)
 
 	if n, err := clientConn.Read(methods); n != int(nMethods) || err != nil {
-		return errors.New(fmt.Sprintf("read methods error, need %d , read  %d, error %s", nMethods, n, err.Error()))
+		return ctx, errors.New(fmt.Sprintf("read methods error, need %d , read  %d, error %s", nMethods, n, err.Error()))
 	} else {
-		context.WithValue(ctx, "methods", methods[:n])
+		ctx = context.WithValue(ctx, "methods", methods[:n])
 	}
 
-	return nil
+	return ctx, nil
 }

+ 7 - 7
server/socks5/socks5_read_access_handle.go

@@ -25,24 +25,24 @@ func (access *Access) GetConfigName() *core.NpsConfigs {
 	return core.NewNpsConfigs("socks5_check_access_check", "need check the permission simply")
 }
 
-func (access *Access) Run(ctx context.Context, config map[string]string) error {
+func (access *Access) Run(ctx context.Context, config map[string]string) (context.Context, error) {
 	access.clientConn = access.GetClientConn(ctx)
 	if config["socks5_check_access"] != "true" {
-		return access.sendAccessMsgToClient(UserNoAuth)
+		return ctx, access.sendAccessMsgToClient(UserNoAuth)
 	}
 	// need auth
 	if err := access.sendAccessMsgToClient(UserPassAuth); err != nil {
-		return err
+		return ctx, err
 	}
 	// send auth reply to client ,and get the auth information
 	username, password, err := access.getAuthInfoFromClient()
 	if err != nil {
-		return err
+		return ctx, err
 	}
-	context.WithValue(ctx, "socks_client_username", username)
-	context.WithValue(ctx, "socks_client_password", password)
+	ctx = context.WithValue(ctx, "socks_client_username", username)
+	ctx = context.WithValue(ctx, "socks_client_password", password)
 	// check
-	return nil
+	return ctx, nil
 }
 
 func (access *Access) sendAccessMsgToClient(auth uint8) error {

+ 11 - 11
server/socks5/socks5_read_request_handle.go

@@ -32,7 +32,7 @@ const (
 	addrTypeNotSupported = 8
 )
 
-func (request *Request) Run(ctx context.Context, config map[string]string) error {
+func (request *Request) Run(ctx context.Context, config map[string]string) (context.Context, error) {
 	request.clientConn = request.GetClientConn(ctx)
 	request.ctx = ctx
 
@@ -49,23 +49,23 @@ func (request *Request) Run(ctx context.Context, config map[string]string) error
 	_, err := io.ReadFull(request.clientConn, header)
 
 	if err != nil {
-		return errors.New("illegal request" + err.Error())
+		return request.ctx, errors.New("illegal request" + err.Error())
 	}
 
 	switch header[1] {
 	case connectMethod:
-		context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
-		return request.doConnect()
+		request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
+		return request.ctx, request.doConnect()
 	case bindMethod:
-		return request.handleBind()
+		return request.ctx, request.handleBind()
 	case associateMethod:
-		context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
-		return request.handleUDP()
+		request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
+		return request.ctx, request.handleUDP()
 	default:
 		request.sendReply(commandNotSupported)
-		return errors.New("command not supported")
+		return request.ctx, errors.New("command not supported")
 	}
-	return nil
+	return request.ctx, nil
 }
 
 func (request *Request) sendReply(rep uint8) error {
@@ -116,8 +116,8 @@ func (request *Request) doConnect() error {
 	var port uint16
 	binary.Read(request.clientConn, binary.BigEndian, &port)
 
-	context.WithValue(request.ctx, core.PROXY_CONNECTION_ADDR, host)
-	context.WithValue(request.ctx, core.PROXY_CONNECTION_PORT, port)
+	request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_ADDR, host)
+	request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_PORT, port)
 	return nil
 }
 

+ 36 - 0
server/socks5/socks5_server.go

@@ -0,0 +1,36 @@
+package socks5
+
+import (
+	"github.com/cnlh/nps/core"
+	"github.com/cnlh/nps/lib/conn"
+	"github.com/cnlh/nps/server/common"
+	"net"
+	"strconv"
+)
+
+type S5Server struct {
+	globalConfig map[string]string
+	clientConfig map[string]string
+	pluginConfig map[string]string
+	ServerIp     string
+	ServerPort   int
+	plugins      *core.Plugins
+	listener     net.Listener
+}
+
+func NewS5Server(globalConfig, clientConfig, pluginConfig map[string]string) *S5Server {
+	s5 := &S5Server{
+		globalConfig: globalConfig,
+		clientConfig: clientConfig,
+		pluginConfig: pluginConfig,
+		plugins:      &core.Plugins{},
+	}
+	s5.plugins.Add(new(Handshake), new(Access), new(CheckAccess), new(Request), new(common.Proxy))
+	return s5
+}
+
+func (s5 *S5Server) Start() error {
+	return conn.NewTcpListenerAndProcess(s5.ServerIp+":"+strconv.Itoa(s5.ServerPort), func(c net.Conn) {
+
+	}, &s5.listener)
+}