nps/server/server.go

211 lines
4.5 KiB
Go
Raw Normal View History

2019-01-09 12:33:00 +00:00
package server
import (
"errors"
2019-01-10 01:33:05 +00:00
"github.com/astaxie/beego"
2019-01-09 12:33:00 +00:00
"github.com/cnlh/easyProxy/bridge"
"github.com/cnlh/easyProxy/utils"
"log"
"reflect"
"strings"
"sync"
)
var (
Bridge *bridge.Tunnel
RunList map[string]interface{} //运行中的任务
CsvDb *Csv
VerifyKey string
)
func init() {
RunList = make(map[string]interface{})
}
//从csv文件中恢复任务
func InitFromCsv() {
for _, v := range CsvDb.Tasks {
if v.Start == 1 {
log.Println("启动模式:", v.Mode, "监听端口:", v.TcpPort, "客户端令牌:", v.VerifyKey)
AddTask(v)
}
}
}
//start a new server
func StartNewServer(bridgePort int, cnf *ServerConfig) {
Bridge = bridge.NewTunnel(bridgePort, RunList)
if err := Bridge.StartTunnel(); err != nil {
log.Fatalln("服务端开启失败", err)
}
if svr := NewMode(Bridge, cnf); svr != nil {
RunList[cnf.VerifyKey] = svr
err := reflect.ValueOf(svr).MethodByName("Start").Call(nil)[0]
if err.Interface() != nil {
log.Println(err)
}
} else {
log.Fatalln("启动模式不正确")
}
}
//new a server by mode name
func NewMode(Bridge *bridge.Tunnel, config *ServerConfig) interface{} {
switch config.Mode {
case "tunnelServer":
return NewTunnelModeServer(ProcessTunnel, Bridge, config)
case "socks5Server":
return NewSock5ModeServer(Bridge, config)
case "httpProxyServer":
return NewTunnelModeServer(ProcessHttp, Bridge, config)
case "udpServer":
return NewUdpModeServer(Bridge, config)
case "webServer":
InitCsvDb()
InitFromCsv()
2019-01-10 01:33:05 +00:00
p, _ := beego.AppConfig.Int("hostPort")
2019-01-09 12:33:00 +00:00
t := &ServerConfig{
2019-01-10 01:33:05 +00:00
TcpPort: p,
2019-01-09 12:33:00 +00:00
Mode: "httpHostServer",
Target: "",
VerifyKey: "",
U: "",
P: "",
Compress: "",
Start: 1,
IsRun: 0,
ClientStatus: 0,
}
AddTask(t)
return NewWebServer(Bridge)
case "hostServer":
return NewHostServer(config)
case "httpHostServer":
return NewTunnelModeServer(ProcessHost, Bridge, config)
}
return nil
}
//stop server
func StopServer(cFlag string) error {
if v, ok := RunList[cFlag]; ok {
reflect.ValueOf(v).MethodByName("Close").Call(nil)
delete(RunList, cFlag)
if VerifyKey == "" { //多客户端模式关闭相关隧道
Bridge.DelClientSignal(cFlag)
Bridge.DelClientTunnel(cFlag)
}
if t, err := CsvDb.GetTask(cFlag); err != nil {
return err
} else {
t.Start = 0
CsvDb.UpdateTask(t)
}
return nil
}
return errors.New("未在运行中")
}
//add task
func AddTask(t *ServerConfig) error {
t.CompressDecode, t.CompressEncode = utils.GetCompressType(t.Compress)
if svr := NewMode(Bridge, t); svr != nil {
RunList[t.VerifyKey] = svr
go func() {
err := reflect.ValueOf(svr).MethodByName("Start").Call(nil)[0]
if err.Interface() != nil {
log.Println("客户端", t.VerifyKey, "启动失败,错误:", err)
delete(RunList, t.VerifyKey)
}
}()
} else {
return errors.New("启动模式不正确")
}
return nil
}
//start task
func StartTask(vKey string) error {
if t, err := CsvDb.GetTask(vKey); err != nil {
return err
} else {
AddTask(t)
t.Start = 1
CsvDb.UpdateTask(t)
}
return nil
}
//delete task
func DelTask(vKey string) error {
if err := StopServer(vKey); err != nil {
return err
}
return CsvDb.DelTask(vKey)
}
//init csv from file
func InitCsvDb() *Csv {
var once sync.Once
once.Do(func() {
CsvDb = NewCsv(RunList)
CsvDb.Init()
})
return CsvDb
}
//get key by host from x
func GetKeyByHost(host string) (h *HostList, t *ServerConfig, err error) {
for _, v := range CsvDb.Hosts {
if strings.Contains(host, v.Host) {
h = v
t, err = CsvDb.GetTask(v.Vkey)
return
}
}
err = errors.New("未找到host对应的内网目标")
return
}
//get task list by page num
func GetServerConfig(start, length int, typeVal string) ([]*ServerConfig, int) {
list := make([]*ServerConfig, 0)
var cnt int
for _, v := range CsvDb.Tasks {
if v.Mode != typeVal {
continue
}
cnt++
if start--; start < 0 {
if length--; length > 0 {
if _, ok := RunList[v.VerifyKey]; ok {
v.IsRun = 1
} else {
v.IsRun = 0
}
if s, ok := Bridge.SignalList[getverifyval(v.VerifyKey)]; ok {
if s.Len() > 0 {
v.ClientStatus = 1
} else {
v.ClientStatus = 0
}
} else {
v.ClientStatus = 0
}
list = append(list, v)
}
}
}
return list, cnt
}
//get verify value
//when mode is webServer and vKey is not none
func getverifyval(vkey string) string {
if VerifyKey != "" {
return utils.Md5(VerifyKey)
}
return utils.Md5(vkey)
}