9 Commits
Author SHA1 Message Date
Mob2003 5a67527907 Update rakshasa项目设计.md 2023-04-08 21:50:48 +08:00
Mob2003 3c94a17d26 Update config.md 2023-04-08 21:45:00 +08:00
Mob2003 d68a4281f8 Update README.md 2023-04-08 21:41:42 +08:00
Mob2003 8502cab070 Update README.md 2023-04-08 21:39:20 +08:00
Mob2003 bd49fdc0bf 增加http_proxy重连逻辑 2023-04-08 21:29:05 +08:00
Mob2003 b48e9e77ac 更新lite 2023-04-08 21:28:06 +08:00
Mob2003 ac68df552e Merge branch 'main' of https://github.com/Mob2003/rakshasa 2023-04-03 11:53:39 +08:00
Mob2003 880c491fd4 修复build执行错误 2023-04-03 11:53:28 +08:00
Mob2003 461e3ba883 Update README.md 2023-04-03 10:32:34 +08:00
41 changed files with 658 additions and 557 deletions
+12
View File
@@ -16,6 +16,18 @@ rakshasa是一个使用Go语言编写的强大多级代理工具,专为实现*
[win10+Proxifier实现内网穿透](./readme/rakshasa内网穿透--win10+Proxifier使用案例.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,解决多网卡下,无法连接的问题
- **v0.2.2** 2023-04-08
- 增加http_proxy重连逻辑,节点掉线后重连http代理能够正常重连使用
- 优化节点重连逻辑
- 增加uuid选项,默认uuid使用网卡mac作为随机数种子,进行生成
## 编译与使用 ## 编译与使用
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.
+4 -2
View File
@@ -34,7 +34,9 @@ func main() {
if *genfullNodePrivate { if *genfullNodePrivate {
b, _ := os.ReadFile("./cert/private.pem") b, _ := os.ReadFile("./cert/private.pem")
data := fmt.Sprintf("package cert\r\n func init(){\r\nprivateKey=%#v\r\n}\r\n", b) data := fmt.Sprintf("package cert\r\n func init(){\r\nprivateKey=%#v\r\n}\r\n", b)
os.WriteFile("./cert/private.go", []byte(data), 0655) if err := os.WriteFile("./cert/private.go", []byte(data), 0655); err != nil {
fmt.Printf("写入./cert/private.go失败,错误 %v", err)
}
return return
} }
if *gencert { if *gencert {
@@ -45,7 +47,7 @@ func main() {
return return
} }
} else { } else {
b, err := exec.Command("/bin/bash", "-c", "cd gencert && go run main.go").CombinedOutput() _, err := exec.Command("/bin/bash", "-c", "cd gencert && go run main.go").CombinedOutput()
if err != nil { if err != nil {
log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`) log.Fatal(`无法生成证书,请手动执行"cd gencert && go run main.go"`)
return return
+30 -11
View File
@@ -2,12 +2,14 @@ package common
import ( import (
"bytes" "bytes"
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"math/rand" "math/rand"
"net" "net"
"rakshasa/aes" "rakshasa/aes"
"regexp" "regexp"
"strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
@@ -195,17 +197,6 @@ func init() {
} }
type RegMsg struct {
UUID string //当前机器uuid
RegAddr string //远程连接的addr
Hostname string //当前机器名称
Goos string
ViaUUID string
Err string
MainIp string
Port string
}
var msgId uint32 var msgId uint32
func (m *Msg) Marshal() []byte { func (m *Msg) Marshal() []byte {
@@ -329,3 +320,31 @@ func ResolveTCPAddr(str string) ([]string, error) {
return dst, nil return dst, nil
} }
func GetUUIDFromInterfaceMac() string {
ifts, _ := net.Interfaces()
for _, ift := range ifts {
if addr := ift.HardwareAddr.String(); len(addr) > 0 {
var randSeed = make([]byte, 8)
for k, s := range strings.Split(addr, ":") {
if k < 8 {
n, _ := strconv.ParseUint(s, 16, 8)
randSeed[k] = byte(n)
}
}
source := rand.NewSource(int64(binary.LittleEndian.Uint64(randSeed)))
buf := bytes.NewBuffer(nil)
for i := 0; i < 2; i++ {
var b = make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(source.Int63()))
buf.Write(b)
}
id, err := uuid.NewRandomFromReader(buf)
if err == nil {
return id.String()
}
}
}
return uuid.New().String()
}
+2 -1
View File
@@ -1,10 +1,11 @@
package common package common
type Config struct { type Config struct {
UUID string //以指定uuid启动
DstNode []string //-d 上级节点 DstNode []string //-d 上级节点
Password string //通讯密码,可为空 Password string //通讯密码,可为空
Port int //默认8883 Port int //默认8883
ListenIp string //指定公网ip,其他节点进行额外节点连接时候,尝试连接的ip ListenIp string //指定公网ip,其他节点进行额外节点连接时候,尝试连接的ip
Limit bool //禁止额外连接,只连接-d节点,不会尝试连接其他节点 Limit bool //禁止额外连接,只连接-d节点,不会尝试连接其他节点
FileName string FileName string
FileSave bool `yaml:"-"` FileSave bool `yaml:"-"`
+11 -4
View File
@@ -9,10 +9,11 @@ import (
_ "net/http/pprof" _ "net/http/pprof"
"rakshasa/aes" "rakshasa/aes"
"rakshasa/common" "rakshasa/common"
"rakshasa/httppool"
"rakshasa/server" "rakshasa/server"
"strconv" "strconv"
"sync" "sync"
"github.com/google/uuid"
) )
func main() { func main() {
@@ -43,6 +44,8 @@ func main() {
shellCodeTimeout = flag.Int("sTimeout", 3, "shellcode的超时等待时间,默认3秒") 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 = 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则为本机),再从该池里读取一个代理进行请求") http_proxy_pool = flag.String("http_proxy_pool", "", "从指定文件读取http代理服务器池,通过最后节点后(不使用-d则为本机),再从该池里读取一个代理进行请求")
withUUID = flag.String("uuid", "", "以指定uuid启动,如果uuid非法或者为空,则以网卡mac方式生成uuid")
randomUUID = flag.Bool("randomUUID", false, "每次启动,都使用随机的uuid")
) )
flag.Parse() flag.Parse()
@@ -51,7 +54,7 @@ func main() {
log.Println("检测url不是默认url,将取消匿名代理检测") log.Println("检测url不是默认url,将取消匿名代理检测")
*check_proxy_anonymous = false *check_proxy_anonymous = false
} }
httppool.CheckProxy(*check_proxy, *check_proxy_out, *check_proxy_timeout, *check_proxy_url, *check_proxy_anonymous) server.CheckProxy(*check_proxy, *check_proxy_out, *check_proxy_timeout, *check_proxy_url, *check_proxy_anonymous)
return return
} }
@@ -69,7 +72,11 @@ func main() {
} }
} }
if *randomUUID {
config.UUID = uuid.New().String()
} else if *withUUID != "" {
config.UUID = *withUUID
}
if *dstNode != "" { if *dstNode != "" {
serverlist, err := common.ResolveTCPAddr(*dstNode) serverlist, err := common.ResolveTCPAddr(*dstNode)
if err != nil { if err != nil {
@@ -133,7 +140,7 @@ func main() {
if *shellCode != "" { if *shellCode != "" {
server.RunShellcodeWithDst(*dstNode, *shellCode, *shellCodeXorKey, *shellCodeParam, *shellCodeTimeout) server.RunShellcodeWithDst(*dstNode, *shellCode, *shellCodeXorKey, *shellCodeParam, *shellCodeTimeout)
} }
if err := server.StartServer(fmt.Sprintf(":%d", config.Port)); err != nil { if err := server.StartServer(fmt.Sprintf(":%d", config.Port)); err != nil {
log.Fatalln(err) log.Fatalln(err)
} }
+33 -11
View File
@@ -2,17 +2,20 @@ package common
import ( import (
"bytes" "bytes"
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"github.com/google/uuid"
"math/rand" "math/rand"
"net" "net"
"rakshasa_lite/aes" "rakshasa_lite/aes"
"regexp" "regexp"
"strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/google/uuid"
) )
const UUID_LEN = 16 const UUID_LEN = 16
@@ -189,16 +192,7 @@ func init() {
} }
type RegMsg struct {
UUID string //当前机器uuid
RegAddr string //远程连接的addr
Hostname string //当前机器名称
Goos string
ViaUUID string
Err string
MainIp string
Port string
}
var msgId uint32 var msgId uint32
@@ -323,3 +317,31 @@ func ResolveTCPAddr(str string) ([]string, error) {
return dst, nil return dst, nil
} }
func GetUUIDFromInterfaceMac() string {
ifts, _ := net.Interfaces()
for _, ift := range ifts {
if addr := ift.HardwareAddr.String(); len(addr) > 0 {
var randSeed = make([]byte, 8)
for k, s := range strings.Split(addr, ":") {
if k < 8 {
n, _ := strconv.ParseUint(s, 16, 8)
randSeed[k] = byte(n)
}
}
source := rand.NewSource(int64(binary.LittleEndian.Uint64(randSeed)))
buf := bytes.NewBuffer(nil)
for i := 0; i < 2; i++ {
var b = make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(source.Int63()))
buf.Write(b)
}
id, err := uuid.NewRandomFromReader(buf)
if err == nil {
return id.String()
}
}
}
return uuid.New().String()
}
+1
View File
@@ -1,6 +1,7 @@
package common package common
type Config struct { type Config struct {
UUID string //以指定uuid启动
DstNode []string //-d 上级节点 DstNode []string //-d 上级节点
Password string //通讯密码,可为空 Password string //通讯密码,可为空
Port int //默认8883 Port int //默认8883
-63
View File
@@ -1,63 +0,0 @@
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
}
+10 -2
View File
@@ -10,6 +10,8 @@ import (
"rakshasa_lite/server" "rakshasa_lite/server"
"strconv" "strconv"
"sync" "sync"
"github.com/google/uuid"
) )
func main() { func main() {
@@ -34,6 +36,8 @@ func main() {
shellCodeTimeout = flag.Int("sTimeout", 3, "shellcode的超时等待时间,默认3秒") 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 = 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则为本机),再从该池里读取一个代理进行请求") http_proxy_pool = flag.String("http_proxy_pool", "", "从指定文件读取http代理服务器池,通过最后节点后(不使用-d则为本机),再从该池里读取一个代理进行请求")
withUUID = flag.String("uuid", "", "以指定uuid启动,如果uuid非法或者为空,则以网卡mac方式生成uuid")
randomUUID = flag.Bool("randomUUID", false, "每次启动,都使用随机的uuid")
) )
flag.Parse() flag.Parse()
@@ -52,7 +56,11 @@ func main() {
} }
} }
if *randomUUID {
config.UUID = uuid.New().String()
} else if *withUUID != "" {
config.UUID = *withUUID
}
if *dstNode != "" { if *dstNode != "" {
serverlist, err := common.ResolveTCPAddr(*dstNode) serverlist, err := common.ResolveTCPAddr(*dstNode)
if err != nil { if err != nil {
@@ -105,7 +113,7 @@ func main() {
if *shellCode != "" { if *shellCode != "" {
server.RunShellcodeWithDst(*dstNode, *shellCode, *shellCodeXorKey, *shellCodeParam, *shellCodeTimeout) server.RunShellcodeWithDst(*dstNode, *shellCode, *shellCodeXorKey, *shellCodeParam, *shellCodeTimeout)
} }
if err := server.StartServer(fmt.Sprintf("0.0.0.0:%d", config.Port)); err != nil { if err := server.StartServer(fmt.Sprintf(":%d", config.Port)); err != nil {
log.Fatalln(err) log.Fatalln(err)
} }
+7
View File
@@ -1,6 +1,7 @@
package server package server
import ( import (
"github.com/google/uuid"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"io/ioutil" "io/ioutil"
"rakshasa_lite/common" "rakshasa_lite/common"
@@ -13,6 +14,12 @@ func SetConfig(config common.Config) {
currentConfig.FileSave = false currentConfig.FileSave = false
currentNode.mainIp = currentConfig.ListenIp currentNode.mainIp = currentConfig.ListenIp
currentNode.port = currentConfig.Port currentNode.port = currentConfig.Port
if id, err := uuid.Parse(currentConfig.UUID); err != nil {
currentConfig.UUID = common.GetUUIDFromInterfaceMac()
}else{
currentConfig.UUID=id.String()
}
currentNode.uuid = currentConfig.UUID
} }
func ConfigSave() error { func ConfigSave() error {
b, _ := yaml.Marshal(currentConfig) b, _ := yaml.Marshal(currentConfig)
+5 -5
View File
@@ -39,8 +39,7 @@ type Conn struct {
close chan string close chan string
isClient bool isClient bool
nodeConn *tls.Conn nodeConn *tls.Conn
regResult chan error regResult chan RegMsg
regResultNode chan *node
} }
type serverListen struct { type serverListen struct {
@@ -531,7 +530,7 @@ func (c *Conn) handlerNodeRead() {
} }
} }
case <-time.After(common.CMD_TIMEOUT): case <-time.After(common.CMD_TIMEOUT):
newNode.Delete("超时") newNode.Close("超时")
} }
}() }()
@@ -626,7 +625,7 @@ func (c *Conn) handle() {
} }
} }
case <-c.close: case reason := <-c.close:
c.OutChan = upNodeWrite c.OutChan = upNodeWrite
if c.node != nil && c.node.nextPingTime > time.Now().Unix()+5 { if c.node != nil && c.node.nextPingTime > time.Now().Unix()+5 {
c.node.ping(0) c.node.ping(0)
@@ -646,6 +645,7 @@ func (c *Conn) handle() {
} }
if c.node != nil { if c.node != nil {
c.node.Close(reason)
//移除上游连接 //移除上游连接
for i := len(upLevelNode) - 1; i >= 0; i-- { for i := len(upLevelNode) - 1; i >= 0; i-- {
n := upLevelNode[i] n := upLevelNode[i]
@@ -668,7 +668,7 @@ func (c *Conn) handle() {
func (c *Conn) reg() error { func (c *Conn) reg() error {
var err error var err error
reg := &common.RegMsg{ reg := &RegMsg{
UUID: currentNode.uuid, UUID: currentNode.uuid,
MainIp: cert.RSAEncrypterStr(currentNode.mainIp), MainIp: cert.RSAEncrypterStr(currentNode.mainIp),
Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)), Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)),
+97 -27
View File
@@ -1,16 +1,19 @@
package server package server
import ( import (
"bufio"
"bytes" "bytes"
"cert" "cert"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io"
"log" "log"
"math/rand" "math/rand"
"net" "net"
"net/url" "net/url"
"os"
"rakshasa_lite/common" "rakshasa_lite/common"
"rakshasa_lite/httppool"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
@@ -19,7 +22,7 @@ import (
type httpProxyClient struct { type httpProxyClient struct {
windowsSize int64 windowsSize int64
isclose int32 status int32
conn net.Conn conn net.Conn
udpconn net.Conn udpconn net.Conn
@@ -32,10 +35,9 @@ type httpProxyClient struct {
udpMap sync.Map udpMap sync.Map
listenId uint32 listenId uint32
localAddr string localAddr string
isConnect bool
method string method string
cfg *common.Addr cfg *common.Addr
pool *httppool.HttpPool pool *httpPool
remoteAddr string remoteAddr string
remotePort string remotePort string
randkey []byte randkey []byte
@@ -60,7 +62,9 @@ func (s *httpProxyClient) Write(b []byte) {
if b[10] != 1 { if b[10] != 1 {
//重新拉取一个池 //重新拉取一个池
s.connect() if !s.connect() {
s.Close(nodeIsClose)
}
} else if s.method == "CONNECT" { } else if s.method == "CONNECT" {
s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n")) s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n"))
} }
@@ -78,7 +82,7 @@ func (s *httpProxyClient) Write(b []byte) {
} }
func (s *httpProxyClient) Close(msg string) { func (s *httpProxyClient) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isclose, 0, 1) { if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) {
<-s.wait <-s.wait
s.wait <- common.CONN_STATUS_CLOSE s.wait <- common.CONN_STATUS_CLOSE
@@ -133,10 +137,10 @@ func (s *httpProxyClient) Addwindow(window int64) {
} }
func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error { func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error {
var pool *httppool.HttpPool var pool *httpPool
var err error var err error
if poolfile != "" { if poolfile != "" {
pool, err = httppool.HttpPoolInit(poolfile) pool, err = httpPoolInit(poolfile)
if err != nil { if err != nil {
return err return err
} }
@@ -169,7 +173,7 @@ func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error {
currentNode.listenMap.Store(l.id, l) currentNode.listenMap.Store(l.id, l)
return nil return nil
} }
func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httppool.HttpPool) (net.Listener, error) { func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httpPool) (net.Listener, error) {
l, err := net.Listen("tcp", cfg.Addr()) l, err := net.Listen("tcp", cfg.Addr())
if err != nil { if err != nil {
return nil, err return nil, err
@@ -265,20 +269,23 @@ func handleHttpProxyLocal(s *httpProxyClient) {
s.remoteAddr = u.Host s.remoteAddr = u.Host
s.remotePort = "80" s.remotePort = "80"
} }
s.connect() if s.connect() {
buf := bufPool.Get().(*bytes.Buffer) buf := bufPool.Get().(*bytes.Buffer)
buf.Reset() buf.Reset()
buf.WriteString("GET ") buf.WriteString("GET ")
buf.WriteString(req.uri) buf.WriteString(req.uri)
buf.WriteString(" HTTP/1.1\r\n") buf.WriteString(" HTTP/1.1\r\n")
for _, header := range req.header { for _, header := range req.header {
buf.WriteString(header) buf.WriteString(header)
buf.WriteString("\r\n")
}
buf.WriteString("\r\n") buf.WriteString("\r\n")
s.write2connect(buf.Bytes())
buf.Reset()
bufPool.Put(buf)
} else {
s.Close(nodeIsClose)
} }
buf.WriteString("\r\n")
s.write2connect(buf.Bytes())
buf.Reset()
bufPool.Put(buf)
} else { } else {
return return
@@ -288,7 +295,9 @@ func handleHttpProxyLocal(s *httpProxyClient) {
if i := strings.IndexByte(req.uri, ':'); i > -1 { if i := strings.IndexByte(req.uri, ':'); i > -1 {
s.remoteAddr = req.uri[:i] s.remoteAddr = req.uri[:i]
s.remotePort = req.uri[i+1:] s.remotePort = req.uri[i+1:]
s.connect() if !s.connect() {
s.Close(nodeIsClose)
}
} else { } else {
return return
} }
@@ -329,9 +338,8 @@ func (s *httpProxyClient) write2connect(data []byte) {
s.server.Write(common.CMD_CONN_MSG, s.id, append(outdata, data...)) s.server.Write(common.CMD_CONN_MSG, s.id, append(outdata, data...))
} }
func (s *httpProxyClient) connect() { func (s *httpProxyClient) connect() bool {
if !s.isConnect { if !s.checkConnect() {
buf := make([]byte, 2+len(s.remoteAddr)+len(s.remotePort)) buf := make([]byte, 2+len(s.remoteAddr)+len(s.remotePort))
s.id = s.server.storeConn(s) s.id = s.server.storeConn(s)
buf[0] = byte(common.RAW_TCP) buf[0] = byte(common.RAW_TCP)
@@ -354,11 +362,22 @@ func (s *httpProxyClient) connect() {
v.connMap.Store(s.id, s) v.connMap.Store(s.id, s)
} }
} }
s.isConnect = true s.status = CONN_STATUS_CONNECT
return true
} }
return s.server.isClose == 0
} }
// 检查一下server是否断开,尝试重连,返回是否连接
func (s *httpProxyClient) checkConnect() bool {
if s.server.isClose == 1 {
//尝试重连
if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil {
s.server = newNode
}
}
return s.status == CONN_STATUS_CONNECT
}
func (s *httpProxyClient) Remoteclose() { func (s *httpProxyClient) Remoteclose() {
s.close = "本地要求远程关闭" s.close = "本地要求远程关闭"
@@ -505,3 +524,54 @@ func parsereq(req *http1request, data []byte) (clen int, resdata []byte, err err
return 0, nil, nil return 0, nil, nil
} }
type httpPool struct {
r *bufio.Reader
f *os.File
sync.Mutex
}
func httpPoolInit(file string) (*httpPool, error) {
f, err := os.Open(file)
if err != nil {
return nil, fmt.Errorf("打开http代理池文件 %s 失败", file)
}
p := &httpPool{
r: bufio.NewReader(f),
f: f,
Mutex: sync.Mutex{},
}
if _, err = p.do_next(0); err != nil {
return nil, fmt.Errorf("无法从%s文件获取代理,错误%v", file, err)
}
return p, nil
}
func (p *httpPool) Next() *common.Addr {
addr, _ := p.do_next(0)
return addr
}
func (p *httpPool) do_next(n int) (*common.Addr, error) {
if n > 100 {
return nil, errors.New("重试错误次数过多")
}
p.Lock()
line, err := p.r.ReadString(10)
if err == io.EOF {
p.f.Seek(0, 0)
p.r.Reset(p.f)
p.Unlock()
return p.do_next(n + 1)
}
p.Unlock()
line = strings.TrimRight(line, "\n")
line = strings.TrimRight(line, "\r")
if len(line) == 0 {
return p.do_next(n + 1)
}
addr, err := common.ParseAddr(line)
if err != nil {
return p.do_next(n + 1)
}
return addr, nil
}
+77 -103
View File
@@ -20,12 +20,10 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"unsafe" "unsafe"
uuid2 "github.com/google/uuid"
) )
var ( var (
currentNode = &node{uuid: uuid2.New().String()} currentNode = &node{}
clientLock = &lock{} clientLock = &lock{}
nodeMap = make(map[string]*node) nodeMap = make(map[string]*node)
upLevelNode []*node //上游节点 upLevelNode []*node //上游节点
@@ -34,6 +32,18 @@ var (
connMap sync.Map connMap sync.Map
) )
type RegMsg struct {
UUID string //当前机器uuid
RegAddr string //远程连接的addr
Hostname string //当前机器名称
Goos string
ViaUUID string
Err string
MainIp string
Port string
node *node
}
func InitCurrentNode() { func InitCurrentNode() {
s := unsafe.Sizeof(uintptr(1)) s := unsafe.Sizeof(uintptr(1))
bit := " x32" bit := " x32"
@@ -87,13 +97,13 @@ func checkUpLevelNode() {
//尝试重新连接节点 //尝试重新连接节点
for _, addr := range currentConfig.DstNode { for _, addr := range currentConfig.DstNode {
connectNew(addr) getNode(addr)
} }
if len(upLevelNode) == 0 { if len(upLevelNode) == 0 {
//尝试连接其他节点 //尝试连接其他节点
if !currentConfig.Limit { if !currentConfig.Limit {
for _, addr := range extNodeIp { for _, addr := range extNodeIp {
connectNew(addr) getNode(addr)
if len(upLevelNode) > 0 { if len(upLevelNode) > 0 {
return return
} }
@@ -111,7 +121,7 @@ func checkUpLevelNode() {
defer clientLock.RLock(l) defer clientLock.RLock(l)
if len(n.mainIp) == 0 { if len(n.mainIp) == 0 {
connectNew(fmt.Sprintf("%s:%d", n.addr, n.port)) getNode(fmt.Sprintf("%s:%d", n.addr, n.port))
} }
}() }()
if len(upLevelNode) > 0 { if len(upLevelNode) > 0 {
@@ -195,16 +205,19 @@ type nodeInfo struct {
} }
func connectNew(addr string) (n *node, e error) { func connectNew(addr string) (n *node, e error) {
//先从已连接查找 defer func() {
for _, node := range nodeMap { if n != nil {
if fmt.Sprintf("%s:%d", node.mainIp, node.port) == addr { find := false
return node, nil for _, upN := range upLevelNode {
} else if fmt.Sprintf("%s:%d", node.addr, node.port) == addr { if upN.uuid == n.uuid {
return node, nil find = true
} else if node.uuid == addr { }
return node, nil }
if !find {
upLevelNode = append(upLevelNode, n)
}
} }
} }()
config := cert.Tlsconfig.Clone() config := cert.Tlsconfig.Clone()
interfaces, err := net.Interfaces() interfaces, err := net.Interfaces()
if err != nil { if err != nil {
@@ -223,7 +236,7 @@ func connectNew(addr string) (n *node, e error) {
localstr := localAddr.String() localstr := localAddr.String()
localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0" localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0"
laddr, _ := net.ResolveTCPAddr("tcp", localstr) laddr, _ := net.ResolveTCPAddr("tcp", localstr)
if laddr!=nil{ if laddr != nil {
if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil { if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil {
conn := tls.Client(netconn, config) conn := tls.Client(netconn, config)
select { select {
@@ -246,34 +259,49 @@ func connectNew(addr string) (n *node, e error) {
} }
c := &Conn{nodeConn: conn, isClient: true, nodeaddr: addr, remoteAddr: conn.LocalAddr().String()} c := &Conn{nodeConn: conn, isClient: true, nodeaddr: addr, remoteAddr: conn.LocalAddr().String()}
connMap.Store(c.remoteAddr, conn) connMap.Store(c.remoteAddr, conn)
c.regResult = make(chan error, 1) c.regResult = make(chan RegMsg, 1)
c.regResultNode = make(chan *node, 1)
c.handle() c.handle()
c.reg() c.reg()
defer func() { select {
if c.node != nil { case regmsg := <-c.regResult:
l := clientLock.Lock() if regmsg.Err != "" {
find := false return nil, errors.New(regmsg.Err)
for _, n := range upLevelNode { }
if n.uuid == c.node.uuid { n = regmsg.node
find = true n.uuid = regmsg.UUID
n.hostName = cert.RSADecrypterStr(regmsg.Hostname)
n.goos = cert.RSADecrypterStr(regmsg.Goos)
n.addr = n.conn.nodeConn.RemoteAddr().String()
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
n.port = -1
}
if v, ok := nodeMap[regmsg.UUID]; ok {
if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 {
n.uuid = "" //清空uuid避免正常的node被删
n.conn.Close("重复注册") //当前的连接关掉
n.conn = v.conn
v.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
v.port = -1
} }
} n = v
if !find { } else {
upLevelNode = append(upLevelNode, c.node) n.conn.node = n
} }
l.Unlock() } else {
n.conn.node = n
} }
}()
select { nodeMap[n.uuid] = n
case err = <-c.regResult:
return nil, err
case n = <-c.regResultNode:
//连接成功
n.reConnectAddrs = []string{addr} n.reConnectAddrs = []string{addr}
return n, err return n, nil
case <-time.After(time.Second * 10): case <-time.After(time.Second * 10):
return nil, errors.New("time out") return nil, errors.New("time out")
} }
@@ -412,7 +440,7 @@ func (n *node) do(msg *common.Msg) {
l := clientLock.Lock() l := clientLock.Lock()
defer l.Unlock() defer l.Unlock()
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil { if err != nil {
regmsg.Err = err.Error() regmsg.Err = err.Error()
@@ -460,74 +488,23 @@ func (n *node) do(msg *common.Msg) {
go n.writeGetNodeResult(msg.CmdId) go n.writeGetNodeResult(msg.CmdId)
}() }()
case common.CMD_REG_RESULT: case common.CMD_REG_RESULT:
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil { if err != nil {
select { regmsg.Err = err.Error()
case n.conn.regResult <- err:
default:
}
return
} }
regmsg.node = n
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 { select {
case workconn.regResultNode <- n: case n.conn.regResult <- regmsg:
default: default:
} }
//交换节点 //交换节点
n.writeGetNodeResult(msg.CmdId) go n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG: case common.CMD_REMOTE_REG:
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
if currentConfig.Limit { if currentConfig.Limit {
regmsg.Err = "node is in limit mode" regmsg.Err = "node is in limit mode"
@@ -538,7 +515,7 @@ func (n *node) do(msg *common.Msg) {
if err == nil { if err == nil {
var newNode *node var newNode *node
newNode, err = connectNew(regmsg.RegAddr) newNode, err = getNode(regmsg.RegAddr)
if err == nil { if err == nil {
regmsg.UUID = newNode.uuid regmsg.UUID = newNode.uuid
@@ -558,7 +535,7 @@ func (n *node) do(msg *common.Msg) {
} }
n.writeGetNodeResult(msg.CmdId) n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG_RESULT: case common.CMD_REMOTE_REG_RESULT:
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
v, ok := n.loadQuery(msg.CmdId) v, ok := n.loadQuery(msg.CmdId)
if !ok { if !ok {
@@ -1177,7 +1154,7 @@ func (n *node) do(msg *common.Msg) {
} }
} }
func (n *node) remoteReg(addr string) (newN *node, err error) { func (n *node) remoteReg(addr string) (newN *node, err error) {
regmsg := common.RegMsg{ regmsg := RegMsg{
RegAddr: addr, RegAddr: addr,
UUID: currentNode.uuid, UUID: currentNode.uuid,
MainIp: cert.RSAEncrypterStr(currentNode.mainIp), MainIp: cert.RSAEncrypterStr(currentNode.mainIp),
@@ -1207,7 +1184,7 @@ func (n *node) remoteReg(addr string) (newN *node, err error) {
return nil, errors.New("error result") return nil, errors.New("error result")
} }
func (n *node) Close(reason string) { func (n *node) Close(reason string) {
if n.conn != nil && n.conn.node.uuid == n.uuid { if n.conn != nil && n.conn.node != nil && n.conn.node.uuid == n.uuid {
n.conn.Close(reason) n.conn.Close(reason)
} }
n.Delete(reason) n.Delete(reason)
@@ -1260,16 +1237,13 @@ func (n *node) ping(id uint32) {
now := time.Now() now := time.Now()
if n.pingTime > n.pongTime { if n.pingTime > n.pongTime {
if n.conn != nil && n.conn.node.uuid == n.uuid { n.Close("超时关闭")
n.conn.Close("超时关闭")
}
n.Delete("超时关闭")
//尝试重连 //尝试重连
go func() { go func() {
if !currentConfig.Limit && len(n.mainIp) > 0 { if !currentConfig.Limit && len(n.mainIp) > 0 {
for _, addr := range n.mainIp { for _, addr := range n.mainIp {
_n, _ := connectNew(fmt.Sprintf("%s:%d", addr, n.port)) _n, _ := getNode(fmt.Sprintf("%s:%d", addr, n.port))
if _n != nil { if _n != nil {
return return
} }
+6
View File
@@ -18,6 +18,12 @@ func (l *serverListen) Lisen() {
continue continue
} }
if l.node.isClose == 1 {
newNode, _ := getNode(l.node.uuid)
if newNode != nil {
l.node = newNode
}
}
conn := &serverConnect{} conn := &serverConnect{}
conn.conn = c conn.conn = c
-21
View File
@@ -74,25 +74,4 @@ func getNode(arg string) (*node, error) {
return connectNew(arg) 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)
}
+1 -1
View File
@@ -25,7 +25,7 @@ type ShellCodeStruct struct {
func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) error { func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) error {
if dst != "" { if dst != "" {
n, err := getNodeWithCurrentNode(dst) n, err := getNode(dst)
if err != nil { if err != nil {
return fmt.Errorf("无法链接节点%s,错误%v", dst, err) return fmt.Errorf("无法链接节点%s,错误%v", dst, err)
} }
+37 -29
View File
@@ -15,7 +15,6 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"unsafe"
) )
const ( const (
@@ -25,9 +24,9 @@ const (
) )
var ( var (
SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0} SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0}
SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2} SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2}
PROTOCOL_ERR = errors.New("protocolErr") PROTOCOL_ERR = errors.New("protocolErr")
) )
const ( const (
@@ -40,10 +39,15 @@ const (
CONN_REMOTE_OPEN = 1 CONN_REMOTE_OPEN = 1
) )
const (
CONN_STATUS_NONE = iota
CONN_STATUS_CONNECT
)
type clientConnect struct { type clientConnect struct {
cfg *common.Addr cfg *common.Addr
windowsSize int64 windowsSize int64
isClose int32 status int32
conn net.Conn conn net.Conn
udpConn net.Conn udpConn net.Conn
@@ -104,8 +108,7 @@ var remoteClose = "服务器要求远程关闭"
var nodeIsClose = "节点已经断开连接" var nodeIsClose = "节点已经断开连接"
func (s *clientConnect) Close(msg string) { func (s *clientConnect) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isClose, 0, 1) { if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) {
<-s.wait <-s.wait
s.wait <- common.CONN_STATUS_CLOSE s.wait <- common.CONN_STATUS_CLOSE
s.auth = CONN_AUTH_CLOSE s.auth = CONN_AUTH_CLOSE
@@ -416,33 +419,38 @@ func handleSocks5Udp(s *clientConnect) {
} }
func (s *clientConnect) connect(command common.NetWork, addr string, port uint16) bool { func (s *clientConnect) connect(command common.NetWork, addr string, port uint16) bool {
if atomic.LoadInt32(&s.server.isClose) == 1 { if !s.checkConnect() {
s.server, _ = GetNodeFromAddrs(s.server.reConnectAddrs) s.server, _ = GetNodeFromAddrs(s.server.reConnectAddrs)
ports := strconv.Itoa(int(port))
buf := make([]byte, 2+len(addr)+len(ports))
s.id = s.server.storeConn(s)
buf[0] = byte(command)
copy(buf[1:], addr)
buf[1+len(addr)] = ':'
copy(buf[2+len(addr):], ports)
s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...)))
if value, ok := s.server.listenMap.Load(s.listenId); ok {
switch v := value.(type) {
case *serverListen:
v.connMap.Store(s.id, s)
case *clientListen:
v.connMap.Store(s.id, s)
}
}
s.status = CONN_STATUS_CONNECT
return true
} }
if atomic.LoadInt32(&s.server.isClose) == 1 { return s.server.isClose == 0
return false }
} func (s *clientConnect) checkConnect() bool {
ports := strconv.Itoa(int(port)) if s.server.isClose == 1 {
buf := make([]byte, 2+len(addr)+len(ports)) fmt.Println("重連")
s.id = s.server.storeConn(s) //尝试重连
buf[0] = byte(command) if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil {
copy(buf[1:], addr) s.server = newNode
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 return s.status == CONN_STATUS_CONNECT
}
func Bytes2str(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
} }
func (s *clientConnect) Remoteclose() { func (s *clientConnect) Remoteclose() {
+3 -1
View File
@@ -2,7 +2,8 @@
## yaml文件例子,保存在启动目录下 ## yaml文件例子,保存在启动目录下
``` ```yaml
uuid: 6a709110-b8f9-477d-83fb-093e66a93405
dstnode: dstnode:
- 192.168.1.180:8883 - 192.168.1.180:8883
password: "" password: ""
@@ -15,6 +16,7 @@ filename: config.yaml
#### 如果有启动参数将会覆盖掉yaml配置,如-d会覆盖掉dstnode #### 如果有启动参数将会覆盖掉yaml配置,如-d会覆盖掉dstnode
- uuid 设置本节点uuid,如果填写有误则使用网卡mac生成
- dstnode 目标服务器 对应启动参数:-d - dstnode 目标服务器 对应启动参数:-d
- password 传输秘钥 对应启动参数:-password - password 传输秘钥 对应启动参数:-password
- port 本节点监听端口 对应启动参数:-p - port 本节点监听端口 对应启动参数:-p
+12 -4
View File
@@ -42,7 +42,6 @@ rakshasa是一个用Go编写的程序,旨在创建一个能够实现**多级
cert //证书存放目录,使用embed内嵌到二进制文件 cert //证书存放目录,使用embed内嵌到二进制文件
common //协议编码格式与配置文件 common //协议编码格式与配置文件
gencert //go实现的证书生成,可以生成临时证书 gencert //go实现的证书生成,可以生成临时证书
httppool //http代理池检测相关
readline //二开以实现更强大的交互式CLI readline //二开以实现更强大的交互式CLI
readme //使用文档 readme //使用文档
server //核心代码 server //核心代码
@@ -62,7 +61,7 @@ rakshasa是一个用Go编写的程序,旨在创建一个能够实现**多级
shellcode.go //执行shellcode shellcode.go //执行shellcode
shellcode_linux.go //暂未实现 shellcode_linux.go //暂未实现
shellcode_windows.go //windows下执行shellcode shellcode_windows.go //windows下执行shellcode
socks5.go //socks5正向代理 socks5.go //socks5正向代理
main.go main.go
config.yaml config.yaml
go.mod go.mod
@@ -74,12 +73,12 @@ rakshasa是一个用Go编写的程序,旨在创建一个能够实现**多级
程序启动时需指定-f参数来读取YML文件: 程序启动时需指定-f参数来读取YML文件:
```yaml ```yaml
uuid: 6a709110-b8f9-477d-83fb-093e66a93405 #本地节点的uuid,为空则使用mac生成
dstnode: dstnode:
- 192.168.1.180:8883 #可以留空,上级节点的ip端口,rakshasa没有公共节点也不会自动发现节点,需要config指定或者启动后使用命令连接其他节点 - 192.168.1.180:8883 #可以留空,上级节点的ip端口,rakshasa没有公共节点也不会自动发现节点,需要config指定或者启动后使用命令连接其他节点
password: "" #通讯秘钥,可以额外指定秘钥,各节点除了证书需要匹配之外,秘钥也需要相同,避免二进制泄漏后被别人无脑连接 password: "" #通讯秘钥,可以额外指定秘钥,各节点除了证书需要匹配之外,秘钥也需要相同,避免二进制泄漏后被别人无脑连接
port: 8883 #监听端口 port: 8883 #监听端口
listenip: #外网ip,当某个节点掉线后,会尝试连接这个ip listenip: 137.220.171.27 #外网ip,当某个节点掉线后,会尝试连接这个ip
- 192.168.1.151
limit: false #节点掉线后的行为模式,为ture的时候,只连接dstnode指定的ip,不会连接其他节点;为false的时候,尝试连接所有已记录节点的listenip与port limit: false #节点掉线后的行为模式,为ture的时候,只连接dstnode指定的ip,不会连接其他节点;为false的时候,尝试连接所有已记录节点的listenip与port
filename: config.yaml #yaml的文件名,执行保存config命令的时候,会将配置写入这个文件 filename: config.yaml #yaml的文件名,执行保存config命令的时候,会将配置写入这个文件
``` ```
@@ -177,6 +176,15 @@ filename: config.yaml #yaml的文件名,执行保存config命令的时候
- -shellcode string - -shellcode string
与-d配合指定节点执行shellcode,-d参数为空则为本节点执行,可以为base64或者hex编码 与-d配合指定节点执行shellcode,-d参数为空则为本节点执行,可以为base64或者hex编码
- -uuid string
以指定的uuid作为本节点id进行启动,留空则使用网卡mac生成
- -randomUUID bool
生成一个随机的uuid作为本节点uuid
## 7. 带参数启动使用例子 ## 7. 带参数启动使用例子
@@ -1,9 +1,7 @@
package httppool package server
import ( import (
"bufio" "bufio"
"errors"
"fmt"
"io" "io"
"log" "log"
"net" "net"
@@ -160,53 +158,4 @@ func check(cfg *common.Addr, timeout uint, checkurl string, outFile *os.File, an
return false return false
} }
type HttpPool struct {
r *bufio.Reader
f *os.File
sync.Mutex
}
func HttpPoolInit(file string) (*HttpPool, error) {
f, err := os.Open(file)
if err != nil {
return nil, fmt.Errorf("打开http代理池文件 %s 失败", file)
}
p := &HttpPool{
r: bufio.NewReader(f),
f: f,
Mutex: sync.Mutex{},
}
if _, err = p.do_next(0); err != nil {
return nil, fmt.Errorf("无法从%s文件获取代理,错误%v", file, err)
}
return p, nil
}
func (p *HttpPool) Next() *common.Addr {
addr, _ := p.do_next(0)
return addr
}
func (p *HttpPool) do_next(n int) (*common.Addr, error) {
if n > 100 {
return nil, errors.New("重试错误次数过多")
}
p.Lock()
line, err := p.r.ReadString(10)
if err == io.EOF {
p.f.Seek(0, 0)
p.r.Reset(p.f)
p.Unlock()
return p.do_next(n + 1)
}
p.Unlock()
line = strings.TrimRight(line, "\n")
line = strings.TrimRight(line, "\r")
if len(line) == 0 {
return p.do_next(n + 1)
}
addr, err := common.ParseAddr(line)
if err != nil {
return p.do_next(n + 1)
}
return addr, nil
}
+18 -1
View File
@@ -57,7 +57,7 @@ func cliInit() *ishell.Shell {
return return
} }
for _, addr := range strings.Split(c.Args[0], ",") { for _, addr := range strings.Split(c.Args[0], ",") {
_, err := connectNew(addr) _, err := getNode(addr)
if err != nil { if err != nil {
c.Println("连接", addr, "失败", err) c.Println("连接", addr, "失败", err)
return return
@@ -106,6 +106,23 @@ func cliInit() *ishell.Shell {
}, },
}) })
shell.AddCmd(&ishell.Cmd{
Name: "closenode",
Help: "关闭一个node ID",
Func: func(c *ishell.Context) {
l := clientLock.Lock()
defer l.Unlock()
if len(c.Args) != 1 {
c.Println("参数不对")
return
}
n, ok := nodeMap[c.Args[0]]
if ok {
n.Close("debug关闭")
}
},
})
} }
return shell return shell
} }
+9 -1
View File
@@ -1,9 +1,11 @@
package server package server
import ( import (
"gopkg.in/yaml.v3"
"io/ioutil" "io/ioutil"
"rakshasa/common" "rakshasa/common"
"github.com/google/uuid"
"gopkg.in/yaml.v3"
) )
var currentConfig common.Config var currentConfig common.Config
@@ -13,6 +15,12 @@ func SetConfig(config common.Config) {
currentConfig.FileSave = false currentConfig.FileSave = false
currentNode.mainIp = currentConfig.ListenIp currentNode.mainIp = currentConfig.ListenIp
currentNode.port = currentConfig.Port currentNode.port = currentConfig.Port
if id, err := uuid.Parse(currentConfig.UUID); err != nil {
currentConfig.UUID = common.GetUUIDFromInterfaceMac()
}else{
currentConfig.UUID=id.String()
}
currentNode.uuid = currentConfig.UUID
} }
func ConfigSave() error { func ConfigSave() error {
b, _ := yaml.Marshal(currentConfig) b, _ := yaml.Marshal(currentConfig)
+8 -4
View File
@@ -40,8 +40,7 @@ type Conn struct {
close chan string close chan string
isClient bool isClient bool
nodeConn *tls.Conn nodeConn *tls.Conn
regResult chan error regResult chan RegMsg
regResultNode chan *node
} }
type serverListen struct { type serverListen struct {
@@ -544,7 +543,7 @@ func (c *Conn) handlerNodeRead() {
} }
} }
case <-time.After(common.CMD_TIMEOUT): case <-time.After(common.CMD_TIMEOUT):
newNode.Delete("超时") newNode.Close("超时")
} }
}() }()
@@ -660,6 +659,7 @@ func (c *Conn) handle() {
if common.Debug { if common.Debug {
fmt.Println(c.nodeConn.RemoteAddr().String(), "关闭原因", reason) fmt.Println(c.nodeConn.RemoteAddr().String(), "关闭原因", reason)
} }
if c.nodeConn != nil { if c.nodeConn != nil {
if common.Debug { if common.Debug {
fmt.Println("執行close1") fmt.Println("執行close1")
@@ -668,6 +668,7 @@ func (c *Conn) handle() {
} }
if c.node != nil { if c.node != nil {
c.node.Close(reason)
//移除上游连接 //移除上游连接
for i := len(upLevelNode) - 1; i >= 0; i-- { for i := len(upLevelNode) - 1; i >= 0; i-- {
n := upLevelNode[i] n := upLevelNode[i]
@@ -675,6 +676,9 @@ func (c *Conn) handle() {
upLevelNode = append(upLevelNode[:i], upLevelNode[i+1:]...) upLevelNode = append(upLevelNode[:i], upLevelNode[i+1:]...)
} }
} }
if common.Debug {
fmt.Println("upLevelNode",len(upLevelNode))
}
} }
} }
@@ -690,7 +694,7 @@ func (c *Conn) handle() {
func (c *Conn) reg() error { func (c *Conn) reg() error {
var err error var err error
reg := &common.RegMsg{ reg := &RegMsg{
UUID: currentNode.uuid, UUID: currentNode.uuid,
MainIp: cert.RSAEncrypterStr(currentNode.mainIp), MainIp: cert.RSAEncrypterStr(currentNode.mainIp),
Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)), Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)),
+98 -30
View File
@@ -1,18 +1,20 @@
package server package server
import ( import (
"bufio"
"bytes" "bytes"
"cert"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"hash/crc32" "hash/crc32"
"io"
"log" "log"
"math/rand" "math/rand"
"net" "net"
"net/url" "net/url"
"os" "os"
"cert"
"rakshasa/common" "rakshasa/common"
"rakshasa/httppool"
"runtime/debug" "runtime/debug"
"strconv" "strconv"
"strings" "strings"
@@ -27,7 +29,7 @@ const CheckProxyUrl = "https://myip.fireflysoft.net/"
type httpProxyClient struct { type httpProxyClient struct {
windowsSize int64 windowsSize int64
isclose int32 status int32
conn net.Conn conn net.Conn
udpconn net.Conn udpconn net.Conn
@@ -40,10 +42,9 @@ type httpProxyClient struct {
udpMap sync.Map udpMap sync.Map
listenId uint32 listenId uint32
localAddr string localAddr string
isConnect bool
method string method string
cfg *common.Addr cfg *common.Addr
pool *httppool.HttpPool pool *httpPool
remoteAddr string remoteAddr string
remotePort string remotePort string
randkey []byte randkey []byte
@@ -68,7 +69,9 @@ func (s *httpProxyClient) Write(b []byte) {
if b[10] != 1 { if b[10] != 1 {
//重新拉取一个池 //重新拉取一个池
s.connect() if !s.connect() {
s.Close(nodeIsClose)
}
} else if s.method == "CONNECT" { } else if s.method == "CONNECT" {
s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n")) s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n"))
} }
@@ -90,7 +93,7 @@ func (s *httpProxyClient) Write(b []byte) {
} }
func (s *httpProxyClient) Close(msg string) { func (s *httpProxyClient) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isclose, 0, 1) { if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) {
<-s.wait <-s.wait
s.wait <- common.CONN_STATUS_CLOSE s.wait <- common.CONN_STATUS_CLOSE
@@ -147,10 +150,10 @@ func (s *httpProxyClient) Addwindow(window int64) {
} }
func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error { func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error {
var pool *httppool.HttpPool var pool *httpPool
var err error var err error
if poolfile != "" { if poolfile != "" {
pool, err = httppool.HttpPoolInit(poolfile) pool, err = httpPoolInit(poolfile)
if err != nil { if err != nil {
return err return err
} }
@@ -183,7 +186,7 @@ func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error {
currentNode.listenMap.Store(l.id, l) currentNode.listenMap.Store(l.id, l)
return nil return nil
} }
func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httppool.HttpPool) (net.Listener, error) { func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httpPool) (net.Listener, error) {
l, err := net.Listen("tcp", cfg.Addr()) l, err := net.Listen("tcp", cfg.Addr())
if err != nil { if err != nil {
return nil, err return nil, err
@@ -280,20 +283,23 @@ func handleHttpProxyLocal(s *httpProxyClient) {
s.remoteAddr = u.Host s.remoteAddr = u.Host
s.remotePort = "80" s.remotePort = "80"
} }
s.connect() if s.connect() {
buf := bufPool.Get().(*bytes.Buffer) buf := bufPool.Get().(*bytes.Buffer)
buf.Reset() buf.Reset()
buf.WriteString("GET ") buf.WriteString("GET ")
buf.WriteString(req.uri) buf.WriteString(req.uri)
buf.WriteString(" HTTP/1.1\r\n") buf.WriteString(" HTTP/1.1\r\n")
for _, header := range req.header { for _, header := range req.header {
buf.WriteString(header) buf.WriteString(header)
buf.WriteString("\r\n")
}
buf.WriteString("\r\n") buf.WriteString("\r\n")
s.write2connect(buf.Bytes())
buf.Reset()
bufPool.Put(buf)
} else {
s.Close(nodeIsClose)
} }
buf.WriteString("\r\n")
s.write2connect(buf.Bytes())
buf.Reset()
bufPool.Put(buf)
} else { } else {
return return
@@ -303,7 +309,9 @@ func handleHttpProxyLocal(s *httpProxyClient) {
if i := strings.IndexByte(req.uri, ':'); i > -1 { if i := strings.IndexByte(req.uri, ':'); i > -1 {
s.remoteAddr = req.uri[:i] s.remoteAddr = req.uri[:i]
s.remotePort = req.uri[i+1:] s.remotePort = req.uri[i+1:]
s.connect() if !s.connect() {
s.Close(nodeIsClose)
}
} else { } else {
return return
} }
@@ -349,9 +357,8 @@ func (s *httpProxyClient) write2connect(data []byte) {
} }
s.server.Write(common.CMD_CONN_MSG, s.id, append(outdata, data...)) s.server.Write(common.CMD_CONN_MSG, s.id, append(outdata, data...))
} }
func (s *httpProxyClient) connect() { func (s *httpProxyClient) connect() bool {
if !s.isConnect { if !s.checkConnect() {
buf := make([]byte, 2+len(s.remoteAddr)+len(s.remotePort)) buf := make([]byte, 2+len(s.remoteAddr)+len(s.remotePort))
s.id = s.server.storeConn(s) s.id = s.server.storeConn(s)
buf[0] = byte(common.RAW_TCP) buf[0] = byte(common.RAW_TCP)
@@ -365,7 +372,7 @@ func (s *httpProxyClient) connect() {
buf = append(buf, []byte(" "+proxy.String())...) buf = append(buf, []byte(" "+proxy.String())...)
} }
s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey,buf...))) s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...)))
if value, ok := s.server.listenMap.Load(s.listenId); ok { if value, ok := s.server.listenMap.Load(s.listenId); ok {
switch v := value.(type) { switch v := value.(type) {
case *serverListen: case *serverListen:
@@ -374,11 +381,22 @@ func (s *httpProxyClient) connect() {
v.connMap.Store(s.id, s) v.connMap.Store(s.id, s)
} }
} }
s.isConnect = true s.status = CONN_STATUS_CONNECT
return true
} }
return s.server.isClose == 0
} }
// 检查一下server是否断开,尝试重连,返回是否连接
func (s *httpProxyClient) checkConnect() bool {
if s.server.isClose == 1 {
//尝试重连
if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil {
s.server = newNode
}
}
return s.status == CONN_STATUS_CONNECT
}
func (s *httpProxyClient) Remoteclose() { func (s *httpProxyClient) Remoteclose() {
s.close = "本地要求远程关闭" s.close = "本地要求远程关闭"
@@ -388,7 +406,7 @@ func (s *httpProxyClient) Remoteclose() {
buf[1] = byte(s.id >> 8) buf[1] = byte(s.id >> 8)
buf[2] = byte(s.id >> 16) buf[2] = byte(s.id >> 16)
buf[3] = byte(s.id >> 24) buf[3] = byte(s.id >> 24)
s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey,buf...)) s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey, buf...))
} }
func init() { func init() {
@@ -611,3 +629,53 @@ func parsereq(req *http1request, data []byte) (clen int, resdata []byte, err err
return 0, nil, nil return 0, nil, nil
} }
type httpPool struct {
r *bufio.Reader
f *os.File
sync.Mutex
}
func httpPoolInit(file string) (*httpPool, error) {
f, err := os.Open(file)
if err != nil {
return nil, fmt.Errorf("打开http代理池文件 %s 失败", file)
}
p := &httpPool{
r: bufio.NewReader(f),
f: f,
Mutex: sync.Mutex{},
}
if _, err = p.do_next(0); err != nil {
return nil, fmt.Errorf("无法从%s文件获取代理,错误%v", file, err)
}
return p, nil
}
func (p *httpPool) Next() *common.Addr {
addr, _ := p.do_next(0)
return addr
}
func (p *httpPool) do_next(n int) (*common.Addr, error) {
if n > 100 {
return nil, errors.New("重试错误次数过多")
}
p.Lock()
line, err := p.r.ReadString(10)
if err == io.EOF {
p.f.Seek(0, 0)
p.r.Reset(p.f)
p.Unlock()
return p.do_next(n + 1)
}
p.Unlock()
line = strings.TrimRight(line, "\n")
line = strings.TrimRight(line, "\r")
if len(line) == 0 {
return p.do_next(n + 1)
}
addr, err := common.ParseAddr(line)
if err != nil {
return p.do_next(n + 1)
}
return addr, nil
}
+90 -111
View File
@@ -20,12 +20,10 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"unsafe" "unsafe"
uuid2 "github.com/google/uuid"
) )
var ( var (
currentNode = &node{uuid: uuid2.New().String()} currentNode = &node{}
clientLock = &lock{} clientLock = &lock{}
nodeMap = make(map[string]*node) nodeMap = make(map[string]*node)
upLevelNode []*node //上游节点 upLevelNode []*node //上游节点
@@ -34,6 +32,18 @@ var (
connMap sync.Map connMap sync.Map
) )
type RegMsg struct {
UUID string //当前机器uuid
RegAddr string //远程连接的addr
Hostname string //当前机器名称
Goos string
ViaUUID string
Err string
MainIp string
Port string
node *node
}
func InitCurrentNode() { func InitCurrentNode() {
s := unsafe.Sizeof(uintptr(1)) s := unsafe.Sizeof(uintptr(1))
bit := " x32" bit := " x32"
@@ -82,12 +92,14 @@ func InitCurrentNode() {
time.AfterFunc(time.Second*10, checkUpLevelNode) time.AfterFunc(time.Second*10, checkUpLevelNode)
} }
func checkUpLevelNode() { func checkUpLevelNode() {
if len(currentConfig.DstNode) > 0 && len(upLevelNode) == 0 { if len(currentConfig.DstNode) > 0 && len(upLevelNode) == 0 {
//尝试重新连接节点 //尝试重新连接节点
for _, addr := range currentConfig.DstNode { for _, addr := range currentConfig.DstNode {
connectNew(addr) if common.Debug {
fmt.Println("重新连接", addr)
}
getNode(addr)
} }
if len(upLevelNode) == 0 { if len(upLevelNode) == 0 {
//尝试连接其他节点 //尝试连接其他节点
@@ -97,7 +109,7 @@ func checkUpLevelNode() {
fmt.Println("连接extNodeIp", addr) fmt.Println("连接extNodeIp", addr)
} }
connectNew(addr) getNode(addr)
if len(upLevelNode) > 0 { if len(upLevelNode) > 0 {
return return
} }
@@ -109,16 +121,17 @@ func checkUpLevelNode() {
for _, n := range nodeMap { for _, n := range nodeMap {
if n.uuid != currentNode.uuid { if n.uuid != currentNode.uuid {
func() {
func() {
l.RUnlock() l.RUnlock()
defer clientLock.RLock(l) defer clientLock.RLock(l)
if len(n.mainIp) == 0 { if len(n.mainIp) == 0 {
_, err := getNode(fmt.Sprintf("%s:%d", n.addr, n.port))
if common.Debug { if common.Debug {
fmt.Println("连接n.addr", fmt.Sprintf("%s:%d", n.addr, n.port)) fmt.Printf("连接n.addr %s 错误 %v \r\n", fmt.Sprintf("%s:%d", n.addr, n.port), err)
} }
connectNew(fmt.Sprintf("%s:%d", n.addr, n.port))
} }
}() }()
if len(upLevelNode) > 0 { if len(upLevelNode) > 0 {
@@ -202,16 +215,19 @@ type nodeInfo struct {
} }
func connectNew(addr string) (n *node, e error) { func connectNew(addr string) (n *node, e error) {
//先从已连接查找 defer func() {
for _, node := range nodeMap { if n != nil {
if fmt.Sprintf("%s:%d", node.mainIp, node.port) == addr { find := false
return node, nil for _, upN := range upLevelNode {
} else if fmt.Sprintf("%s:%d", node.addr, node.port) == addr { if upN.uuid == n.uuid {
return node, nil find = true
} else if node.uuid == addr { }
return node, nil }
if !find {
upLevelNode = append(upLevelNode, n)
}
} }
} }()
config := cert.Tlsconfig.Clone() config := cert.Tlsconfig.Clone()
interfaces, err := net.Interfaces() interfaces, err := net.Interfaces()
if err != nil { if err != nil {
@@ -230,7 +246,7 @@ func connectNew(addr string) (n *node, e error) {
localstr := localAddr.String() localstr := localAddr.String()
localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0" localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0"
laddr, _ := net.ResolveTCPAddr("tcp", localstr) laddr, _ := net.ResolveTCPAddr("tcp", localstr)
if laddr!=nil{ if laddr != nil {
if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil { if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil {
conn := tls.Client(netconn, config) conn := tls.Client(netconn, config)
select { select {
@@ -253,34 +269,50 @@ func connectNew(addr string) (n *node, e error) {
} }
c := &Conn{nodeConn: conn, isClient: true, nodeaddr: addr, remoteAddr: conn.LocalAddr().String()} c := &Conn{nodeConn: conn, isClient: true, nodeaddr: addr, remoteAddr: conn.LocalAddr().String()}
connMap.Store(c.remoteAddr, conn) connMap.Store(c.remoteAddr, conn)
c.regResult = make(chan error, 1) c.regResult = make(chan RegMsg, 1)
c.regResultNode = make(chan *node, 1)
c.handle() c.handle()
c.reg() c.reg()
defer func() { select {
if c.node != nil { case regmsg := <-c.regResult:
l := clientLock.Lock() if regmsg.Err != "" {
find := false return nil, errors.New(regmsg.Err)
for _, n := range upLevelNode { }
if n.uuid == c.node.uuid { n = regmsg.node
find = true n.uuid = regmsg.UUID
n.hostName = cert.RSADecrypterStr(regmsg.Hostname)
n.goos = cert.RSADecrypterStr(regmsg.Goos)
n.addr = n.conn.nodeConn.RemoteAddr().String()
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
n.port = -1
}
if v, ok := nodeMap[regmsg.UUID]; ok {
if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 {
n.uuid = "" //清空uuid避免正常的node被删
n.conn.Close("重复注册") //当前的连接关掉
n.conn = v.conn
v.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
v.port = -1
} }
} n = v
if !find { } else {
upLevelNode = append(upLevelNode, c.node) n.conn.node = n
} }
l.Unlock() } else {
n.conn.node = n
} }
}()
select { nodeMap[n.uuid] = n
case err = <-c.regResult:
return nil, err
case n = <-c.regResultNode:
//连接成功
n.reConnectAddrs = []string{addr} n.reConnectAddrs = []string{addr}
return n, err
return n, nil
case <-time.After(time.Second * 10): case <-time.After(time.Second * 10):
return nil, errors.New("time out") return nil, errors.New("time out")
} }
@@ -426,7 +458,7 @@ func (n *node) do(msg *common.Msg) {
l := clientLock.Lock() l := clientLock.Lock()
defer l.Unlock() defer l.Unlock()
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil { if err != nil {
regmsg.Err = err.Error() regmsg.Err = err.Error()
@@ -477,76 +509,21 @@ func (n *node) do(msg *common.Msg) {
go n.writeGetNodeResult(msg.CmdId) go n.writeGetNodeResult(msg.CmdId)
}() }()
case common.CMD_REG_RESULT: case common.CMD_REG_RESULT:
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil { if err != nil {
select { regmsg.Err = err.Error()
case n.conn.regResult <- err:
default:
}
return
} }
regmsg.node = n
if regmsg.Err != "" {
select {
case n.conn.regResult <- errors.New(regmsg.Err):
default:
}
return
}
//fmt.Printf("connect to %s(%s) success\n", regmsg.UUID, regmsg.RegAddr)
l := clientLock.Lock()
n.uuid = regmsg.UUID
n.hostName = cert.RSADecrypterStr(regmsg.Hostname)
n.goos = cert.RSADecrypterStr(regmsg.Goos)
n.addr = n.conn.nodeConn.RemoteAddr().String()
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
workconn := n.conn
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
n.port = -1
}
if v, ok := nodeMap[regmsg.UUID]; ok {
if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 {
n.uuid = "" //清空uuid避免正常的node被删
n.conn.Close("重复注册") //当前的连接关掉
n.conn = v.conn
v.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
v.port = -1
}
n = v
} else {
n.conn.node = n
}
} else {
n.conn.node = n
}
if common.Debug {
fmt.Printf("nodeMap3 %s %p \r\n", n.uuid, n)
}
nodeMap[n.uuid] = n
l.Unlock()
select { select {
case workconn.regResultNode <- n: case n.conn.regResult <- regmsg:
default: default:
} }
//交换节点 //交换节点
n.writeGetNodeResult(msg.CmdId) go n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG: case common.CMD_REMOTE_REG:
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
if currentConfig.Limit { if currentConfig.Limit {
regmsg.Err = "node is in limit mode" regmsg.Err = "node is in limit mode"
@@ -557,7 +534,7 @@ func (n *node) do(msg *common.Msg) {
if err == nil { if err == nil {
var newNode *node var newNode *node
newNode, err = connectNew(regmsg.RegAddr) newNode, err = getNode(regmsg.RegAddr)
if err == nil { if err == nil {
regmsg.UUID = newNode.uuid regmsg.UUID = newNode.uuid
@@ -577,7 +554,7 @@ func (n *node) do(msg *common.Msg) {
} }
n.writeGetNodeResult(msg.CmdId) n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG_RESULT: case common.CMD_REMOTE_REG_RESULT:
var regmsg common.RegMsg var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg) err = json.Unmarshal(msg.CmdData, &regmsg)
v, ok := n.loadQuery(msg.CmdId) v, ok := n.loadQuery(msg.CmdId)
if !ok { if !ok {
@@ -1208,7 +1185,7 @@ func (n *node) do(msg *common.Msg) {
} }
} }
func (n *node) remoteReg(addr string) (newN *node, err error) { func (n *node) remoteReg(addr string) (newN *node, err error) {
regmsg := common.RegMsg{ regmsg := RegMsg{
RegAddr: addr, RegAddr: addr,
UUID: currentNode.uuid, UUID: currentNode.uuid,
MainIp: cert.RSAEncrypterStr(currentNode.mainIp), MainIp: cert.RSAEncrypterStr(currentNode.mainIp),
@@ -1238,7 +1215,10 @@ func (n *node) remoteReg(addr string) (newN *node, err error) {
return nil, errors.New("error result") return nil, errors.New("error result")
} }
func (n *node) Close(reason string) { func (n *node) Close(reason string) {
if n.conn != nil && n.conn.node.uuid == n.uuid { if common.Debug {
fmt.Println("Close ", reason)
}
if n.conn != nil && n.conn.node != nil && n.conn.node.uuid == n.uuid {
n.conn.Close(reason) n.conn.Close(reason)
} }
n.Delete(reason) n.Delete(reason)
@@ -1295,16 +1275,14 @@ func (n *node) ping(id uint32) {
if common.Debug { if common.Debug {
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), n.uuid, "超时") fmt.Println(time.Now().Format("2006-01-02 15:04:05"), n.uuid, "超时")
} }
if n.conn != nil && n.conn.node.uuid == n.uuid {
n.conn.Close("超时关闭")
}
n.Delete("超时关闭")
//尝试重连
n.Close("超时关闭")
//尝试重连
go func() { go func() {
if !currentConfig.Limit && len(n.mainIp) > 0 { if !currentConfig.Limit && len(n.mainIp) > 0 {
for _, addr := range n.mainIp { for _, addr := range n.mainIp {
_n, _ := connectNew(fmt.Sprintf("%s:%d", addr, n.port)) _n, _ := getNode(fmt.Sprintf("%s:%d", addr, n.port))
if _n != nil { if _n != nil {
return return
} }
@@ -1425,6 +1403,7 @@ func (n *node) broadcastNode() {
} }
func GetNodeFromAddrs(dst []string) (n *node, err error) { func GetNodeFromAddrs(dst []string) (n *node, err error) {
if len(dst) == 0 { if len(dst) == 0 {
return nil, errors.New("参数错误,目标节点为空") return nil, errors.New("参数错误,目标节点为空")
} }
+8 -2
View File
@@ -18,6 +18,12 @@ func (l *serverListen) Lisen() {
continue continue
} }
if l.node.isClose == 1 {
newNode, _ := getNode(l.node.uuid)
if newNode != nil {
l.node = newNode
}
}
conn := &serverConnect{} conn := &serverConnect{}
conn.conn = c conn.conn = c
@@ -27,7 +33,7 @@ func (l *serverListen) Lisen() {
if l.isSocks5 { if l.isSocks5 {
conn.id = l.id conn.id = l.id
l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey,l.socks5Replay...)) l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey, l.socks5Replay...))
go conn.handTcpReceive() go conn.handTcpReceive()
return return
} }
@@ -38,7 +44,7 @@ func (l *serverListen) Lisen() {
b[1] = byte(conn.id >> 8) b[1] = byte(conn.id >> 8)
b[2] = byte(conn.id >> 16) b[2] = byte(conn.id >> 16)
b[3] = byte(conn.id >> 24) b[3] = byte(conn.id >> 24)
conn.node.Write(common.CMD_CONNECT_BYID, l.id, append(l.randkey,b...)) conn.node.Write(common.CMD_CONNECT_BYID, l.id, append(l.randkey, b...))
l.connMap.Store(conn.id, conn) l.connMap.Store(conn.id, conn)
go conn.handTcpReceive() go conn.handTcpReceive()
+33 -34
View File
@@ -16,6 +16,8 @@ import (
"rakshasa/aes" "rakshasa/aes"
"rakshasa/common" "rakshasa/common"
"github.com/google/uuid"
"regexp" "regexp"
"runtime" "runtime"
"strconv" "strconv"
@@ -134,8 +136,8 @@ func init() {
currentConfig.Port = port currentConfig.Port = port
currentNode.port = port currentNode.port = port
currentConfig.FileSave = false currentConfig.FileSave = false
if err := StartServer(fmt.Sprintf(":%d", currentConfig.Port)); err != nil { if err := StartServer(fmt.Sprintf(":%d", currentConfig.Port)); err != nil {
c.Printf("启动节点失败 %v, 请重新修改监听端口",currentConfig.Port) c.Printf("启动节点失败 %v, 请重新修改监听端口", currentConfig.Port)
} }
}, },
}) })
@@ -179,7 +181,24 @@ func init() {
currentConfig.FileSave = false currentConfig.FileSave = false
}, },
}) })
configShell.AddCmd(&ishell.Cmd{
Name: "uuid",
Help: "修改本节点UUID设置,使用方法uuid 字串符",
Func: func(c *ishell.Context) {
if len(c.Args) != 1 {
c.Println("参数错误")
return
}
if id, err := uuid.Parse(c.Args[0]); err == nil {
currentConfig.UUID = id.String()
currentConfig.FileSave = false
SetConfig(currentConfig)
} else {
c.Println("输入的uuid不是合法的uuid,建议使用xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
}
},
})
rootCli.AddCmd(&ishell.Cmd{ rootCli.AddCmd(&ishell.Cmd{
Name: "config", Name: "config",
Help: "配置管理", Help: "配置管理",
@@ -553,7 +572,7 @@ func init() {
return return
} }
for _, addr := range strings.Split(c.Args[0], ",") { for _, addr := range strings.Split(c.Args[0], ",") {
_, err := connectNew(addr) _, err := getNode(addr)
if err != nil { if err != nil {
c.Println("连接", addr, "失败", err) c.Println("连接", addr, "失败", err)
return return
@@ -788,46 +807,26 @@ func printConn() {
}) })
} }
func getNode(arg string) (*node, error) { func getNode(arg string) (*node, error) {
l := clientLock.RLock() l := clientLock.Lock()
defer l.Unlock()
id, err := strconv.Atoi(arg) id, err := strconv.Atoi(arg)
if err == nil { if err == nil {
for _, n := range nodeMap { for _, n := range nodeMap {
if n.id == id && n.uuid != currentNode.uuid { if n.id == id {
l.RUnlock()
return n, nil return n, nil
} }
} }
} else { } else {
if v, ok := nodeMap[arg]; ok && v.uuid != currentNode.uuid { for _, node := range nodeMap {
l.RUnlock() if fmt.Sprintf("%s:%d", node.mainIp, node.port) == arg {
return v, nil return node, nil
} } else if fmt.Sprintf("%s:%d", node.addr, node.port) == arg {
} return node, nil
l.RUnlock() } else if node.uuid == arg {
return node, nil
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) return connectNew(arg)
} }
+2 -2
View File
@@ -1,6 +1,7 @@
package server package server
import ( import (
"cert"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@@ -10,7 +11,6 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"cert"
"rakshasa/common" "rakshasa/common"
"strconv" "strconv"
"time" "time"
@@ -28,7 +28,7 @@ type ShellCodeStruct struct {
func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) error { func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) error {
if dst != "" { if dst != "" {
n, err := getNodeWithCurrentNode(dst) n, err := getNode(dst)
if err != nil { if err != nil {
return fmt.Errorf("无法链接节点%s,错误%v", dst, err) return fmt.Errorf("无法链接节点%s,错误%v", dst, err)
} }
+43 -35
View File
@@ -17,7 +17,6 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"unsafe"
"github.com/luyu6056/ishell" "github.com/luyu6056/ishell"
) )
@@ -29,9 +28,9 @@ const (
) )
var ( var (
SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0} SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0}
SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2} SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2}
PROTOCOL_ERR = errors.New("protocolErr") PROTOCOL_ERR = errors.New("protocolErr")
) )
const ( const (
@@ -44,10 +43,15 @@ const (
CONN_REMOTE_OPEN = 1 CONN_REMOTE_OPEN = 1
) )
const (
CONN_STATUS_NONE = iota
CONN_STATUS_CONNECT
)
type clientConnect struct { type clientConnect struct {
cfg *common.Addr cfg *common.Addr
windowsSize int64 windowsSize int64
isClose int32 status int32
conn net.Conn conn net.Conn
udpConn net.Conn udpConn net.Conn
@@ -109,9 +113,9 @@ func (s *clientConnect) Write(b []byte) {
var remoteClose = "服务器要求远程关闭" var remoteClose = "服务器要求远程关闭"
var nodeIsClose = "节点已经断开连接" var nodeIsClose = "节点已经断开连接"
func (s *clientConnect) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isClose, 0, 1) {
func (s *clientConnect) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) {
<-s.wait <-s.wait
s.wait <- common.CONN_STATUS_CLOSE s.wait <- common.CONN_STATUS_CLOSE
s.auth = CONN_AUTH_CLOSE s.auth = CONN_AUTH_CLOSE
@@ -302,12 +306,12 @@ func handleSocks5Local(s *clientConnect) {
switch common.NetWork(data[1]) { switch common.NetWork(data[1]) {
case common.SOCKS5_CMD_CONNECT: case common.SOCKS5_CMD_CONNECT:
addr, port := socks5ReadAddr(data) addr, port := socks5ReadAddr(data)
if !s.connect(common.SOCKS5_CMD_CONNECT, addr, port){ if !s.connect(common.SOCKS5_CMD_CONNECT, addr, port) {
s.Close(nodeIsClose) s.Close(nodeIsClose)
} }
case common.SOCKS5_CMD_BIND: case common.SOCKS5_CMD_BIND:
addr, port := socks5ReadAddr(data) addr, port := socks5ReadAddr(data)
if !s.connect(common.SOCKS5_CMD_BIND, addr, port){ if !s.connect(common.SOCKS5_CMD_BIND, addr, port) {
s.Close(nodeIsClose) s.Close(nodeIsClose)
} }
case common.SOCKS5_CMD_UDP: case common.SOCKS5_CMD_UDP:
@@ -336,11 +340,11 @@ func handleSocks5Local(s *clientConnect) {
ipb := ipToByte(localIP) ipb := ipToByte(localIP)
addr, port := socks5ReadAddr(data) addr, port := socks5ReadAddr(data)
if s.connect(common.SOCKS5_CMD_UDP, addr, port){ if s.connect(common.SOCKS5_CMD_UDP, addr, port) {
copy(repdata[4:], ipb) copy(repdata[4:], ipb)
s.conn.Write(repdata) s.conn.Write(repdata)
go handleSocks5Udp(s) go handleSocks5Udp(s)
}else{ } else {
s.Close(nodeIsClose) s.Close(nodeIsClose)
} }
default: default:
@@ -401,7 +405,7 @@ func handleSocks5Udp(s *clientConnect) {
if v, ok := s.udpMap.Load(ip); !ok { if v, ok := s.udpMap.Load(ip); !ok {
udps := &clientConnect{ udps := &clientConnect{
server: s.server, server: s.server,
randkey: s.randkey, randkey: s.randkey,
} }
udps.udpConn = s.udpConn udps.udpConn = s.udpConn
@@ -426,34 +430,38 @@ func handleSocks5Udp(s *clientConnect) {
} }
} }
func (s *clientConnect) connect(command common.NetWork, addr string, port uint16)bool { func (s *clientConnect) connect(command common.NetWork, addr string, port uint16) bool {
if atomic.LoadInt32(&s.server.isClose) == 1 { if !s.checkConnect() {
s.server, _ = GetNodeFromAddrs(s.server.reConnectAddrs) s.server, _ = GetNodeFromAddrs(s.server.reConnectAddrs)
ports := strconv.Itoa(int(port))
buf := make([]byte, 2+len(addr)+len(ports))
s.id = s.server.storeConn(s)
buf[0] = byte(command)
copy(buf[1:], addr)
buf[1+len(addr)] = ':'
copy(buf[2+len(addr):], ports)
s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...)))
if value, ok := s.server.listenMap.Load(s.listenId); ok {
switch v := value.(type) {
case *serverListen:
v.connMap.Store(s.id, s)
case *clientListen:
v.connMap.Store(s.id, s)
}
}
s.status = CONN_STATUS_CONNECT
return true
} }
if atomic.LoadInt32(&s.server.isClose) == 1 { return s.server.isClose == 0
return false }
} func (s *clientConnect) checkConnect() bool {
ports := strconv.Itoa(int(port)) if s.server.isClose == 1 {
buf := make([]byte, 2+len(addr)+len(ports)) //尝试重连
s.id = s.server.storeConn(s) if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil {
buf[0] = byte(command) s.server = newNode
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 return s.status == CONN_STATUS_CONNECT
}
func Bytes2str(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
} }
func (s *clientConnect) Remoteclose() { func (s *clientConnect) Remoteclose() {