刘河 5 years ago
parent
commit
b6a9001d43

+ 50 - 0
core/const.go

@@ -0,0 +1,50 @@
+package core
+
+const (
+	CONN_DATA_SEQ     = "*#*" //Separator
+	VERIFY_EER        = "vkey"
+	VERIFY_SUCCESS    = "sucs"
+	WORK_MAIN         = "main"
+	WORK_CHAN         = "chan"
+	WORK_CONFIG       = "conf"
+	WORK_REGISTER     = "rgst"
+	WORK_SECRET       = "sert"
+	WORK_FILE         = "file"
+	WORK_P2P          = "p2pm"
+	WORK_P2P_VISITOR  = "p2pv"
+	WORK_P2P_PROVIDER = "p2pp"
+	WORK_P2P_CONNECT  = "p2pc"
+	WORK_P2P_SUCCESS  = "p2ps"
+	WORK_P2P_END      = "p2pe"
+	WORK_P2P_LAST     = "p2pl"
+	WORK_STATUS       = "stus"
+	RES_MSG           = "msg0"
+	RES_CLOSE         = "clse"
+	NEW_UDP_CONN      = "udpc" //p2p udp conn
+	NEW_TASK          = "task"
+	NEW_CONF          = "conf"
+	NEW_HOST          = "host"
+	CONN_TCP          = "tcp"
+	CONN_UDP          = "udp"
+	CONN_TEST         = "TST"
+	UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
+Content-Type: text/plain; charset=utf-8
+WWW-Authenticate: Basic realm="easyProxy"
+
+401 Unauthorized`
+	ConnectionFailBytes = `HTTP/1.1 404 Not Found
+
+`
+)
+
+const (
+	MUX_PING_FLAG uint8 = iota
+	MUX_NEW_CONN_OK
+	MUX_NEW_CONN_Fail
+	MUX_NEW_MSG
+	MUX_MSG_SEND_OK
+	MUX_NEW_CONN
+	MUX_CONN_CLOSE
+	MUX_PING_RETURN
+	MUX_PING int32 = -1
+)

+ 209 - 0
core/netpackager.go

@@ -0,0 +1,209 @@
+package core
+
+import (
+	"bytes"
+	"encoding/binary"
+	"encoding/json"
+	"errors"
+	"io"
+	"strings"
+)
+
+type NetPackager interface {
+	Pack(writer io.Writer) (err error)
+	UnPack(reader io.Reader) (err error)
+}
+
+type BasePackager struct {
+	Length  uint32
+	Content []byte
+}
+
+func (Self *BasePackager) NewPac(contents ...interface{}) (err error) {
+	Self.clean()
+	for _, content := range contents {
+		switch content.(type) {
+		case nil:
+			Self.Content = Self.Content[:0]
+		case []byte:
+			err = Self.appendByte(content.([]byte))
+		case string:
+			err = Self.appendByte([]byte(content.(string)))
+			if err != nil {
+				return
+			}
+			err = Self.appendByte([]byte(CONN_DATA_SEQ))
+		default:
+			err = Self.marshal(content)
+		}
+	}
+	Self.setLength()
+	return
+}
+
+func (Self *BasePackager) appendByte(data []byte) (err error) {
+	m := len(Self.Content)
+	n := m + len(data)
+	if n <= cap(Self.Content) {
+		Self.Content = Self.Content[0:n] // grow the length for copy
+		copy(Self.Content[m:n], data)
+		return nil
+	} else {
+		return errors.New("pack content too large")
+	}
+}
+
+//似乎这里涉及到父类作用域问题,当子类调用父类的方法时,其struct仅仅为父类的
+func (Self *BasePackager) Pack(writer io.Writer) (err error) {
+	err = binary.Write(writer, binary.LittleEndian, Self.Length)
+	if err != nil {
+		return
+	}
+	err = binary.Write(writer, binary.LittleEndian, Self.Content)
+	return
+}
+
+//Unpack 会导致传入的数字类型转化成float64!!
+//主要原因是json unmarshal并未传入正确的数据类型
+func (Self *BasePackager) UnPack(reader io.Reader) (err error) {
+	Self.clean()
+	err = binary.Read(reader, binary.LittleEndian, &Self.Length)
+	if err != nil {
+		return
+	}
+	if int(Self.Length) > cap(Self.Content) {
+		err = errors.New("unpack err, content length too large")
+	}
+	Self.Content = Self.Content[:int(Self.Length)]
+	//n, err := io.ReadFull(reader, Self.Content)
+	//if n != int(Self.Length) {
+	//	err = io.ErrUnexpectedEOF
+	//}
+	err = binary.Read(reader, binary.LittleEndian, Self.Content)
+	return
+}
+
+func (Self *BasePackager) marshal(content interface{}) (err error) {
+	tmp, err := json.Marshal(content)
+	if err != nil {
+		return err
+	}
+	err = Self.appendByte(tmp)
+	return
+}
+
+func (Self *BasePackager) Unmarshal(content interface{}) (err error) {
+	err = json.Unmarshal(Self.Content, content)
+	if err != nil {
+		return err
+	}
+	return
+}
+
+func (Self *BasePackager) setLength() {
+	Self.Length = uint32(len(Self.Content))
+	return
+}
+
+func (Self *BasePackager) clean() {
+	Self.Length = 0
+	Self.Content = Self.Content[:0] // reset length
+}
+
+func (Self *BasePackager) Split() (strList []string) {
+	n := bytes.IndexByte(Self.Content, 0)
+	strList = strings.Split(string(Self.Content[:n]), CONN_DATA_SEQ)
+	strList = strList[0 : len(strList)-1]
+	return
+}
+
+type ConnPackager struct { // Todo
+	ConnType uint8
+	BasePackager
+}
+
+func (Self *ConnPackager) NewPac(connType uint8, content ...interface{}) (err error) {
+	Self.ConnType = connType
+	err = Self.BasePackager.NewPac(content...)
+	return
+}
+
+func (Self *ConnPackager) Pack(writer io.Writer) (err error) {
+	err = binary.Write(writer, binary.LittleEndian, Self.ConnType)
+	if err != nil {
+		return
+	}
+	err = Self.BasePackager.Pack(writer)
+	return
+}
+
+func (Self *ConnPackager) UnPack(reader io.Reader) (err error) {
+	err = binary.Read(reader, binary.LittleEndian, &Self.ConnType)
+	if err != nil && err != io.EOF {
+		return
+	}
+	err = Self.BasePackager.UnPack(reader)
+	return
+}
+
+type MuxPackager struct {
+	Flag   uint8
+	Id     int32
+	Window uint16
+	BasePackager
+}
+
+func (Self *MuxPackager) NewPac(flag uint8, id int32, content ...interface{}) (err error) {
+	Self.Flag = flag
+	Self.Id = id
+	if flag == MUX_NEW_MSG {
+		err = Self.BasePackager.NewPac(content...)
+	}
+	if flag == MUX_MSG_SEND_OK {
+		// MUX_MSG_SEND_OK only allows one data
+		switch content[0].(type) {
+		case int:
+			Self.Window = uint16(content[0].(int))
+		case uint16:
+			Self.Window = content[0].(uint16)
+		}
+	}
+	return
+}
+
+func (Self *MuxPackager) Pack(writer io.Writer) (err error) {
+	err = binary.Write(writer, binary.LittleEndian, Self.Flag)
+	if err != nil {
+		return
+	}
+	err = binary.Write(writer, binary.LittleEndian, Self.Id)
+	if err != nil {
+		return
+	}
+	if Self.Flag == MUX_NEW_MSG {
+		err = Self.BasePackager.Pack(writer)
+	}
+	if Self.Flag == MUX_MSG_SEND_OK {
+		err = binary.Write(writer, binary.LittleEndian, Self.Window)
+	}
+	return
+}
+
+func (Self *MuxPackager) UnPack(reader io.Reader) (err error) {
+	Self.BasePackager.clean() // also clean the content
+	err = binary.Read(reader, binary.LittleEndian, &Self.Flag)
+	if err != nil {
+		return
+	}
+	err = binary.Read(reader, binary.LittleEndian, &Self.Id)
+	if err != nil {
+		return
+	}
+	if Self.Flag == MUX_NEW_MSG {
+		err = Self.BasePackager.UnPack(reader)
+	}
+	if Self.Flag == MUX_MSG_SEND_OK {
+		err = binary.Read(reader, binary.LittleEndian, &Self.Window)
+	}
+	return
+}

+ 14 - 7
core/plugin.go

@@ -9,7 +9,7 @@ import (
 // Plugin interface, all plugins must implement those functions.
 type Plugin interface {
 	GetConfigName() *NpsConfigs
-	InitConfig(globalConfig, clientConfig, pluginConfig map[string]string)
+	InitConfig(globalConfig, clientConfig, pluginConfig map[string]string, pgCnf []*Config)
 	GetStage() []Stage
 	Start(ctx context.Context) (context.Context, error)
 	Run(ctx context.Context) (context.Context, error)
@@ -25,9 +25,9 @@ func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs {
 	return nil
 }
 
-func (npsPlugin *NpsPlugin) InitConfig(globalConfig, clientConfig, pluginConfig map[string]string) {
+func (npsPlugin *NpsPlugin) InitConfig(globalConfig, clientConfig, pluginConfig map[string]string, pgCnf []*Config) {
 	npsPlugin.Configs = make(map[string]string)
-	for _, cfg := range npsPlugin.GetConfigName().GetAll() {
+	for _, cfg := range pgCnf {
 		switch cfg.ConfigLevel {
 		case CONFIG_LEVEL_PLUGIN:
 			npsPlugin.Configs[cfg.ConfigName] = pluginConfig[cfg.ConfigName]
@@ -105,13 +105,20 @@ func (pl *Plugins) Add(plugins ...Plugin) {
 	}
 }
 
-func RunPlugin(ctx context.Context, pgs []Plugin) error {
+func RunPlugin(ctx context.Context, pgs []Plugin, stage Stage) (context.Context, error) {
 	var err error
 	for _, pg := range pgs {
-		ctx, err = pg.Start(ctx)
+		switch stage {
+		case STAGE_RUN:
+			ctx, err = pg.Run(ctx)
+		case STAGE_START:
+			ctx, err = pg.Start(ctx)
+		case STAGE_END:
+			ctx, err = pg.End(ctx)
+		}
 		if err != nil {
-			return err
+			return ctx, err
 		}
 	}
-	return nil
+	return ctx, nil
 }

+ 18 - 9
server/common/common_inet_proxy_handle.go

@@ -2,14 +2,14 @@ package common
 
 import (
 	"context"
+	"fmt"
 	"github.com/cnlh/nps/core"
 	"net"
+	"strconv"
 )
 
 type Proxy struct {
 	core.NpsPlugin
-	clientConn net.Conn
-	ctx        context.Context
 }
 
 func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
@@ -17,10 +17,9 @@ func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
 }
 
 func (proxy *Proxy) Run(ctx context.Context) (context.Context, error) {
-	proxy.ctx = ctx
-	proxy.clientConn = proxy.GetClientConn(ctx)
-	clientId := proxy.GetClientId(ctx)
-	brg := proxy.GetBridge(ctx)
+	clientConn := proxy.GetClientConn(ctx)
+	//clientId := proxy.GetClientId(ctx)
+	//brg := proxy.GetBridge(ctx)
 
 	//severConn, err := brg.GetConnByClientId(clientId)
 	//if err != nil {
@@ -31,12 +30,22 @@ func (proxy *Proxy) Run(ctx context.Context) (context.Context, error) {
 	//if _, err := core.SendInfo(severConn, nil); err != nil {
 	//	return ctx, err
 	//}
-	severConn, err := net.Dial(ctx.Value(core.PROXY_CONNECTION_TYPE).(string), ctx.Value(core.PROXY_CONNECTION_ADDR).(string)+":"+ctx.Value(core.PROXY_CONNECTION_PORT).(string))
+	connType := ctx.Value(core.PROXY_CONNECTION_TYPE).(string)
+	connAddr := ctx.Value(core.PROXY_CONNECTION_ADDR).(string)
+	connPort := strconv.Itoa(int(ctx.Value(core.PROXY_CONNECTION_PORT).(uint16)))
+	fmt.Println(connType, connAddr, connPort, clientConn.RemoteAddr().String())
+	serverConn, err := net.Dial(connType, connAddr+":"+connPort)
 	if err != nil {
 		return ctx, err
 	}
 	// data exchange
-	go core.CopyBuffer(severConn, proxy.clientConn)
-	core.CopyBuffer(proxy.clientConn, severConn)
+	go func() {
+		core.CopyBuffer(serverConn, clientConn)
+		serverConn.Close()
+		clientConn.Close()
+	}()
+	core.CopyBuffer(clientConn, serverConn)
+	serverConn.Close()
+	clientConn.Close()
 	return ctx, core.REQUEST_EOF
 }

+ 13 - 11
server/socks5/socks5_check_access_handle.go

@@ -3,15 +3,13 @@ package socks5
 import (
 	"context"
 	"errors"
+	"fmt"
 	"github.com/cnlh/nps/core"
 	"net"
 )
 
 type CheckAccess struct {
 	core.NpsPlugin
-	clientConn     net.Conn
-	clientUsername string
-	clientPassword string
 	configUsername string
 	configPassword string
 }
@@ -24,19 +22,23 @@ func (check *CheckAccess) GetConfigName() *core.NpsConfigs {
 }
 
 func (check *CheckAccess) Run(ctx context.Context) (context.Context, error) {
-	check.clientConn = check.GetClientConn(ctx)
-	check.configUsername = check.Configs["socks5_access_username"]
-	check.configPassword = check.Configs["socks5_access_password"]
-
+	clientConn := check.GetClientConn(ctx)
+	check.configUsername = check.Configs["socks5_simple_access_username"]
+	check.configPassword = check.Configs["socks5_simple_access_password"]
+	if check.Configs["socks5_simple_access_check"] == "true" {
+		connUsername := ctx.Value("socks_client_username").(string)
+		connPassword := ctx.Value("socks_client_password").(string)
+		return ctx, check.checkAuth(clientConn, connUsername, connPassword)
+	}
 	return ctx, nil
 }
 
-func (check *CheckAccess) checkAuth(configUserName, configPassword string) error {
-	if check.clientUsername == configUserName && check.clientPassword == configPassword {
-		_, err := check.clientConn.Write([]byte{userAuthVersion, authSuccess})
+func (check *CheckAccess) checkAuth(clientConn net.Conn, connUserName, connPassword string) error {
+	if check.configUsername == connUserName && check.configPassword == connPassword {
+		_, err := clientConn.Write([]byte{userAuthVersion, authSuccess})
 		return err
 	} else {
-		_, err := check.clientConn.Write([]byte{userAuthVersion, authFailure})
+		_, err := clientConn.Write([]byte{userAuthVersion, authFailure})
 		if err != nil {
 			return err
 		}

+ 12 - 13
server/socks5/socks5_read_access_handle.go

@@ -18,24 +18,23 @@ const (
 
 type Access struct {
 	core.NpsPlugin
-	clientConn net.Conn
 }
 
 func (access *Access) GetConfigName() *core.NpsConfigs {
-	return core.NewNpsConfigs("socks5_check_access_check", "need check the permission simply",core.CONFIG_LEVEL_PLUGIN)
+	return core.NewNpsConfigs("socks5_check_access", "need check the permission simply", core.CONFIG_LEVEL_PLUGIN)
 }
 
 func (access *Access) Run(ctx context.Context) (context.Context, error) {
-	access.clientConn = access.GetClientConn(ctx)
+	clientConn := access.GetClientConn(ctx)
 	if access.Configs["socks5_check_access"] != "true" {
-		return ctx, access.sendAccessMsgToClient(UserNoAuth)
+		return ctx, access.sendAccessMsgToClient(clientConn, UserNoAuth)
 	}
 	// need auth
-	if err := access.sendAccessMsgToClient(UserPassAuth); err != nil {
+	if err := access.sendAccessMsgToClient(clientConn, UserPassAuth); err != nil {
 		return ctx, err
 	}
 	// send auth reply to client ,and get the auth information
-	username, password, err := access.getAuthInfoFromClient()
+	username, password, err := access.getAuthInfoFromClient(clientConn)
 	if err != nil {
 		return ctx, err
 	}
@@ -45,20 +44,20 @@ func (access *Access) Run(ctx context.Context) (context.Context, error) {
 	return ctx, nil
 }
 
-func (access *Access) sendAccessMsgToClient(auth uint8) error {
+func (access *Access) sendAccessMsgToClient(clientConn net.Conn, auth uint8) error {
 	buf := make([]byte, 2)
 	buf[0] = 5
 	buf[1] = auth
-	n, err := access.clientConn.Write(buf)
+	n, err := clientConn.Write(buf)
 	if err != nil || n != 2 {
 		return errors.New("write access message to client error " + err.Error())
 	}
 	return nil
 }
 
-func (access *Access) getAuthInfoFromClient() (username string, password string, err error) {
+func (access *Access) getAuthInfoFromClient(clientConn net.Conn) (username string, password string, err error) {
 	header := []byte{0, 0}
-	if _, err = io.ReadAtLeast(access.clientConn, header, 2); err != nil {
+	if _, err = io.ReadAtLeast(clientConn, header, 2); err != nil {
 		return
 	}
 	if header[0] != userAuthVersion {
@@ -67,16 +66,16 @@ func (access *Access) getAuthInfoFromClient() (username string, password string,
 	}
 	userLen := int(header[1])
 	user := make([]byte, userLen)
-	if _, err = io.ReadAtLeast(access.clientConn, user, userLen); err != nil {
+	if _, err = io.ReadAtLeast(clientConn, user, userLen); err != nil {
 		return
 	}
-	if _, err := access.clientConn.Read(header[:1]); err != nil {
+	if _, err = clientConn.Read(header[:1]); err != nil {
 		err = errors.New("get password length error" + err.Error())
 		return
 	}
 	passLen := int(header[0])
 	pass := make([]byte, passLen)
-	if _, err := io.ReadAtLeast(access.clientConn, pass, passLen); err != nil {
+	if _, err = io.ReadAtLeast(clientConn, pass, passLen); err != nil {
 		err = errors.New("get password error" + err.Error())
 		return
 	}

+ 33 - 36
server/socks5/socks5_read_request_handle.go

@@ -12,8 +12,6 @@ import (
 
 type Request struct {
 	core.NpsPlugin
-	clientConn net.Conn
-	ctx        context.Context
 }
 
 const (
@@ -30,11 +28,11 @@ const (
 	maxUDPPacketSize     = 1476
 	commandNotSupported  = 7
 	addrTypeNotSupported = 8
+	succeeded            = 0
 )
 
 func (request *Request) Run(ctx context.Context) (context.Context, error) {
-	request.clientConn = request.GetClientConn(ctx)
-	request.ctx = ctx
+	clientConn := request.GetClientConn(ctx)
 
 	/*
 		The SOCKS request is formed as follows:
@@ -46,36 +44,36 @@ func (request *Request) Run(ctx context.Context) (context.Context, error) {
 	*/
 	header := make([]byte, 3)
 
-	_, err := io.ReadFull(request.clientConn, header)
+	_, err := io.ReadFull(clientConn, header)
 
 	if err != nil {
-		return request.ctx, errors.New("illegal request" + err.Error())
+		return ctx, errors.New("illegal request" + err.Error())
 	}
 
 	switch header[1] {
 	case connectMethod:
-		request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
-		return request.ctx, request.doConnect()
+		ctx = context.WithValue(ctx, core.PROXY_CONNECTION_TYPE, "tcp")
+		return request.doConnect(ctx, clientConn)
 	case bindMethod:
-		return request.ctx, request.handleBind()
+		return ctx, request.handleBind()
 	case associateMethod:
-		request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
-		return request.ctx, request.handleUDP()
+		ctx = context.WithValue(ctx, core.PROXY_CONNECTION_TYPE, "udp")
+		return request.handleUDP(ctx, clientConn)
 	default:
-		request.sendReply(commandNotSupported)
-		return request.ctx, errors.New("command not supported")
+		request.sendReply(clientConn, commandNotSupported)
+		return ctx, errors.New("command not supported")
 	}
-	return request.ctx, nil
+	return ctx, nil
 }
 
-func (request *Request) sendReply(rep uint8) error {
+func (request *Request) sendReply(clientConn net.Conn, rep uint8) error {
 	reply := []byte{
 		5,
 		rep,
 		0,
 		1,
 	}
-	localAddr := request.clientConn.LocalAddr().String()
+	localAddr := clientConn.LocalAddr().String()
 	localHost, localPort, _ := net.SplitHostPort(localAddr)
 	ipBytes := net.ParseIP(localHost).To4()
 	nPort, _ := strconv.Atoi(localPort)
@@ -83,42 +81,41 @@ func (request *Request) sendReply(rep uint8) error {
 	portBytes := make([]byte, 2)
 	binary.BigEndian.PutUint16(portBytes, uint16(nPort))
 	reply = append(reply, portBytes...)
-	_, err := request.clientConn.Write(reply)
+	_, err := clientConn.Write(reply)
 	return err
 }
 
 //do conn
-func (request *Request) doConnect() error {
+func (request *Request) doConnect(ctx context.Context, clientConn net.Conn) (context.Context, error) {
 	addrType := make([]byte, 1)
-	request.clientConn.Read(addrType)
+	clientConn.Read(addrType)
 
 	var host string
 	switch addrType[0] {
 	case ipV4:
 		ipv4 := make(net.IP, net.IPv4len)
-		request.clientConn.Read(ipv4)
+		clientConn.Read(ipv4)
 		host = ipv4.String()
 	case ipV6:
 		ipv6 := make(net.IP, net.IPv6len)
-		request.clientConn.Read(ipv6)
+		clientConn.Read(ipv6)
 		host = ipv6.String()
 	case domainName:
 		var domainLen uint8
-		binary.Read(request.clientConn, binary.BigEndian, &domainLen)
+		binary.Read(clientConn, binary.BigEndian, &domainLen)
 		domain := make([]byte, domainLen)
-		request.clientConn.Read(domain)
+		clientConn.Read(domain)
 		host = string(domain)
 	default:
-		request.sendReply(addrTypeNotSupported)
-		return errors.New("target address type is not support")
+		request.sendReply(clientConn, addrTypeNotSupported)
+		return ctx, errors.New("target address type is not support")
 	}
-
 	var port uint16
-	binary.Read(request.clientConn, binary.BigEndian, &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
+	binary.Read(clientConn, binary.BigEndian, &port)
+	ctx = context.WithValue(ctx, core.PROXY_CONNECTION_ADDR, host)
+	ctx = context.WithValue(ctx, core.PROXY_CONNECTION_PORT, port)
+	request.sendReply(clientConn, succeeded)
+	return ctx, nil
 }
 
 // passive mode
@@ -127,7 +124,7 @@ func (request *Request) handleBind() error {
 }
 
 //udp
-func (request *Request) handleUDP() error {
+func (request *Request) handleUDP(ctx context.Context, clientConn net.Conn) (context.Context, error) {
 	/*
 	   +----+------+------+----------+----------+----------+
 	   |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
@@ -136,13 +133,13 @@ func (request *Request) handleUDP() error {
 	   +----+------+------+----------+----------+----------+
 	*/
 	buf := make([]byte, 3)
-	request.clientConn.Read(buf)
+	clientConn.Read(buf)
 	// relay udp datagram silently, without any notification to the requesting client
 	if buf[2] != 0 {
 		// does not support fragmentation, drop it
 		dummy := make([]byte, maxUDPPacketSize)
-		request.clientConn.Read(dummy)
-		return errors.New("does not support fragmentation, drop")
+		clientConn.Read(dummy)
+		return ctx, errors.New("does not support fragmentation, drop")
 	}
-	return request.doConnect()
+	return request.doConnect(ctx, clientConn)
 }

+ 17 - 9
server/socks5/socks5_server.go

@@ -35,25 +35,33 @@ func NewS5Server(globalConfig, clientConfig, pluginConfig map[string]string, Ser
 func (s5 *S5Server) Start(ctx context.Context) error {
 	// init config of plugin
 	for _, pg := range s5.plugins.AllPgs {
-		pg.InitConfig(s5.globalConfig, s5.clientConfig, s5.pluginConfig)
-	}
-	// run the plugin contains start
-	if core.RunPlugin(ctx, s5.plugins.StartPgs) != nil {
-		return nil
+		if pg.GetConfigName() != nil {
+			pg.InitConfig(s5.globalConfig, s5.clientConfig, s5.pluginConfig, pg.GetConfigName().GetAll())
+		}
 	}
 
-	return core.NewTcpListenerAndProcess(s5.ServerIp+":"+strconv.Itoa(s5.ServerPort), func(c net.Conn) {
+	core.NewTcpListenerAndProcess(s5.ServerIp+":"+strconv.Itoa(s5.ServerPort), func(c net.Conn) {
 		// init ctx value clientConn
-		ctx = context.WithValue(ctx, core.CLIENT_CONNECTION, c)
+		connCtx := context.WithValue(ctx, core.CLIENT_CONNECTION, c)
+		var err error
+
+		// run the plugin contains start
+		if connCtx, err = core.RunPlugin(connCtx, s5.plugins.StartPgs, core.STAGE_START); err != nil {
+			fmt.Println(err)
+			return
+		}
+
 		// start run the plugin run
-		if err := core.RunPlugin(ctx, s5.plugins.RunPgs); err != nil {
+		if connCtx, err = core.RunPlugin(connCtx, s5.plugins.RunPgs, core.STAGE_RUN); err != nil {
 			fmt.Println(err)
 			return
 		}
+
 		// start run the plugin end
-		if err := core.RunPlugin(ctx, s5.plugins.EndPgs); err != nil {
+		if connCtx, err = core.RunPlugin(connCtx, s5.plugins.EndPgs, core.STAGE_END); err != nil {
 			fmt.Println(err)
 			return
 		}
 	}, &s5.listener)
+	return nil
 }

+ 4 - 0
server/socks5/socks5_server_test.go

@@ -9,6 +9,10 @@ func TestNewS5Server(t *testing.T) {
 	g := make(map[string]string)
 	c := make(map[string]string)
 	p := make(map[string]string)
+	p["socks5_check_access"] = "true"
+	p["socks5_simple_access_check"] = "true"
+	p["socks5_simple_access_username"] = "111"
+	p["socks5_simple_access_password"] = "222"
 	s5 := NewS5Server(g, c, p, "", 1099)
 	ctx := context.Background()
 	s5.Start(ctx)