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
5e5df224b7
commit
b6a9001d43
50
core/const.go
Normal file
50
core/const.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
const (
|
||||||
|
CONN_DATA_SEQ = "*#*" //Separator
|
||||||
|
VERIFY_EER = "vkey"
|
||||||
|
VERIFY_SUCCESS = "sucs"
|
||||||
|
WORK_MAIN = "main"
|
||||||
|
WORK_CHAN = "chan"
|
||||||
|
WORK_CONFIG = "conf"
|
||||||
|
WORK_REGISTER = "rgst"
|
||||||
|
WORK_SECRET = "sert"
|
||||||
|
WORK_FILE = "file"
|
||||||
|
WORK_P2P = "p2pm"
|
||||||
|
WORK_P2P_VISITOR = "p2pv"
|
||||||
|
WORK_P2P_PROVIDER = "p2pp"
|
||||||
|
WORK_P2P_CONNECT = "p2pc"
|
||||||
|
WORK_P2P_SUCCESS = "p2ps"
|
||||||
|
WORK_P2P_END = "p2pe"
|
||||||
|
WORK_P2P_LAST = "p2pl"
|
||||||
|
WORK_STATUS = "stus"
|
||||||
|
RES_MSG = "msg0"
|
||||||
|
RES_CLOSE = "clse"
|
||||||
|
NEW_UDP_CONN = "udpc" //p2p udp conn
|
||||||
|
NEW_TASK = "task"
|
||||||
|
NEW_CONF = "conf"
|
||||||
|
NEW_HOST = "host"
|
||||||
|
CONN_TCP = "tcp"
|
||||||
|
CONN_UDP = "udp"
|
||||||
|
CONN_TEST = "TST"
|
||||||
|
UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
WWW-Authenticate: Basic realm="easyProxy"
|
||||||
|
|
||||||
|
401 Unauthorized`
|
||||||
|
ConnectionFailBytes = `HTTP/1.1 404 Not Found
|
||||||
|
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MUX_PING_FLAG uint8 = iota
|
||||||
|
MUX_NEW_CONN_OK
|
||||||
|
MUX_NEW_CONN_Fail
|
||||||
|
MUX_NEW_MSG
|
||||||
|
MUX_MSG_SEND_OK
|
||||||
|
MUX_NEW_CONN
|
||||||
|
MUX_CONN_CLOSE
|
||||||
|
MUX_PING_RETURN
|
||||||
|
MUX_PING int32 = -1
|
||||||
|
)
|
209
core/netpackager.go
Normal file
209
core/netpackager.go
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NetPackager interface {
|
||||||
|
Pack(writer io.Writer) (err error)
|
||||||
|
UnPack(reader io.Reader) (err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasePackager struct {
|
||||||
|
Length uint32
|
||||||
|
Content []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *BasePackager) NewPac(contents ...interface{}) (err error) {
|
||||||
|
Self.clean()
|
||||||
|
for _, content := range contents {
|
||||||
|
switch content.(type) {
|
||||||
|
case nil:
|
||||||
|
Self.Content = Self.Content[:0]
|
||||||
|
case []byte:
|
||||||
|
err = Self.appendByte(content.([]byte))
|
||||||
|
case string:
|
||||||
|
err = Self.appendByte([]byte(content.(string)))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = Self.appendByte([]byte(CONN_DATA_SEQ))
|
||||||
|
default:
|
||||||
|
err = Self.marshal(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self.setLength()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *BasePackager) appendByte(data []byte) (err error) {
|
||||||
|
m := len(Self.Content)
|
||||||
|
n := m + len(data)
|
||||||
|
if n <= cap(Self.Content) {
|
||||||
|
Self.Content = Self.Content[0:n] // grow the length for copy
|
||||||
|
copy(Self.Content[m:n], data)
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("pack content too large")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//似乎这里涉及到父类作用域问题,当子类调用父类的方法时,其struct仅仅为父类的
|
||||||
|
func (Self *BasePackager) Pack(writer io.Writer) (err error) {
|
||||||
|
err = binary.Write(writer, binary.LittleEndian, Self.Length)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = binary.Write(writer, binary.LittleEndian, Self.Content)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Unpack 会导致传入的数字类型转化成float64!!
|
||||||
|
//主要原因是json unmarshal并未传入正确的数据类型
|
||||||
|
func (Self *BasePackager) UnPack(reader io.Reader) (err error) {
|
||||||
|
Self.clean()
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, &Self.Length)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if int(Self.Length) > cap(Self.Content) {
|
||||||
|
err = errors.New("unpack err, content length too large")
|
||||||
|
}
|
||||||
|
Self.Content = Self.Content[:int(Self.Length)]
|
||||||
|
//n, err := io.ReadFull(reader, Self.Content)
|
||||||
|
//if n != int(Self.Length) {
|
||||||
|
// err = io.ErrUnexpectedEOF
|
||||||
|
//}
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, Self.Content)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *BasePackager) marshal(content interface{}) (err error) {
|
||||||
|
tmp, err := json.Marshal(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = Self.appendByte(tmp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *BasePackager) Unmarshal(content interface{}) (err error) {
|
||||||
|
err = json.Unmarshal(Self.Content, content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *BasePackager) setLength() {
|
||||||
|
Self.Length = uint32(len(Self.Content))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *BasePackager) clean() {
|
||||||
|
Self.Length = 0
|
||||||
|
Self.Content = Self.Content[:0] // reset length
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *BasePackager) Split() (strList []string) {
|
||||||
|
n := bytes.IndexByte(Self.Content, 0)
|
||||||
|
strList = strings.Split(string(Self.Content[:n]), CONN_DATA_SEQ)
|
||||||
|
strList = strList[0 : len(strList)-1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnPackager struct { // Todo
|
||||||
|
ConnType uint8
|
||||||
|
BasePackager
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *ConnPackager) NewPac(connType uint8, content ...interface{}) (err error) {
|
||||||
|
Self.ConnType = connType
|
||||||
|
err = Self.BasePackager.NewPac(content...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *ConnPackager) Pack(writer io.Writer) (err error) {
|
||||||
|
err = binary.Write(writer, binary.LittleEndian, Self.ConnType)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = Self.BasePackager.Pack(writer)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *ConnPackager) UnPack(reader io.Reader) (err error) {
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, &Self.ConnType)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = Self.BasePackager.UnPack(reader)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type MuxPackager struct {
|
||||||
|
Flag uint8
|
||||||
|
Id int32
|
||||||
|
Window uint16
|
||||||
|
BasePackager
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *MuxPackager) NewPac(flag uint8, id int32, content ...interface{}) (err error) {
|
||||||
|
Self.Flag = flag
|
||||||
|
Self.Id = id
|
||||||
|
if flag == MUX_NEW_MSG {
|
||||||
|
err = Self.BasePackager.NewPac(content...)
|
||||||
|
}
|
||||||
|
if flag == MUX_MSG_SEND_OK {
|
||||||
|
// MUX_MSG_SEND_OK only allows one data
|
||||||
|
switch content[0].(type) {
|
||||||
|
case int:
|
||||||
|
Self.Window = uint16(content[0].(int))
|
||||||
|
case uint16:
|
||||||
|
Self.Window = content[0].(uint16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *MuxPackager) Pack(writer io.Writer) (err error) {
|
||||||
|
err = binary.Write(writer, binary.LittleEndian, Self.Flag)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = binary.Write(writer, binary.LittleEndian, Self.Id)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if Self.Flag == MUX_NEW_MSG {
|
||||||
|
err = Self.BasePackager.Pack(writer)
|
||||||
|
}
|
||||||
|
if Self.Flag == MUX_MSG_SEND_OK {
|
||||||
|
err = binary.Write(writer, binary.LittleEndian, Self.Window)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Self *MuxPackager) UnPack(reader io.Reader) (err error) {
|
||||||
|
Self.BasePackager.clean() // also clean the content
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, &Self.Flag)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, &Self.Id)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if Self.Flag == MUX_NEW_MSG {
|
||||||
|
err = Self.BasePackager.UnPack(reader)
|
||||||
|
}
|
||||||
|
if Self.Flag == MUX_MSG_SEND_OK {
|
||||||
|
err = binary.Read(reader, binary.LittleEndian, &Self.Window)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
@ -9,7 +9,7 @@ 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
|
||||||
InitConfig(globalConfig, clientConfig, pluginConfig map[string]string)
|
InitConfig(globalConfig, clientConfig, pluginConfig map[string]string, pgCnf []*Config)
|
||||||
GetStage() []Stage
|
GetStage() []Stage
|
||||||
Start(ctx context.Context) (context.Context, error)
|
Start(ctx context.Context) (context.Context, error)
|
||||||
Run(ctx context.Context) (context.Context, error)
|
Run(ctx context.Context) (context.Context, error)
|
||||||
@ -25,9 +25,9 @@ func (npsPlugin *NpsPlugin) GetConfigName() *NpsConfigs {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npsPlugin *NpsPlugin) InitConfig(globalConfig, clientConfig, pluginConfig map[string]string) {
|
func (npsPlugin *NpsPlugin) InitConfig(globalConfig, clientConfig, pluginConfig map[string]string, pgCnf []*Config) {
|
||||||
npsPlugin.Configs = make(map[string]string)
|
npsPlugin.Configs = make(map[string]string)
|
||||||
for _, cfg := range npsPlugin.GetConfigName().GetAll() {
|
for _, cfg := range pgCnf {
|
||||||
switch cfg.ConfigLevel {
|
switch cfg.ConfigLevel {
|
||||||
case CONFIG_LEVEL_PLUGIN:
|
case CONFIG_LEVEL_PLUGIN:
|
||||||
npsPlugin.Configs[cfg.ConfigName] = pluginConfig[cfg.ConfigName]
|
npsPlugin.Configs[cfg.ConfigName] = pluginConfig[cfg.ConfigName]
|
||||||
@ -105,13 +105,20 @@ func (pl *Plugins) Add(plugins ...Plugin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunPlugin(ctx context.Context, pgs []Plugin) error {
|
func RunPlugin(ctx context.Context, pgs []Plugin, stage Stage) (context.Context, error) {
|
||||||
var err error
|
var err error
|
||||||
for _, pg := range pgs {
|
for _, pg := range pgs {
|
||||||
|
switch stage {
|
||||||
|
case STAGE_RUN:
|
||||||
|
ctx, err = pg.Run(ctx)
|
||||||
|
case STAGE_START:
|
||||||
ctx, err = pg.Start(ctx)
|
ctx, err = pg.Start(ctx)
|
||||||
|
case STAGE_END:
|
||||||
|
ctx, err = pg.End(ctx)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return ctx, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,14 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/cnlh/nps/core"
|
"github.com/cnlh/nps/core"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
core.NpsPlugin
|
core.NpsPlugin
|
||||||
clientConn net.Conn
|
|
||||||
ctx context.Context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
|
func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
|
||||||
@ -17,10 +17,9 @@ func (proxy *Proxy) GetConfigName() *core.NpsConfigs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) Run(ctx context.Context) (context.Context, error) {
|
func (proxy *Proxy) Run(ctx context.Context) (context.Context, error) {
|
||||||
proxy.ctx = ctx
|
clientConn := proxy.GetClientConn(ctx)
|
||||||
proxy.clientConn = proxy.GetClientConn(ctx)
|
//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 {
|
||||||
@ -31,12 +30,22 @@ func (proxy *Proxy) Run(ctx context.Context) (context.Context, error) {
|
|||||||
//if _, err := core.SendInfo(severConn, nil); err != nil {
|
//if _, err := core.SendInfo(severConn, nil); err != nil {
|
||||||
// return ctx, err
|
// return ctx, err
|
||||||
//}
|
//}
|
||||||
severConn, err := net.Dial(ctx.Value(core.PROXY_CONNECTION_TYPE).(string), ctx.Value(core.PROXY_CONNECTION_ADDR).(string)+":"+ctx.Value(core.PROXY_CONNECTION_PORT).(string))
|
connType := ctx.Value(core.PROXY_CONNECTION_TYPE).(string)
|
||||||
|
connAddr := ctx.Value(core.PROXY_CONNECTION_ADDR).(string)
|
||||||
|
connPort := strconv.Itoa(int(ctx.Value(core.PROXY_CONNECTION_PORT).(uint16)))
|
||||||
|
fmt.Println(connType, connAddr, connPort, clientConn.RemoteAddr().String())
|
||||||
|
serverConn, err := net.Dial(connType, connAddr+":"+connPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, err
|
return ctx, err
|
||||||
}
|
}
|
||||||
// data exchange
|
// data exchange
|
||||||
go core.CopyBuffer(severConn, proxy.clientConn)
|
go func() {
|
||||||
core.CopyBuffer(proxy.clientConn, severConn)
|
core.CopyBuffer(serverConn, clientConn)
|
||||||
|
serverConn.Close()
|
||||||
|
clientConn.Close()
|
||||||
|
}()
|
||||||
|
core.CopyBuffer(clientConn, serverConn)
|
||||||
|
serverConn.Close()
|
||||||
|
clientConn.Close()
|
||||||
return ctx, core.REQUEST_EOF
|
return ctx, core.REQUEST_EOF
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,13 @@ package socks5
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/cnlh/nps/core"
|
"github.com/cnlh/nps/core"
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CheckAccess struct {
|
type CheckAccess struct {
|
||||||
core.NpsPlugin
|
core.NpsPlugin
|
||||||
clientConn net.Conn
|
|
||||||
clientUsername string
|
|
||||||
clientPassword string
|
|
||||||
configUsername string
|
configUsername string
|
||||||
configPassword string
|
configPassword string
|
||||||
}
|
}
|
||||||
@ -24,19 +22,23 @@ func (check *CheckAccess) GetConfigName() *core.NpsConfigs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (check *CheckAccess) Run(ctx context.Context) (context.Context, error) {
|
func (check *CheckAccess) Run(ctx context.Context) (context.Context, error) {
|
||||||
check.clientConn = check.GetClientConn(ctx)
|
clientConn := check.GetClientConn(ctx)
|
||||||
check.configUsername = check.Configs["socks5_access_username"]
|
check.configUsername = check.Configs["socks5_simple_access_username"]
|
||||||
check.configPassword = check.Configs["socks5_access_password"]
|
check.configPassword = check.Configs["socks5_simple_access_password"]
|
||||||
|
if check.Configs["socks5_simple_access_check"] == "true" {
|
||||||
|
connUsername := ctx.Value("socks_client_username").(string)
|
||||||
|
connPassword := ctx.Value("socks_client_password").(string)
|
||||||
|
return ctx, check.checkAuth(clientConn, connUsername, connPassword)
|
||||||
|
}
|
||||||
return ctx, nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *CheckAccess) checkAuth(configUserName, configPassword string) error {
|
func (check *CheckAccess) checkAuth(clientConn net.Conn, connUserName, connPassword string) error {
|
||||||
if check.clientUsername == configUserName && check.clientPassword == configPassword {
|
if check.configUsername == connUserName && check.configPassword == connPassword {
|
||||||
_, err := check.clientConn.Write([]byte{userAuthVersion, authSuccess})
|
_, err := clientConn.Write([]byte{userAuthVersion, authSuccess})
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
_, err := check.clientConn.Write([]byte{userAuthVersion, authFailure})
|
_, err := clientConn.Write([]byte{userAuthVersion, authFailure})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -18,24 +18,23 @@ const (
|
|||||||
|
|
||||||
type Access struct {
|
type Access struct {
|
||||||
core.NpsPlugin
|
core.NpsPlugin
|
||||||
clientConn net.Conn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (access *Access) GetConfigName() *core.NpsConfigs {
|
func (access *Access) GetConfigName() *core.NpsConfigs {
|
||||||
return core.NewNpsConfigs("socks5_check_access_check", "need check the permission simply",core.CONFIG_LEVEL_PLUGIN)
|
return core.NewNpsConfigs("socks5_check_access", "need check the permission simply", core.CONFIG_LEVEL_PLUGIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (access *Access) Run(ctx context.Context) (context.Context, error) {
|
func (access *Access) Run(ctx context.Context) (context.Context, error) {
|
||||||
access.clientConn = access.GetClientConn(ctx)
|
clientConn := access.GetClientConn(ctx)
|
||||||
if access.Configs["socks5_check_access"] != "true" {
|
if access.Configs["socks5_check_access"] != "true" {
|
||||||
return ctx, access.sendAccessMsgToClient(UserNoAuth)
|
return ctx, access.sendAccessMsgToClient(clientConn, UserNoAuth)
|
||||||
}
|
}
|
||||||
// need auth
|
// need auth
|
||||||
if err := access.sendAccessMsgToClient(UserPassAuth); err != nil {
|
if err := access.sendAccessMsgToClient(clientConn, UserPassAuth); err != nil {
|
||||||
return ctx, 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(clientConn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, err
|
return ctx, err
|
||||||
}
|
}
|
||||||
@ -45,20 +44,20 @@ func (access *Access) Run(ctx context.Context) (context.Context, error) {
|
|||||||
return ctx, nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (access *Access) sendAccessMsgToClient(auth uint8) error {
|
func (access *Access) sendAccessMsgToClient(clientConn net.Conn, auth uint8) error {
|
||||||
buf := make([]byte, 2)
|
buf := make([]byte, 2)
|
||||||
buf[0] = 5
|
buf[0] = 5
|
||||||
buf[1] = auth
|
buf[1] = auth
|
||||||
n, err := access.clientConn.Write(buf)
|
n, err := clientConn.Write(buf)
|
||||||
if err != nil || n != 2 {
|
if err != nil || n != 2 {
|
||||||
return errors.New("write access message to client error " + err.Error())
|
return errors.New("write access message to client error " + err.Error())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (access *Access) getAuthInfoFromClient() (username string, password string, err error) {
|
func (access *Access) getAuthInfoFromClient(clientConn net.Conn) (username string, password string, err error) {
|
||||||
header := []byte{0, 0}
|
header := []byte{0, 0}
|
||||||
if _, err = io.ReadAtLeast(access.clientConn, header, 2); err != nil {
|
if _, err = io.ReadAtLeast(clientConn, header, 2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if header[0] != userAuthVersion {
|
if header[0] != userAuthVersion {
|
||||||
@ -67,16 +66,16 @@ func (access *Access) getAuthInfoFromClient() (username string, password string,
|
|||||||
}
|
}
|
||||||
userLen := int(header[1])
|
userLen := int(header[1])
|
||||||
user := make([]byte, userLen)
|
user := make([]byte, userLen)
|
||||||
if _, err = io.ReadAtLeast(access.clientConn, user, userLen); err != nil {
|
if _, err = io.ReadAtLeast(clientConn, user, userLen); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := access.clientConn.Read(header[:1]); err != nil {
|
if _, err = clientConn.Read(header[:1]); err != nil {
|
||||||
err = errors.New("get password length error" + err.Error())
|
err = errors.New("get password length error" + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
passLen := int(header[0])
|
passLen := int(header[0])
|
||||||
pass := make([]byte, passLen)
|
pass := make([]byte, passLen)
|
||||||
if _, err := io.ReadAtLeast(access.clientConn, pass, passLen); err != nil {
|
if _, err = io.ReadAtLeast(clientConn, pass, passLen); err != nil {
|
||||||
err = errors.New("get password error" + err.Error())
|
err = errors.New("get password error" + err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@ import (
|
|||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
core.NpsPlugin
|
core.NpsPlugin
|
||||||
clientConn net.Conn
|
|
||||||
ctx context.Context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -30,11 +28,11 @@ const (
|
|||||||
maxUDPPacketSize = 1476
|
maxUDPPacketSize = 1476
|
||||||
commandNotSupported = 7
|
commandNotSupported = 7
|
||||||
addrTypeNotSupported = 8
|
addrTypeNotSupported = 8
|
||||||
|
succeeded = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
func (request *Request) Run(ctx context.Context) (context.Context, error) {
|
func (request *Request) Run(ctx context.Context) (context.Context, error) {
|
||||||
request.clientConn = request.GetClientConn(ctx)
|
clientConn := request.GetClientConn(ctx)
|
||||||
request.ctx = ctx
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The SOCKS request is formed as follows:
|
The SOCKS request is formed as follows:
|
||||||
@ -46,36 +44,36 @@ func (request *Request) Run(ctx context.Context) (context.Context, error) {
|
|||||||
*/
|
*/
|
||||||
header := make([]byte, 3)
|
header := make([]byte, 3)
|
||||||
|
|
||||||
_, err := io.ReadFull(request.clientConn, header)
|
_, err := io.ReadFull(clientConn, header)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return request.ctx, errors.New("illegal request" + err.Error())
|
return ctx, errors.New("illegal request" + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
switch header[1] {
|
switch header[1] {
|
||||||
case connectMethod:
|
case connectMethod:
|
||||||
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "tcp")
|
ctx = context.WithValue(ctx, core.PROXY_CONNECTION_TYPE, "tcp")
|
||||||
return request.ctx, request.doConnect()
|
return request.doConnect(ctx, clientConn)
|
||||||
case bindMethod:
|
case bindMethod:
|
||||||
return request.ctx, request.handleBind()
|
return ctx, request.handleBind()
|
||||||
case associateMethod:
|
case associateMethod:
|
||||||
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_TYPE, "udp")
|
ctx = context.WithValue(ctx, core.PROXY_CONNECTION_TYPE, "udp")
|
||||||
return request.ctx, request.handleUDP()
|
return request.handleUDP(ctx, clientConn)
|
||||||
default:
|
default:
|
||||||
request.sendReply(commandNotSupported)
|
request.sendReply(clientConn, commandNotSupported)
|
||||||
return request.ctx, errors.New("command not supported")
|
return ctx, errors.New("command not supported")
|
||||||
}
|
}
|
||||||
return request.ctx, nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (request *Request) sendReply(rep uint8) error {
|
func (request *Request) sendReply(clientConn net.Conn, rep uint8) error {
|
||||||
reply := []byte{
|
reply := []byte{
|
||||||
5,
|
5,
|
||||||
rep,
|
rep,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
}
|
}
|
||||||
localAddr := request.clientConn.LocalAddr().String()
|
localAddr := clientConn.LocalAddr().String()
|
||||||
localHost, localPort, _ := net.SplitHostPort(localAddr)
|
localHost, localPort, _ := net.SplitHostPort(localAddr)
|
||||||
ipBytes := net.ParseIP(localHost).To4()
|
ipBytes := net.ParseIP(localHost).To4()
|
||||||
nPort, _ := strconv.Atoi(localPort)
|
nPort, _ := strconv.Atoi(localPort)
|
||||||
@ -83,42 +81,41 @@ func (request *Request) sendReply(rep uint8) error {
|
|||||||
portBytes := make([]byte, 2)
|
portBytes := make([]byte, 2)
|
||||||
binary.BigEndian.PutUint16(portBytes, uint16(nPort))
|
binary.BigEndian.PutUint16(portBytes, uint16(nPort))
|
||||||
reply = append(reply, portBytes...)
|
reply = append(reply, portBytes...)
|
||||||
_, err := request.clientConn.Write(reply)
|
_, err := clientConn.Write(reply)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//do conn
|
//do conn
|
||||||
func (request *Request) doConnect() error {
|
func (request *Request) doConnect(ctx context.Context, clientConn net.Conn) (context.Context, error) {
|
||||||
addrType := make([]byte, 1)
|
addrType := make([]byte, 1)
|
||||||
request.clientConn.Read(addrType)
|
clientConn.Read(addrType)
|
||||||
|
|
||||||
var host string
|
var host string
|
||||||
switch addrType[0] {
|
switch addrType[0] {
|
||||||
case ipV4:
|
case ipV4:
|
||||||
ipv4 := make(net.IP, net.IPv4len)
|
ipv4 := make(net.IP, net.IPv4len)
|
||||||
request.clientConn.Read(ipv4)
|
clientConn.Read(ipv4)
|
||||||
host = ipv4.String()
|
host = ipv4.String()
|
||||||
case ipV6:
|
case ipV6:
|
||||||
ipv6 := make(net.IP, net.IPv6len)
|
ipv6 := make(net.IP, net.IPv6len)
|
||||||
request.clientConn.Read(ipv6)
|
clientConn.Read(ipv6)
|
||||||
host = ipv6.String()
|
host = ipv6.String()
|
||||||
case domainName:
|
case domainName:
|
||||||
var domainLen uint8
|
var domainLen uint8
|
||||||
binary.Read(request.clientConn, binary.BigEndian, &domainLen)
|
binary.Read(clientConn, binary.BigEndian, &domainLen)
|
||||||
domain := make([]byte, domainLen)
|
domain := make([]byte, domainLen)
|
||||||
request.clientConn.Read(domain)
|
clientConn.Read(domain)
|
||||||
host = string(domain)
|
host = string(domain)
|
||||||
default:
|
default:
|
||||||
request.sendReply(addrTypeNotSupported)
|
request.sendReply(clientConn, addrTypeNotSupported)
|
||||||
return errors.New("target address type is not support")
|
return ctx, errors.New("target address type is not support")
|
||||||
}
|
}
|
||||||
|
|
||||||
var port uint16
|
var port uint16
|
||||||
binary.Read(request.clientConn, binary.BigEndian, &port)
|
binary.Read(clientConn, binary.BigEndian, &port)
|
||||||
|
ctx = context.WithValue(ctx, core.PROXY_CONNECTION_ADDR, host)
|
||||||
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_ADDR, host)
|
ctx = context.WithValue(ctx, core.PROXY_CONNECTION_PORT, port)
|
||||||
request.ctx = context.WithValue(request.ctx, core.PROXY_CONNECTION_PORT, port)
|
request.sendReply(clientConn, succeeded)
|
||||||
return nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// passive mode
|
// passive mode
|
||||||
@ -127,7 +124,7 @@ func (request *Request) handleBind() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//udp
|
//udp
|
||||||
func (request *Request) handleUDP() error {
|
func (request *Request) handleUDP(ctx context.Context, clientConn net.Conn) (context.Context, error) {
|
||||||
/*
|
/*
|
||||||
+----+------+------+----------+----------+----------+
|
+----+------+------+----------+----------+----------+
|
||||||
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
||||||
@ -136,13 +133,13 @@ func (request *Request) handleUDP() error {
|
|||||||
+----+------+------+----------+----------+----------+
|
+----+------+------+----------+----------+----------+
|
||||||
*/
|
*/
|
||||||
buf := make([]byte, 3)
|
buf := make([]byte, 3)
|
||||||
request.clientConn.Read(buf)
|
clientConn.Read(buf)
|
||||||
// relay udp datagram silently, without any notification to the requesting client
|
// relay udp datagram silently, without any notification to the requesting client
|
||||||
if buf[2] != 0 {
|
if buf[2] != 0 {
|
||||||
// does not support fragmentation, drop it
|
// does not support fragmentation, drop it
|
||||||
dummy := make([]byte, maxUDPPacketSize)
|
dummy := make([]byte, maxUDPPacketSize)
|
||||||
request.clientConn.Read(dummy)
|
clientConn.Read(dummy)
|
||||||
return errors.New("does not support fragmentation, drop")
|
return ctx, errors.New("does not support fragmentation, drop")
|
||||||
}
|
}
|
||||||
return request.doConnect()
|
return request.doConnect(ctx, clientConn)
|
||||||
}
|
}
|
||||||
|
@ -35,25 +35,33 @@ func NewS5Server(globalConfig, clientConfig, pluginConfig map[string]string, Ser
|
|||||||
func (s5 *S5Server) Start(ctx context.Context) error {
|
func (s5 *S5Server) Start(ctx context.Context) error {
|
||||||
// init config of plugin
|
// init config of plugin
|
||||||
for _, pg := range s5.plugins.AllPgs {
|
for _, pg := range s5.plugins.AllPgs {
|
||||||
pg.InitConfig(s5.globalConfig, s5.clientConfig, s5.pluginConfig)
|
if pg.GetConfigName() != nil {
|
||||||
|
pg.InitConfig(s5.globalConfig, s5.clientConfig, s5.pluginConfig, pg.GetConfigName().GetAll())
|
||||||
}
|
}
|
||||||
// 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) {
|
core.NewTcpListenerAndProcess(s5.ServerIp+":"+strconv.Itoa(s5.ServerPort), func(c net.Conn) {
|
||||||
// init ctx value clientConn
|
// init ctx value clientConn
|
||||||
ctx = context.WithValue(ctx, core.CLIENT_CONNECTION, c)
|
connCtx := context.WithValue(ctx, core.CLIENT_CONNECTION, c)
|
||||||
// start run the plugin run
|
var err error
|
||||||
if err := core.RunPlugin(ctx, s5.plugins.RunPgs); err != nil {
|
|
||||||
|
// run the plugin contains start
|
||||||
|
if connCtx, err = core.RunPlugin(connCtx, s5.plugins.StartPgs, core.STAGE_START); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start run the plugin run
|
||||||
|
if connCtx, err = core.RunPlugin(connCtx, s5.plugins.RunPgs, core.STAGE_RUN); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// start run the plugin end
|
// start run the plugin end
|
||||||
if err := core.RunPlugin(ctx, s5.plugins.EndPgs); err != nil {
|
if connCtx, err = core.RunPlugin(connCtx, s5.plugins.EndPgs, core.STAGE_END); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}, &s5.listener)
|
}, &s5.listener)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,10 @@ func TestNewS5Server(t *testing.T) {
|
|||||||
g := make(map[string]string)
|
g := make(map[string]string)
|
||||||
c := make(map[string]string)
|
c := make(map[string]string)
|
||||||
p := make(map[string]string)
|
p := make(map[string]string)
|
||||||
|
p["socks5_check_access"] = "true"
|
||||||
|
p["socks5_simple_access_check"] = "true"
|
||||||
|
p["socks5_simple_access_username"] = "111"
|
||||||
|
p["socks5_simple_access_password"] = "222"
|
||||||
s5 := NewS5Server(g, c, p, "", 1099)
|
s5 := NewS5Server(g, c, p, "", 1099)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
s5.Start(ctx)
|
s5.Start(ctx)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user