mirror of
https://github.com/ehang-io/nps.git
synced 2025-07-03 21:20:41 +00:00
module
This commit is contained in:
parent
6771816be7
commit
f0a9f4e471
@ -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 {
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user