This commit is contained in:
unknown 2019-10-16 18:28:36 +08:00
parent 6771816be7
commit f0a9f4e471
10 changed files with 136 additions and 44 deletions

View File

@ -4,21 +4,22 @@ package core
type Config struct { type Config struct {
ConfigName string ConfigName string
Description string Description string
ConfigLevel ConfigLevel
} }
type NpsConfigs struct { type NpsConfigs struct {
configs []*Config configs []*Config
} }
func NewNpsConfigs(name, des string) *NpsConfigs { func NewNpsConfigs(name, des string, level ConfigLevel) *NpsConfigs {
c := &NpsConfigs{} c := &NpsConfigs{}
c.configs = make([]*Config, 0) c.configs = make([]*Config, 0)
c.Add(name, des) c.Add(name, des, level)
return c return c
} }
func (config *NpsConfigs) Add(name, des string) { func (config *NpsConfigs) Add(name, des string, level ConfigLevel) {
config.configs = append(config.configs, &Config{ConfigName: name, Description: des}) config.configs = append(config.configs, &Config{ConfigName: name, Description: des, ConfigLevel: level})
} }
func (config *NpsConfigs) GetAll() []*Config { func (config *NpsConfigs) GetAll() []*Config {

View File

@ -9,40 +9,51 @@ import (
// Plugin interface, all plugins must implement those functions. // Plugin interface, all plugins must implement those functions.
type Plugin interface { type Plugin interface {
GetConfigName() *NpsConfigs GetConfigName() *NpsConfigs
GetConfigLevel() ConfigLevel InitConfig(globalConfig, clientConfig, pluginConfig map[string]string)
GetStage() Stage GetStage() []Stage
Start(ctx context.Context, config map[string]string) (context.Context, error) Start(ctx context.Context) (context.Context, error)
Run(ctx context.Context, config map[string]string) (context.Context, error) Run(ctx context.Context) (context.Context, error)
End(ctx context.Context, config map[string]string) (context.Context, error) End(ctx context.Context) (context.Context, error)
} }
type NpsPlugin struct { type NpsPlugin struct {
Version string Version string
Configs map[string]string
} }
func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs { func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs {
return nil return nil
} }
// describe the config level func (npsPlugin *NpsPlugin) InitConfig(globalConfig, clientConfig, pluginConfig map[string]string) {
func (npsPlugin *NpsPlugin) GetConfigLevel() ConfigLevel { npsPlugin.Configs = make(map[string]string)
return CONFIG_LEVEL_PLUGIN for _, cfg := range npsPlugin.GetConfigName().GetAll() {
switch cfg.ConfigLevel {
case CONFIG_LEVEL_PLUGIN:
npsPlugin.Configs[cfg.ConfigName] = pluginConfig[cfg.ConfigName]
case CONFIG_LEVEL_CLIENT:
npsPlugin.Configs[cfg.ConfigName] = clientConfig[cfg.ConfigName]
case CONFIG_LEVEL_GLOBAL:
npsPlugin.Configs[cfg.ConfigName] = globalConfig[cfg.ConfigName]
}
}
return
} }
// describe the stage of the plugin // describe the stage of the plugin
func (npsPlugin *NpsPlugin) GetStage() Stage { func (npsPlugin *NpsPlugin) GetStage() []Stage {
return STAGE_RUN return []Stage{STAGE_RUN}
} }
func (npsPlugin *NpsPlugin) Start(ctx context.Context, config map[string]string) (context.Context, error) { func (npsPlugin *NpsPlugin) Start(ctx context.Context) (context.Context, error) {
return ctx, nil return ctx, nil
} }
func (npsPlugin *NpsPlugin) Run(ctx context.Context, config map[string]string) (context.Context, error) { func (npsPlugin *NpsPlugin) Run(ctx context.Context) (context.Context, error) {
return ctx, nil return ctx, nil
} }
func (npsPlugin *NpsPlugin) End(ctx context.Context, config map[string]string) (context.Context, error) { func (npsPlugin *NpsPlugin) End(ctx context.Context) (context.Context, error) {
return ctx, nil return ctx, nil
} }
@ -50,6 +61,10 @@ func (npsPlugin *NpsPlugin) GetClientConn(ctx context.Context) net.Conn {
return ctx.Value(CLIENT_CONNECTION).(net.Conn) return ctx.Value(CLIENT_CONNECTION).(net.Conn)
} }
func (npsPlugin *NpsPlugin) SetClientConn(ctx context.Context, conn net.Conn) context.Context {
return context.WithValue(ctx, CLIENT_CONNECTION, conn)
}
func (npsPlugin *NpsPlugin) GetBridge(ctx context.Context) *bridge.Bridge { func (npsPlugin *NpsPlugin) GetBridge(ctx context.Context) *bridge.Bridge {
return ctx.Value(BRIDGE).(*bridge.Bridge) return ctx.Value(BRIDGE).(*bridge.Bridge)
} }
@ -59,17 +74,44 @@ func (npsPlugin *NpsPlugin) GetClientId(ctx context.Context) int {
} }
type Plugins struct { type Plugins struct {
pgs []Plugin StartPgs []Plugin
RunPgs []Plugin
EndPgs []Plugin
AllPgs []Plugin
} }
func NewPlugins() *Plugins { func NewPlugins() *Plugins {
p := &Plugins{} p := &Plugins{}
p.pgs = make([]Plugin, 0) p.StartPgs = make([]Plugin, 0)
p.RunPgs = make([]Plugin, 0)
p.EndPgs = make([]Plugin, 0)
p.AllPgs = make([]Plugin, 0)
return p return p
} }
func (pl *Plugins) Add(plugins ...Plugin) { func (pl *Plugins) Add(plugins ...Plugin) {
for _, plugin := range plugins { for _, plugin := range plugins {
pl.pgs = append(pl.pgs, plugin) for _, v := range plugin.GetStage() {
pl.AllPgs = append(pl.RunPgs, plugin)
switch v {
case STAGE_RUN:
pl.RunPgs = append(pl.RunPgs, plugin)
case STAGE_END:
pl.EndPgs = append(pl.EndPgs, plugin)
case STAGE_START:
pl.StartPgs = append(pl.StartPgs, plugin)
}
}
} }
} }
func RunPlugin(ctx context.Context, pgs []Plugin) error {
var err error
for _, pg := range pgs {
ctx, err = pg.Start(ctx)
if err != nil {
return err
}
}
return nil
}

