diff --git a/bin/rakshasa_fullnode_amd64_darwin b/bin/rakshasa_fullnode_amd64_darwin index 3a32e2e..9b2f946 100644 Binary files a/bin/rakshasa_fullnode_amd64_darwin and b/bin/rakshasa_fullnode_amd64_darwin differ diff --git a/bin/rakshasa_fullnode_amd64_linux b/bin/rakshasa_fullnode_amd64_linux index 1070b47..7d9a3d8 100644 Binary files a/bin/rakshasa_fullnode_amd64_linux and b/bin/rakshasa_fullnode_amd64_linux differ diff --git a/bin/rakshasa_fullnode_amd64_win.exe b/bin/rakshasa_fullnode_amd64_win.exe index 54562cb..7d21593 100644 Binary files a/bin/rakshasa_fullnode_amd64_win.exe and b/bin/rakshasa_fullnode_amd64_win.exe differ diff --git a/bin/rakshasa_fullnode_lite_amd64_darwin b/bin/rakshasa_fullnode_lite_amd64_darwin index 77f0270..a0153fe 100644 Binary files a/bin/rakshasa_fullnode_lite_amd64_darwin and b/bin/rakshasa_fullnode_lite_amd64_darwin differ diff --git a/bin/rakshasa_fullnode_lite_amd64_linux b/bin/rakshasa_fullnode_lite_amd64_linux index 871bd6a..c20e396 100644 Binary files a/bin/rakshasa_fullnode_lite_amd64_linux and b/bin/rakshasa_fullnode_lite_amd64_linux differ diff --git a/bin/rakshasa_fullnode_lite_amd64_win.exe b/bin/rakshasa_fullnode_lite_amd64_win.exe index 0e1c228..a883006 100644 Binary files a/bin/rakshasa_fullnode_lite_amd64_win.exe and b/bin/rakshasa_fullnode_lite_amd64_win.exe differ diff --git a/bin/rakshasa_node_amd64_darwin b/bin/rakshasa_node_amd64_darwin index cfd1193..aab3917 100644 Binary files a/bin/rakshasa_node_amd64_darwin and b/bin/rakshasa_node_amd64_darwin differ diff --git a/bin/rakshasa_node_amd64_linux b/bin/rakshasa_node_amd64_linux index 20a56b7..45348dd 100644 Binary files a/bin/rakshasa_node_amd64_linux and b/bin/rakshasa_node_amd64_linux differ diff --git a/bin/rakshasa_node_amd64_win.exe b/bin/rakshasa_node_amd64_win.exe index 588ec78..5bd137d 100644 Binary files a/bin/rakshasa_node_amd64_win.exe and b/bin/rakshasa_node_amd64_win.exe differ diff --git a/bin/rakshasa_node_lite_amd64_darwin b/bin/rakshasa_node_lite_amd64_darwin index 5fae669..5a30ddc 100644 Binary files a/bin/rakshasa_node_lite_amd64_darwin and b/bin/rakshasa_node_lite_amd64_darwin differ diff --git a/bin/rakshasa_node_lite_amd64_linux b/bin/rakshasa_node_lite_amd64_linux index 7d346c8..d69c723 100644 Binary files a/bin/rakshasa_node_lite_amd64_linux and b/bin/rakshasa_node_lite_amd64_linux differ diff --git a/bin/rakshasa_node_lite_amd64_win.exe b/bin/rakshasa_node_lite_amd64_win.exe index 5101424..7f819c8 100644 Binary files a/bin/rakshasa_node_lite_amd64_win.exe and b/bin/rakshasa_node_lite_amd64_win.exe differ diff --git a/build.go b/build.go index d066ca6..f382be2 100644 --- a/build.go +++ b/build.go @@ -34,7 +34,9 @@ func main() { if *genfullNodePrivate { b, _ := os.ReadFile("./cert/private.pem") data := fmt.Sprintf("package cert\r\n func init(){\r\nprivateKey=%#v\r\n}\r\n", b) - os.WriteFile("./cert/private.go", []byte(data), 0655) + if err := os.WriteFile("./cert/private.go", []byte(data), 0655); err != nil { + fmt.Printf("写入./cert/private.go失败,错误 %v", err) + } return } if *gencert { diff --git a/common/cmd.go b/common/cmd.go index 2c66197..4260a0b 100644 --- a/common/cmd.go +++ b/common/cmd.go @@ -2,12 +2,14 @@ package common import ( "bytes" + "encoding/binary" "errors" "fmt" "math/rand" "net" "rakshasa/aes" "regexp" + "strconv" "strings" "sync" "sync/atomic" @@ -195,17 +197,6 @@ func init() { } -type RegMsg struct { - UUID string //当前机器uuid - RegAddr string //远程连接的addr - Hostname string //当前机器名称 - Goos string - ViaUUID string - Err string - MainIp string - Port string -} - var msgId uint32 func (m *Msg) Marshal() []byte { @@ -329,3 +320,31 @@ func ResolveTCPAddr(str string) ([]string, error) { return dst, nil } +func GetUUIDFromInterfaceMac() string { + ifts, _ := net.Interfaces() + for _, ift := range ifts { + if addr := ift.HardwareAddr.String(); len(addr) > 0 { + var randSeed = make([]byte, 8) + for k, s := range strings.Split(addr, ":") { + if k < 8 { + n, _ := strconv.ParseUint(s, 16, 8) + randSeed[k] = byte(n) + } + + } + source := rand.NewSource(int64(binary.LittleEndian.Uint64(randSeed))) + buf := bytes.NewBuffer(nil) + for i := 0; i < 2; i++ { + var b = make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(source.Int63())) + buf.Write(b) + } + id, err := uuid.NewRandomFromReader(buf) + if err == nil { + return id.String() + } + } + + } + return uuid.New().String() +} diff --git a/common/config.go b/common/config.go index ab9880e..a7a1b07 100644 --- a/common/config.go +++ b/common/config.go @@ -1,10 +1,11 @@ package common type Config struct { + UUID string //以指定uuid启动 DstNode []string //-d 上级节点 Password string //通讯密码,可为空 Port int //默认8883 - ListenIp string //指定公网ip,其他节点进行额外节点连接时候,尝试连接的ip + ListenIp string //指定公网ip,其他节点进行额外节点连接时候,尝试连接的ip Limit bool //禁止额外连接,只连接-d节点,不会尝试连接其他节点 FileName string FileSave bool `yaml:"-"` diff --git a/main.go b/main.go index 0d20005..c38fbb6 100644 --- a/main.go +++ b/main.go @@ -9,10 +9,11 @@ import ( _ "net/http/pprof" "rakshasa/aes" "rakshasa/common" - "rakshasa/httppool" "rakshasa/server" "strconv" "sync" + + "github.com/google/uuid" ) func main() { @@ -43,6 +44,8 @@ func main() { shellCodeTimeout = flag.Int("sTimeout", 3, "shellcode的超时等待时间,默认3秒") http_proxy = flag.String("http_proxy", "", "以本地http代理服务端模式运行,通过-d的服务器多级代理转出数据,如果没有-d参数,则使用本机进行下一步连接, 用户名:密码@ip:端口 可以省略为端口,如: \r\n -http_proxy admin:12345@0.0.0.0:8080\r\n -http_proxy admin:12345@8080\r\n -http_proxy 8080") http_proxy_pool = flag.String("http_proxy_pool", "", "从指定文件读取http代理服务器池,通过最后节点后(不使用-d则为本机),再从该池里读取一个代理进行请求") + withUUID = flag.String("uuid", "", "以指定uuid启动,如果uuid非法或者为空,则以网卡mac方式生成uuid") + randomUUID = flag.Bool("randomUUID", false, "每次启动,都使用随机的uuid") ) flag.Parse() @@ -51,7 +54,7 @@ func main() { log.Println("检测url不是默认url,将取消匿名代理检测") *check_proxy_anonymous = false } - httppool.CheckProxy(*check_proxy, *check_proxy_out, *check_proxy_timeout, *check_proxy_url, *check_proxy_anonymous) + server.CheckProxy(*check_proxy, *check_proxy_out, *check_proxy_timeout, *check_proxy_url, *check_proxy_anonymous) return } @@ -69,7 +72,11 @@ func main() { } } - + if *randomUUID { + config.UUID = uuid.New().String() + } else if *withUUID != "" { + config.UUID = *withUUID + } if *dstNode != "" { serverlist, err := common.ResolveTCPAddr(*dstNode) if err != nil { @@ -133,7 +140,7 @@ func main() { if *shellCode != "" { server.RunShellcodeWithDst(*dstNode, *shellCode, *shellCodeXorKey, *shellCodeParam, *shellCodeTimeout) } - if err := server.StartServer(fmt.Sprintf(":%d", config.Port)); err != nil { + if err := server.StartServer(fmt.Sprintf(":%d", config.Port)); err != nil { log.Fatalln(err) } diff --git a/httppool/check_proxy.go b/server/check_proxy.go similarity index 78% rename from httppool/check_proxy.go rename to server/check_proxy.go index d23b313..efd6de1 100644 --- a/httppool/check_proxy.go +++ b/server/check_proxy.go @@ -1,9 +1,7 @@ -package httppool +package server import ( "bufio" - "errors" - "fmt" "io" "log" "net" @@ -160,53 +158,4 @@ func check(cfg *common.Addr, timeout uint, checkurl string, outFile *os.File, an return false } -type HttpPool struct { - r *bufio.Reader - f *os.File - sync.Mutex -} -func HttpPoolInit(file string) (*HttpPool, error) { - f, err := os.Open(file) - if err != nil { - return nil, fmt.Errorf("打开http代理池文件 %s 失败", file) - } - p := &HttpPool{ - r: bufio.NewReader(f), - f: f, - Mutex: sync.Mutex{}, - } - if _, err = p.do_next(0); err != nil { - return nil, fmt.Errorf("无法从%s文件获取代理,错误%v", file, err) - } - return p, nil -} -func (p *HttpPool) Next() *common.Addr { - addr, _ := p.do_next(0) - return addr -} -func (p *HttpPool) do_next(n int) (*common.Addr, error) { - if n > 100 { - return nil, errors.New("重试错误次数过多") - } - p.Lock() - line, err := p.r.ReadString(10) - if err == io.EOF { - p.f.Seek(0, 0) - p.r.Reset(p.f) - p.Unlock() - return p.do_next(n + 1) - } - p.Unlock() - line = strings.TrimRight(line, "\n") - line = strings.TrimRight(line, "\r") - - if len(line) == 0 { - return p.do_next(n + 1) - } - addr, err := common.ParseAddr(line) - if err != nil { - return p.do_next(n + 1) - } - return addr, nil -} diff --git a/server/cli.go b/server/cli.go index c64175c..5d84930 100644 --- a/server/cli.go +++ b/server/cli.go @@ -57,7 +57,7 @@ func cliInit() *ishell.Shell { return } for _, addr := range strings.Split(c.Args[0], ",") { - _, err := connectNew(addr) + _, err := getNode(addr) if err != nil { c.Println("连接", addr, "失败", err) return @@ -106,6 +106,23 @@ func cliInit() *ishell.Shell { }, }) + shell.AddCmd(&ishell.Cmd{ + Name: "closenode", + Help: "关闭一个node ID", + Func: func(c *ishell.Context) { + l := clientLock.Lock() + defer l.Unlock() + if len(c.Args) != 1 { + c.Println("参数不对") + return + } + n, ok := nodeMap[c.Args[0]] + if ok { + n.Close("debug关闭") + } + + }, + }) } return shell } diff --git a/server/config.go b/server/config.go index 574a6a6..be96184 100644 --- a/server/config.go +++ b/server/config.go @@ -1,9 +1,11 @@ package server import ( - "gopkg.in/yaml.v3" "io/ioutil" "rakshasa/common" + + "github.com/google/uuid" + "gopkg.in/yaml.v3" ) var currentConfig common.Config @@ -13,6 +15,12 @@ func SetConfig(config common.Config) { currentConfig.FileSave = false currentNode.mainIp = currentConfig.ListenIp currentNode.port = currentConfig.Port + if id, err := uuid.Parse(currentConfig.UUID); err != nil { + currentConfig.UUID = common.GetUUIDFromInterfaceMac() + }else{ + currentConfig.UUID=id.String() + } + currentNode.uuid = currentConfig.UUID } func ConfigSave() error { b, _ := yaml.Marshal(currentConfig) diff --git a/server/conn.go b/server/conn.go index 1ca3e0e..ccdbaf7 100644 --- a/server/conn.go +++ b/server/conn.go @@ -40,8 +40,7 @@ type Conn struct { close chan string isClient bool nodeConn *tls.Conn - regResult chan error - regResultNode chan *node + regResult chan RegMsg } type serverListen struct { @@ -544,7 +543,7 @@ func (c *Conn) handlerNodeRead() { } } case <-time.After(common.CMD_TIMEOUT): - newNode.Delete("超时") + newNode.Close("超时") } }() @@ -660,6 +659,7 @@ func (c *Conn) handle() { if common.Debug { fmt.Println(c.nodeConn.RemoteAddr().String(), "关闭原因", reason) } + if c.nodeConn != nil { if common.Debug { fmt.Println("執行close1") @@ -668,6 +668,7 @@ func (c *Conn) handle() { } if c.node != nil { + c.node.Close(reason) //移除上游连接 for i := len(upLevelNode) - 1; i >= 0; i-- { n := upLevelNode[i] @@ -675,6 +676,9 @@ func (c *Conn) handle() { upLevelNode = append(upLevelNode[:i], upLevelNode[i+1:]...) } } + if common.Debug { + fmt.Println("upLevelNode",len(upLevelNode)) + } } } @@ -690,7 +694,7 @@ func (c *Conn) handle() { func (c *Conn) reg() error { var err error - reg := &common.RegMsg{ + reg := &RegMsg{ UUID: currentNode.uuid, MainIp: cert.RSAEncrypterStr(currentNode.mainIp), Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)), diff --git a/server/http_proxy.go b/server/http_proxy.go index d2db6e5..2ebf6e1 100644 --- a/server/http_proxy.go +++ b/server/http_proxy.go @@ -1,18 +1,20 @@ package server import ( + "bufio" "bytes" + "cert" "encoding/binary" + "errors" "fmt" "hash/crc32" + "io" "log" "math/rand" "net" "net/url" "os" - "cert" "rakshasa/common" - "rakshasa/httppool" "runtime/debug" "strconv" "strings" @@ -27,7 +29,7 @@ const CheckProxyUrl = "https://myip.fireflysoft.net/" type httpProxyClient struct { windowsSize int64 - isclose int32 + status int32 conn net.Conn udpconn net.Conn @@ -40,10 +42,9 @@ type httpProxyClient struct { udpMap sync.Map listenId uint32 localAddr string - isConnect bool method string cfg *common.Addr - pool *httppool.HttpPool + pool *httpPool remoteAddr string remotePort string randkey []byte @@ -68,7 +69,9 @@ func (s *httpProxyClient) Write(b []byte) { if b[10] != 1 { //重新拉取一个池 - s.connect() + if !s.connect() { + s.Close(nodeIsClose) + } } else if s.method == "CONNECT" { s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n")) } @@ -90,7 +93,7 @@ func (s *httpProxyClient) Write(b []byte) { } func (s *httpProxyClient) Close(msg string) { - if atomic.CompareAndSwapInt32(&s.isclose, 0, 1) { + if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) { <-s.wait s.wait <- common.CONN_STATUS_CLOSE @@ -147,10 +150,10 @@ func (s *httpProxyClient) Addwindow(window int64) { } func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error { - var pool *httppool.HttpPool + var pool *httpPool var err error if poolfile != "" { - pool, err = httppool.HttpPoolInit(poolfile) + pool, err = httpPoolInit(poolfile) if err != nil { return err } @@ -183,7 +186,7 @@ func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error { currentNode.listenMap.Store(l.id, l) return nil } -func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httppool.HttpPool) (net.Listener, error) { +func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httpPool) (net.Listener, error) { l, err := net.Listen("tcp", cfg.Addr()) if err != nil { return nil, err @@ -280,20 +283,23 @@ func handleHttpProxyLocal(s *httpProxyClient) { s.remoteAddr = u.Host s.remotePort = "80" } - s.connect() - buf := bufPool.Get().(*bytes.Buffer) - buf.Reset() - buf.WriteString("GET ") - buf.WriteString(req.uri) - buf.WriteString(" HTTP/1.1\r\n") - for _, header := range req.header { - buf.WriteString(header) + if s.connect() { + buf := bufPool.Get().(*bytes.Buffer) + buf.Reset() + buf.WriteString("GET ") + buf.WriteString(req.uri) + buf.WriteString(" HTTP/1.1\r\n") + for _, header := range req.header { + buf.WriteString(header) + buf.WriteString("\r\n") + } buf.WriteString("\r\n") + s.write2connect(buf.Bytes()) + buf.Reset() + bufPool.Put(buf) + } else { + s.Close(nodeIsClose) } - buf.WriteString("\r\n") - s.write2connect(buf.Bytes()) - buf.Reset() - bufPool.Put(buf) } else { return @@ -303,7 +309,9 @@ func handleHttpProxyLocal(s *httpProxyClient) { if i := strings.IndexByte(req.uri, ':'); i > -1 { s.remoteAddr = req.uri[:i] s.remotePort = req.uri[i+1:] - s.connect() + if !s.connect() { + s.Close(nodeIsClose) + } } else { return } @@ -349,9 +357,8 @@ func (s *httpProxyClient) write2connect(data []byte) { } s.server.Write(common.CMD_CONN_MSG, s.id, append(outdata, data...)) } -func (s *httpProxyClient) connect() { - if !s.isConnect { - +func (s *httpProxyClient) connect() bool { + if !s.checkConnect() { buf := make([]byte, 2+len(s.remoteAddr)+len(s.remotePort)) s.id = s.server.storeConn(s) buf[0] = byte(common.RAW_TCP) @@ -365,7 +372,7 @@ func (s *httpProxyClient) connect() { buf = append(buf, []byte(" "+proxy.String())...) } - s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey,buf...))) + s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...))) if value, ok := s.server.listenMap.Load(s.listenId); ok { switch v := value.(type) { case *serverListen: @@ -374,11 +381,22 @@ func (s *httpProxyClient) connect() { v.connMap.Store(s.id, s) } } - s.isConnect = true + s.status = CONN_STATUS_CONNECT + return true } - + return s.server.isClose == 0 } +// 检查一下server是否断开,尝试重连,返回是否连接 +func (s *httpProxyClient) checkConnect() bool { + if s.server.isClose == 1 { + //尝试重连 + if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil { + s.server = newNode + } + } + return s.status == CONN_STATUS_CONNECT +} func (s *httpProxyClient) Remoteclose() { s.close = "本地要求远程关闭" @@ -388,7 +406,7 @@ func (s *httpProxyClient) Remoteclose() { buf[1] = byte(s.id >> 8) buf[2] = byte(s.id >> 16) buf[3] = byte(s.id >> 24) - s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey,buf...)) + s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey, buf...)) } func init() { @@ -611,3 +629,53 @@ func parsereq(req *http1request, data []byte) (clen int, resdata []byte, err err return 0, nil, nil } +type httpPool struct { + r *bufio.Reader + f *os.File + sync.Mutex +} + +func httpPoolInit(file string) (*httpPool, error) { + f, err := os.Open(file) + if err != nil { + return nil, fmt.Errorf("打开http代理池文件 %s 失败", file) + } + p := &httpPool{ + r: bufio.NewReader(f), + f: f, + Mutex: sync.Mutex{}, + } + if _, err = p.do_next(0); err != nil { + return nil, fmt.Errorf("无法从%s文件获取代理,错误%v", file, err) + } + return p, nil +} +func (p *httpPool) Next() *common.Addr { + addr, _ := p.do_next(0) + return addr +} +func (p *httpPool) do_next(n int) (*common.Addr, error) { + if n > 100 { + return nil, errors.New("重试错误次数过多") + } + p.Lock() + line, err := p.r.ReadString(10) + if err == io.EOF { + p.f.Seek(0, 0) + p.r.Reset(p.f) + p.Unlock() + return p.do_next(n + 1) + } + p.Unlock() + line = strings.TrimRight(line, "\n") + line = strings.TrimRight(line, "\r") + + if len(line) == 0 { + return p.do_next(n + 1) + } + addr, err := common.ParseAddr(line) + if err != nil { + return p.do_next(n + 1) + } + return addr, nil +} \ No newline at end of file diff --git a/server/node.go b/server/node.go index 86611f8..63e62a6 100644 --- a/server/node.go +++ b/server/node.go @@ -20,12 +20,10 @@ import ( "sync/atomic" "time" "unsafe" - - uuid2 "github.com/google/uuid" ) var ( - currentNode = &node{uuid: uuid2.New().String()} + currentNode = &node{} clientLock = &lock{} nodeMap = make(map[string]*node) upLevelNode []*node //上游节点 @@ -34,6 +32,18 @@ var ( connMap sync.Map ) +type RegMsg struct { + UUID string //当前机器uuid + RegAddr string //远程连接的addr + Hostname string //当前机器名称 + Goos string + ViaUUID string + Err string + MainIp string + Port string + node *node +} + func InitCurrentNode() { s := unsafe.Sizeof(uintptr(1)) bit := " x32" @@ -82,12 +92,14 @@ func InitCurrentNode() { time.AfterFunc(time.Second*10, checkUpLevelNode) } func checkUpLevelNode() { - if len(currentConfig.DstNode) > 0 && len(upLevelNode) == 0 { //尝试重新连接节点 for _, addr := range currentConfig.DstNode { - connectNew(addr) + if common.Debug { + fmt.Println("重新连接", addr) + } + getNode(addr) } if len(upLevelNode) == 0 { //尝试连接其他节点 @@ -97,7 +109,7 @@ func checkUpLevelNode() { fmt.Println("连接extNodeIp", addr) } - connectNew(addr) + getNode(addr) if len(upLevelNode) > 0 { return } @@ -109,16 +121,17 @@ func checkUpLevelNode() { for _, n := range nodeMap { if n.uuid != currentNode.uuid { - func() { + func() { l.RUnlock() defer clientLock.RLock(l) if len(n.mainIp) == 0 { + _, err := getNode(fmt.Sprintf("%s:%d", n.addr, n.port)) if common.Debug { - fmt.Println("连接n.addr", fmt.Sprintf("%s:%d", n.addr, n.port)) + fmt.Printf("连接n.addr %s 错误 %v \r\n", fmt.Sprintf("%s:%d", n.addr, n.port), err) } - connectNew(fmt.Sprintf("%s:%d", n.addr, n.port)) + } }() if len(upLevelNode) > 0 { @@ -202,16 +215,19 @@ type nodeInfo struct { } func connectNew(addr string) (n *node, e error) { - //先从已连接查找 - for _, node := range nodeMap { - if fmt.Sprintf("%s:%d", node.mainIp, node.port) == addr { - return node, nil - } else if fmt.Sprintf("%s:%d", node.addr, node.port) == addr { - return node, nil - } else if node.uuid == addr { - return node, nil + defer func() { + if n != nil { + find := false + for _, upN := range upLevelNode { + if upN.uuid == n.uuid { + find = true + } + } + if !find { + upLevelNode = append(upLevelNode, n) + } } - } + }() config := cert.Tlsconfig.Clone() interfaces, err := net.Interfaces() if err != nil { @@ -230,7 +246,7 @@ func connectNew(addr string) (n *node, e error) { localstr := localAddr.String() localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0" laddr, _ := net.ResolveTCPAddr("tcp", localstr) - if laddr!=nil{ + if laddr != nil { if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil { conn := tls.Client(netconn, config) select { @@ -253,34 +269,50 @@ func connectNew(addr string) (n *node, e error) { } c := &Conn{nodeConn: conn, isClient: true, nodeaddr: addr, remoteAddr: conn.LocalAddr().String()} connMap.Store(c.remoteAddr, conn) - c.regResult = make(chan error, 1) - c.regResultNode = make(chan *node, 1) + c.regResult = make(chan RegMsg, 1) c.handle() c.reg() - defer func() { - if c.node != nil { - l := clientLock.Lock() - find := false - for _, n := range upLevelNode { - if n.uuid == c.node.uuid { - find = true + select { + case regmsg := <-c.regResult: + if regmsg.Err != "" { + return nil, errors.New(regmsg.Err) + } + n = regmsg.node + n.uuid = regmsg.UUID + n.hostName = cert.RSADecrypterStr(regmsg.Hostname) + n.goos = cert.RSADecrypterStr(regmsg.Goos) + n.addr = n.conn.nodeConn.RemoteAddr().String() + if i := strings.Index(n.addr, ":"); i > -1 { + n.addr = n.addr[:i] + } + + n.mainIp = cert.RSADecrypterStr(regmsg.MainIp) + if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil { + n.port = -1 + } + if v, ok := nodeMap[regmsg.UUID]; ok { + if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 { + n.uuid = "" //清空uuid避免正常的node被删 + n.conn.Close("重复注册") //当前的连接关掉 + n.conn = v.conn + v.mainIp = cert.RSADecrypterStr(regmsg.MainIp) + if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil { + v.port = -1 } - } - if !find { - upLevelNode = append(upLevelNode, c.node) + n = v + } else { + n.conn.node = n } - l.Unlock() + } else { + n.conn.node = n } - }() - select { - case err = <-c.regResult: - return nil, err - case n = <-c.regResultNode: - //连接成功 + + nodeMap[n.uuid] = n n.reConnectAddrs = []string{addr} - return n, err + + return n, nil case <-time.After(time.Second * 10): return nil, errors.New("time out") } @@ -426,7 +458,7 @@ func (n *node) do(msg *common.Msg) { l := clientLock.Lock() defer l.Unlock() - var regmsg common.RegMsg + var regmsg RegMsg err = json.Unmarshal(msg.CmdData, ®msg) if err != nil { regmsg.Err = err.Error() @@ -477,76 +509,21 @@ func (n *node) do(msg *common.Msg) { go n.writeGetNodeResult(msg.CmdId) }() case common.CMD_REG_RESULT: - var regmsg common.RegMsg + var regmsg RegMsg err = json.Unmarshal(msg.CmdData, ®msg) - if err != nil { - select { - case n.conn.regResult <- err: - default: - } - return + regmsg.Err = err.Error() } - - if regmsg.Err != "" { - select { - case n.conn.regResult <- errors.New(regmsg.Err): - - default: - } - return - } - - //fmt.Printf("connect to %s(%s) success\n", regmsg.UUID, regmsg.RegAddr) - l := clientLock.Lock() - - n.uuid = regmsg.UUID - n.hostName = cert.RSADecrypterStr(regmsg.Hostname) - n.goos = cert.RSADecrypterStr(regmsg.Goos) - n.addr = n.conn.nodeConn.RemoteAddr().String() - if i := strings.Index(n.addr, ":"); i > -1 { - n.addr = n.addr[:i] - } - workconn := n.conn - n.mainIp = cert.RSADecrypterStr(regmsg.MainIp) - if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil { - n.port = -1 - } - if v, ok := nodeMap[regmsg.UUID]; ok { - if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 { - n.uuid = "" //清空uuid避免正常的node被删 - n.conn.Close("重复注册") //当前的连接关掉 - n.conn = v.conn - v.mainIp = cert.RSADecrypterStr(regmsg.MainIp) - if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil { - v.port = -1 - } - n = v - } else { - n.conn.node = n - } - - } else { - n.conn.node = n - } - if common.Debug { - fmt.Printf("nodeMap3 %s %p \r\n", n.uuid, n) - } - nodeMap[n.uuid] = n - l.Unlock() - + regmsg.node = n select { - case workconn.regResultNode <- n: - + case n.conn.regResult <- regmsg: default: } - //交换节点 - n.writeGetNodeResult(msg.CmdId) - + go n.writeGetNodeResult(msg.CmdId) case common.CMD_REMOTE_REG: - var regmsg common.RegMsg + var regmsg RegMsg err = json.Unmarshal(msg.CmdData, ®msg) if currentConfig.Limit { regmsg.Err = "node is in limit mode" @@ -557,7 +534,7 @@ func (n *node) do(msg *common.Msg) { if err == nil { var newNode *node - newNode, err = connectNew(regmsg.RegAddr) + newNode, err = getNode(regmsg.RegAddr) if err == nil { regmsg.UUID = newNode.uuid @@ -577,7 +554,7 @@ func (n *node) do(msg *common.Msg) { } n.writeGetNodeResult(msg.CmdId) case common.CMD_REMOTE_REG_RESULT: - var regmsg common.RegMsg + var regmsg RegMsg err = json.Unmarshal(msg.CmdData, ®msg) v, ok := n.loadQuery(msg.CmdId) if !ok { @@ -1208,7 +1185,7 @@ func (n *node) do(msg *common.Msg) { } } func (n *node) remoteReg(addr string) (newN *node, err error) { - regmsg := common.RegMsg{ + regmsg := RegMsg{ RegAddr: addr, UUID: currentNode.uuid, MainIp: cert.RSAEncrypterStr(currentNode.mainIp), @@ -1238,7 +1215,10 @@ func (n *node) remoteReg(addr string) (newN *node, err error) { return nil, errors.New("error result") } func (n *node) Close(reason string) { - if n.conn != nil && n.conn.node.uuid == n.uuid { + if common.Debug { + fmt.Println("Close ", reason) + } + if n.conn != nil && n.conn.node != nil && n.conn.node.uuid == n.uuid { n.conn.Close(reason) } n.Delete(reason) @@ -1295,16 +1275,14 @@ func (n *node) ping(id uint32) { if common.Debug { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), n.uuid, "超时") } - if n.conn != nil && n.conn.node.uuid == n.uuid { - n.conn.Close("超时关闭") - } - n.Delete("超时关闭") - //尝试重连 + n.Close("超时关闭") + + //尝试重连 go func() { if !currentConfig.Limit && len(n.mainIp) > 0 { for _, addr := range n.mainIp { - _n, _ := connectNew(fmt.Sprintf("%s:%d", addr, n.port)) + _n, _ := getNode(fmt.Sprintf("%s:%d", addr, n.port)) if _n != nil { return } @@ -1425,6 +1403,7 @@ func (n *node) broadcastNode() { } func GetNodeFromAddrs(dst []string) (n *node, err error) { + if len(dst) == 0 { return nil, errors.New("参数错误,目标节点为空") } diff --git a/server/raw_tcp_server.go b/server/raw_tcp_server.go index 8a010be..5eb8ee4 100644 --- a/server/raw_tcp_server.go +++ b/server/raw_tcp_server.go @@ -18,6 +18,12 @@ func (l *serverListen) Lisen() { continue } + if l.node.isClose == 1 { + newNode, _ := getNode(l.node.uuid) + if newNode != nil { + l.node = newNode + } + } conn := &serverConnect{} conn.conn = c @@ -27,7 +33,7 @@ func (l *serverListen) Lisen() { if l.isSocks5 { conn.id = l.id - l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey,l.socks5Replay...)) + l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey, l.socks5Replay...)) go conn.handTcpReceive() return } @@ -38,7 +44,7 @@ func (l *serverListen) Lisen() { b[1] = byte(conn.id >> 8) b[2] = byte(conn.id >> 16) b[3] = byte(conn.id >> 24) - conn.node.Write(common.CMD_CONNECT_BYID, l.id, append(l.randkey,b...)) + conn.node.Write(common.CMD_CONNECT_BYID, l.id, append(l.randkey, b...)) l.connMap.Store(conn.id, conn) go conn.handTcpReceive() diff --git a/server/shell.go b/server/shell.go index 3d361e5..d844a8c 100644 --- a/server/shell.go +++ b/server/shell.go @@ -16,6 +16,8 @@ import ( "rakshasa/aes" "rakshasa/common" + "github.com/google/uuid" + "regexp" "runtime" "strconv" @@ -134,8 +136,8 @@ func init() { currentConfig.Port = port currentNode.port = port currentConfig.FileSave = false - if err := StartServer(fmt.Sprintf(":%d", currentConfig.Port)); err != nil { - c.Printf("启动节点失败 %v, 请重新修改监听端口",currentConfig.Port) + if err := StartServer(fmt.Sprintf(":%d", currentConfig.Port)); err != nil { + c.Printf("启动节点失败 %v, 请重新修改监听端口", currentConfig.Port) } }, }) @@ -179,7 +181,24 @@ func init() { currentConfig.FileSave = false }, }) + configShell.AddCmd(&ishell.Cmd{ + Name: "uuid", + Help: "修改本节点UUID设置,使用方法uuid 字串符", + Func: func(c *ishell.Context) { + if len(c.Args) != 1 { + c.Println("参数错误") + return + } + if id, err := uuid.Parse(c.Args[0]); err == nil { + currentConfig.UUID = id.String() + currentConfig.FileSave = false + SetConfig(currentConfig) + } else { + c.Println("输入的uuid不是合法的uuid,建议使用xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") + } + }, + }) rootCli.AddCmd(&ishell.Cmd{ Name: "config", Help: "配置管理", @@ -553,7 +572,7 @@ func init() { return } for _, addr := range strings.Split(c.Args[0], ",") { - _, err := connectNew(addr) + _, err := getNode(addr) if err != nil { c.Println("连接", addr, "失败", err) return @@ -788,46 +807,26 @@ func printConn() { }) } func getNode(arg string) (*node, error) { - l := clientLock.RLock() - + l := clientLock.Lock() + defer l.Unlock() id, err := strconv.Atoi(arg) - if err == nil { for _, n := range nodeMap { - if n.id == id && n.uuid != currentNode.uuid { - l.RUnlock() + if n.id == id { return n, nil } } } else { - if v, ok := nodeMap[arg]; ok && v.uuid != currentNode.uuid { - l.RUnlock() - return v, nil - } - } - l.RUnlock() - - return connectNew(arg) -} -func getNodeWithCurrentNode(arg string) (*node, error) { - l := clientLock.RLock() - - id, err := strconv.Atoi(arg) - - if err == nil { - for _, n := range nodeMap { - if n.id == id { - l.RUnlock() - return n, nil + for _, node := range nodeMap { + if fmt.Sprintf("%s:%d", node.mainIp, node.port) == arg { + return node, nil + } else if fmt.Sprintf("%s:%d", node.addr, node.port) == arg { + return node, nil + } else if node.uuid == arg { + return node, nil } } - } else { - if v, ok := nodeMap[arg]; ok { - l.RUnlock() - return v, nil - } } - l.RUnlock() - return connectNew(arg) } + diff --git a/server/shellcode.go b/server/shellcode.go index 6009618..6fea8a6 100644 --- a/server/shellcode.go +++ b/server/shellcode.go @@ -1,6 +1,7 @@ package server import ( + "cert" "encoding/base64" "encoding/hex" "encoding/json" @@ -10,7 +11,6 @@ import ( "os" "os/exec" "path/filepath" - "cert" "rakshasa/common" "strconv" "time" @@ -28,7 +28,7 @@ type ShellCodeStruct struct { func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) error { if dst != "" { - n, err := getNodeWithCurrentNode(dst) + n, err := getNode(dst) if err != nil { return fmt.Errorf("无法链接节点%s,错误%v", dst, err) } diff --git a/server/socks5.go b/server/socks5.go index d8dbeff..eb28fa8 100644 --- a/server/socks5.go +++ b/server/socks5.go @@ -17,7 +17,6 @@ import ( "sync" "sync/atomic" "time" - "unsafe" "github.com/luyu6056/ishell" ) @@ -29,9 +28,9 @@ const ( ) var ( - SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0} + SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0} SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2} - PROTOCOL_ERR = errors.New("protocolErr") + PROTOCOL_ERR = errors.New("protocolErr") ) const ( @@ -44,10 +43,15 @@ const ( CONN_REMOTE_OPEN = 1 ) +const ( + CONN_STATUS_NONE = iota + CONN_STATUS_CONNECT +) + type clientConnect struct { cfg *common.Addr windowsSize int64 - isClose int32 + status int32 conn net.Conn udpConn net.Conn @@ -109,9 +113,9 @@ func (s *clientConnect) Write(b []byte) { var remoteClose = "服务器要求远程关闭" var nodeIsClose = "节点已经断开连接" -func (s *clientConnect) Close(msg string) { - if atomic.CompareAndSwapInt32(&s.isClose, 0, 1) { +func (s *clientConnect) Close(msg string) { + if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) { <-s.wait s.wait <- common.CONN_STATUS_CLOSE s.auth = CONN_AUTH_CLOSE @@ -302,12 +306,12 @@ func handleSocks5Local(s *clientConnect) { switch common.NetWork(data[1]) { case common.SOCKS5_CMD_CONNECT: addr, port := socks5ReadAddr(data) - if !s.connect(common.SOCKS5_CMD_CONNECT, addr, port){ + if !s.connect(common.SOCKS5_CMD_CONNECT, addr, port) { s.Close(nodeIsClose) } case common.SOCKS5_CMD_BIND: addr, port := socks5ReadAddr(data) - if !s.connect(common.SOCKS5_CMD_BIND, addr, port){ + if !s.connect(common.SOCKS5_CMD_BIND, addr, port) { s.Close(nodeIsClose) } case common.SOCKS5_CMD_UDP: @@ -336,11 +340,11 @@ func handleSocks5Local(s *clientConnect) { ipb := ipToByte(localIP) addr, port := socks5ReadAddr(data) - if s.connect(common.SOCKS5_CMD_UDP, addr, port){ + if s.connect(common.SOCKS5_CMD_UDP, addr, port) { copy(repdata[4:], ipb) s.conn.Write(repdata) go handleSocks5Udp(s) - }else{ + } else { s.Close(nodeIsClose) } default: @@ -401,7 +405,7 @@ func handleSocks5Udp(s *clientConnect) { if v, ok := s.udpMap.Load(ip); !ok { udps := &clientConnect{ - server: s.server, + server: s.server, randkey: s.randkey, } udps.udpConn = s.udpConn @@ -426,34 +430,38 @@ func handleSocks5Udp(s *clientConnect) { } } -func (s *clientConnect) connect(command common.NetWork, addr string, port uint16)bool { - if atomic.LoadInt32(&s.server.isClose) == 1 { +func (s *clientConnect) connect(command common.NetWork, addr string, port uint16) bool { + if !s.checkConnect() { s.server, _ = GetNodeFromAddrs(s.server.reConnectAddrs) + ports := strconv.Itoa(int(port)) + buf := make([]byte, 2+len(addr)+len(ports)) + s.id = s.server.storeConn(s) + buf[0] = byte(command) + copy(buf[1:], addr) + buf[1+len(addr)] = ':' + copy(buf[2+len(addr):], ports) + s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...))) + if value, ok := s.server.listenMap.Load(s.listenId); ok { + switch v := value.(type) { + case *serverListen: + v.connMap.Store(s.id, s) + case *clientListen: + v.connMap.Store(s.id, s) + } + } + s.status = CONN_STATUS_CONNECT + return true } - if atomic.LoadInt32(&s.server.isClose) == 1 { - return false - } - ports := strconv.Itoa(int(port)) - buf := make([]byte, 2+len(addr)+len(ports)) - s.id = s.server.storeConn(s) - buf[0] = byte(command) - copy(buf[1:], addr) - buf[1+len(addr)] = ':' - copy(buf[2+len(addr):], ports) - s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...))) - if value, ok := s.server.listenMap.Load(s.listenId); ok { - switch v := value.(type) { - case *serverListen: - v.connMap.Store(s.id, s) - case *clientListen: - v.connMap.Store(s.id, s) + return s.server.isClose == 0 +} +func (s *clientConnect) checkConnect() bool { + if s.server.isClose == 1 { + //尝试重连 + if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil { + s.server = newNode } } - return true -} - -func Bytes2str(b []byte) string { - return *(*string)(unsafe.Pointer(&b)) + return s.status == CONN_STATUS_CONNECT } func (s *clientConnect) Remoteclose() {