package socks5 import ( "context" "errors" "fmt" "github.com/cnlh/nps/core" "io" "net" ) type Handshake struct { } func (handshake *Handshake) GetConfigName() []*core.Config { return nil } func (handshake *Handshake) GetStage() core.Stage { return core.STAGE_RUN } func (handshake *Handshake) GetBeforePlugin() core.Plugin { return nil } func (handshake *Handshake) Start(ctx context.Context, config map[string]string) error { return nil } func (handshake *Handshake) Run(ctx context.Context, config map[string]string) error { clientCtxConn := ctx.Value("clientConn") if clientCtxConn == nil { return errors.New("the client connection is not exist") } clientConn := clientCtxConn.(net.Conn) 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()) } if version := buf[0]; version != 5 { return 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())) } else { context.WithValue(ctx, "methods", methods[:n]) } return nil } func (handshake *Handshake) End(ctx context.Context, config map[string]string) error { return nil }