pugin init

This commit is contained in:
刘河
2019-10-13 13:25:22 +08:00
parent 8bcf5313f4
commit e11511637b
9 changed files with 265 additions and 1 deletions

View File

@@ -0,0 +1,128 @@
package socks5
import (
"context"
"errors"
"github.com/cnlh/nps/core"
"io"
"net"
)
const (
UserPassAuth = uint8(2)
userAuthVersion = uint8(1)
authSuccess = uint8(0)
authFailure = uint8(1)
UserNoAuth = uint8(0)
)
type Access struct {
clientConn net.Conn
username string
password string
}
func (access *Access) GetConfigName() []*core.Config {
c := make([]*core.Config, 0)
c = append(c, &core.Config{ConfigName: "socks5_check_access", Description: "need check the permission?"})
c = append(c, &core.Config{ConfigName: "socks5_access_username", Description: "auth username"})
c = append(c, &core.Config{ConfigName: "socks5_access_password", Description: "auth password"})
return nil
}
func (access *Access) GetStage() core.Stage {
return core.STAGE_RUN
}
func (access *Access) GetBeforePlugin() core.Plugin {
return &Handshake{}
}
func (access *Access) Start(ctx context.Context, config map[string]string) error {
return nil
}
func (access *Access) End(ctx context.Context, config map[string]string) error {
return nil
}
func (access *Access) Run(ctx context.Context, config map[string]string) error {
clientCtxConn := ctx.Value("clientConn")
if clientCtxConn == nil {
return errors.New("the client access.clientConnection is not exist")
}
access.clientConn = clientCtxConn.(net.Conn)
if config["socks5_check_access"] != "true" {
return access.sendAccessMsgToClient(UserNoAuth)
}
configUsername := config["socks5_access_username"]
configPassword := config["socks5_access_password"]
if configUsername == "" || configPassword == "" {
return access.sendAccessMsgToClient(UserNoAuth)
}
// need auth
if err := access.sendAccessMsgToClient(UserPassAuth); err != nil {
return err
}
// send auth reply to client ,and get the auth information
var err error
access.username, access.password, err = access.getAuthInfoFromClient()
if err != nil {
return err
}
context.WithValue(ctx, access.username, access.password)
// check
return access.checkAuth(configUsername, configPassword)
}
func (access *Access) sendAccessMsgToClient(auth uint8) error {
buf := make([]byte, 2)
buf[0] = 5
buf[1] = auth
n, err := access.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) {
header := []byte{0, 0}
if _, err = io.ReadAtLeast(access.clientConn, header, 2); err != nil {
return
}
if header[0] != userAuthVersion {
err = errors.New("authentication method is not supported")
return
}
userLen := int(header[1])
user := make([]byte, userLen)
if _, err = io.ReadAtLeast(access.clientConn, user, userLen); err != nil {
return
}
if _, err := access.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 {
err = errors.New("get password error" + err.Error())
return
}
username = string(user)
password = string(pass)
return
}
func (access *Access) checkAuth(configUserName, configPassword string) error {
if access.username == configUserName && access.password == configPassword {
_, err := access.clientConn.Write([]byte{userAuthVersion, authSuccess})
return err
} else {
_, err := access.clientConn.Write([]byte{userAuthVersion, authFailure})
if err != nil {
return err
}
return errors.New("auth check error,username or password does not match")
}
}

View File

@@ -0,0 +1,58 @@
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
}