View File

@ -8,11 +8,7 @@ type Stage uint8
// These constants are meant to describe the stage in which the plugin is running. // These constants are meant to describe the stage in which the plugin is running.
const ( const (
STAGE_START_RUN_END Stage = iota STAGE_START Stage = iota
STAGE_START_RUN
STAGE_START_END
STAGE_RUN_END
STAGE_START
STAGE_END STAGE_END
STAGE_RUN STAGE_RUN
PROXY_CONNECTION_TYPE = "proxy_target_type" PROXY_CONNECTION_TYPE = "proxy_target_type"
@ -33,8 +29,7 @@ const (
var ( var (
CLIENT_CONNECTION_NOT_EXIST = errors.New("the client connection is not exist") CLIENT_CONNECTION_NOT_EXIST = errors.New("the client connection is not exist")
BRIDGE_NOT_EXIST = errors.New("the client connection is not exist") BRIDGE_NOT_EXIST = errors.New("the bridge is not exist")
REQUEST_EOF = errors.New("the request has finished") REQUEST_EOF = errors.New("the request has finished")
CLIENT_ID_NOT_EXIST = errors.New("the client id is not exist") CLIENT_ID_NOT_EXIST = errors.New("the client id is not exist")
) )

View File

@ -4,8 +4,10 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"github.com/astaxie/beego/logs"
"io" "io"
"net" "net"
"strings"
) )
func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) { func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
@ -69,3 +71,28 @@ func GetLenBytes(buf []byte) (b []byte, err error) {
b = raw.Bytes() b = raw.Bytes()
return return
} }
func NewTcpListenerAndProcess(addr string, f func(c net.Conn), listener *net.Listener) error {
var err error
*listener, err = net.Listen("tcp", addr)
if err != nil {
return err
}
Accept(*listener, f)
return nil
}
func Accept(l net.Listener, f func(c net.Conn)) {
for {
c, err := l.Accept()
if err != nil {
if strings.Contains(err.Error(), "use of closed network connection") {
break
}
logs.Warn(err)
continue
}
go f(c)
}
}

View File

@ -13,10 +13,10 @@ type Proxy struct {
} }
func (proxy *Proxy) GetConfigName() *core.NpsConfigs { func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
return core.NewNpsConfigs("socks5_proxy", "proxy to inet") return core.NewNpsConfigs("socks5_proxy", "proxy to inet", core.CONFIG_LEVEL_PLUGIN)
} }
func (proxy *Proxy) Run(ctx context.Context, config map[string]string) (context.Context, error) { func (proxy *Proxy) Run(ctx context.Context) (context.Context, error) {
proxy.ctx = ctx proxy.ctx = ctx
proxy.clientConn = proxy.GetClientConn(ctx) proxy.clientConn = proxy.GetClientConn(ctx)
clientId := proxy.GetClientId(ctx) clientId := proxy.GetClientId(ctx)
@ -27,7 +27,13 @@ func (proxy *Proxy) Run(ctx context.Context, config map[string]string) (context.
return ctx, err return ctx, err
} }
// send connection information to the npc
if _, err := core.SendInfo(severConn, nil); err != nil {
return ctx, err
}
// data exchange
go core.CopyBuffer(severConn, proxy.clientConn) go core.CopyBuffer(severConn, proxy.clientConn)
core.CopyBuffer(proxy.clientConn, severConn) core.CopyBuffer(proxy.clientConn, severConn)
return ctx, nil return ctx, core.REQUEST_EOF
} }

