mirror of
https://github.com/ehang-io/nps.git
synced 2025-07-03 04:53:50 +00:00
module
This commit is contained in:
parent
f4ae503982
commit
6771816be7
75
core/plugin.go
Normal file
75
core/plugin.go
Normal file
@ -0,0 +1,75 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cnlh/nps/bridge"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Plugin interface, all plugins must implement those functions.
|
||||
type Plugin interface {
|
||||
GetConfigName() *NpsConfigs
|
||||
GetConfigLevel() ConfigLevel
|
||||
GetStage() Stage
|
||||
Start(ctx context.Context, config map[string]string) (context.Context, error)
|
||||
Run(ctx context.Context, config map[string]string) (context.Context, error)
|
||||
End(ctx context.Context, config map[string]string) (context.Context, error)
|
||||
}
|
||||
|
||||
type NpsPlugin struct {
|
||||
Version string
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs {
|
||||
return nil
|
||||
}
|
||||
|
||||
// describe the config level
|
||||
func (npsPlugin *NpsPlugin) GetConfigLevel() ConfigLevel {
|
||||
return CONFIG_LEVEL_PLUGIN
|
||||
}
|
||||
|
||||
// describe the stage of the plugin
|
||||
func (npsPlugin *NpsPlugin) GetStage() Stage {
|
||||
return STAGE_RUN
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) Start(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) Run(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) End(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetClientConn(ctx context.Context) net.Conn {
|
||||
return ctx.Value(CLIENT_CONNECTION).(net.Conn)
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetBridge(ctx context.Context) *bridge.Bridge {
|
||||
return ctx.Value(BRIDGE).(*bridge.Bridge)
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetClientId(ctx context.Context) int {
|
||||
return ctx.Value(CLIENT_ID).(int)
|
||||
}
|
||||
|
||||
type Plugins struct {
|
||||
pgs []Plugin
|
||||
}
|
||||
|
||||
func NewPlugins() *Plugins {
|
||||
p := &Plugins{}
|
||||
p.pgs = make([]Plugin, 0)
|
||||
return p
|
||||
}
|
||||
|
||||
func (pl *Plugins) Add(plugins ...Plugin) {
|
||||
for _, plugin := range plugins {
|
||||
pl.pgs = append(pl.pgs, plugin)
|
||||
}
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/cnlh/nps/bridge"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Stage uint8
|
||||
@ -26,53 +23,18 @@ const (
|
||||
CLIENT_ID = "client_id"
|
||||
)
|
||||
|
||||
type ConfigLevel uint8
|
||||
|
||||
const (
|
||||
CONFIG_LEVEL_CLIENT ConfigLevel = iota
|
||||
CONFIG_LEVEL_PLUGIN
|
||||
CONFIG_LEVEL_GLOBAL
|
||||
)
|
||||
|
||||
var (
|
||||
CLIENT_CONNECTION_NOT_EXIST = errors.New("the client connection is not exist")
|
||||
BRIDGE_NOT_EXIST = errors.New("the client connection is not exist")
|
||||
REQUEST_EOF = errors.New("the request has finished")
|
||||
CLIENT_ID_NOT_EXIST = errors.New("the request has finished")
|
||||
CLIENT_ID_NOT_EXIST = errors.New("the client id is not exist")
|
||||
)
|
||||
|
||||
// Plugin interface, all plugins must implement those functions.
|
||||
type Plugin interface {
|
||||
GetConfigName() *NpsConfigs
|
||||
GetStage() Stage
|
||||
Start(ctx context.Context, config map[string]string) error
|
||||
Run(ctx context.Context, config map[string]string) error
|
||||
End(ctx context.Context, config map[string]string) error
|
||||
}
|
||||
|
||||
type NpsPlugin struct {
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetStage() Stage {
|
||||
return STAGE_RUN
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) Start(ctx context.Context, config map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) Run(ctx context.Context, config map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) End(ctx context.Context, config map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetClientConn(ctx context.Context) net.Conn {
|
||||
return ctx.Value(CLIENT_CONNECTION).(net.Conn)
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetBridge(ctx context.Context) *bridge.Bridge {
|
||||
return ctx.Value(BRIDGE).(*bridge.Bridge)
|
||||
}
|
||||
|
||||
func (npsPlugin *NpsPlugin) GetClientId(ctx context.Context) int {
|
||||
return ctx.Value(CLIENT_ID).(int)
|
||||
}
|
||||
|
@ -16,24 +16,18 @@ func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
|
||||
return core.NewNpsConfigs("socks5_proxy", "proxy to inet")
|
||||
}
|
||||
|
||||
func (proxy *Proxy) Run(ctx context.Context, config map[string]string) error {
|
||||
proxy.clientConn = proxy.GetClientConn(ctx)
|
||||
func (proxy *Proxy) Run(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
proxy.ctx = ctx
|
||||
|
||||
clientCtxConn := ctx.Value(core.CLIENT_CONNECTION)
|
||||
if clientCtxConn == nil {
|
||||
return core.CLIENT_CONNECTION_NOT_EXIST
|
||||
}
|
||||
|
||||
proxy.clientConn = proxy.GetClientConn(ctx)
|
||||
clientId := proxy.GetClientId(ctx)
|
||||
|
||||
brg := proxy.GetBridge(ctx)
|
||||
|
||||
severConn, err := brg.GetConnByClientId(clientId)
|
||||
if err != nil {
|
||||
return err
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
go core.CopyBuffer(severConn, clientCtxConn.(net.Conn))
|
||||
core.CopyBuffer(clientCtxConn.(net.Conn), severConn)
|
||||
return nil
|
||||
go core.CopyBuffer(severConn, proxy.clientConn)
|
||||
core.CopyBuffer(proxy.clientConn, severConn)
|
||||
return ctx, nil
|
||||
}
|
||||
|
@ -23,12 +23,12 @@ func (check *CheckAccess) GetConfigName() *core.NpsConfigs {
|
||||
return c
|
||||
}
|
||||
|
||||
func (check *CheckAccess) Run(ctx context.Context, config map[string]string) error {
|
||||
func (check *CheckAccess) Run(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
check.clientConn = check.GetClientConn(ctx)
|
||||
check.configUsername = config["socks5_access_username"]
|
||||
check.configPassword = config["socks5_access_password"]
|
||||
|
||||
return nil
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (check *CheckAccess) checkAuth(configUserName, configPassword string) error {
|
||||
|
@ -12,25 +12,25 @@ type Handshake struct {
|
||||
core.NpsPlugin
|
||||
}
|
||||
|
||||
func (handshake *Handshake) Run(ctx context.Context, config map[string]string) error {
|
||||
func (handshake *Handshake) Run(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
clientConn := handshake.GetClientConn(ctx)
|
||||
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())
|
||||
return ctx, 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")
|
||||
return ctx, 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()))
|
||||
return ctx, errors.New(fmt.Sprintf("read methods error, need %d , read %d, error %s", nMethods, n, err.Error()))
|
||||
} else {
|
||||
context.WithValue(ctx, "methods", methods[:n])
|
||||
ctx = context.WithValue(ctx, "methods", methods[:n])
|
||||
}
|
||||
|
||||
return nil
|
||||
return ctx, nil
|
||||
}
|
||||
|
@ -25,24 +25,24 @@ func (access *Access) GetConfigName() *core.NpsConfigs {
|
||||
return core.NewNpsConfigs("socks5_check_access_check", "need check the permission simply")
|
||||
}
|
||||
|
||||
func (access *Access) Run(ctx context.Context, config map[string]string) error {
|
||||
func (access *Access) Run(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
access.clientConn = access.GetClientConn(ctx)
|
||||
if config["socks5_check_access"] != "true" {
|
||||
return access.sendAccessMsgToClient(UserNoAuth)
|
||||
return ctx, access.sendAccessMsgToClient(UserNoAuth)
|
||||
}
|
||||
// need auth
|
||||
if err := access.sendAccessMsgToClient(UserPassAuth); err != nil {
|
||||
return err
|
||||
return ctx, err
|
||||
}
|
||||
// send auth reply to client ,and get the auth information
|
||||
username, password, err := access.getAuthInfoFromClient()
|
||||
if err != nil {
|
||||
return err
|
||||
return ctx, err
|
||||
}
|
||||
context.WithValue(ctx, "socks_client_username", username)
|
||||
context.WithValue(ctx, "socks_client_password", password)
|
||||
ctx = context.WithValue(ctx, "socks_client_username", username)
|
||||
ctx = context.WithValue(ctx, "socks_client_password", password)
|
||||
// check
|
||||
return nil
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (access *Access) sendAccessMsgToClient(auth uint8) error {
|
||||
|
@ -32,7 +32,7 @@ const (
|
||||
addrTypeNotSupported = 8
|
||||
)
|
||||
|
||||
func (request *Request) Run(ctx context.Context, config map[string]string) error {
|
||||
func (request *Request) Run(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||
request.clientConn = request.GetClientConn(ctx)
|
||||
request.ctx = ctx
|
||||
|
||||
@ -49,23 +49,23 @@ func (request *Request) Run(ctx context.Context, config map[string]string) error
|
||||
_, err := io.ReadFull(request.clientConn, header)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("illegal request" + err.Error())
|
||||
return request.ctx, errors.New("illegal request" + err.Error())
|
||||
}
|
||||
|
||||
switch header[1] {
|
||||
case connectMethod:
|
||||
context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
|
||||
return request.doConnect()
|
||||
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
|
||||
return request.ctx, request.doConnect()
|
||||
case bindMethod:
|
||||
return request.handleBind()
|
||||
return request.ctx, request.handleBind()
|
||||
case associateMethod:
|
||||
context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
|
||||
return request.handleUDP()
|
||||
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
|
||||
return request.ctx, request.handleUDP()
|
||||
default:
|
||||
request.sendReply(commandNotSupported)
|
||||
return errors.New("command not supported")
|
||||
return request.ctx, errors.New("command not supported")
|
||||
}
|
||||
return nil
|
||||
return request.ctx, nil
|
||||
}
|
||||
|
||||
func (request *Request) sendReply(rep uint8) error {
|
||||
@ -116,8 +116,8 @@ func (request *Request) doConnect() error {
|
||||
var port uint16
|
||||
binary.Read(request.clientConn, binary.BigEndian, &port)
|
||||
|
||||
context.WithValue(request.ctx, core.PROXY_CONNECTION_ADDR, host)
|
||||
context.WithValue(request.ctx, core.PROXY_CONNECTION_PORT, 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
|
||||
}
|
||||
|
||||
|
36
server/socks5/socks5_server.go
Normal file
36
server/socks5/socks5_server.go
Normal file
@ -0,0 +1,36 @@
|
||||
package socks5
|
||||
|
||||
import (
|
||||
"github.com/cnlh/nps/core"
|
||||
"github.com/cnlh/nps/lib/conn"
|
||||
"github.com/cnlh/nps/server/common"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type S5Server struct {
|
||||
globalConfig map[string]string
|
||||
clientConfig map[string]string
|
||||
pluginConfig map[string]string
|
||||
ServerIp string
|
||||
ServerPort int
|
||||
plugins *core.Plugins
|
||||
listener net.Listener
|
||||
}
|
||||
|
||||
func NewS5Server(globalConfig, clientConfig, pluginConfig map[string]string) *S5Server {
|
||||
s5 := &S5Server{
|
||||
globalConfig: globalConfig,
|
||||
clientConfig: clientConfig,
|
||||
pluginConfig: pluginConfig,
|
||||
plugins: &core.Plugins{},
|
||||
}
|
||||
s5.plugins.Add(new(Handshake), new(Access), new(CheckAccess), new(Request), new(common.Proxy))
|
||||
return s5
|
||||
}
|
||||
|
||||
func (s5 *S5Server) Start() error {
|
||||
return conn.NewTcpListenerAndProcess(s5.ServerIp+":"+strconv.Itoa(s5.ServerPort), func(c net.Conn) {
|
||||
|
||||
}, &s5.listener)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user