diff --git a/bin/rakshasa_fullnode_amd64_darwin b/bin/rakshasa_fullnode_amd64_darwin new file mode 100644 index 0000000..eb77762 Binary files /dev/null and b/bin/rakshasa_fullnode_amd64_darwin differ diff --git a/bin/rakshasa.exe b/bin/rakshasa_fullnode_amd64_linux similarity index 51% rename from bin/rakshasa.exe rename to bin/rakshasa_fullnode_amd64_linux index b06df9e..cd46cfa 100644 Binary files a/bin/rakshasa.exe and b/bin/rakshasa_fullnode_amd64_linux differ diff --git a/bin/rakshasa_darwin b/bin/rakshasa_fullnode_amd64_win.exe similarity index 52% rename from bin/rakshasa_darwin rename to bin/rakshasa_fullnode_amd64_win.exe index be020d9..c4f5a5b 100644 Binary files a/bin/rakshasa_darwin and b/bin/rakshasa_fullnode_amd64_win.exe differ diff --git a/bin/rakshasa_node_amd64_darwin b/bin/rakshasa_node_amd64_darwin new file mode 100644 index 0000000..99f5988 Binary files /dev/null and b/bin/rakshasa_node_amd64_darwin differ diff --git a/bin/rakshasa_linux b/bin/rakshasa_node_amd64_linux similarity index 50% rename from bin/rakshasa_linux rename to bin/rakshasa_node_amd64_linux index 16daa4f..6c50e76 100644 Binary files a/bin/rakshasa_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 new file mode 100644 index 0000000..0f1cd43 Binary files /dev/null and b/bin/rakshasa_node_amd64_win.exe differ diff --git a/build.go b/build.go new file mode 100644 index 0000000..56773a1 --- /dev/null +++ b/build.go @@ -0,0 +1,85 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/exec" + "runtime" +) + +func main() { + all := flag.Bool("nocli", false, "生成新的证书,使用随机的种子生成控制端节点和普通节点") + gencert := flag.Bool("gencert", false, "生成证书") + fullNode := flag.Bool("fullnode", false, "只编译生成控制端节点+普通节点") + node := flag.Bool("node", false, "只生成普通节点") + flag.Parse() + if *all == true { + *gencert = true + *fullNode = true + *node = false + } + if *gencert { + if runtime.GOOS == "windows" { + _, err := exec.Command("cmd.exe", "/c", "cd gencert && go run main.go").CombinedOutput() + if err != nil { + log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`) + return + } + } else { + _, err := exec.Command("bin/bash", "-c", "cd gencert && go run main.go").CombinedOutput() + if err != nil { + log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`) + return + } + } + } + if b, _ := os.ReadFile("./cert/private.pem"); len(b) == 0 { + log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`) + return + } + if b, _ := os.ReadFile("./cert/public.pem"); len(b) == 0 { + log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`) + return + } + if b, _ := os.ReadFile("./cert/server.crt"); len(b) == 0 { + log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`) + return + } + if b, _ := os.ReadFile("./cert/server.key"); len(b) == 0 { + log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`) + return + } + if *fullNode { + 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) + buildNode("build_fullnode") + } else if *node { + os.Remove("./cert/private.go") + buildNode("build_node") + } else { + flag.PrintDefaults() + + } +} +func buildNode(name string) { + if runtime.GOOS == "windows" { + cmdstr := fmt.Sprintf(`cd build && %s.bat`, name) + _, err := exec.Command("cmd.exe", "/c", cmdstr).CombinedOutput() + if err != nil { + log.Fatal(`无法编译,请手动执行 ` + cmdstr) + return + } + + } else { + exec.Command("bin/bash", "-c", "cd build && sudo chmod 755 "+name+".sh").CombinedOutput() + cmdstr := fmt.Sprintf(`cd build && ./%s.sh`, name) + _, err := exec.Command("/bin/bash", "-c", cmdstr).CombinedOutput() + if err != nil { + log.Fatal(`无法编译,请手动执行 ` + cmdstr) + return + } + } +} diff --git a/build/build_cert.bat b/build/build_cert.bat new file mode 100644 index 0000000..457401f --- /dev/null +++ b/build/build_cert.bat @@ -0,0 +1,2 @@ +cd ../gencert && go run main.go +echo ok \ No newline at end of file diff --git a/build/build_cert.sh b/build/build_cert.sh new file mode 100644 index 0000000..b26ed5d --- /dev/null +++ b/build/build_cert.sh @@ -0,0 +1,3 @@ +#! /bin/sh +cd ../gencert && go run main.go +echo ok \ No newline at end of file diff --git a/build/build_fullnode.bat b/build/build_fullnode.bat new file mode 100644 index 0000000..9e8d6bd --- /dev/null +++ b/build/build_fullnode.bat @@ -0,0 +1,22 @@ +@echo off +cd ../ + +IF EXIST ./cert/private.go ( +echo Start build fullnode +echo build windows +set GOOS=windows +go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_fullnode_amd64_win.exe main.go +echo build linux +set GOOS=linux +go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_fullnode_amd64_linux main.go +echo build darwin +set GOOS=darwin +go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_fullnode_amd64_darwin main.go +cd cert +del "private.go" +cd ../build +build_node.bat +) ELSE ( + echo Ҳprivate.go,ʹ go run build.go -full-node +ping -n 3 127.0.0.1 > nul +) diff --git a/build/build_fullnode.sh b/build/build_fullnode.sh new file mode 100644 index 0000000..333c2a4 --- /dev/null +++ b/build/build_fullnode.sh @@ -0,0 +1,21 @@ +#! /bin/sh +cd ../ + +file=./cert/private.go + +if [ -f "$file" ]; then +echo "Start build fullnode" +echo "build windows" +GOOS=windows go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_fullnode_amd64_win.exe main.go +echo "build linux" +GOOS=linux go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_fullnode_amd64_linux main.go +echo "build darwin" +GOOS=darwin go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_fullnode_amd64_darwin main.go +cd cert +rm -f "private.go" +cd ../build +chmod 755 build_node.sh +./build_node.sh +else + echo "找不到private.go,请使用 go run build.go -full-node来编译" +fi \ No newline at end of file diff --git a/build/build_node.bat b/build/build_node.bat new file mode 100644 index 0000000..b6bcefe --- /dev/null +++ b/build/build_node.bat @@ -0,0 +1,20 @@ +@echo off +cd ../ + +IF EXIST ./cert/private.go ( +echo ɾprivate.goڱ +ping -n 3 127.0.0.1 > nul +) ELSE ( +echo Start build node +echo build windows +set GOOS=windows +go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_node_amd64_win.exe main.go +echo build linux +set GOOS=linux +go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_node_amd64_linux main.go +echo build darwin +set GOOS=darwin +go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_node_amd64_darwin main.go +echo End + +) diff --git a/build/build_node.sh b/build/build_node.sh new file mode 100644 index 0000000..3453ca7 --- /dev/null +++ b/build/build_node.sh @@ -0,0 +1,16 @@ +#! /bin/sh +cd ../ + +file=./cert/private.go + +if [ ! -f "$file" ]; then +echo "Start build node" +echo "build windows" +GOOS=windows go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_node_amd64_win.exe main.go +echo "build linux" +GOOS=linux go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_node_amd64_linux main.go +echo "build darwin" +GOOS=darwin go build -a -ldflags="-w -s" -trimpath -o ./bin/rakshasa_node_amd64_darwin main.go +else + echo "请删除private.go后在编译" +fi \ No newline at end of file diff --git a/cert/tls.go b/cert/tls.go index 381695a..fe0a3c1 100644 --- a/cert/tls.go +++ b/cert/tls.go @@ -1,9 +1,14 @@ package cert import ( + "crypto/rand" + "crypto/rsa" "crypto/tls" "crypto/x509" _ "embed" + "encoding/base64" + "encoding/pem" + "github.com/farmerx/gorsa" "log" ) @@ -11,14 +16,14 @@ import ( var rsaCert []byte //go:embed server.key -var PublicKey []byte +var PrivateKey []byte var Tlsconfig *tls.Config func init() { //内置证书 - cert, err := tls.X509KeyPair(rsaCert, PublicKey) + cert, err := tls.X509KeyPair(rsaCert, PrivateKey) if err != nil { log.Panicln(err) return @@ -51,3 +56,63 @@ func init() { } } + +//go:embed public.pem +var publicKey []byte + + +var privateKey []byte + +// 使用公钥进行加密 +func RSAEncrypter(msg []byte) []byte { + block, _ := pem.Decode(publicKey) + pub, _ := x509.ParsePKIXPublicKey(block.Bytes) + cipherText, _ := rsa.EncryptPKCS1v15(rand.Reader, pub.(*rsa.PublicKey), msg) + return cipherText +} +func RSAEncrypterStr(msg string) string { + block, _ := pem.Decode(publicKey) + pub, _ := x509.ParsePKIXPublicKey(block.Bytes) + cipherText, _ := rsa.EncryptPKCS1v15(rand.Reader, pub.(*rsa.PublicKey), []byte(msg)) + return base64.StdEncoding.EncodeToString(cipherText) +} + +// 使用私钥进行解密 +func RSADecrypter(cipherText []byte) []byte { + if block, _ := pem.Decode(privateKey); block != nil { + p, _ := x509.ParsePKCS1PrivateKey(block.Bytes) + afterDecrypter, _ := rsa.DecryptPKCS1v15(rand.Reader, p, cipherText) + return afterDecrypter + } + return []byte{} +} +func RSADecrypterStr(cipherText string) string { + if block, _ := pem.Decode(privateKey); block != nil { + p, _ := x509.ParsePKCS1PrivateKey(block.Bytes) + b, _ := base64.StdEncoding.DecodeString(cipherText) + afterDecrypter, _ := rsa.DecryptPKCS1v15(rand.Reader, p, b) + return string(afterDecrypter) + } + return "" +} +func RSAEncrypterByPriv(msg string) string { + prienctypt, _ := gorsa.RSA.PriKeyENCTYPT([]byte(msg)) + return base64.StdEncoding.EncodeToString(prienctypt) +} +func RSAEncrypterByPrivByte(msg []byte) []byte { + prienctypt, _ := gorsa.RSA.PriKeyENCTYPT([]byte(msg)) + return prienctypt +} +func RSADecrypterByPub(cipherText string) string{ + b, _ := base64.StdEncoding.DecodeString(cipherText) + pubdecrypt, _ := gorsa.RSA.PubKeyDECRYPT(b) + return string(pubdecrypt) +} +func RSADecrypterByPubByte(cipherText []byte) []byte { + pubdecrypt, _ := gorsa.RSA.PubKeyDECRYPT(cipherText) + return pubdecrypt +} +func init(){ + gorsa.RSA.SetPublicKey(string(publicKey)) + gorsa.RSA.SetPrivateKey(string(privateKey)) +} diff --git a/common/cmd.go b/common/cmd.go index c4cf61e..ba3870f 100644 --- a/common/cmd.go +++ b/common/cmd.go @@ -202,7 +202,7 @@ type RegMsg struct { ViaUUID string Err string MainIp string - Port int + Port string } var msgId uint32 diff --git a/gencert/main.go b/gencert/main.go index 541bc4c..68efc1f 100644 --- a/gencert/main.go +++ b/gencert/main.go @@ -7,6 +7,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" + "fmt" "log" "math/big" "math/rand" @@ -14,8 +15,11 @@ import ( "os" "time" ) - +type RandReader struct { + rand.Source +} func main() { + rand.Seed(time.Now().Unix()) subj := &pkix.Name{ CommonName: "chinamobile.com", Organization: []string{"Company, INC."}, @@ -29,16 +33,17 @@ func main() { if err != nil { log.Panic(err) } - - Write(ca, "../cert/server") - - crt, err := Req(ca.CSR, subj, 10, []string{"test.default.svc", "test"}, []net.IP{}) + //Write(ca, "../cert/server") + crt, err := Req(ca.CSR, subj, 365, []string{"test.default.svc", "test"}, []net.IP{}) if err != nil { log.Panic(err) } - Write(crt, "../cert/server") + GenerateRSAKey(2096) + 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) } type CERT struct { @@ -162,3 +167,47 @@ func Write(cert *CERT, file string) error { } return nil } + +func GenerateRSAKey(bits int) { + //GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥 + //Reader是一个全局、共享的密码用强随机数生成器 + privateKey, err := rsa.GenerateKey(cr.Reader, bits) + if err != nil { + panic(err) + } + //保存私钥 + //通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串 + X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey) + //使用pem格式对x509输出的内容进行编码 + //创建文件保存私钥 + privateFile, err := os.Create("../cert/private.pem") + if err != nil { + panic(err) + } + defer privateFile.Close() + //构建一个pem.Block结构体对象 + privateBlock := pem.Block{Type: "RSA Private Key", Bytes: X509PrivateKey} + //将数据保存到文件 + pem.Encode(privateFile, &privateBlock) + + //保存公钥 + //获取公钥的数据 + publicKey := privateKey.PublicKey + //X509对公钥编码 + X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey) + if err != nil { + panic(err) + } + //pem格式编码 + //创建用于保存公钥的文件 + publicFile, err := os.Create("../cert/public.pem") + if err != nil { + panic(err) + } + defer publicFile.Close() + //创建一个pem.Block结构体对象 + publicBlock := pem.Block{Type: "RSA Public Key", Bytes: X509PublicKey} + //保存到文件 + pem.Encode(publicFile, &publicBlock) +} + diff --git a/go.mod b/go.mod index adfb854..6b36be3 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db github.com/creack/pty v1.1.18 github.com/dlclark/regexp2 v1.7.0 + github.com/farmerx/gorsa v0.0.0-20161211100049-3ae06f674f40 github.com/google/uuid v1.3.0 github.com/luyu6056/ishell v1.0.1 github.com/mattn/go-colorable v0.1.12 // indirect diff --git a/go.sum b/go.sum index b96aaae..55c6024 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/farmerx/gorsa v0.0.0-20161211100049-3ae06f674f40 h1:OgoboV484kN/ngW4apHvSw8iy9YhhQusAKSLT8nGl94= +github.com/farmerx/gorsa v0.0.0-20161211100049-3ae06f674f40/go.mod h1:Gdtd77IQrjXqFfiourWpNnE1jDPC4opZPDPxPLWFlr0= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= diff --git a/main.go b/main.go index eb2e1da..1229958 100644 --- a/main.go +++ b/main.go @@ -108,7 +108,7 @@ func main() { server.SetConfig(config) //设置一下秘钥 - aes.Key = aes.MD5_B(config.Password + string(cert.PublicKey[:16])) + aes.Key = aes.MD5_B(config.Password + string(cert.PrivateKey[:16])) //初始化node server.InitCurrentNode() diff --git a/server/conn.go b/server/conn.go index f6f488a..3fb6e22 100644 --- a/server/conn.go +++ b/server/conn.go @@ -9,7 +9,6 @@ import ( "io" "net" "net/url" - "os" "rakshasa/aes" "rakshasa/cert" "rakshasa/common" @@ -54,6 +53,7 @@ type serverListen struct { replayid uint32 id uint32 connMap sync.Map + randkey []byte } type serverConnect struct { close int32 @@ -67,6 +67,7 @@ type serverConnect struct { wait chan int closeReason string + randkey []byte } // 中转与最终出口 @@ -281,14 +282,14 @@ func (conn *serverConnect) doConnectTcp(network common.NetWork, addr string) { buf := make([]byte, 2) buf[0] = byte(network) buf[1] = 0 - conn.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, conn.id, buf) + conn.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, conn.id, append(conn.randkey, buf...)) conn.Close("fd拨号失败") return } else { buf := make([]byte, 2) buf[0] = byte(network) buf[1] = 1 - conn.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, conn.id, buf) + conn.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, conn.id, append(conn.randkey, buf...)) if conn.close == 0 { conn.conn = netconn go conn.handTcpReceive() @@ -305,7 +306,7 @@ func (conn *serverConnect) doConnectTcpWithHttpProxy(network common.NetWork, add if res { buf[1] = 1 } - conn.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, conn.id, buf) + conn.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, conn.id, append(conn.randkey, buf...)) } if i := strings.IndexByte(addr, 32); i > -1 { @@ -504,13 +505,13 @@ func (c *Conn) handlerNodeRead() { newNode.do(msg) } } else if msg.To == currentNode.uuid { + func() { l := clientLock.RLock() v, ok := nodeMap[msg.From] l.RUnlock() - if ok && v.port > 0 { + if ok && v.port != 0 { c.inChan <- func() { - v.do(msg) } } else { @@ -564,11 +565,13 @@ func (c *Conn) handlerNodeRead() { res <- err return } - v.hostName = nmsg.HostName - v.uuid = nmsg.UUID - v.port = nmsg.Port - v.mainIp = nmsg.MainIp - v.goos = nmsg.Goos + v.hostName = cert.RSADecrypterStr(nmsg.HostName) + v.uuid = cert.RSADecrypterStr(nmsg.UUID) + if v.port, err = strconv.Atoi(cert.RSADecrypterStr(nmsg.Port)); err != nil { + v.port = -1 + } + v.mainIp = cert.RSADecrypterStr(nmsg.MainIp) + v.goos = cert.RSADecrypterStr(nmsg.Goos) res <- nil } else { v.waitMsg = append(v.waitMsg, msg) @@ -693,15 +696,13 @@ func (c *Conn) reg() error { return err } - reg := common.RegMsg{ - RegAddr: c.nodeaddr, - UUID: currentNode.uuid, - MainIp: currentNode.mainIp, - Port: currentNode.port, - Goos: currentNode.goos, + reg := &common.RegMsg{ + UUID: currentNode.uuid, + MainIp: cert.RSAEncrypterStr(currentNode.mainIp), + Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)), + Goos: cert.RSAEncrypterStr(currentNode.goos), + Hostname: cert.RSAEncrypterStr(currentNode.hostName), } - reg.Hostname, _ = os.Hostname() - regb, _ := json.Marshal(reg) msg := common.Msg{ From: currentNode.uuid, diff --git a/server/http_proxy.go b/server/http_proxy.go index d9847ed..4634381 100644 --- a/server/http_proxy.go +++ b/server/http_proxy.go @@ -2,12 +2,15 @@ package server import ( "bytes" + "encoding/binary" "fmt" "hash/crc32" "log" + "math/rand" "net" "net/url" "os" + "rakshasa/cert" "rakshasa/common" "rakshasa/httppool" "runtime/debug" @@ -15,6 +18,7 @@ import ( "strings" "sync" "sync/atomic" + "time" "github.com/luyu6056/ishell" ) @@ -42,32 +46,34 @@ type httpProxyClient struct { pool *httppool.HttpPool remoteAddr string remotePort string + randkey []byte } func (s *httpProxyClient) Write(b []byte) { switch b[0] { - case common.CMD_CONNECT_BYIDADDR_RESULT: - - switch common.NetWork(b[1]) { + if string(s.randkey) != string(b[1:9]) { + return + } + switch common.NetWork(b[9]) { case common.RAW_TCP: - if b[2] != 1 { + if b[10] != 1 { go func() { s.Close("") }() } else if s.method == "CONNECT" { s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n")) } case common.RAW_TCP_WITH_PROXY: - if b[2] != 1 { + if b[10] != 1 { //重新拉取一个池 s.connect() } else if s.method == "CONNECT" { s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n")) } default: - log.Println("未处理") + log.Println("httpProxyClient 未处理") } case common.CMD_CONN_MSG: @@ -165,7 +171,9 @@ func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error { localAddr: cfg.Addr(), id: common.GetID(), typ: "http", + randkey: make([]byte, 8), } + binary.LittleEndian.PutUint64(l.randkey, uint64(rand.NewSource(time.Now().UnixNano()).Int63())) l.listen, err = StartHttpProxyWithServer(cfg, target, l.id, pool) if err != nil { @@ -180,7 +188,8 @@ func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httppo if err != nil { return nil, err } - + randkey := make([]byte, 8) + binary.LittleEndian.PutUint64(randkey, uint64(rand.NewSource(time.Now().UnixNano()).Int63())) fmt.Println("httpproxy start ", cfg.Addr()) go func() { for { @@ -198,6 +207,7 @@ func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httppo server: n, listenId: id, pool: pool, + randkey: randkey, } go handleHttpProxyLocal(s) } @@ -354,7 +364,8 @@ func (s *httpProxyClient) connect() { buf[0] = byte(common.RAW_TCP_WITH_PROXY) buf = append(buf, []byte(" "+proxy.String())...) } - s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, 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: @@ -377,7 +388,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, buf) + s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey,buf...)) } func init() { @@ -454,7 +465,7 @@ func init() { c.Println("没有找到ID为", id, "的连接") } else { l.Close("命令行关闭") - l.server.Write(common.CMD_DELETE_LISTEN, l.id, nil) + l.server.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey) currentNode.listenMap.Delete(uint32(id)) } @@ -514,7 +525,6 @@ func parsereq(req *http1request, data []byte) (clen int, resdata []byte, err err } }() - // method, path, proto line req.Proto = "" diff --git a/server/node.go b/server/node.go index 8512e14..deedc04 100644 --- a/server/node.go +++ b/server/node.go @@ -14,7 +14,6 @@ import ( "rakshasa/cert" "rakshasa/common" "runtime" - "runtime/debug" "strconv" "strings" "sync" @@ -189,14 +188,16 @@ type node struct { listen net.Listener nextPingTime int64 - waitMsg []*common.Msg //需要等待处理的消息 - mirrorNode *node //currentNode会生成一个互为mirror的node,以实现client-server功能,比如httpProxy在单节点启动 + waitMsg []*common.Msg //需要等待处理的消息 + mirrorNode *node //currentNode会生成一个互为mirror的node,以实现client-server功能,比如httpProxy在单节点启动 + isClose int32 + reConnectAddrs []string //重连节点需要的信息 } type nodeInfo struct { UUID string HostName string MainIp string - Port int + Port string Goos string } @@ -274,6 +275,8 @@ func connectNew(addr string) (n *node, e error) { case err = <-c.regResult: return nil, err case n = <-c.regResultNode: + //连接成功 + n.reConnectAddrs = []string{addr} return n, err case <-time.After(time.Second * 10): return nil, errors.New("time out") @@ -297,9 +300,7 @@ func (n *node) Write(option uint8, id uint32, b []byte) { if common.Debug { fmt.Println("write", msg.From, msg.To, common.CmdToName[msg.CmdOpteion], len(b)) } - if len(b) == 195 { - debug.PrintStack() - } + if n.conn != nil { n.conn.OutChan <- b } else { @@ -325,9 +326,11 @@ func (n *node) do(msg *common.Msg) { //fmt.Println(common.CmdToName[msg.CmdOpteion]) switch msg.CmdOpteion { case common.CMD_CONNECT_BYIDADDR: - + msg.CmdData = cert.RSADecrypterByPubByte(msg.CmdData) + if len(msg.CmdData) < 9 { + return + } conn := &serverConnect{} - conn.node = n conn.id = msg.CmdId conn.write = make(chan *bytes.Buffer, 64) @@ -335,9 +338,11 @@ func (n *node) do(msg *common.Msg) { conn.windowsSize = 0 conn.wait = make(chan int) n.connMap.Store(conn.id, conn) - addr := string(msg.CmdData[1:]) + conn.randkey = make([]byte, 8) + copy(conn.randkey, msg.CmdData) + addr := string(msg.CmdData[9:]) - switch common.NetWork(msg.CmdData[0]) { + switch common.NetWork(msg.CmdData[8]) { case common.SOCKS5_CMD_CONNECT: conn.address = addr go conn.doConnectTcp(common.SOCKS5_CMD_CONNECT, addr) @@ -350,16 +355,18 @@ func (n *node) do(msg *common.Msg) { case common.SOCKS5_CMD_BIND: _l, err := net.Listen("tcp", addr) if err != nil { - n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, append([]byte{0}, err.Error()...)) + data := append(conn.randkey, 0) + data = append(data, err.Error()...) + n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, data) return } - l := &serverListen{listen: _l, node: n, isSocks5: true, id: common.GetID(), replayid: msg.CmdId} + l := &serverListen{listen: _l, node: n, isSocks5: true, id: common.GetID(), replayid: msg.CmdId, randkey: conn.randkey} n.connMap.Delete(conn.id) - l.socks5Replay = make([]byte, len(msg.CmdData)) - copy(l.socks5Replay, msg.CmdData) - n.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, l.socks5Replay) + l.socks5Replay = make([]byte, len(msg.CmdData[8:])) + copy(l.socks5Replay, msg.CmdData[8:]) + n.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey, l.socks5Replay...)) n.listenMap.Store(l.id, l) go l.Lisen() } @@ -432,20 +439,22 @@ func (n *node) do(msg *common.Msg) { return } - n.hostName = regmsg.Hostname - n.mainIp = regmsg.MainIp - n.port = regmsg.Port - n.goos = regmsg.Goos + n.hostName = cert.RSADecrypterStr(regmsg.Hostname) + n.mainIp = cert.RSADecrypterStr(regmsg.MainIp) + if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil { + n.port = -1 + } + 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] } resultMsg := regmsg resultMsg.UUID = currentNode.uuid - resultMsg.Hostname = currentNode.hostName - resultMsg.MainIp = currentNode.mainIp - resultMsg.Port = currentNode.port - resultMsg.Goos = currentNode.goos + resultMsg.Hostname = cert.RSAEncrypterStr(currentNode.hostName) + resultMsg.MainIp = cert.RSAEncrypterStr(currentNode.mainIp) + resultMsg.Port = cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)) + resultMsg.Goos = cert.RSAEncrypterStr(currentNode.goos) b, _ := json.Marshal(resultMsg) //返回成功结果 @@ -487,22 +496,26 @@ func (n *node) do(msg *common.Msg) { l := clientLock.Lock() n.uuid = regmsg.UUID - n.hostName = regmsg.Hostname - n.goos = regmsg.Goos + 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 = regmsg.MainIp - n.port = regmsg.Port + 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 = regmsg.MainIp - v.port = regmsg.Port + 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 @@ -543,11 +556,11 @@ func (n *node) do(msg *common.Msg) { if err == nil { regmsg.UUID = newNode.uuid - regmsg.Hostname = newNode.hostName - regmsg.ViaUUID = currentNode.uuid - regmsg.MainIp = newNode.mainIp - regmsg.Port = newNode.port - regmsg.Goos = newNode.goos + regmsg.Hostname = cert.RSADecrypterStr(newNode.hostName) + regmsg.ViaUUID = cert.RSADecrypterStr(currentNode.uuid) + regmsg.MainIp = cert.RSADecrypterStr(newNode.mainIp) + regmsg.Port = cert.RSADecrypterStr(strconv.Itoa(newNode.port)) + regmsg.Goos = cert.RSADecrypterStr(newNode.goos) b, _ := json.Marshal(regmsg) n.Write(common.CMD_REMOTE_REG_RESULT, msg.CmdId, b) } @@ -579,10 +592,10 @@ func (n *node) do(msg *common.Msg) { if targetNode, ok = nodeMap[regmsg.UUID]; !ok { targetNode = getNewNode(nodeInfo{ UUID: regmsg.UUID, - HostName: regmsg.Hostname, - MainIp: regmsg.MainIp, - Port: regmsg.Port, - Goos: regmsg.Goos, + HostName: cert.RSADecrypterStr(regmsg.Hostname), + MainIp: cert.RSADecrypterStr(regmsg.MainIp), + Port: cert.RSADecrypterStr(regmsg.Port), + Goos: cert.RSADecrypterStr(regmsg.Goos), }, n) if common.Debug { fmt.Printf("nodeMap4 %s %p \r\n", regmsg.UUID, n) @@ -591,10 +604,10 @@ func (n *node) do(msg *common.Msg) { } else { targetNode.updateNode(nodeInfo{ UUID: regmsg.UUID, - HostName: regmsg.Hostname, - MainIp: regmsg.MainIp, - Port: regmsg.Port, - Goos: regmsg.Goos, + HostName: cert.RSADecrypterStr(regmsg.Hostname), + MainIp: cert.RSADecrypterStr(regmsg.MainIp), + Port: cert.RSADecrypterStr(regmsg.Port), + Goos: cert.RSADecrypterStr(regmsg.Goos), }) } v <- targetNode @@ -670,86 +683,121 @@ func (n *node) do(msg *common.Msg) { } case common.CMD_LISTEN: - + msg.CmdData = cert.RSADecrypterByPubByte(msg.CmdData) + if len(msg.CmdData) < 8 { + return + } + randkey := make([]byte, 8) + copy(randkey, msg.CmdData) //fmt.Println("listen", string(data[common.Headlen+4:])) - _l, err := net.Listen("tcp", string(msg.CmdData)) + _l, err := net.Listen("tcp", string(msg.CmdData[8:])) if err != nil { - n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, append([]byte{0}, err.Error()...)) + data := append(randkey, 0) + data = append(randkey, err.Error()...) + n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, data) return } else { - n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, []byte{1}) + n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, append(randkey, 1)) } - l := &serverListen{listen: _l, node: n, id: msg.CmdId} + l := &serverListen{listen: _l, node: n, id: msg.CmdId, randkey: randkey} n.listenMap.Store(msg.CmdId, l) go l.Lisen() case common.CMD_REMOTE_SOCKS5: - - cfg, err := common.ParseAddr(string(msg.CmdData)) - if err != nil { - n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, append([]byte{0}, err.Error()...)) + msg.CmdData = cert.RSADecrypterByPubByte(msg.CmdData) + if len(msg.CmdData) < 8 { return } - l := &serverListen{node: n, id: msg.CmdId} + randkey := make([]byte, 8) + copy(randkey, msg.CmdData) + + cfg, err := common.ParseAddr(string(msg.CmdData[8:])) + if err != nil { + data := append(randkey, 0) + data = append(data, err.Error()...) + n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, data) + return + } + l := &serverListen{node: n, id: msg.CmdId, randkey: randkey} l.listen, err = StartSocks5WithServer(cfg, n, l.id) if err != nil { - n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, append([]byte{0}, err.Error()...)) + data := append(randkey, 0) + data = append(data, err.Error()...) + n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, data) return } else { - n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, []byte{1}) + n.Write(common.CMD_LISTEN_RESULT, msg.CmdId, append(randkey, 1)) } n.listenMap.Store(l.id, l) case common.CMD_LISTEN_RESULT: + if len(msg.CmdData) < 9 { + return + } if v, ok := currentNode.listenMap.Load(msg.CmdId); ok { if c, ok := v.(*clientListen); ok { - if msg.CmdData[0] == 0 { - select { - case c.result <- errors.New(string(msg.CmdData[1:])): - default: - } + if string(c.randkey) == string(msg.CmdData[:8]) { + if msg.CmdData[8] == 0 { + select { + case c.result <- errors.New(string(msg.CmdData[9:])): + default: + } - } else { - select { - case c.result <- nil: - default: + } else { + select { + case c.result <- nil: + default: + } } - } - } } case common.CMD_DELETE_LISTEN: + if len(msg.CmdData) < 8 { + return + } if v, ok := n.listenMap.Load(msg.CmdId); ok { switch s := v.(type) { case *serverListen: - s.Close(remoteClose) - case *clientListen: - s.Close(remoteClose) - } - - } - n.listenMap.Delete(msg.CmdId) - case common.CMD_DELETE_LISTENCONN_BYID: - deleteId := uint32(msg.CmdData[0]) | uint32(msg.CmdData[1])<<8 | uint32(msg.CmdData[2])<<16 | uint32(msg.CmdData[3])<<24 - if v, ok := n.listenMap.Load(msg.CmdId); ok { - if s, ok := v.(*serverListen); ok { - conn, ok := s.connMap.Load(deleteId) - if ok { - conn.(*serverConnect).Close(remoteClose) - s.connMap.Delete(deleteId) + if string(s.randkey) == string(msg.CmdData[:8]) { + s.Close(remoteClose) + n.listenMap.Delete(msg.CmdId) } + case *clientListen: + if string(s.randkey) == string(msg.CmdData[:8]) { + s.Close(remoteClose) + n.listenMap.Delete(msg.CmdId) + } } + } + case common.CMD_DELETE_LISTENCONN_BYID: + if len(msg.CmdData) != 12 { + return + } + deleteId := uint32(msg.CmdData[8]) | uint32(msg.CmdData[9])<<8 | uint32(msg.CmdData[10])<<16 | uint32(msg.CmdData[11])<<24 + if v, ok := n.listenMap.Load(msg.CmdId); ok { + if s, ok := v.(*serverListen); ok { + if string(s.randkey) == string(msg.CmdData[:8]) { + conn, ok := s.connMap.Load(deleteId) + if ok { + conn.(*serverConnect).Close(remoteClose) + s.connMap.Delete(deleteId) + } + } + } } case common.CMD_PWD: - pwd, _ := os.Getwd() - n.Write(common.CMD_PWD_RESULT, msg.CmdId, []byte(pwd)) + if currentConfig.Password == cert.RSADecrypterByPub(string(msg.CmdData)) { + pwd, _ := os.Getwd() + n.Write(common.CMD_PWD_RESULT, msg.CmdId, []byte(pwd)) + } + case common.CMD_PWD_RESULT: if v, ok := n.loadQuery(msg.CmdId); ok { select { @@ -768,13 +816,20 @@ func (n *node) do(msg *common.Msg) { err = json.Unmarshal(msg.CmdData, &s) if err == nil { for _, _n := range s { + _n = nodeInfo{ + UUID: _n.UUID, + HostName: cert.RSADecrypterStr(_n.HostName), + MainIp: cert.RSADecrypterStr(_n.MainIp), + Port: cert.RSADecrypterStr(_n.Port), + Goos: cert.RSADecrypterStr(_n.Goos), + } if _n.UUID != currentNode.uuid { if v, ok := nodeMap[_n.UUID]; !ok { nodeMap[_n.UUID] = getNewNode(_n, n) } else { v.hostName = _n.HostName v.mainIp = _n.MainIp - v.port = _n.Port + v.port, _ = strconv.Atoi(_n.Port) } } @@ -789,12 +844,12 @@ func (n *node) do(msg *common.Msg) { } } case common.CMD_GET_CURRENT_NODE: - nmsg := nodeInfo{ + nmsg := &nodeInfo{ UUID: currentNode.uuid, - HostName: currentNode.hostName, - MainIp: currentNode.mainIp, - Port: currentNode.port, - Goos: currentNode.goos, + HostName: cert.RSAEncrypterStr(currentNode.hostName), + MainIp: cert.RSAEncrypterStr(currentNode.mainIp), + Port: cert.RSAEncrypterStr(fmt.Sprint(currentNode.port)), + Goos: cert.RSAEncrypterStr(currentNode.goos), } b, _ := json.Marshal(nmsg) n.Write(common.CMD_GET_CURRENT_NODE_RESULT, msg.CmdId, b) @@ -817,11 +872,16 @@ func (n *node) do(msg *common.Msg) { nodeMap[nmsg.UUID] = newNode } else if nmsg.UUID != currentNode.uuid { + port, err := strconv.Atoi(cert.RSADecrypterStr(nmsg.Port)) + if err == nil { + v.port = port + } else { + v.port = -1 + } - v.port = nmsg.Port - v.mainIp = nmsg.MainIp - v.hostName = nmsg.HostName - v.goos = nmsg.Goos + v.mainIp = cert.RSADecrypterStr(nmsg.MainIp) + v.hostName = cert.RSADecrypterStr(nmsg.HostName) + v.goos = cert.RSADecrypterStr(nmsg.Goos) v.uuid = nmsg.UUID if common.Debug { fmt.Printf("nodeMap6 %s %p \r\n", nmsg.UUID, v) @@ -832,7 +892,7 @@ func (n *node) do(msg *common.Msg) { } case common.CMD_DIR: - dirPth := string(msg.CmdData) + dirPth := cert.RSADecrypterByPub(string(msg.CmdData)) dir, err := ioutil.ReadDir(dirPth) if err != nil { n.Write(common.CMD_DIR_RESULT, msg.CmdId, []byte("读取目录 "+dirPth+" 失败")) @@ -872,7 +932,7 @@ func (n *node) do(msg *common.Msg) { } case common.CMD_CD: - dirPth := string(msg.CmdData) + dirPth := cert.RSADecrypterByPub(string(msg.CmdData)) s, err := os.Stat(dirPth) if err != nil { n.Write(common.CMD_CD_RESULT, msg.CmdId, append([]byte{0}, err.Error()...)) @@ -899,12 +959,17 @@ func (n *node) do(msg *common.Msg) { } case common.CMD_CONNECT_BYID: + var l *clientListen if v, ok := currentNode.listenMap.Load(msg.CmdId); ok { l, _ = v.(*clientListen) } if l == nil { - n.Write(common.CMD_DELETE_LISTEN, msg.CmdId, nil) + n.Write(common.CMD_DELETE_LISTEN, msg.CmdId, l.randkey) + return + } + if len(msg.CmdData) < 8 || string(l.randkey) != string(msg.CmdData[:8]) { + n.Write(common.CMD_DELETE_LISTEN, msg.CmdId, l.randkey) return } //l := clientLock.Lock() @@ -912,17 +977,16 @@ func (n *node) do(msg *common.Msg) { //l.Unlock() conn, err := net.Dial("tcp", l.localAddr) if err != nil { - n.Write(common.CMD_DELETE_LISTENCONN_BYID, l.id, msg.CmdData) + n.Write(common.CMD_DELETE_LISTENCONN_BYID, l.id, append(l.randkey, msg.CmdData...)) return } client := &clientConnect{} - client.id = uint32(msg.CmdData[0]) | uint32(msg.CmdData[1])<<8 | uint32(msg.CmdData[2])<<16 | uint32(msg.CmdData[3])<<24 - + client.id = uint32(msg.CmdData[8]) | uint32(msg.CmdData[9])<<8 | uint32(msg.CmdData[10])<<16 | uint32(msg.CmdData[11])<<24 client.server = l.server client.listenId = msg.CmdId client.conn = conn client.OnOpened() - + client.randkey = append([]byte{}, l.randkey...) l.connMap.Store(client.id, client) l.server.connMap.Store(client.id, client) go rawHandleLocal(client) @@ -954,6 +1018,7 @@ func (n *node) do(msg *common.Msg) { } } case common.CMD_UPLOAD: + msg.CmdData = cert.RSADecrypterByPubByte(msg.CmdData) i := bytes.IndexByte(msg.CmdData, 0) if i == -1 { n.Write(common.CMD_UPLOAD_RESULT, msg.CmdId, append([]byte{0}, "协议错误"...)) @@ -1006,6 +1071,7 @@ func (n *node) do(msg *common.Msg) { } case common.CMD_DOWNLOAD: + msg.CmdData = cert.RSADecrypterByPubByte(msg.CmdData) i := bytes.IndexByte(msg.CmdData, 0) file := string(msg.CmdData[:i]) offset := int64(msg.CmdData[i+1]) | int64(msg.CmdData[i+2])<<8 | int64(msg.CmdData[i+3])<<16 | int64(msg.CmdData[i+4])<<24 | int64(msg.CmdData[i+5])<<32 | int64(msg.CmdData[i+6])<<40 | int64(msg.CmdData[i+7])<<48 | int64(msg.CmdData[i+8])<<56 @@ -1067,7 +1133,7 @@ func (n *node) do(msg *common.Msg) { } case common.CMD_SHELL: var param StartCmdParam - if err = json.Unmarshal(msg.CmdData, ¶m); err != nil { + if err = json.Unmarshal(cert.RSADecrypterByPubByte(msg.CmdData), ¶m); err != nil { n.Write(common.CMD_SHELL_RESULT, msg.CmdId, append([]byte{0}, err.Error()...)) } if err := startCMD(n, msg.CmdId, param); err != nil { @@ -1104,8 +1170,7 @@ func (n *node) do(msg *common.Msg) { case common.CMD_RUN_SHELLCODE: go func() { var s ShellCodeStruct - err = json.Unmarshal(msg.CmdData, &s) - + err = json.Unmarshal(cert.RSADecrypterByPubByte(msg.CmdData), &s) if err != nil { n.Write(common.CMD_RUN_SHELLCODE_RESULT, msg.CmdId, []byte(err.Error())) } @@ -1142,9 +1207,9 @@ func (n *node) remoteReg(addr string) (newN *node, err error) { regmsg := common.RegMsg{ RegAddr: addr, UUID: currentNode.uuid, - MainIp: currentNode.mainIp, - Port: currentNode.port, - Goos: currentNode.goos, + MainIp: cert.RSAEncrypterStr(currentNode.mainIp), + Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)), + Goos: cert.RSAEncrypterStr(currentNode.goos), } regmsg.Hostname, _ = os.Hostname() b, _ := json.Marshal(regmsg) @@ -1175,13 +1240,14 @@ func (n *node) Close(reason string) { n.Delete(reason) } func getNewNode(m nodeInfo, n *node) *node { + port, _ := strconv.Atoi(m.Port) newNode := &node{ uuid: m.UUID, hostName: m.HostName, conn: n.conn, pongTime: time.Now().Unix(), mainIp: m.MainIp, - port: m.Port, + port: port, goos: m.Goos, } @@ -1283,54 +1349,57 @@ func (n *node) ping(id uint32) { } func (n *node) Delete(reason string) { go func() { - l := clientLock.Lock() - _, ok := nodeMap[n.uuid] - if ok { - delete(nodeMap, n.uuid) - } - l.Unlock() - n.connMap.Range(func(key, value interface{}) bool { - if v, ok := value.(common.Conn); ok { - v.Close(reason) + if atomic.CompareAndSwapInt32(&n.isClose, 0, 1) { + l := clientLock.Lock() + _, ok := nodeMap[n.uuid] + if ok { + delete(nodeMap, n.uuid) } - n.connMap.Delete(key) - return true - }) - n.udpConnMap.Range(func(key, value interface{}) bool { - if v, ok := value.(common.Conn); ok { - v.Close(reason) - } - n.udpConnMap.Delete(key) - return true - }) - n.listenMap.Range(func(key, value interface{}) bool { + l.Unlock() + n.connMap.Range(func(key, value interface{}) bool { + if v, ok := value.(common.Conn); ok { + v.Close(reason) + } + n.connMap.Delete(key) + return true + }) + n.udpConnMap.Range(func(key, value interface{}) bool { + if v, ok := value.(common.Conn); ok { + v.Close(reason) + } + n.udpConnMap.Delete(key) + return true + }) + n.listenMap.Range(func(key, value interface{}) bool { + + if v, ok := value.(*serverListen); ok { + v.listen.Close() + } + n.listenMap.Delete(key) + return true + }) + n.shellMap.Range(func(key, value interface{}) bool { + v := value.(*remoteCmd) + if v.cmd != nil { + v.cmd.Process.Kill() + } + n.shellMap.Delete(key) + return true + }) + } - if v, ok := value.(*serverListen); ok { - v.listen.Close() - } - n.listenMap.Delete(key) - return true - }) - n.shellMap.Range(func(key, value interface{}) bool { - v := value.(*remoteCmd) - if v.cmd != nil { - v.cmd.Process.Kill() - } - n.shellMap.Delete(key) - return true - }) }() } func (n *node) broadcastNode() { //广播新增节点 - nmsg := nodeInfo{ + nmsg := &nodeInfo{ UUID: n.uuid, - HostName: n.hostName, - MainIp: n.mainIp, - Port: n.port, - Goos: n.goos, + HostName: cert.RSAEncrypterStr(n.hostName), + MainIp: cert.RSAEncrypterStr(n.mainIp), + Port: cert.RSAEncrypterStr(fmt.Sprint(n.port)), + Goos: cert.RSAEncrypterStr(n.goos), } b, _ := json.Marshal(nmsg) @@ -1371,6 +1440,8 @@ func GetNodeFromAddrs(dst []string) (n *node, err error) { if n.uuid == currentNode.uuid { return nil, errors.New("不能连接自己") } + n.reConnectAddrs = make([]string, len(dst)) + copy(n.reConnectAddrs, dst) return } @@ -1415,16 +1486,16 @@ func (n *node) writeGetNodeResult(id uint32) { defer l.RUnlock() - var s []nodeInfo + var s []*nodeInfo for _, _n := range nodeMap { if _n.uuid != currentNode.uuid { - s = append(s, nodeInfo{ + s = append(s, &nodeInfo{ UUID: _n.uuid, - HostName: _n.hostName, - MainIp: _n.mainIp, - Port: _n.port, - Goos: _n.goos, + HostName: cert.RSAEncrypterStr(_n.hostName), + MainIp: cert.RSAEncrypterStr(_n.mainIp), + Port: cert.RSAEncrypterStr(strconv.Itoa(_n.port)), + Goos: cert.RSAEncrypterStr(_n.goos), }) } @@ -1436,6 +1507,6 @@ func (n *node) writeGetNodeResult(id uint32) { func (n *node) updateNode(msg nodeInfo) { n.hostName = msg.HostName n.mainIp = msg.MainIp - n.port = msg.Port + n.port, _ = strconv.Atoi(msg.Port) n.goos = msg.Goos } diff --git a/server/raw_tcp_client.go b/server/raw_tcp_client.go index 12334e1..2bf4e29 100644 --- a/server/raw_tcp_client.go +++ b/server/raw_tcp_client.go @@ -1,10 +1,13 @@ package server import ( + "encoding/binary" "errors" "fmt" "hash/crc32" + "math/rand" "net" + "rakshasa/cert" "rakshasa/common" "strconv" "strings" @@ -31,6 +34,7 @@ type clientListen struct { connMap sync.Map //clientListen关闭的时候关掉这里的id listen net.Listener result chan interface{} + randkey []byte //随机key int64 } func StartRawBind(str string, dst []string) error { @@ -57,8 +61,10 @@ func StartRawBind(str string, dst []string) error { typ: "bind", result: make(chan interface{}), openOption: common.CMD_LISTEN, + randkey: make([]byte, 8), } - l.openMsg = []byte(addrs[1]) + binary.LittleEndian.PutUint64(l.randkey, uint64(rand.NewSource(time.Now().UnixNano()).Int63())) + l.openMsg =cert.RSAEncrypterByPrivByte(append(l.randkey,[]byte(addrs[1])...)) currentNode.listenMap.Store(l.id, l) n.Write(l.openOption, l.id, l.openMsg) select { @@ -101,7 +107,9 @@ func StartRawConnect(str string, n *node) error { listen: listen, server: n, typ: "connect", + randkey: make([]byte, 8), } + binary.LittleEndian.PutUint64(l.randkey, uint64(rand.NewSource(time.Now().UnixNano()).Int63())) currentNode.listenMap.Store(l.id, l) go func() { @@ -117,10 +125,17 @@ func StartRawConnect(str string, n *node) error { s := &clientConnect{ conn: conn, server: n, + randkey: l.randkey, } s.OnOpened() - s.connect(common.RAW_TCP, addr1.IP.String(), uint16(addr1.Port)) - go rawHandleLocal(s) + if s.connect(common.RAW_TCP, addr1.IP.String(), uint16(addr1.Port)) { + go rawHandleLocal(s) + } else { + s.Close(nodeIsClose) + if common.Debug { + fmt.Println("Connect连接失败,远程节点已关闭") + } + } } }() @@ -169,7 +184,7 @@ func rawHandleLocal(s *clientConnect) { } data := make([]byte, 8+n) copy(data, buf) - s.server.Write(common.CMD_CONN_MSG, s.id, buf) + s.server.Write(common.CMD_CONN_MSG, s.id, buf[:8+n]) } } func init() { @@ -230,7 +245,7 @@ func init() { c.Println("没有找到ID为", id, "的连接") } else { l.Close("命令行关闭") - l.server.Write(common.CMD_DELETE_LISTEN, l.id, nil) + l.server.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey) currentNode.listenMap.Delete(uint32(id)) } @@ -244,7 +259,7 @@ func init() { bindshell.Run() }, }) - connectshell := ishell.New() + connectshell := cliInit() connectshell.SetPrompt("rakshasa\\connect>") connectshell.AddCmd(&ishell.Cmd{ Name: "list", @@ -308,7 +323,7 @@ func init() { c.Println("没有找到ID为", id, "的连接") } else { l.Close("命令行关闭") - l.server.Write(common.CMD_DELETE_LISTEN, l.id, nil) + l.server.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey) currentNode.listenMap.Delete(uint32(id)) } diff --git a/server/raw_tcp_server.go b/server/raw_tcp_server.go index a957bc1..8a010be 100644 --- a/server/raw_tcp_server.go +++ b/server/raw_tcp_server.go @@ -27,7 +27,7 @@ func (l *serverListen) Lisen() { if l.isSocks5 { conn.id = l.id - l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, l.socks5Replay) + l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey,l.socks5Replay...)) go conn.handTcpReceive() return } @@ -38,7 +38,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, b) + conn.node.Write(common.CMD_CONNECT_BYID, l.id, append(l.randkey,b...)) l.connMap.Store(conn.id, conn) go conn.handTcpReceive() @@ -58,7 +58,7 @@ func (l *serverListen) Close(reason string) { }) if reason != remoteClose { - l.node.Write(common.CMD_DELETE_LISTEN, l.id, nil) + l.node.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey) } } } diff --git a/server/remote_socks5.go b/server/remote_socks5.go index 231db2f..7c69e29 100644 --- a/server/remote_socks5.go +++ b/server/remote_socks5.go @@ -1,8 +1,11 @@ package server import ( + "encoding/binary" "errors" "fmt" + "math/rand" + "rakshasa/cert" "rakshasa/common" "strconv" "strings" @@ -20,9 +23,11 @@ func StartRemoteSocks5(cfg *common.Addr, n *node) error { 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 = []byte(cfg.String()) + l.openMsg = cert.RSAEncrypterByPrivByte(append(l.randkey,cfg.String()...)) n.Write(l.openOption, l.id, l.openMsg) currentNode.listenMap.Store(l.id, l) select { @@ -110,7 +115,7 @@ func init() { c.Println("没有找到ID为", id, "的连接") } else { l.Close("命令行关闭") - l.server.Write(common.CMD_DELETE_LISTEN, l.id, nil) + l.server.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey) currentNode.listenMap.Delete(uint32(id)) } diff --git a/server/shell.go b/server/shell.go index d94c8d7..8aebcb0 100644 --- a/server/shell.go +++ b/server/shell.go @@ -109,7 +109,7 @@ func init() { c.Println(c.Args) currentConfig.Password = c.Args[0] currentConfig.FileSave = false - aes.Key = aes.MD5_B(currentConfig.Password + string(cert.PublicKey[:16])) + aes.Key = aes.MD5_B(currentConfig.Password + string(cert.PrivateKey[:16])) }, }) configShell.AddCmd(&ishell.Cmd{ @@ -133,7 +133,7 @@ func init() { currentConfig.Port = port currentNode.port = port currentConfig.FileSave = false - StartServer(fmt.Sprintf("%s:%d",currentConfig.ListenIp,currentConfig.Port)) + StartServer(fmt.Sprintf("%s:%d", currentConfig.ListenIp, currentConfig.Port)) }, }) @@ -188,7 +188,7 @@ func init() { remoteShell.SetPrompt("rakshasa\\remoteshell>") - fileShell := ishell.New() + fileShell := cliInit() remoteShell.AddCmd(&ishell.Cmd{ Name: "file", Help: "连到节点进行文件管理,参数为id或者uuid", @@ -208,7 +208,7 @@ func init() { fileShell.Set("node", workN) result := make(chan interface{}, 1) id := workN.storeQuery(result) - workN.Write(common.CMD_PWD, id, nil) + workN.Write(common.CMD_PWD, id, []byte(cert.RSAEncrypterByPriv(currentConfig.Password))) select { case pwd := <-result: workN.deleteQuery(id) @@ -234,7 +234,7 @@ func init() { n := c.Get("node").(*node) resChan := make(chan interface{}, 1) id := n.storeQuery(resChan) - n.Write(common.CMD_DIR, id, []byte(pwd.(string))) + n.Write(common.CMD_DIR, id, []byte(cert.RSAEncrypterByPriv(pwd.(string)))) select { case res := <-resChan: n.deleteQuery(id) @@ -266,7 +266,7 @@ func init() { resChan := make(chan interface{}, 1) id := n.storeQuery(resChan) - n.Write(common.CMD_CD, id, []byte(pwd)) + n.Write(common.CMD_CD, id, []byte(cert.RSAEncrypterByPriv(pwd))) select { case res := <-resChan: @@ -372,7 +372,7 @@ func init() { b[be+6] = byte(offset >> 48) b[be+7] = byte(offset >> 56) offset += len(data) - n.Write(common.CMD_UPLOAD, id, append(b, data...)) + n.Write(common.CMD_UPLOAD, id, cert.RSAEncrypterByPrivByte(append(b, data...))) case res := <-resChan: switch v := res.(type) { case error: @@ -468,7 +468,7 @@ func init() { b[be+5] = byte(total >> 40) b[be+6] = byte(total >> 48) b[be+7] = byte(total >> 56) - n.Write(common.CMD_DOWNLOAD, id, b) + n.Write(common.CMD_DOWNLOAD, id,cert.RSAEncrypterByPrivByte(b)) c.ProgressBar().Start() size := int64(0) resnum := 0 @@ -525,7 +525,7 @@ func init() { b[be+5] = byte(total >> 40) b[be+6] = byte(total >> 48) b[be+7] = byte(total >> 56) - n.Write(common.CMD_DOWNLOAD, id, b) + n.Write(common.CMD_DOWNLOAD, id, cert.RSAEncrypterByPrivByte(b)) } default: c.Println("协议错误") @@ -585,7 +585,7 @@ func init() { } b, _ := json.Marshal(p) - n.Write(common.CMD_SHELL, id, b) + n.Write(common.CMD_SHELL, id, cert.RSAEncrypterByPrivByte(b)) s := &remoteCmd{ cmd: nil, stdin: nil, diff --git a/server/shellcode.go b/server/shellcode.go index 20bb0e2..2c4de6a 100644 --- a/server/shellcode.go +++ b/server/shellcode.go @@ -10,6 +10,7 @@ import ( "os" "os/exec" "path/filepath" + "rakshasa/cert" "rakshasa/common" "strconv" "time" @@ -44,7 +45,7 @@ func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) erro id := n.storeQuery(res) b, _ := json.Marshal(s) - n.Write(common.CMD_RUN_SHELLCODE, id, b) + n.Write(common.CMD_RUN_SHELLCODE, id, cert.RSAEncrypterByPrivByte(b)) select { case v := <-res: fmt.Println("运行结果\n", v) diff --git a/server/socks5.go b/server/socks5.go index d6bec3b..9ed01c5 100644 --- a/server/socks5.go +++ b/server/socks5.go @@ -7,13 +7,16 @@ import ( "fmt" "hash/crc32" "log" + "math/rand" "net" + "rakshasa/cert" "rakshasa/common" "runtime/debug" "strconv" "strings" "sync" "sync/atomic" + "time" "unsafe" "github.com/luyu6056/ishell" @@ -64,6 +67,7 @@ type clientConnect struct { addrData []byte listenId uint32 + randkey []byte } func (s *clientConnect) Write(b []byte) { @@ -72,10 +76,10 @@ func (s *clientConnect) Write(b []byte) { case common.CMD_CONNECT_BYIDADDR_RESULT: - switch common.NetWork(b[1]) { + switch common.NetWork(b[9]) { case common.SOCKS5_CMD_CONNECT: - if b[2] != 1 { + if b[10] != 1 { go func() { s.Close("") }() } else { @@ -87,11 +91,11 @@ func (s *clientConnect) Write(b []byte) { s.auth = CONN_AUTH_MESSAGE s.conn.Write(append([]byte{5, 0, 0}, s.addrData...)) case common.RAW_TCP: - if b[2] != 1 { + if b[10] != 1 { go func() { s.Close("") }() } default: - log.Println("未处理") + log.Println("socks5 未处理") } case common.CMD_CONN_MSG: @@ -108,7 +112,7 @@ func (s *clientConnect) Write(b []byte) { } var remoteClose = "服务器要求远程关闭" - +var nodeIsClose = "节点已经断开连接" func (s *clientConnect) Close(msg string) { if atomic.CompareAndSwapInt32(&s.isClose, 0, 1) { @@ -184,7 +188,9 @@ func StartSocks5(cfg *common.Addr, dst []string) error { localAddr: cfg.Addr(), id: common.GetID(), typ: "socks5", + randkey: make([]byte, 8), } + binary.LittleEndian.PutUint64(l.randkey, uint64(rand.NewSource(time.Now().UnixNano()).Int63())) l.listen, err = StartSocks5WithServer(cfg, target, l.id) if err != nil { @@ -199,7 +205,8 @@ func StartSocks5WithServer(cfg *common.Addr, n *node, id uint32) (net.Listener, if err != nil { return nil, err } - + randkey := make([]byte, 8) + binary.LittleEndian.PutUint64(randkey, uint64(rand.NewSource(time.Now().UnixNano()).Int63())) fmt.Println("socks5 start ", cfg.Addr()) go func() { for { @@ -216,6 +223,7 @@ func StartSocks5WithServer(cfg *common.Addr, n *node, id uint32) (net.Listener, conn: conn, server: n, listenId: id, + randkey: randkey, } go handleSocks5Local(c) @@ -298,11 +306,14 @@ func handleSocks5Local(s *clientConnect) { switch common.NetWork(data[1]) { case common.SOCKS5_CMD_CONNECT: addr, port := socks5ReadAddr(data) - - 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) - 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: localIP := s.conn.LocalAddr().String() @@ -329,11 +340,13 @@ func handleSocks5Local(s *clientConnect) { ipb := ipToByte(localIP) addr, port := socks5ReadAddr(data) - s.connect(common.SOCKS5_CMD_UDP, addr, port) - - copy(repdata[4:], ipb) - s.conn.Write(repdata) - go handleSocks5Udp(s) + if s.connect(common.SOCKS5_CMD_UDP, addr, port){ + copy(repdata[4:], ipb) + s.conn.Write(repdata) + go handleSocks5Udp(s) + }else{ + s.Close(nodeIsClose) + } default: data[0] = 5 data[1] = 7 //RepCmdNotSupported @@ -393,6 +406,7 @@ func handleSocks5Udp(s *clientConnect) { udps := &clientConnect{ server: s.server, + randkey: s.randkey, } udps.udpConn = s.udpConn udps.id = udps.server.storeConn(s) @@ -416,17 +430,21 @@ func handleSocks5Udp(s *clientConnect) { } } -func (s *clientConnect) connect(command common.NetWork, addr string, port uint16) { +func (s *clientConnect) connect(command common.NetWork, addr string, port uint16)bool { + if atomic.LoadInt32(&s.server.isClose) == 1 { + s.server, _ = GetNodeFromAddrs(s.server.reConnectAddrs) + } + 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, 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: @@ -435,6 +453,7 @@ func (s *clientConnect) connect(command common.NetWork, addr string, port uint16 v.connMap.Store(s.id, s) } } + return true } func Bytes2str(b []byte) string { @@ -450,7 +469,7 @@ func (s *clientConnect) 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, buf) + s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey, buf...)) } func init() { @@ -521,7 +540,7 @@ func init() { c.Println("没有找到ID为", id, "的连接") } else { l.Close("命令行关闭") - l.server.Write(common.CMD_DELETE_LISTEN, l.id, nil) + l.server.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey) currentNode.listenMap.Delete(uint32(id)) }