Files
rakshasa/server/remote_socks5.go
T
2023-04-02 21:43:50 +08:00

134 lines
3.3 KiB
Go

package server
import (
"encoding/binary"
"errors"
"fmt"
"math/rand"
"cert"
"rakshasa/common"
"strconv"
"strings"
"time"
"github.com/luyu6056/ishell"
)
func StartRemoteSocks5(cfg *common.Addr, n *node) error {
l := &clientListen{
id: common.GetID(),
localAddr: "",
remoteAddr: cfg.Addr(),
server: n,
typ: "socks5",
result: make(chan interface{}),
randkey: make([]byte,8),
}
binary.LittleEndian.PutUint64(l.randkey,uint64(rand.NewSource(time.Now().UnixNano()).Int63()))
l.openOption = common.CMD_REMOTE_SOCKS5
l.openMsg = cert.RSAEncrypterByPrivByte(append(l.randkey,cfg.String()...))
n.Write(l.openOption, l.id, l.openMsg)
currentNode.listenMap.Store(l.id, l)
select {
case res := <-l.result:
if err, ok := res.(error); ok {
l.Close(remoteClose)
return err
}
case <-time.After(common.CMD_TIMEOUT):
l.Close(remoteClose)
return errors.New("time out")
}
return nil
}
func init() {
remoteSocks5shell := cliInit()
remoteSocks5shell.SetPrompt("rakshasa\\remotesocks5>")
remoteSocks5shell.AddCmd(&ishell.Cmd{
Name: "list",
Help: "列出当前连接的ID和其他信息",
Func: func(c *ishell.Context) {
var list []*clientListen
currentNode.listenMap.Range(func(key, value interface{}) bool {
if v, ok := value.(*clientListen); ok {
if v.typ == "socks5" {
list = append(list, v)
}
}
return true
})
orderClientListen(list)
fmt.Println("当前连接数量:", len(list))
for _, v := range list {
fmt.Println("ID", v.id, "本地端口", v.localAddr, "远程端口", v.remoteAddr, "服务器uuid", v.server.uuid)
}
},
})
remoteSocks5shell.AddCmd(&ishell.Cmd{
Name: "new-remotesocks5",
Help: "新建一个remotesocks5连接到本节点,使用方法 new-remotesocks5 配置字串符 目标服务器 如 new-remotesocks5 admin:[email protected]:1080 127.0.0.1:1081",
Func: func(c *ishell.Context) {
if len(c.Args) != 2 {
c.Println("参数错误")
return
}
n, err := GetNodeFromAddrs(strings.Split(c.Args[1], ","))
if err != nil {
c.Println("无法连接 ", c.Args[1], err)
return
}
cfg, err := common.ParseAddr(c.Args[0])
if err != nil {
c.Println(err)
return
}
if err = StartRemoteSocks5(cfg, n); err != nil {
c.Println("连接", c.Args[1], "失败", err)
return
}
c.Println("节点", c.Args[1], "配置信息,", c.Args[0], ",启动socks5 到 本节点 成功")
},
})
remoteSocks5shell.AddCmd(&ishell.Cmd{
Name: "close",
Help: "关闭一个remotesocks5连接,使用方法 close ID",
Func: func(c *ishell.Context) {
if len(c.Args) != 1 {
c.Println("参数错误,例子 close 1")
return
}
id, _ := strconv.Atoi(c.Args[0])
var l *clientListen
if value, ok := currentNode.listenMap.Load(uint32(id)); ok {
if v, ok := value.(*clientListen); ok && v.typ == "socks5" {
l = v
}
}
if l == nil {
c.Println("没有找到ID为", id, "的连接")
} else {
l.Close("命令行关闭")
l.server.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey)
currentNode.listenMap.Delete(uint32(id))
}
},
})
rootCli.AddCmd(&ishell.Cmd{
Name: "remotesocks5",
Help: "进入remotesocks5功能",
Func: func(c *ishell.Context) {
remoteSocks5shell.Run()
},
})
}