增加http_proxy重连逻辑

This commit is contained in:
Mob2003
2023-04-08 21:29:05 +08:00
parent b48e9e77ac
commit bd49fdc0bf
26 changed files with 356 additions and 289 deletions
+161
View File
@@ -0,0 +1,161 @@
package server
import (
"bufio"
"io"
"log"
"net"
"net/http"
"net/url"
"os"
"rakshasa/common"
"strings"
"sync"
"time"
)
func CheckProxy(in, out string, timeout uint, checkurl string, anonymous bool) {
outFile, err := os.OpenFile(out, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
if err != nil {
log.Fatalf("CheckProxy 无法写出文件 %s", out)
}
defer outFile.Close()
var res int
if cfg, err := common.ParseAddr(in); err == nil {
if check(cfg, timeout, checkurl, outFile, anonymous) {
res = 1
}
} else {
inFile, err := os.OpenFile(in, os.O_RDONLY, 0666)
if err != nil {
log.Fatalf("-check_proxy 无法识别无法读取 %s", in)
}
limit := make(chan struct{}, 32)
reader := bufio.NewReader(inFile)
var wg sync.WaitGroup
for {
line, err := reader.ReadString(10)
if err == io.EOF && line == "" {
break
}
wg.Add(1)
limit <- struct{}{}
go func() {
line = strings.TrimRight(line, "\n")
line = strings.TrimRight(line, "\r")
if cfg, err = common.ParseAddr(line); err == nil {
if check(cfg, timeout, checkurl, outFile, anonymous) {
res++
}
}
<-limit
wg.Done()
}()
}
wg.Wait()
}
log.Printf("一共有%d个代理通过检测,已保存到 %v", res, out)
}
func check(cfg *common.Addr, timeout uint, checkurl string, outFile *os.File, anonymous bool) bool {
switch cfg.Scheam() {
case "", "http://":
proxy := func(_ *http.Request) (*url.URL, error) {
return url.Parse(cfg.HttpUrl())
}
transport := &http.Transport{Proxy: proxy}
client := &http.Client{Transport: transport, Timeout: time.Second * time.Duration(timeout)}
resp, err := client.Get(checkurl)
if err != nil {
if strings.Contains(err.Error(), "Client.Timeout") {
//log.Printf("地址 %v 检测失败 超时没响应\r\n", cfg)
//} else {
//log.Printf("地址 %v 检测失败 %v\r\n", cfg, err)
}
return false
}
if resp.StatusCode == 200 {
if anonymous {
b, _ := io.ReadAll(resp.Body)
if string(b) == cfg.IP() {
log.Printf("地址 %v 通过匿名代理检测\r\n", cfg.String())
if _, err = outFile.WriteString(cfg.String() + "\r\n"); err != nil {
log.Printf("无法写入文件%s", outFile.Name())
}
if err = outFile.Sync(); err != nil {
log.Printf("无法写入文件%s", outFile.Name())
}
} else {
return false
}
} else {
log.Printf("地址 %v 通过检测\r\n", cfg.String())
if _, err = outFile.WriteString(cfg.String() + "\r\n"); err != nil {
log.Printf("无法写入文件%s", outFile.Name())
}
if err = outFile.Sync(); err != nil {
log.Printf("无法写入文件%s", outFile.Name())
}
}
return true
}
//log.Printf("地址 %v 检测失败 结果状态码不是 200\r\n", addr)
return false
case "socks5://":
netconn, err := net.Dial("tcp", cfg.Addr())
if err != nil {
return false
}
netconn.Write([]byte{5, 1, 2})
var result [8192]byte
n, err := netconn.Read(result[:])
if err != nil {
return false
}
if string(result[:n]) == string([]byte{5, 2}) { //需要认证
user, password := cfg.User(), cfg.Password()
if user == "" && password == "" {
return false
}
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}) {
return false
}
}
log.Printf("地址 %v 通过socks5检测\r\n", cfg.String())
if _, err = outFile.WriteString(cfg.String() + "\r\n"); err != nil {
log.Printf("无法写入文件%s", outFile.Name())
}
if err = outFile.Sync(); err != nil {
log.Printf("无法写入文件%s", outFile.Name())
}
return true
default:
}
return false
}
+18 -1
View File
@@ -57,7 +57,7 @@ func cliInit() *ishell.Shell {
return
}
for _, addr := range strings.Split(c.Args[0], ",") {
_, err := connectNew(addr)
_, err := getNode(addr)
if err != nil {
c.Println("连接", addr, "失败", err)
return
@@ -106,6 +106,23 @@ func cliInit() *ishell.Shell {
},
})
shell.AddCmd(&ishell.Cmd{
Name: "closenode",
Help: "关闭一个node ID",
Func: func(c *ishell.Context) {
l := clientLock.Lock()
defer l.Unlock()
if len(c.Args) != 1 {
c.Println("参数不对")
return
}
n, ok := nodeMap[c.Args[0]]
if ok {
n.Close("debug关闭")
}
},
})
}
return shell
}
+9 -1
View File
@@ -1,9 +1,11 @@
package server
import (
"gopkg.in/yaml.v3"
"io/ioutil"
"rakshasa/common"
"github.com/google/uuid"
"gopkg.in/yaml.v3"
)
var currentConfig common.Config
@@ -13,6 +15,12 @@ func SetConfig(config common.Config) {
currentConfig.FileSave = false
currentNode.mainIp = currentConfig.ListenIp
currentNode.port = currentConfig.Port
if id, err := uuid.Parse(currentConfig.UUID); err != nil {
currentConfig.UUID = common.GetUUIDFromInterfaceMac()
}else{
currentConfig.UUID=id.String()
}
currentNode.uuid = currentConfig.UUID
}
func ConfigSave() error {
b, _ := yaml.Marshal(currentConfig)
+8 -4
View File
@@ -40,8 +40,7 @@ type Conn struct {
close chan string
isClient bool
nodeConn *tls.Conn
regResult chan error
regResultNode chan *node
regResult chan RegMsg
}
type serverListen struct {
@@ -544,7 +543,7 @@ func (c *Conn) handlerNodeRead() {
}
}
case <-time.After(common.CMD_TIMEOUT):
newNode.Delete("超时")
newNode.Close("超时")
}
}()
@@ -660,6 +659,7 @@ func (c *Conn) handle() {
if common.Debug {
fmt.Println(c.nodeConn.RemoteAddr().String(), "关闭原因", reason)
}
if c.nodeConn != nil {
if common.Debug {
fmt.Println("執行close1")
@@ -668,6 +668,7 @@ func (c *Conn) handle() {
}
if c.node != nil {
c.node.Close(reason)
//移除上游连接
for i := len(upLevelNode) - 1; i >= 0; i-- {
n := upLevelNode[i]
@@ -675,6 +676,9 @@ func (c *Conn) handle() {
upLevelNode = append(upLevelNode[:i], upLevelNode[i+1:]...)
}
}
if common.Debug {
fmt.Println("upLevelNode",len(upLevelNode))
}
}
}
@@ -690,7 +694,7 @@ func (c *Conn) handle() {
func (c *Conn) reg() error {
var err error
reg := &common.RegMsg{
reg := &RegMsg{
UUID: currentNode.uuid,
MainIp: cert.RSAEncrypterStr(currentNode.mainIp),
Port: cert.RSAEncrypterStr(strconv.Itoa(currentNode.port)),
+98 -30
View File
@@ -1,18 +1,20 @@
package server
import (
"bufio"
"bytes"
"cert"
"encoding/binary"
"errors"
"fmt"
"hash/crc32"
"io"
"log"
"math/rand"
"net"
"net/url"
"os"
"cert"
"rakshasa/common"
"rakshasa/httppool"
"runtime/debug"
"strconv"
"strings"
@@ -27,7 +29,7 @@ const CheckProxyUrl = "https://myip.fireflysoft.net/"
type httpProxyClient struct {
windowsSize int64
isclose int32
status int32
conn net.Conn
udpconn net.Conn
@@ -40,10 +42,9 @@ type httpProxyClient struct {
udpMap sync.Map
listenId uint32
localAddr string
isConnect bool
method string
cfg *common.Addr
pool *httppool.HttpPool
pool *httpPool
remoteAddr string
remotePort string
randkey []byte
@@ -68,7 +69,9 @@ func (s *httpProxyClient) Write(b []byte) {
if b[10] != 1 {
//重新拉取一个池
s.connect()
if !s.connect() {
s.Close(nodeIsClose)
}
} else if s.method == "CONNECT" {
s.conn.Write([]byte("HTTP/1.0 200 Connection established\r\n\r\n"))
}
@@ -90,7 +93,7 @@ func (s *httpProxyClient) Write(b []byte) {
}
func (s *httpProxyClient) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isclose, 0, 1) {
if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) {
<-s.wait
s.wait <- common.CONN_STATUS_CLOSE
@@ -147,10 +150,10 @@ func (s *httpProxyClient) Addwindow(window int64) {
}
func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error {
var pool *httppool.HttpPool
var pool *httpPool
var err error
if poolfile != "" {
pool, err = httppool.HttpPoolInit(poolfile)
pool, err = httpPoolInit(poolfile)
if err != nil {
return err
}
@@ -183,7 +186,7 @@ func StartHttpProxy(cfg *common.Addr, dst []string, poolfile string) error {
currentNode.listenMap.Store(l.id, l)
return nil
}
func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httppool.HttpPool) (net.Listener, error) {
func StartHttpProxyWithServer(cfg *common.Addr, n *node, id uint32, pool *httpPool) (net.Listener, error) {
l, err := net.Listen("tcp", cfg.Addr())
if err != nil {
return nil, err
@@ -280,20 +283,23 @@ func handleHttpProxyLocal(s *httpProxyClient) {
s.remoteAddr = u.Host
s.remotePort = "80"
}
s.connect()
buf := bufPool.Get().(*bytes.Buffer)
buf.Reset()
buf.WriteString("GET ")
buf.WriteString(req.uri)
buf.WriteString(" HTTP/1.1\r\n")
for _, header := range req.header {
buf.WriteString(header)
if s.connect() {
buf := bufPool.Get().(*bytes.Buffer)
buf.Reset()
buf.WriteString("GET ")
buf.WriteString(req.uri)
buf.WriteString(" HTTP/1.1\r\n")
for _, header := range req.header {
buf.WriteString(header)
buf.WriteString("\r\n")
}
buf.WriteString("\r\n")
s.write2connect(buf.Bytes())
buf.Reset()
bufPool.Put(buf)
} else {
s.Close(nodeIsClose)
}
buf.WriteString("\r\n")
s.write2connect(buf.Bytes())
buf.Reset()
bufPool.Put(buf)
} else {
return
@@ -303,7 +309,9 @@ func handleHttpProxyLocal(s *httpProxyClient) {
if i := strings.IndexByte(req.uri, ':'); i > -1 {
s.remoteAddr = req.uri[:i]
s.remotePort = req.uri[i+1:]
s.connect()
if !s.connect() {
s.Close(nodeIsClose)
}
} else {
return
}
@@ -349,9 +357,8 @@ func (s *httpProxyClient) write2connect(data []byte) {
}
s.server.Write(common.CMD_CONN_MSG, s.id, append(outdata, data...))
}
func (s *httpProxyClient) connect() {
if !s.isConnect {
func (s *httpProxyClient) connect() bool {
if !s.checkConnect() {
buf := make([]byte, 2+len(s.remoteAddr)+len(s.remotePort))
s.id = s.server.storeConn(s)
buf[0] = byte(common.RAW_TCP)
@@ -365,7 +372,7 @@ func (s *httpProxyClient) connect() {
buf = append(buf, []byte(" "+proxy.String())...)
}
s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey,buf...)))
s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...)))
if value, ok := s.server.listenMap.Load(s.listenId); ok {
switch v := value.(type) {
case *serverListen:
@@ -374,11 +381,22 @@ func (s *httpProxyClient) connect() {
v.connMap.Store(s.id, s)
}
}
s.isConnect = true
s.status = CONN_STATUS_CONNECT
return true
}
return s.server.isClose == 0
}
// 检查一下server是否断开,尝试重连,返回是否连接
func (s *httpProxyClient) checkConnect() bool {
if s.server.isClose == 1 {
//尝试重连
if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil {
s.server = newNode
}
}
return s.status == CONN_STATUS_CONNECT
}
func (s *httpProxyClient) Remoteclose() {
s.close = "本地要求远程关闭"
@@ -388,7 +406,7 @@ func (s *httpProxyClient) Remoteclose() {
buf[1] = byte(s.id >> 8)
buf[2] = byte(s.id >> 16)
buf[3] = byte(s.id >> 24)
s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey,buf...))
s.server.Write(common.CMD_DELETE_LISTENCONN_BYID, s.listenId, append(s.randkey, buf...))
}
func init() {
@@ -611,3 +629,53 @@ func parsereq(req *http1request, data []byte) (clen int, resdata []byte, err err
return 0, nil, nil
}
type httpPool struct {
r *bufio.Reader
f *os.File
sync.Mutex
}
func httpPoolInit(file string) (*httpPool, error) {
f, err := os.Open(file)
if err != nil {
return nil, fmt.Errorf("打开http代理池文件 %s 失败", file)
}
p := &httpPool{
r: bufio.NewReader(f),
f: f,
Mutex: sync.Mutex{},
}
if _, err = p.do_next(0); err != nil {
return nil, fmt.Errorf("无法从%s文件获取代理,错误%v", file, err)
}
return p, nil
}
func (p *httpPool) Next() *common.Addr {
addr, _ := p.do_next(0)
return addr
}
func (p *httpPool) do_next(n int) (*common.Addr, error) {
if n > 100 {
return nil, errors.New("重试错误次数过多")
}
p.Lock()
line, err := p.r.ReadString(10)
if err == io.EOF {
p.f.Seek(0, 0)
p.r.Reset(p.f)
p.Unlock()
return p.do_next(n + 1)
}
p.Unlock()
line = strings.TrimRight(line, "\n")
line = strings.TrimRight(line, "\r")
if len(line) == 0 {
return p.do_next(n + 1)
}
addr, err := common.ParseAddr(line)
if err != nil {
return p.do_next(n + 1)
}
return addr, nil
}
+90 -111
View File
@@ -20,12 +20,10 @@ import (
"sync/atomic"
"time"
"unsafe"
uuid2 "github.com/google/uuid"
)
var (
currentNode = &node{uuid: uuid2.New().String()}
currentNode = &node{}
clientLock = &lock{}
nodeMap = make(map[string]*node)
upLevelNode []*node //上游节点
@@ -34,6 +32,18 @@ var (
connMap sync.Map
)
type RegMsg struct {
UUID string //当前机器uuid
RegAddr string //远程连接的addr
Hostname string //当前机器名称
Goos string
ViaUUID string
Err string
MainIp string
Port string
node *node
}
func InitCurrentNode() {
s := unsafe.Sizeof(uintptr(1))
bit := " x32"
@@ -82,12 +92,14 @@ func InitCurrentNode() {
time.AfterFunc(time.Second*10, checkUpLevelNode)
}
func checkUpLevelNode() {
if len(currentConfig.DstNode) > 0 && len(upLevelNode) == 0 {
//尝试重新连接节点
for _, addr := range currentConfig.DstNode {
connectNew(addr)
if common.Debug {
fmt.Println("重新连接", addr)
}
getNode(addr)
}
if len(upLevelNode) == 0 {
//尝试连接其他节点
@@ -97,7 +109,7 @@ func checkUpLevelNode() {
fmt.Println("连接extNodeIp", addr)
}
connectNew(addr)
getNode(addr)
if len(upLevelNode) > 0 {
return
}
@@ -109,16 +121,17 @@ func checkUpLevelNode() {
for _, n := range nodeMap {
if n.uuid != currentNode.uuid {
func() {
func() {
l.RUnlock()
defer clientLock.RLock(l)
if len(n.mainIp) == 0 {
_, err := getNode(fmt.Sprintf("%s:%d", n.addr, n.port))
if common.Debug {
fmt.Println("连接n.addr", fmt.Sprintf("%s:%d", n.addr, n.port))
fmt.Printf("连接n.addr %s 错误 %v \r\n", fmt.Sprintf("%s:%d", n.addr, n.port), err)
}
connectNew(fmt.Sprintf("%s:%d", n.addr, n.port))
}
}()
if len(upLevelNode) > 0 {
@@ -202,16 +215,19 @@ type nodeInfo struct {
}
func connectNew(addr string) (n *node, e error) {
//先从已连接查找
for _, node := range nodeMap {
if fmt.Sprintf("%s:%d", node.mainIp, node.port) == addr {
return node, nil
} else if fmt.Sprintf("%s:%d", node.addr, node.port) == addr {
return node, nil
} else if node.uuid == addr {
return node, nil
defer func() {
if n != nil {
find := false
for _, upN := range upLevelNode {
if upN.uuid == n.uuid {
find = true
}
}
if !find {
upLevelNode = append(upLevelNode, n)
}
}
}
}()
config := cert.Tlsconfig.Clone()
interfaces, err := net.Interfaces()
if err != nil {
@@ -230,7 +246,7 @@ func connectNew(addr string) (n *node, e error) {
localstr := localAddr.String()
localstr = localstr[:strings.LastIndex(localstr, "/")] + ":0"
laddr, _ := net.ResolveTCPAddr("tcp", localstr)
if laddr!=nil{
if laddr != nil {
if netconn, e := net.DialTCP("tcp", laddr, raddr); e == nil {
conn := tls.Client(netconn, config)
select {
@@ -253,34 +269,50 @@ func connectNew(addr string) (n *node, e error) {
}
c := &Conn{nodeConn: conn, isClient: true, nodeaddr: addr, remoteAddr: conn.LocalAddr().String()}
connMap.Store(c.remoteAddr, conn)
c.regResult = make(chan error, 1)
c.regResultNode = make(chan *node, 1)
c.regResult = make(chan RegMsg, 1)
c.handle()
c.reg()
defer func() {
if c.node != nil {
l := clientLock.Lock()
find := false
for _, n := range upLevelNode {
if n.uuid == c.node.uuid {
find = true
select {
case regmsg := <-c.regResult:
if regmsg.Err != "" {
return nil, errors.New(regmsg.Err)
}
n = regmsg.node
n.uuid = regmsg.UUID
n.hostName = cert.RSADecrypterStr(regmsg.Hostname)
n.goos = cert.RSADecrypterStr(regmsg.Goos)
n.addr = n.conn.nodeConn.RemoteAddr().String()
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
n.port = -1
}
if v, ok := nodeMap[regmsg.UUID]; ok {
if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 {
n.uuid = "" //清空uuid避免正常的node被删
n.conn.Close("重复注册") //当前的连接关掉
n.conn = v.conn
v.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
v.port = -1
}
}
if !find {
upLevelNode = append(upLevelNode, c.node)
n = v
} else {
n.conn.node = n
}
l.Unlock()
} else {
n.conn.node = n
}
}()
select {
case err = <-c.regResult:
return nil, err
case n = <-c.regResultNode:
//连接成功
nodeMap[n.uuid] = n
n.reConnectAddrs = []string{addr}
return n, err
return n, nil
case <-time.After(time.Second * 10):
return nil, errors.New("time out")
}
@@ -426,7 +458,7 @@ func (n *node) do(msg *common.Msg) {
l := clientLock.Lock()
defer l.Unlock()
var regmsg common.RegMsg
var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil {
regmsg.Err = err.Error()
@@ -477,76 +509,21 @@ func (n *node) do(msg *common.Msg) {
go n.writeGetNodeResult(msg.CmdId)
}()
case common.CMD_REG_RESULT:
var regmsg common.RegMsg
var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil {
select {
case n.conn.regResult <- err:
default:
}
return
regmsg.Err = err.Error()
}
if regmsg.Err != "" {
select {
case n.conn.regResult <- errors.New(regmsg.Err):
default:
}
return
}
//fmt.Printf("connect to %s(%s) success\n", regmsg.UUID, regmsg.RegAddr)
l := clientLock.Lock()
n.uuid = regmsg.UUID
n.hostName = cert.RSADecrypterStr(regmsg.Hostname)
n.goos = cert.RSADecrypterStr(regmsg.Goos)
n.addr = n.conn.nodeConn.RemoteAddr().String()
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
workconn := n.conn
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
n.port = -1
}
if v, ok := nodeMap[regmsg.UUID]; ok {
if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 {
n.uuid = "" //清空uuid避免正常的node被删
n.conn.Close("重复注册") //当前的连接关掉
n.conn = v.conn
v.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
v.port = -1
}
n = v
} else {
n.conn.node = n
}
} else {
n.conn.node = n
}
if common.Debug {
fmt.Printf("nodeMap3 %s %p \r\n", n.uuid, n)
}
nodeMap[n.uuid] = n
l.Unlock()
regmsg.node = n
select {
case workconn.regResultNode <- n:
case n.conn.regResult <- regmsg:
default:
}
//交换节点
n.writeGetNodeResult(msg.CmdId)
go n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG:
var regmsg common.RegMsg
var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if currentConfig.Limit {
regmsg.Err = "node is in limit mode"
@@ -557,7 +534,7 @@ func (n *node) do(msg *common.Msg) {
if err == nil {
var newNode *node
newNode, err = connectNew(regmsg.RegAddr)
newNode, err = getNode(regmsg.RegAddr)
if err == nil {
regmsg.UUID = newNode.uuid
@@ -577,7 +554,7 @@ func (n *node) do(msg *common.Msg) {
}
n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG_RESULT:
var regmsg common.RegMsg
var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
v, ok := n.loadQuery(msg.CmdId)
if !ok {
@@ -1208,7 +1185,7 @@ func (n *node) do(msg *common.Msg) {
}
}
func (n *node) remoteReg(addr string) (newN *node, err error) {
regmsg := common.RegMsg{
regmsg := RegMsg{
RegAddr: addr,
UUID: currentNode.uuid,
MainIp: cert.RSAEncrypterStr(currentNode.mainIp),
@@ -1238,7 +1215,10 @@ func (n *node) remoteReg(addr string) (newN *node, err error) {
return nil, errors.New("error result")
}
func (n *node) Close(reason string) {
if n.conn != nil && n.conn.node.uuid == n.uuid {
if common.Debug {
fmt.Println("Close ", reason)
}
if n.conn != nil && n.conn.node != nil && n.conn.node.uuid == n.uuid {
n.conn.Close(reason)
}
n.Delete(reason)
@@ -1295,16 +1275,14 @@ func (n *node) ping(id uint32) {
if common.Debug {
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), n.uuid, "超时")
}
if n.conn != nil && n.conn.node.uuid == n.uuid {
n.conn.Close("超时关闭")
}
n.Delete("超时关闭")
//尝试重连
n.Close("超时关闭")
//尝试重连
go func() {
if !currentConfig.Limit && len(n.mainIp) > 0 {
for _, addr := range n.mainIp {
_n, _ := connectNew(fmt.Sprintf("%s:%d", addr, n.port))
_n, _ := getNode(fmt.Sprintf("%s:%d", addr, n.port))
if _n != nil {
return
}
@@ -1425,6 +1403,7 @@ func (n *node) broadcastNode() {
}
func GetNodeFromAddrs(dst []string) (n *node, err error) {
if len(dst) == 0 {
return nil, errors.New("参数错误,目标节点为空")
}
+8 -2
View File
@@ -18,6 +18,12 @@ func (l *serverListen) Lisen() {
continue
}
if l.node.isClose == 1 {
newNode, _ := getNode(l.node.uuid)
if newNode != nil {
l.node = newNode
}
}
conn := &serverConnect{}
conn.conn = c
@@ -27,7 +33,7 @@ func (l *serverListen) Lisen() {
if l.isSocks5 {
conn.id = l.id
l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey,l.socks5Replay...))
l.node.Write(common.CMD_CONNECT_BYIDADDR_RESULT, l.replayid, append(l.randkey, l.socks5Replay...))
go conn.handTcpReceive()
return
}
@@ -38,7 +44,7 @@ func (l *serverListen) Lisen() {
b[1] = byte(conn.id >> 8)
b[2] = byte(conn.id >> 16)
b[3] = byte(conn.id >> 24)
conn.node.Write(common.CMD_CONNECT_BYID, l.id, append(l.randkey,b...))
conn.node.Write(common.CMD_CONNECT_BYID, l.id, append(l.randkey, b...))
l.connMap.Store(conn.id, conn)
go conn.handTcpReceive()
+33 -34
View File
@@ -16,6 +16,8 @@ import (
"rakshasa/aes"
"rakshasa/common"
"github.com/google/uuid"
"regexp"
"runtime"
"strconv"
@@ -134,8 +136,8 @@ func init() {
currentConfig.Port = port
currentNode.port = port
currentConfig.FileSave = false
if err := StartServer(fmt.Sprintf(":%d", currentConfig.Port)); err != nil {
c.Printf("启动节点失败 %v, 请重新修改监听端口",currentConfig.Port)
if err := StartServer(fmt.Sprintf(":%d", currentConfig.Port)); err != nil {
c.Printf("启动节点失败 %v, 请重新修改监听端口", currentConfig.Port)
}
},
})
@@ -179,7 +181,24 @@ func init() {
currentConfig.FileSave = false
},
})
configShell.AddCmd(&ishell.Cmd{
Name: "uuid",
Help: "修改本节点UUID设置,使用方法uuid 字串符",
Func: func(c *ishell.Context) {
if len(c.Args) != 1 {
c.Println("参数错误")
return
}
if id, err := uuid.Parse(c.Args[0]); err == nil {
currentConfig.UUID = id.String()
currentConfig.FileSave = false
SetConfig(currentConfig)
} else {
c.Println("输入的uuid不是合法的uuid,建议使用xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
}
},
})
rootCli.AddCmd(&ishell.Cmd{
Name: "config",
Help: "配置管理",
@@ -553,7 +572,7 @@ func init() {
return
}
for _, addr := range strings.Split(c.Args[0], ",") {
_, err := connectNew(addr)
_, err := getNode(addr)
if err != nil {
c.Println("连接", addr, "失败", err)
return
@@ -788,46 +807,26 @@ func printConn() {
})
}
func getNode(arg string) (*node, error) {
l := clientLock.RLock()
l := clientLock.Lock()
defer l.Unlock()
id, err := strconv.Atoi(arg)
if err == nil {
for _, n := range nodeMap {
if n.id == id && n.uuid != currentNode.uuid {
l.RUnlock()
if n.id == id {
return n, nil
}
}
} else {
if v, ok := nodeMap[arg]; ok && v.uuid != currentNode.uuid {
l.RUnlock()
return v, nil
}
}
l.RUnlock()
return connectNew(arg)
}
func getNodeWithCurrentNode(arg string) (*node, error) {
l := clientLock.RLock()
id, err := strconv.Atoi(arg)
if err == nil {
for _, n := range nodeMap {
if n.id == id {
l.RUnlock()
return n, nil
for _, node := range nodeMap {
if fmt.Sprintf("%s:%d", node.mainIp, node.port) == arg {
return node, nil
} else if fmt.Sprintf("%s:%d", node.addr, node.port) == arg {
return node, nil
} else if node.uuid == arg {
return node, nil
}
}
} else {
if v, ok := nodeMap[arg]; ok {
l.RUnlock()
return v, nil
}
}
l.RUnlock()
return connectNew(arg)
}
+2 -2
View File
@@ -1,6 +1,7 @@
package server
import (
"cert"
"encoding/base64"
"encoding/hex"
"encoding/json"
@@ -10,7 +11,6 @@ import (
"os"
"os/exec"
"path/filepath"
"cert"
"rakshasa/common"
"strconv"
"time"
@@ -28,7 +28,7 @@ type ShellCodeStruct struct {
func RunShellcodeWithDst(dst, shellcode, xorKey, param string, timeout int) error {
if dst != "" {
n, err := getNodeWithCurrentNode(dst)
n, err := getNode(dst)
if err != nil {
return fmt.Errorf("无法链接节点%s,错误%v", dst, err)
}
+43 -35
View File
@@ -17,7 +17,6 @@ import (
"sync"
"sync/atomic"
"time"
"unsafe"
"github.com/luyu6056/ishell"
)
@@ -29,9 +28,9 @@ const (
)
var (
SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0}
SOCKES5_AUTH_SUSSCES []byte = []byte{5, 0}
SOCKES5_AUTH_SUSSCES_PASSWD []byte = []byte{5, 2}
PROTOCOL_ERR = errors.New("protocolErr")
PROTOCOL_ERR = errors.New("protocolErr")
)
const (
@@ -44,10 +43,15 @@ const (
CONN_REMOTE_OPEN = 1
)
const (
CONN_STATUS_NONE = iota
CONN_STATUS_CONNECT
)
type clientConnect struct {
cfg *common.Addr
windowsSize int64
isClose int32
status int32
conn net.Conn
udpConn net.Conn
@@ -109,9 +113,9 @@ func (s *clientConnect) Write(b []byte) {
var remoteClose = "服务器要求远程关闭"
var nodeIsClose = "节点已经断开连接"
func (s *clientConnect) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.isClose, 0, 1) {
func (s *clientConnect) Close(msg string) {
if atomic.CompareAndSwapInt32(&s.status, CONN_STATUS_CONNECT, CONN_STATUS_NONE) {
<-s.wait
s.wait <- common.CONN_STATUS_CLOSE
s.auth = CONN_AUTH_CLOSE
@@ -302,12 +306,12 @@ func handleSocks5Local(s *clientConnect) {
switch common.NetWork(data[1]) {
case common.SOCKS5_CMD_CONNECT:
addr, port := socks5ReadAddr(data)
if !s.connect(common.SOCKS5_CMD_CONNECT, addr, port){
if !s.connect(common.SOCKS5_CMD_CONNECT, addr, port) {
s.Close(nodeIsClose)
}
case common.SOCKS5_CMD_BIND:
addr, port := socks5ReadAddr(data)
if !s.connect(common.SOCKS5_CMD_BIND, addr, port){
if !s.connect(common.SOCKS5_CMD_BIND, addr, port) {
s.Close(nodeIsClose)
}
case common.SOCKS5_CMD_UDP:
@@ -336,11 +340,11 @@ func handleSocks5Local(s *clientConnect) {
ipb := ipToByte(localIP)
addr, port := socks5ReadAddr(data)
if s.connect(common.SOCKS5_CMD_UDP, addr, port){
if s.connect(common.SOCKS5_CMD_UDP, addr, port) {
copy(repdata[4:], ipb)
s.conn.Write(repdata)
go handleSocks5Udp(s)
}else{
} else {
s.Close(nodeIsClose)
}
default:
@@ -401,7 +405,7 @@ func handleSocks5Udp(s *clientConnect) {
if v, ok := s.udpMap.Load(ip); !ok {
udps := &clientConnect{
server: s.server,
server: s.server,
randkey: s.randkey,
}
udps.udpConn = s.udpConn
@@ -426,34 +430,38 @@ func handleSocks5Udp(s *clientConnect) {
}
}
func (s *clientConnect) connect(command common.NetWork, addr string, port uint16)bool {
if atomic.LoadInt32(&s.server.isClose) == 1 {
func (s *clientConnect) connect(command common.NetWork, addr string, port uint16) bool {
if !s.checkConnect() {
s.server, _ = GetNodeFromAddrs(s.server.reConnectAddrs)
ports := strconv.Itoa(int(port))
buf := make([]byte, 2+len(addr)+len(ports))
s.id = s.server.storeConn(s)
buf[0] = byte(command)
copy(buf[1:], addr)
buf[1+len(addr)] = ':'
copy(buf[2+len(addr):], ports)
s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...)))
if value, ok := s.server.listenMap.Load(s.listenId); ok {
switch v := value.(type) {
case *serverListen:
v.connMap.Store(s.id, s)
case *clientListen:
v.connMap.Store(s.id, s)
}
}
s.status = CONN_STATUS_CONNECT
return true
}
if atomic.LoadInt32(&s.server.isClose) == 1 {
return false
}
ports := strconv.Itoa(int(port))
buf := make([]byte, 2+len(addr)+len(ports))
s.id = s.server.storeConn(s)
buf[0] = byte(command)
copy(buf[1:], addr)
buf[1+len(addr)] = ':'
copy(buf[2+len(addr):], ports)
s.server.Write(common.CMD_CONNECT_BYIDADDR, s.id, cert.RSAEncrypterByPrivByte(append(s.randkey, buf...)))
if value, ok := s.server.listenMap.Load(s.listenId); ok {
switch v := value.(type) {
case *serverListen:
v.connMap.Store(s.id, s)
case *clientListen:
v.connMap.Store(s.id, s)
return s.server.isClose == 0
}
func (s *clientConnect) checkConnect() bool {
if s.server.isClose == 1 {
//尝试重连
if newNode, _ := GetNodeFromAddrs(s.server.reConnectAddrs); newNode != nil {
s.server = newNode
}
}
return true
}
func Bytes2str(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
return s.status == CONN_STATUS_CONNECT
}
func (s *clientConnect) Remoteclose() {