2019-01-09 12:33:00 +00:00
|
|
|
|
package bridge
|
|
|
|
|
|
|
|
|
|
import (
|
2019-02-12 19:54:00 +00:00
|
|
|
|
"encoding/binary"
|
2019-01-09 12:33:00 +00:00
|
|
|
|
"errors"
|
2019-02-16 12:43:26 +00:00
|
|
|
|
"fmt"
|
2019-02-12 19:54:00 +00:00
|
|
|
|
"github.com/cnlh/nps/lib/common"
|
2019-02-09 09:07:47 +00:00
|
|
|
|
"github.com/cnlh/nps/lib/conn"
|
2019-02-12 19:54:00 +00:00
|
|
|
|
"github.com/cnlh/nps/lib/crypt"
|
2019-02-09 09:07:47 +00:00
|
|
|
|
"github.com/cnlh/nps/lib/file"
|
2019-03-01 09:23:14 +00:00
|
|
|
|
"github.com/cnlh/nps/lib/mux"
|
2019-02-23 15:29:48 +00:00
|
|
|
|
"github.com/cnlh/nps/lib/version"
|
2019-03-05 01:23:18 +00:00
|
|
|
|
"github.com/cnlh/nps/server/connection"
|
2019-02-12 19:54:00 +00:00
|
|
|
|
"github.com/cnlh/nps/server/tool"
|
2019-02-26 14:40:28 +00:00
|
|
|
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
2019-02-23 15:29:48 +00:00
|
|
|
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
2019-01-09 12:33:00 +00:00
|
|
|
|
"net"
|
2019-03-19 14:41:40 +00:00
|
|
|
|
"os"
|
2019-02-09 09:07:47 +00:00
|
|
|
|
"strconv"
|
2019-03-15 06:03:49 +00:00
|
|
|
|
"strings"
|
2019-01-09 12:33:00 +00:00
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
2019-01-31 18:06:30 +00:00
|
|
|
|
type Client struct {
|
2019-03-02 09:43:21 +00:00
|
|
|
|
tunnel *mux.Mux
|
|
|
|
|
signal *conn.Conn
|
|
|
|
|
file *mux.Mux
|
|
|
|
|
retryTime int // it will be add 1 when ping not ok until to 3 will close the client
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-02 09:43:21 +00:00
|
|
|
|
func NewClient(t, f *mux.Mux, s *conn.Conn) *Client {
|
2019-02-09 09:07:47 +00:00
|
|
|
|
return &Client{
|
2019-03-01 09:23:14 +00:00
|
|
|
|
signal: s,
|
|
|
|
|
tunnel: t,
|
2019-03-02 09:43:21 +00:00
|
|
|
|
file: f,
|
2019-02-09 09:07:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-26 09:27:28 +00:00
|
|
|
|
type Bridge struct {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
TunnelPort int //通信隧道端口
|
|
|
|
|
Client sync.Map
|
|
|
|
|
Register sync.Map
|
|
|
|
|
tunnelType string //bridge type kcp or tcp
|
|
|
|
|
OpenTask chan *file.Tunnel
|
|
|
|
|
CloseTask chan *file.Tunnel
|
|
|
|
|
CloseClient chan int
|
|
|
|
|
SecretChan chan *conn.Secret
|
|
|
|
|
ipVerify bool
|
|
|
|
|
runList map[int]interface{}
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-16 15:18:58 +00:00
|
|
|
|
func NewTunnel(tunnelPort int, tunnelType string, ipVerify bool, runList map[int]interface{}) *Bridge {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return &Bridge{
|
|
|
|
|
TunnelPort: tunnelPort,
|
|
|
|
|
tunnelType: tunnelType,
|
|
|
|
|
OpenTask: make(chan *file.Tunnel),
|
|
|
|
|
CloseTask: make(chan *file.Tunnel),
|
|
|
|
|
CloseClient: make(chan int),
|
|
|
|
|
SecretChan: make(chan *conn.Secret),
|
|
|
|
|
ipVerify: ipVerify,
|
|
|
|
|
runList: runList,
|
|
|
|
|
}
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-26 09:27:28 +00:00
|
|
|
|
func (s *Bridge) StartTunnel() error {
|
2019-03-02 09:43:21 +00:00
|
|
|
|
go s.ping()
|
2019-02-09 09:07:47 +00:00
|
|
|
|
if s.tunnelType == "kcp" {
|
2019-03-19 14:41:40 +00:00
|
|
|
|
logs.Info("server start, the bridge type is %s, the bridge port is %d", s.tunnelType, s.TunnelPort)
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return conn.NewKcpListenerAndProcess(beego.AppConfig.String("bridge_ip")+":"+beego.AppConfig.String("bridge_port"), func(c net.Conn) {
|
|
|
|
|
s.cliProcess(conn.NewConn(c))
|
|
|
|
|
})
|
2019-02-09 09:07:47 +00:00
|
|
|
|
} else {
|
2019-03-19 14:41:40 +00:00
|
|
|
|
listener, err := connection.GetBridgeListener(s.tunnelType)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logs.Error(err)
|
|
|
|
|
os.Exit(0)
|
2019-02-09 09:07:47 +00:00
|
|
|
|
return err
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
conn.Accept(listener, func(c net.Conn) {
|
|
|
|
|
s.cliProcess(conn.NewConn(c))
|
|
|
|
|
})
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
2019-02-09 09:07:47 +00:00
|
|
|
|
return nil
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-15 06:03:49 +00:00
|
|
|
|
//get health information form client
|
|
|
|
|
func (s *Bridge) GetHealthFromClient(id int, c *conn.Conn) {
|
|
|
|
|
for {
|
|
|
|
|
if info, status, err := c.GetHealthInfo(); err != nil {
|
|
|
|
|
break
|
|
|
|
|
} else if !status { //the status is true , return target to the targetArr
|
2019-03-23 14:19:59 +00:00
|
|
|
|
file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
|
|
|
|
|
v := value.(*file.Tunnel)
|
2019-03-15 06:03:49 +00:00
|
|
|
|
if v.Client.Id == id && v.Mode == "tcp" && strings.Contains(v.Target, info) {
|
|
|
|
|
v.Lock()
|
|
|
|
|
if v.TargetArr == nil || (len(v.TargetArr) == 0 && len(v.HealthRemoveArr) == 0) {
|
|
|
|
|
v.TargetArr = common.TrimArr(strings.Split(v.Target, "\n"))
|
|
|
|
|
}
|
|
|
|
|
v.TargetArr = common.RemoveArrVal(v.TargetArr, info)
|
|
|
|
|
if v.HealthRemoveArr == nil {
|
|
|
|
|
v.HealthRemoveArr = make([]string, 0)
|
|
|
|
|
}
|
|
|
|
|
v.HealthRemoveArr = append(v.HealthRemoveArr, info)
|
|
|
|
|
v.Unlock()
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
|
|
|
|
|
v := value.(*file.Host)
|
2019-03-15 06:03:49 +00:00
|
|
|
|
if v.Client.Id == id && strings.Contains(v.Target, info) {
|
|
|
|
|
v.Lock()
|
|
|
|
|
if v.TargetArr == nil || (len(v.TargetArr) == 0 && len(v.HealthRemoveArr) == 0) {
|
|
|
|
|
v.TargetArr = common.TrimArr(strings.Split(v.Target, "\n"))
|
|
|
|
|
}
|
|
|
|
|
v.TargetArr = common.RemoveArrVal(v.TargetArr, info)
|
|
|
|
|
if v.HealthRemoveArr == nil {
|
|
|
|
|
v.HealthRemoveArr = make([]string, 0)
|
|
|
|
|
}
|
|
|
|
|
v.HealthRemoveArr = append(v.HealthRemoveArr, info)
|
|
|
|
|
v.Unlock()
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
|
|
|
|
})
|
2019-03-15 06:03:49 +00:00
|
|
|
|
} else { //the status is false,remove target from the targetArr
|
2019-03-23 14:19:59 +00:00
|
|
|
|
file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
|
|
|
|
|
v := value.(*file.Tunnel)
|
2019-03-15 06:03:49 +00:00
|
|
|
|
if v.Client.Id == id && v.Mode == "tcp" && common.IsArrContains(v.HealthRemoveArr, info) && !common.IsArrContains(v.TargetArr, info) {
|
|
|
|
|
v.Lock()
|
|
|
|
|
v.TargetArr = append(v.TargetArr, info)
|
|
|
|
|
v.HealthRemoveArr = common.RemoveArrVal(v.HealthRemoveArr, info)
|
|
|
|
|
v.Unlock()
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
|
|
|
|
|
v := value.(*file.Host)
|
2019-03-15 06:03:49 +00:00
|
|
|
|
if v.Client.Id == id && common.IsArrContains(v.HealthRemoveArr, info) && !common.IsArrContains(v.TargetArr, info) {
|
|
|
|
|
v.Lock()
|
|
|
|
|
v.TargetArr = append(v.TargetArr, info)
|
|
|
|
|
v.HealthRemoveArr = common.RemoveArrVal(v.HealthRemoveArr, info)
|
|
|
|
|
v.Unlock()
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
|
|
|
|
})
|
2019-03-15 06:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
s.DelClient(id, )
|
2019-03-15 06:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-09 12:33:00 +00:00
|
|
|
|
//验证失败,返回错误验证flag,并且关闭连接
|
2019-02-09 09:07:47 +00:00
|
|
|
|
func (s *Bridge) verifyError(c *conn.Conn) {
|
|
|
|
|
c.Write([]byte(common.VERIFY_EER))
|
2019-01-09 12:33:00 +00:00
|
|
|
|
c.Conn.Close()
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-12 19:54:00 +00:00
|
|
|
|
func (s *Bridge) verifySuccess(c *conn.Conn) {
|
|
|
|
|
c.Write([]byte(common.VERIFY_SUCCESS))
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 09:07:47 +00:00
|
|
|
|
func (s *Bridge) cliProcess(c *conn.Conn) {
|
2019-03-05 01:23:18 +00:00
|
|
|
|
//read test flag
|
|
|
|
|
if _, err := c.GetShortContent(3); err != nil {
|
|
|
|
|
logs.Info("The client %s connect error", c.Conn.RemoteAddr())
|
|
|
|
|
return
|
|
|
|
|
}
|
2019-03-01 09:23:14 +00:00
|
|
|
|
//version check
|
|
|
|
|
if b, err := c.GetShortContent(32); err != nil || string(b) != crypt.Md5(version.GetVersion()) {
|
2019-02-23 15:29:48 +00:00
|
|
|
|
logs.Info("The client %s version does not match", c.Conn.RemoteAddr())
|
|
|
|
|
c.Close()
|
|
|
|
|
return
|
|
|
|
|
}
|
2019-03-02 09:43:21 +00:00
|
|
|
|
//write server version to client
|
2019-02-24 05:17:43 +00:00
|
|
|
|
c.Write([]byte(crypt.Md5(version.GetVersion())))
|
2019-02-09 09:07:47 +00:00
|
|
|
|
c.SetReadDeadline(5, s.tunnelType)
|
2019-01-28 06:45:55 +00:00
|
|
|
|
var buf []byte
|
|
|
|
|
var err error
|
2019-03-05 01:23:18 +00:00
|
|
|
|
//get vKey from client
|
2019-03-01 09:23:14 +00:00
|
|
|
|
if buf, err = c.GetShortContent(32); err != nil {
|
2019-01-28 06:45:55 +00:00
|
|
|
|
c.Close()
|
|
|
|
|
return
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
2019-03-02 09:43:21 +00:00
|
|
|
|
//verify
|
2019-02-09 09:07:47 +00:00
|
|
|
|
id, err := file.GetCsvDb().GetIdByVerifyKey(string(buf), c.Conn.RemoteAddr().String())
|
2019-01-25 04:10:12 +00:00
|
|
|
|
if err != nil {
|
2019-02-23 15:29:48 +00:00
|
|
|
|
logs.Info("Current client connection validation error, close this client:", c.Conn.RemoteAddr())
|
2019-01-09 12:33:00 +00:00
|
|
|
|
s.verifyError(c)
|
2019-01-28 06:45:55 +00:00
|
|
|
|
return
|
2019-02-12 19:54:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
s.verifySuccess(c)
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
2019-01-28 06:45:55 +00:00
|
|
|
|
if flag, err := c.ReadFlag(); err == nil {
|
|
|
|
|
s.typeDeal(flag, c, id)
|
2019-02-12 19:54:00 +00:00
|
|
|
|
} else {
|
2019-02-23 15:29:48 +00:00
|
|
|
|
logs.Warn(err, flag)
|
2019-01-28 06:45:55 +00:00
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-23 14:19:59 +00:00
|
|
|
|
func (s *Bridge) DelClient(id int) {
|
|
|
|
|
if v, ok := s.Client.Load(id); ok {
|
2019-02-17 11:36:48 +00:00
|
|
|
|
if c, err := file.GetCsvDb().GetClient(id); err == nil && c.NoStore {
|
|
|
|
|
s.CloseClient <- c.Id
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
if v.(*Client).signal != nil {
|
|
|
|
|
v.(*Client).signal.Close()
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
s.Client.Delete(id)
|
2019-02-17 11:36:48 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-09 12:33:00 +00:00
|
|
|
|
|
2019-03-01 09:23:14 +00:00
|
|
|
|
//use different
|
2019-02-09 09:07:47 +00:00
|
|
|
|
func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
|
2019-01-09 12:33:00 +00:00
|
|
|
|
switch typeVal {
|
2019-02-09 09:07:47 +00:00
|
|
|
|
case common.WORK_MAIN:
|
2019-03-01 09:23:14 +00:00
|
|
|
|
//the vKey connect by another ,close the client of before
|
2019-03-23 14:19:59 +00:00
|
|
|
|
if v, ok := s.Client.LoadOrStore(id, NewClient(nil, nil, c)); ok {
|
|
|
|
|
if v.(*Client).signal != nil {
|
|
|
|
|
v.(*Client).signal.WriteClose()
|
2019-02-09 09:07:47 +00:00
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
v.(*Client).signal = c
|
2019-01-31 18:06:30 +00:00
|
|
|
|
}
|
2019-03-15 06:03:49 +00:00
|
|
|
|
go s.GetHealthFromClient(id, c)
|
2019-02-23 15:29:48 +00:00
|
|
|
|
logs.Info("clientId %d connection succeeded, address:%s ", id, c.Conn.RemoteAddr())
|
2019-02-09 09:07:47 +00:00
|
|
|
|
case common.WORK_CHAN:
|
2019-03-23 14:19:59 +00:00
|
|
|
|
muxConn := mux.NewMux(c.Conn, s.tunnelType)
|
|
|
|
|
if v, ok := s.Client.LoadOrStore(id, NewClient(muxConn, nil, nil)); ok {
|
|
|
|
|
v.(*Client).tunnel = muxConn
|
2019-01-31 18:06:30 +00:00
|
|
|
|
}
|
2019-02-12 19:54:00 +00:00
|
|
|
|
case common.WORK_CONFIG:
|
2019-03-02 09:43:21 +00:00
|
|
|
|
var isPub bool
|
2019-03-23 14:19:59 +00:00
|
|
|
|
client, err := file.GetCsvDb().GetClient(id)
|
2019-03-02 09:43:21 +00:00
|
|
|
|
if err == nil {
|
2019-03-05 01:23:18 +00:00
|
|
|
|
if client.VerifyKey == beego.AppConfig.String("public_vkey") {
|
2019-03-02 09:43:21 +00:00
|
|
|
|
isPub = true
|
|
|
|
|
} else {
|
|
|
|
|
isPub = false
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
if !isPub && !client.ConfigConnAllow {
|
|
|
|
|
c.Close()
|
|
|
|
|
return
|
|
|
|
|
}
|
2019-03-02 09:43:21 +00:00
|
|
|
|
binary.Write(c, binary.LittleEndian, isPub)
|
|
|
|
|
go s.getConfig(c, isPub, client)
|
2019-02-16 12:43:26 +00:00
|
|
|
|
case common.WORK_REGISTER:
|
|
|
|
|
go s.register(c)
|
2019-02-26 14:40:28 +00:00
|
|
|
|
case common.WORK_SECRET:
|
2019-03-01 09:23:14 +00:00
|
|
|
|
if b, err := c.GetShortContent(32); err == nil {
|
2019-02-23 15:29:48 +00:00
|
|
|
|
s.SecretChan <- conn.NewSecret(string(b), c)
|
|
|
|
|
}
|
2019-03-02 09:43:21 +00:00
|
|
|
|
case common.WORK_FILE:
|
2019-03-23 14:19:59 +00:00
|
|
|
|
muxConn := mux.NewMux(c.Conn, s.tunnelType)
|
|
|
|
|
if v, ok := s.Client.LoadOrStore(id, NewClient(nil, muxConn, nil)); ok {
|
|
|
|
|
v.(*Client).file = muxConn
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
2019-02-26 14:40:28 +00:00
|
|
|
|
case common.WORK_P2P:
|
2019-03-01 09:23:14 +00:00
|
|
|
|
//read md5 secret
|
|
|
|
|
if b, err := c.GetShortContent(32); err != nil {
|
2019-02-26 14:40:28 +00:00
|
|
|
|
return
|
|
|
|
|
} else if t := file.GetCsvDb().GetTaskByMd5Password(string(b)); t == nil {
|
|
|
|
|
return
|
|
|
|
|
} else {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
if v, ok := s.Client.Load(t.Client.Id); !ok {
|
2019-02-26 14:40:28 +00:00
|
|
|
|
return
|
|
|
|
|
} else {
|
|
|
|
|
//向密钥对应的客户端发送与服务端udp建立连接信息,地址,密钥
|
2019-03-23 14:19:59 +00:00
|
|
|
|
v.(*Client).signal.Write([]byte(common.NEW_UDP_CONN))
|
2019-03-05 01:23:18 +00:00
|
|
|
|
svrAddr := beego.AppConfig.String("p2p_ip") + ":" + beego.AppConfig.String("p2p_port")
|
2019-03-01 09:23:14 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
logs.Warn("get local udp addr error")
|
|
|
|
|
return
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
v.(*Client).signal.WriteLenContent([]byte(svrAddr))
|
|
|
|
|
v.(*Client).signal.WriteLenContent(b)
|
2019-02-26 14:40:28 +00:00
|
|
|
|
//向该请求者发送建立连接请求,服务器地址
|
|
|
|
|
c.WriteLenContent([]byte(svrAddr))
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
2019-02-09 09:07:47 +00:00
|
|
|
|
c.SetAlive(s.tunnelType)
|
2019-01-28 06:45:55 +00:00
|
|
|
|
return
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-01 09:23:14 +00:00
|
|
|
|
//register ip
|
2019-02-16 12:43:26 +00:00
|
|
|
|
func (s *Bridge) register(c *conn.Conn) {
|
|
|
|
|
var hour int32
|
|
|
|
|
if err := binary.Read(c, binary.LittleEndian, &hour); err == nil {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
s.Register.Store(common.GetIpByAddr(c.Conn.RemoteAddr().String()), time.Now().Add(time.Hour*time.Duration(hour)))
|
2019-02-16 12:43:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-02 09:43:21 +00:00
|
|
|
|
func (s *Bridge) SendLinkInfo(clientId int, link *conn.Link, linkAddr string, t *file.Tunnel) (target net.Conn, err error) {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
if v, ok := s.Client.Load(clientId); ok {
|
2019-03-02 09:43:21 +00:00
|
|
|
|
//If ip is restricted to do ip verification
|
2019-02-16 12:43:26 +00:00
|
|
|
|
if s.ipVerify {
|
|
|
|
|
ip := common.GetIpByAddr(linkAddr)
|
2019-03-23 14:19:59 +00:00
|
|
|
|
if v, ok := s.Register.Load(ip); !ok {
|
2019-02-16 12:43:26 +00:00
|
|
|
|
return nil, errors.New(fmt.Sprintf("The ip %s is not in the validation list", ip))
|
|
|
|
|
} else {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
if !v.(time.Time).After(time.Now()) {
|
2019-02-16 12:43:26 +00:00
|
|
|
|
return nil, errors.New(fmt.Sprintf("The validity of the ip %s has expired", ip))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-03-02 09:43:21 +00:00
|
|
|
|
var tunnel *mux.Mux
|
|
|
|
|
if t != nil && t.Mode == "file" {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
tunnel = v.(*Client).file
|
2019-03-02 09:43:21 +00:00
|
|
|
|
} else {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
tunnel = v.(*Client).tunnel
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
|
|
|
|
if tunnel == nil {
|
2019-03-01 09:23:14 +00:00
|
|
|
|
err = errors.New("the client connect error")
|
2019-01-31 18:06:30 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2019-03-02 09:43:21 +00:00
|
|
|
|
if target, err = tunnel.NewConn(); err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if t != nil && t.Mode == "file" {
|
2019-01-31 18:06:30 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2019-03-01 09:23:14 +00:00
|
|
|
|
|
|
|
|
|
if _, err = conn.NewConn(target).SendLinkInfo(link); err != nil {
|
2019-03-02 09:43:21 +00:00
|
|
|
|
logs.Info("new connect error ,the target %s refuse to connect", link.Host)
|
2019-01-31 18:06:30 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2019-02-23 15:29:48 +00:00
|
|
|
|
err = errors.New(fmt.Sprintf("the client %d is not connect", clientId))
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
2019-01-31 18:06:30 +00:00
|
|
|
|
return
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-02 09:43:21 +00:00
|
|
|
|
func (s *Bridge) ping() {
|
|
|
|
|
ticker := time.NewTicker(time.Second * 5)
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-ticker.C:
|
|
|
|
|
arr := make([]int, 0)
|
2019-03-23 14:19:59 +00:00
|
|
|
|
s.Client.Range(func(key, value interface{}) bool {
|
|
|
|
|
v := value.(*Client)
|
2019-03-02 12:12:58 +00:00
|
|
|
|
if v.tunnel == nil || v.signal == nil {
|
2019-03-02 09:43:21 +00:00
|
|
|
|
v.retryTime += 1
|
|
|
|
|
if v.retryTime >= 3 {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
arr = append(arr, key.(int))
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
|
|
|
|
if v.tunnel.IsClose {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
arr = append(arr, key.(int))
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
|
|
|
|
})
|
2019-03-02 09:43:21 +00:00
|
|
|
|
for _, v := range arr {
|
|
|
|
|
logs.Info("the client %d closed", v)
|
2019-03-23 14:19:59 +00:00
|
|
|
|
s.DelClient(v)
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-01 09:23:14 +00:00
|
|
|
|
//get config and add task from client config
|
2019-03-02 09:43:21 +00:00
|
|
|
|
func (s *Bridge) getConfig(c *conn.Conn, isPub bool, client *file.Client) {
|
2019-02-12 19:54:00 +00:00
|
|
|
|
var fail bool
|
2019-03-02 12:56:57 +00:00
|
|
|
|
loop:
|
2019-02-12 19:54:00 +00:00
|
|
|
|
for {
|
|
|
|
|
flag, err := c.ReadFlag()
|
|
|
|
|
if err != nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
switch flag {
|
|
|
|
|
case common.WORK_STATUS:
|
2019-03-01 09:23:14 +00:00
|
|
|
|
if b, err := c.GetShortContent(32); err != nil {
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-02-12 19:54:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
var str string
|
|
|
|
|
id, err := file.GetCsvDb().GetClientIdByVkey(string(b))
|
|
|
|
|
if err != nil {
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-02-12 19:54:00 +00:00
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
|
|
|
|
|
v := value.(*file.Host)
|
2019-02-12 19:54:00 +00:00
|
|
|
|
if v.Client.Id == id {
|
|
|
|
|
str += v.Remark + common.CONN_DATA_SEQ
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
|
|
|
|
})
|
|
|
|
|
file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
|
|
|
|
|
v := value.(*file.Tunnel)
|
2019-02-16 15:18:58 +00:00
|
|
|
|
if _, ok := s.runList[v.Id]; ok && v.Client.Id == id {
|
2019-02-12 19:54:00 +00:00
|
|
|
|
str += v.Remark + common.CONN_DATA_SEQ
|
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
return true
|
|
|
|
|
})
|
2019-02-12 19:54:00 +00:00
|
|
|
|
binary.Write(c, binary.LittleEndian, int32(len([]byte(str))))
|
|
|
|
|
binary.Write(c, binary.LittleEndian, []byte(str))
|
|
|
|
|
}
|
|
|
|
|
case common.NEW_CONF:
|
2019-02-23 15:29:48 +00:00
|
|
|
|
var err error
|
|
|
|
|
if client, err = c.GetConfigInfo(); err != nil {
|
2019-02-12 19:54:00 +00:00
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-02-12 19:54:00 +00:00
|
|
|
|
} else {
|
2019-02-24 05:17:43 +00:00
|
|
|
|
if err = file.GetCsvDb().NewClient(client); err != nil {
|
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-02-24 05:17:43 +00:00
|
|
|
|
}
|
2019-02-12 19:54:00 +00:00
|
|
|
|
c.WriteAddOk()
|
2019-02-24 05:17:43 +00:00
|
|
|
|
c.Write([]byte(client.VerifyKey))
|
2019-03-23 14:19:59 +00:00
|
|
|
|
s.Client.Store(client.Id, NewClient(nil, nil, nil))
|
2019-02-12 19:54:00 +00:00
|
|
|
|
}
|
|
|
|
|
case common.NEW_HOST:
|
2019-03-02 09:43:21 +00:00
|
|
|
|
h, err := c.GetHostInfo()
|
|
|
|
|
if err != nil {
|
2019-02-12 19:54:00 +00:00
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
|
|
|
|
h.Client = client
|
|
|
|
|
if h.Location == "" {
|
|
|
|
|
h.Location = "/"
|
|
|
|
|
}
|
|
|
|
|
if !client.HasHost(h) {
|
|
|
|
|
if file.GetCsvDb().IsHostExist(h) {
|
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-03-02 09:43:21 +00:00
|
|
|
|
} else {
|
|
|
|
|
file.GetCsvDb().NewHost(h)
|
|
|
|
|
c.WriteAddOk()
|
|
|
|
|
}
|
2019-02-12 19:54:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
c.WriteAddOk()
|
|
|
|
|
}
|
|
|
|
|
case common.NEW_TASK:
|
|
|
|
|
if t, err := c.GetTaskInfo(); err != nil {
|
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-02-12 19:54:00 +00:00
|
|
|
|
} else {
|
2019-02-15 14:59:28 +00:00
|
|
|
|
ports := common.GetPorts(t.Ports)
|
|
|
|
|
targets := common.GetPorts(t.Target)
|
2019-03-01 09:23:14 +00:00
|
|
|
|
if len(ports) > 1 && (t.Mode == "tcp" || t.Mode == "udp") && (len(ports) != len(targets)) {
|
2019-02-12 19:54:00 +00:00
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-03-01 09:23:14 +00:00
|
|
|
|
} else if t.Mode == "secret" {
|
2019-02-23 15:29:48 +00:00
|
|
|
|
ports = append(ports, 0)
|
|
|
|
|
}
|
|
|
|
|
if len(ports) == 0 {
|
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-02-15 14:59:28 +00:00
|
|
|
|
}
|
|
|
|
|
for i := 0; i < len(ports); i++ {
|
|
|
|
|
tl := new(file.Tunnel)
|
|
|
|
|
tl.Mode = t.Mode
|
|
|
|
|
tl.Port = ports[i]
|
|
|
|
|
if len(ports) == 1 {
|
|
|
|
|
tl.Target = t.Target
|
2019-02-16 15:18:58 +00:00
|
|
|
|
tl.Remark = t.Remark
|
2019-02-15 14:59:28 +00:00
|
|
|
|
} else {
|
2019-02-16 15:18:58 +00:00
|
|
|
|
tl.Remark = t.Remark + "_" + strconv.Itoa(tl.Port)
|
2019-03-01 09:23:14 +00:00
|
|
|
|
if t.TargetAddr != "" {
|
|
|
|
|
tl.Target = t.TargetAddr + ":" + strconv.Itoa(targets[i])
|
|
|
|
|
} else {
|
|
|
|
|
tl.Target = strconv.Itoa(targets[i])
|
|
|
|
|
}
|
2019-02-15 14:59:28 +00:00
|
|
|
|
}
|
2019-03-23 14:19:59 +00:00
|
|
|
|
tl.Id = int(file.GetCsvDb().GetTaskId())
|
2019-02-15 14:59:28 +00:00
|
|
|
|
tl.Status = true
|
|
|
|
|
tl.Flow = new(file.Flow)
|
|
|
|
|
tl.NoStore = true
|
|
|
|
|
tl.Client = client
|
2019-02-23 15:29:48 +00:00
|
|
|
|
tl.Password = t.Password
|
2019-03-02 09:43:21 +00:00
|
|
|
|
tl.LocalPath = t.LocalPath
|
|
|
|
|
tl.StripPre = t.StripPre
|
|
|
|
|
if !client.HasTunnel(tl) {
|
|
|
|
|
if err := file.GetCsvDb().NewTask(tl); err != nil {
|
|
|
|
|
logs.Notice("Add task error ", err.Error())
|
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-03-02 09:43:21 +00:00
|
|
|
|
}
|
|
|
|
|
if b := tool.TestServerPort(tl.Port, tl.Mode); !b && t.Mode != "secret" && t.Mode != "p2p" {
|
|
|
|
|
fail = true
|
|
|
|
|
c.WriteAddFail()
|
2019-03-02 12:56:57 +00:00
|
|
|
|
break loop
|
2019-03-02 09:43:21 +00:00
|
|
|
|
} else {
|
|
|
|
|
s.OpenTask <- tl
|
|
|
|
|
}
|
2019-02-15 14:59:28 +00:00
|
|
|
|
}
|
|
|
|
|
c.WriteAddOk()
|
2019-02-12 19:54:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-02-12 19:54:00 +00:00
|
|
|
|
if fail && client != nil {
|
2019-03-23 14:19:59 +00:00
|
|
|
|
s.DelClient(client.Id)
|
2019-02-12 19:54:00 +00:00
|
|
|
|
}
|
|
|
|
|
c.Close()
|
2019-01-09 12:33:00 +00:00
|
|
|
|
}
|