mirror of
https://github.com/ehang-io/nps.git
synced 2025-07-03 13:10:42 +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
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/cnlh/nps/bridge"
|
|
||||||
"net"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Stage uint8
|
type Stage uint8
|
||||||
@ -26,53 +23,18 @@ const (
|
|||||||
CLIENT_ID = "client_id"
|
CLIENT_ID = "client_id"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ConfigLevel uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
CONFIG_LEVEL_CLIENT ConfigLevel = iota
|
||||||
|
CONFIG_LEVEL_PLUGIN
|
||||||
|
CONFIG_LEVEL_GLOBAL
|
||||||
|
)
|
||||||
|
|
||||||
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 client connection 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 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")
|
return core.NewNpsConfigs("socks5_proxy", "proxy to inet")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) Run(ctx context.Context, config map[string]string) error {
|
func (proxy *Proxy) Run(ctx context.Context, config map[string]string) (context.Context, error) {
|
||||||
proxy.clientConn = proxy.GetClientConn(ctx)
|
|
||||||
proxy.ctx = ctx
|
proxy.ctx = ctx
|
||||||
|
proxy.clientConn = proxy.GetClientConn(ctx)
|
||||||
clientCtxConn := ctx.Value(core.CLIENT_CONNECTION)
|
|
||||||
if clientCtxConn == nil {
|
|
||||||
return core.CLIENT_CONNECTION_NOT_EXIST
|
|
||||||
}
|
|
||||||
|
|
||||||
clientId := proxy.GetClientId(ctx)
|
clientId := proxy.GetClientId(ctx)
|
||||||
|
|
||||||
brg := proxy.GetBridge(ctx)
|
brg := proxy.GetBridge(ctx)
|
||||||
|
|
||||||
severConn, err := brg.GetConnByClientId(clientId)
|
severConn, err := brg.GetConnByClientId(clientId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return ctx, err
|
||||||
}
|
}
|
||||||
|
|
||||||
go core.CopyBuffer(severConn, clientCtxConn.(net.Conn))
|
go core.CopyBuffer(severConn, proxy.clientConn)
|
||||||
core.CopyBuffer(clientCtxConn.(net.Conn), severConn)
|
core.CopyBuffer(proxy.clientConn, severConn)
|
||||||
return nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,12 @@ func (check *CheckAccess) GetConfigName() *core.NpsConfigs {
|
|||||||
return c
|
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.clientConn = check.GetClientConn(ctx)
|
||||||
check.configUsername = config["socks5_access_username"]
|
check.configUsername = config["socks5_access_username"]
|
||||||
check.configPassword = config["socks5_access_password"]
|
check.configPassword = config["socks5_access_password"]
|
||||||
|
|
||||||
return nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *CheckAccess) checkAuth(configUserName, configPassword string) error {
|
func (check *CheckAccess) checkAuth(configUserName, configPassword string) error {
|
||||||
|
@ -12,25 +12,25 @@ type Handshake struct {
|
|||||||
core.NpsPlugin
|
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)
|
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 {
|
||||||
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 {
|
if version := buf[0]; version != 5 {
|
||||||
return errors.New("only support socks5")
|
return ctx, errors.New("only support socks5")
|
||||||
}
|
}
|
||||||
nMethods := buf[1]
|
nMethods := buf[1]
|
||||||
|
|
||||||
methods := make([]byte, nMethods)
|
methods := make([]byte, nMethods)
|
||||||
|
|
||||||
if n, err := clientConn.Read(methods); n != int(nMethods) || err != nil {
|
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 {
|
} 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")
|
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)
|
access.clientConn = access.GetClientConn(ctx)
|
||||||
if config["socks5_check_access"] != "true" {
|
if config["socks5_check_access"] != "true" {
|
||||||
return access.sendAccessMsgToClient(UserNoAuth)
|
return ctx, access.sendAccessMsgToClient(UserNoAuth)
|
||||||
}
|
}
|
||||||
// need auth
|
// need auth
|
||||||
if err := access.sendAccessMsgToClient(UserPassAuth); err != nil {
|
if err := access.sendAccessMsgToClient(UserPassAuth); err != nil {
|
||||||
return err
|
return ctx, err
|
||||||
}
|
}
|
||||||
// send auth reply to client ,and get the auth information
|
// send auth reply to client ,and get the auth information
|
||||||
username, password, err := access.getAuthInfoFromClient()
|
username, password, err := access.getAuthInfoFromClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return ctx, err
|
||||||
}
|
}
|
||||||
context.WithValue(ctx, "socks_client_username", username)
|
ctx = context.WithValue(ctx, "socks_client_username", username)
|
||||||
context.WithValue(ctx, "socks_client_password", password)
|
ctx = context.WithValue(ctx, "socks_client_password", password)
|
||||||
// check
|
// check
|
||||||
return nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (access *Access) sendAccessMsgToClient(auth uint8) error {
|
func (access *Access) sendAccessMsgToClient(auth uint8) error {
|
||||||
|
@ -32,7 +32,7 @@ const (
|
|||||||
addrTypeNotSupported = 8
|
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.clientConn = request.GetClientConn(ctx)
|
||||||
request.ctx = 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)
|
_, err := io.ReadFull(request.clientConn, header)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("illegal request" + err.Error())
|
return request.ctx, errors.New("illegal request" + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
switch header[1] {
|
switch header[1] {
|
||||||
case connectMethod:
|
case connectMethod:
|
||||||
context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
|
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
|
||||||
return request.doConnect()
|
return request.ctx, request.doConnect()
|
||||||
case bindMethod:
|
case bindMethod:
|
||||||
return request.handleBind()
|
return request.ctx, request.handleBind()
|
||||||
case associateMethod:
|
case associateMethod:
|
||||||
context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
|
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
|
||||||
return request.handleUDP()
|
return request.ctx, request.handleUDP()
|
||||||
default:
|
default:
|
||||||
request.sendReply(commandNotSupported)
|
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 {
|
func (request *Request) sendReply(rep uint8) error {
|
||||||
@ -116,8 +116,8 @@ func (request *Request) doConnect() error {
|
|||||||
var port uint16
|
var port uint16
|
||||||
binary.Read(request.clientConn, binary.BigEndian, &port)
|
binary.Read(request.clientConn, binary.BigEndian, &port)
|
||||||
|
|
||||||
context.WithValue(request.ctx, core.PROXY_CONNECTION_ADDR, host)
|
request.ctx = 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_PORT, port)
|
||||||
return nil
|
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