View File

@ -17,16 +17,16 @@ type CheckAccess struct {
} }
func (check *CheckAccess) GetConfigName() *core.NpsConfigs { func (check *CheckAccess) GetConfigName() *core.NpsConfigs {
c := core.NewNpsConfigs("socks5_simple_access_check", "need check the permission simply") c := core.NewNpsConfigs("socks5_simple_access_check", "need check the permission simply", core.CONFIG_LEVEL_PLUGIN)
c.Add("socks5_simple_access_username", "simple auth username") c.Add("socks5_simple_access_username", "simple auth username", core.CONFIG_LEVEL_PLUGIN)
c.Add("socks5_simple_access_password", "simple auth password") c.Add("socks5_simple_access_password", "simple auth password", core.CONFIG_LEVEL_PLUGIN)
return c return c
} }
func (check *CheckAccess) Run(ctx context.Context, config map[string]string) (context.Context, error) { func (check *CheckAccess) Run(ctx context.Context) (context.Context, error) {
check.clientConn = check.GetClientConn(ctx) check.clientConn = check.GetClientConn(ctx)
check.configUsername = config["socks5_access_username"] check.configUsername = check.Configs["socks5_access_username"]
check.configPassword = config["socks5_access_password"] check.configPassword = check.Configs["socks5_access_password"]
return ctx, nil return ctx, nil
} }

View File

@ -12,7 +12,7 @@ type Handshake struct {
core.NpsPlugin core.NpsPlugin
} }
func (handshake *Handshake) Run(ctx context.Context, config map[string]string) (context.Context, error) { func (handshake *Handshake) Run(ctx context.Context) (context.Context, error) {
clientConn := handshake.GetClientConn(ctx) clientConn := handshake.GetClientConn(ctx)
buf := make([]byte, 2) buf := make([]byte, 2)
if _, err := io.ReadFull(clientConn, buf); err != nil { if _, err := io.ReadFull(clientConn, buf); err != nil {

View File

@ -22,12 +22,12 @@ type Access struct {
} }
func (access *Access) GetConfigName() *core.NpsConfigs { func (access *Access) GetConfigName() *core.NpsConfigs {
return core.NewNpsConfigs("socks5_check_access_check", "need check the permission simply") return core.NewNpsConfigs("socks5_check_access_check", "need check the permission simply",core.CONFIG_LEVEL_PLUGIN)
} }
func (access *Access) Run(ctx context.Context, config map[string]string) (context.Context, error) { func (access *Access) Run(ctx context.Context) (context.Context, error) {
access.clientConn = access.GetClientConn(ctx) access.clientConn = access.GetClientConn(ctx)
if config["socks5_check_access"] != "true" { if access.Configs["socks5_check_access"] != "true" {
return ctx, access.sendAccessMsgToClient(UserNoAuth) return ctx, access.sendAccessMsgToClient(UserNoAuth)
} }
// need auth // need auth

View File

@ -32,7 +32,7 @@ const (
addrTypeNotSupported = 8 addrTypeNotSupported = 8
) )
func (request *Request) Run(ctx context.Context, config map[string]string) (context.Context, error) { func (request *Request) Run(ctx context.Context) (context.Context, error) {
request.clientConn = request.GetClientConn(ctx) request.clientConn = request.GetClientConn(ctx)
request.ctx = ctx request.ctx = ctx

View File

@ -1,8 +1,9 @@
package socks5 package socks5
import ( import (
"context"
"fmt"
"github.com/cnlh/nps/core" "github.com/cnlh/nps/core"
"github.com/cnlh/nps/lib/conn"
"github.com/cnlh/nps/server/common" "github.com/cnlh/nps/server/common"
"net" "net"
"strconv" "strconv"
@ -29,8 +30,28 @@ func NewS5Server(globalConfig, clientConfig, pluginConfig map[string]string) *S5
return s5 return s5
} }
func (s5 *S5Server) Start() error { func (s5 *S5Server) Start(ctx context.Context) error {
return conn.NewTcpListenerAndProcess(s5.ServerIp+":"+strconv.Itoa(s5.ServerPort), func(c net.Conn) { // 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
}
return core.NewTcpListenerAndProcess(s5.ServerIp+":"+strconv.Itoa(s5.ServerPort), func(c net.Conn) {
// init ctx value clientConn
ctx = context.WithValue(ctx, core.CLIENT_CONNECTION, c)
// start run the plugin run
if err := core.RunPlugin(ctx, s5.plugins.RunPgs); err != nil {
fmt.Println(err)
return
}
// start run the plugin end
if err := core.RunPlugin(ctx, s5.plugins.EndPgs); err != nil {
fmt.Println(err)
return
}
}, &s5.listener) }, &s5.listener)
} }