mirror of
https://github.com/ehang-io/nps.git
synced 2025-09-02 03:16:53 +00:00
dashboard 备注 客户端管理优化 多客户端支持 流量显示支持 热更新支持 404错误页支持
This commit is contained in:
76
server/base.go
Normal file
76
server/base.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/cnlh/easyProxy/bridge"
|
||||
"github.com/cnlh/easyProxy/utils"
|
||||
"sync"
|
||||
)
|
||||
|
||||
//server base struct
|
||||
type server struct {
|
||||
bridge *bridge.Tunnel
|
||||
config *utils.ServerConfig
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (s *server) GetTunnelAndWriteHost(connType string, cnf *utils.ServerConfig, addr string) (*utils.Conn, error) {
|
||||
var err error
|
||||
link, err := s.bridge.GetTunnel(cnf.ClientId, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = link.WriteHost(connType, addr); err != nil {
|
||||
link.Close()
|
||||
return nil, err
|
||||
}
|
||||
return link, nil
|
||||
}
|
||||
|
||||
func (s *server) FlowAdd(in, out int64) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
if s.config.Flow == nil {
|
||||
s.config.Flow = new(utils.Flow)
|
||||
}
|
||||
s.config.Flow.ExportFlow += out
|
||||
s.config.Flow.InletFlow += in
|
||||
}
|
||||
|
||||
func (s *server) FlowAddHost(host *utils.HostList, in, out int64) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
if s.config.Flow == nil {
|
||||
s.config.Flow = new(utils.Flow)
|
||||
}
|
||||
host.Flow.ExportFlow += out
|
||||
host.Flow.InletFlow += in
|
||||
}
|
||||
|
||||
//热更新配置
|
||||
func (s *server) ResetConfig() {
|
||||
task, err := CsvDb.GetTask(s.config.Id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.config.UseClientCnf = task.UseClientCnf
|
||||
if s.config.UseClientCnf {
|
||||
client, err := CsvDb.GetClient(s.config.ClientId)
|
||||
if err == nil {
|
||||
s.config.U = client.Cnf.U
|
||||
s.config.P = client.Cnf.P
|
||||
s.config.Compress = client.Cnf.Compress
|
||||
s.config.Mux = client.Cnf.Mux
|
||||
s.config.Crypt = client.Cnf.Crypt
|
||||
}
|
||||
s.config.CompressDecode, s.config.CompressEncode = utils.GetCompressType(client.Cnf.Compress)
|
||||
} else {
|
||||
if err == nil {
|
||||
s.config.U = task.U
|
||||
s.config.P = task.P
|
||||
s.config.Compress = task.Compress
|
||||
s.config.Mux = task.Mux
|
||||
s.config.Crypt = task.Crypt
|
||||
}
|
||||
s.config.CompressDecode, s.config.CompressEncode = utils.GetCompressType(task.Compress)
|
||||
}
|
||||
}
|
271
server/file.go
271
server/file.go
@@ -1,271 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/cnlh/easyProxy/utils"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
TcpPort int //服务端与客户端通信端口
|
||||
Mode string //启动方式
|
||||
Target string //目标
|
||||
VerifyKey string //flag
|
||||
U string //socks5验证用户名
|
||||
P string //socks5验证密码
|
||||
Compress string //压缩方式
|
||||
Start int //是否开启
|
||||
IsRun int //是否在运行
|
||||
ClientStatus int //客s户端状态
|
||||
Crypt bool //是否加密
|
||||
Mux bool //是否加密
|
||||
CompressEncode int //加密方式
|
||||
CompressDecode int //解密方式
|
||||
}
|
||||
|
||||
type HostList struct {
|
||||
Vkey string //服务端与客户端通信端口
|
||||
Host string //启动方式
|
||||
Target string //目标
|
||||
HeaderChange string //host修改
|
||||
HostChange string //host修改
|
||||
}
|
||||
|
||||
func NewCsv(runList map[string]interface{}) *Csv {
|
||||
c := new(Csv)
|
||||
c.RunList = runList
|
||||
return c
|
||||
}
|
||||
|
||||
type Csv struct {
|
||||
Tasks []*ServerConfig
|
||||
Path string
|
||||
RunList map[string]interface{}
|
||||
Hosts []*HostList //域名列表
|
||||
}
|
||||
|
||||
func (s *Csv) Init() {
|
||||
s.LoadTaskFromCsv()
|
||||
s.LoadHostFromCsv()
|
||||
}
|
||||
|
||||
func (s *Csv) StoreTasksToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(beego.AppPath + "/conf/tasks.csv")
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
defer csvFile.Close()
|
||||
writer := csv.NewWriter(csvFile)
|
||||
for _, task := range s.Tasks {
|
||||
record := []string{
|
||||
strconv.Itoa(task.TcpPort),
|
||||
task.Mode,
|
||||
task.Target,
|
||||
task.VerifyKey,
|
||||
task.U,
|
||||
task.P,
|
||||
task.Compress,
|
||||
strconv.Itoa(task.Start),
|
||||
utils.GetStrByBool(task.Crypt),
|
||||
utils.GetStrByBool(task.Mux),
|
||||
strconv.Itoa(task.CompressEncode),
|
||||
strconv.Itoa(task.CompressDecode),
|
||||
}
|
||||
err := writer.Write(record)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
}
|
||||
writer.Flush()
|
||||
}
|
||||
|
||||
func (s *Csv) openFile(path string) ([][]string, error) {
|
||||
// 打开文件
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 获取csv的reader
|
||||
reader := csv.NewReader(file)
|
||||
|
||||
// 设置FieldsPerRecord为-1
|
||||
reader.FieldsPerRecord = -1
|
||||
|
||||
// 读取文件中所有行保存到slice中
|
||||
return reader.ReadAll()
|
||||
}
|
||||
|
||||
func (s *Csv) LoadTaskFromCsv() {
|
||||
path := beego.AppPath + "/conf/tasks.csv"
|
||||
records, err := s.openFile(path)
|
||||
if err != nil {
|
||||
log.Fatal("配置文件打开错误:", path)
|
||||
}
|
||||
var tasks []*ServerConfig
|
||||
// 将每一行数据保存到内存slice中
|
||||
for _, item := range records {
|
||||
post := &ServerConfig{
|
||||
TcpPort: utils.GetIntNoErrByStr(item[0]),
|
||||
Mode: item[1],
|
||||
Target: item[2],
|
||||
VerifyKey: item[3],
|
||||
U: item[4],
|
||||
P: item[5],
|
||||
Compress: item[6],
|
||||
Start: utils.GetIntNoErrByStr(item[7]),
|
||||
Crypt: utils.GetBoolByStr(item[8]),
|
||||
Mux: utils.GetBoolByStr(item[9]),
|
||||
CompressEncode: utils.GetIntNoErrByStr(item[10]),
|
||||
CompressDecode: utils.GetIntNoErrByStr(item[11]),
|
||||
}
|
||||
tasks = append(tasks, post)
|
||||
}
|
||||
s.Tasks = tasks
|
||||
}
|
||||
|
||||
func (s *Csv) NewTask(t *ServerConfig) {
|
||||
s.Tasks = append(s.Tasks, t)
|
||||
s.StoreTasksToCsv()
|
||||
}
|
||||
|
||||
func (s *Csv) UpdateTask(t *ServerConfig) error {
|
||||
for k, v := range s.Tasks {
|
||||
if v.VerifyKey == t.VerifyKey {
|
||||
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
|
||||
s.Tasks = append(s.Tasks, t)
|
||||
s.StoreTasksToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) UpdateHost(t *HostList) error {
|
||||
for k, v := range s.Hosts {
|
||||
if v.Host == t.Host {
|
||||
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
|
||||
s.Hosts = append(s.Hosts, t)
|
||||
s.StoreHostToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) AddRunList(vKey string, svr interface{}) {
|
||||
s.RunList[vKey] = svr
|
||||
}
|
||||
|
||||
func (s *Csv) DelRunList(vKey string) {
|
||||
delete(s.RunList, vKey)
|
||||
}
|
||||
|
||||
func (s *Csv) DelTask(vKey string) error {
|
||||
for k, v := range s.Tasks {
|
||||
if v.VerifyKey == vKey {
|
||||
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
|
||||
s.StoreTasksToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) GetTask(vKey string) (v *ServerConfig, err error) {
|
||||
for _, v = range s.Tasks {
|
||||
if v.VerifyKey == vKey {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New("未找到")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Csv) StoreHostToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(beego.AppPath + "/conf/hosts.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer csvFile.Close()
|
||||
// 获取csv的Writer
|
||||
writer := csv.NewWriter(csvFile)
|
||||
// 将map中的Post转换成slice,因为csv的Write需要slice参数
|
||||
// 并写入csv文件
|
||||
for _, host := range s.Hosts {
|
||||
record := []string{
|
||||
host.Host,
|
||||
host.Target,
|
||||
host.Vkey,
|
||||
host.HeaderChange,
|
||||
host.HostChange,
|
||||
}
|
||||
err1 := writer.Write(record)
|
||||
if err1 != nil {
|
||||
panic(err1)
|
||||
}
|
||||
}
|
||||
// 确保所有内存数据刷到csv文件
|
||||
writer.Flush()
|
||||
}
|
||||
|
||||
func (s *Csv) LoadHostFromCsv() {
|
||||
path := beego.AppPath + "/conf/hosts.csv"
|
||||
records, err := s.openFile(path)
|
||||
if err != nil {
|
||||
log.Fatal("配置文件打开错误:", path)
|
||||
}
|
||||
var hosts []*HostList
|
||||
// 将每一行数据保存到内存slice中
|
||||
for _, item := range records {
|
||||
post := &HostList{
|
||||
Vkey: item[2],
|
||||
Host: item[0],
|
||||
Target: item[1],
|
||||
HeaderChange: item[3],
|
||||
HostChange: item[4],
|
||||
}
|
||||
hosts = append(hosts, post)
|
||||
}
|
||||
s.Hosts = hosts
|
||||
}
|
||||
|
||||
func (s *Csv) DelHost(host string) error {
|
||||
for k, v := range s.Hosts {
|
||||
if v.Host == host {
|
||||
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
|
||||
s.StoreHostToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) NewHost(t *HostList) {
|
||||
s.Hosts = append(s.Hosts, t)
|
||||
s.StoreHostToCsv()
|
||||
|
||||
}
|
||||
|
||||
func (s *Csv) GetHostList(start, length int, vKey string) ([]*HostList, int) {
|
||||
list := make([]*HostList, 0)
|
||||
var cnt int
|
||||
for _, v := range s.Hosts {
|
||||
if v.Vkey == vKey {
|
||||
cnt++
|
||||
if start--; start < 0 {
|
||||
if length--; length > 0 {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list, cnt
|
||||
}
|
@@ -41,8 +41,8 @@ func ProcessHost(c *utils.Conn, s *TunnelModeServer) error {
|
||||
var (
|
||||
isConn = true
|
||||
link *utils.Conn
|
||||
cnf *ServerConfig
|
||||
host *HostList
|
||||
client *utils.Client
|
||||
host *utils.HostList
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
for {
|
||||
@@ -52,48 +52,56 @@ func ProcessHost(c *utils.Conn, s *TunnelModeServer) error {
|
||||
}
|
||||
//首次获取conn
|
||||
if isConn {
|
||||
isConn = false
|
||||
if host, cnf, err = GetKeyByHost(r.Host); err != nil {
|
||||
if host, client, err = GetKeyByHost(r.Host); err != nil {
|
||||
log.Printf("the host %s is not found !", r.Host)
|
||||
break
|
||||
}
|
||||
|
||||
if err = s.auth(r, c, cnf.U, cnf.P); err != nil {
|
||||
client.Cnf.ClientId = host.ClientId
|
||||
client.Cnf.CompressDecode, client.Cnf.CompressEncode = utils.GetCompressType(client.Cnf.Compress)
|
||||
if err = s.auth(r, c, client.Cnf.U, client.Cnf.P); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if link, err = s.GetTunnelAndWriteHost(utils.CONN_TCP, cnf, host.Target); err != nil {
|
||||
if link, err = s.GetTunnelAndWriteHost(utils.CONN_TCP, client.Cnf, host.Target); err != nil {
|
||||
log.Println("get bridge tunnel error: ", err)
|
||||
break
|
||||
}
|
||||
|
||||
if flag, err := link.ReadFlag(); err != nil || flag == utils.CONN_ERROR {
|
||||
log.Printf("the host %s connection to %s error", r.Host, host.Target)
|
||||
break
|
||||
} else {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
utils.Relay(c.Conn, link.Conn, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
out, _ := utils.Relay(c.Conn, link.Conn, client.Cnf.CompressDecode, client.Cnf.Crypt, client.Cnf.Mux)
|
||||
wg.Done()
|
||||
s.FlowAddHost(host, 0, out)
|
||||
}()
|
||||
}
|
||||
isConn = false
|
||||
}
|
||||
utils.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
|
||||
b, err := httputil.DumpRequest(r, true)
|
||||
s.FlowAddHost(host, int64(len(b)), 0)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if _, err := link.WriteTo(b, cnf.CompressEncode, cnf.Crypt); err != nil {
|
||||
if _, err := link.WriteTo(b, client.Cnf.CompressEncode, client.Cnf.Crypt); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
if cnf != nil && cnf.Mux && link != nil {
|
||||
link.WriteTo([]byte(utils.IO_EOF), cnf.CompressEncode, cnf.Crypt)
|
||||
s.bridge.ReturnTunnel(link, getverifyval(cnf.VerifyKey))
|
||||
if client != nil && client.Cnf != nil && client.Cnf.Mux && link != nil {
|
||||
link.WriteTo([]byte(utils.IO_EOF), client.Cnf.CompressEncode, client.Cnf.Crypt)
|
||||
s.bridge.ReturnTunnel(link, client.Id)
|
||||
} else if link != nil {
|
||||
link.Close()
|
||||
}
|
||||
|
||||
if isConn {
|
||||
s.writeConnFail(c.Conn)
|
||||
}
|
||||
c.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
187
server/server.go
187
server/server.go
@@ -11,35 +11,43 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type RunServer struct {
|
||||
flag int //标志
|
||||
ExportFlow int64 //出口流量
|
||||
InletFlow int64 //入口流量
|
||||
service interface{}
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
var (
|
||||
Bridge *bridge.Tunnel
|
||||
RunList map[string]interface{} //运行中的任务
|
||||
CsvDb *Csv
|
||||
RunList map[int]interface{} //运行中的任务
|
||||
CsvDb = utils.GetCsvDb()
|
||||
VerifyKey string
|
||||
)
|
||||
|
||||
func init() {
|
||||
RunList = make(map[string]interface{})
|
||||
RunList = make(map[int]interface{})
|
||||
}
|
||||
|
||||
//从csv文件中恢复任务
|
||||
func InitFromCsv() {
|
||||
for _, v := range CsvDb.Tasks {
|
||||
if v.Start == 1 {
|
||||
log.Println("启动模式:", v.Mode, "监听端口:", v.TcpPort, "客户端令牌:", v.VerifyKey)
|
||||
log.Println("启动模式:", v.Mode, "监听端口:", v.TcpPort)
|
||||
AddTask(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//start a new server
|
||||
func StartNewServer(bridgePort int, cnf *ServerConfig) {
|
||||
func StartNewServer(bridgePort int, cnf *utils.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
|
||||
RunList[cnf.Id] = svr
|
||||
err := reflect.ValueOf(svr).MethodByName("Start").Call(nil)[0]
|
||||
if err.Interface() != nil {
|
||||
log.Println(err)
|
||||
@@ -50,7 +58,8 @@ func StartNewServer(bridgePort int, cnf *ServerConfig) {
|
||||
}
|
||||
|
||||
//new a server by mode name
|
||||
func NewMode(Bridge *bridge.Tunnel, config *ServerConfig) interface{} {
|
||||
func NewMode(Bridge *bridge.Tunnel, c *utils.ServerConfig) interface{} {
|
||||
config := utils.DeepCopyConfig(c)
|
||||
switch config.Mode {
|
||||
case "tunnelServer":
|
||||
return NewTunnelModeServer(ProcessTunnel, Bridge, config)
|
||||
@@ -61,14 +70,12 @@ func NewMode(Bridge *bridge.Tunnel, config *ServerConfig) interface{} {
|
||||
case "udpServer":
|
||||
return NewUdpModeServer(Bridge, config)
|
||||
case "webServer":
|
||||
InitCsvDb()
|
||||
InitFromCsv()
|
||||
p, _ := beego.AppConfig.Int("hostPort")
|
||||
t := &ServerConfig{
|
||||
t := &utils.ServerConfig{
|
||||
TcpPort: p,
|
||||
Mode: "httpHostServer",
|
||||
Target: "",
|
||||
VerifyKey: "",
|
||||
U: "",
|
||||
P: "",
|
||||
Compress: "",
|
||||
@@ -87,15 +94,10 @@ func NewMode(Bridge *bridge.Tunnel, config *ServerConfig) interface{} {
|
||||
}
|
||||
|
||||
//stop server
|
||||
func StopServer(cFlag string) error {
|
||||
if v, ok := RunList[cFlag]; ok {
|
||||
func StopServer(id int) error {
|
||||
if v, ok := RunList[id]; 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 {
|
||||
if t, err := CsvDb.GetTask(id); err != nil {
|
||||
return err
|
||||
} else {
|
||||
t.Start = 0
|
||||
@@ -107,15 +109,14 @@ func StopServer(cFlag string) error {
|
||||
}
|
||||
|
||||
//add task
|
||||
func AddTask(t *ServerConfig) error {
|
||||
t.CompressDecode, t.CompressEncode = utils.GetCompressType(t.Compress)
|
||||
func AddTask(t *utils.ServerConfig) error {
|
||||
if svr := NewMode(Bridge, t); svr != nil {
|
||||
RunList[t.VerifyKey] = svr
|
||||
RunList[t.Id] = 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)
|
||||
log.Println("客户端", t.Id, "启动失败,错误:", err)
|
||||
delete(RunList, t.Id)
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
@@ -125,8 +126,8 @@ func AddTask(t *ServerConfig) error {
|
||||
}
|
||||
|
||||
//start task
|
||||
func StartTask(vKey string) error {
|
||||
if t, err := CsvDb.GetTask(vKey); err != nil {
|
||||
func StartTask(id int) error {
|
||||
if t, err := CsvDb.GetTask(id); err != nil {
|
||||
return err
|
||||
} else {
|
||||
AddTask(t)
|
||||
@@ -137,35 +138,20 @@ func StartTask(vKey string) error {
|
||||
}
|
||||
|
||||
//delete task
|
||||
func DelTask(vKey string) error {
|
||||
if err := StopServer(vKey); err != nil {
|
||||
func DelTask(id int) error {
|
||||
if err := StopServer(id); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range CsvDb.Hosts {
|
||||
if v.Vkey == vKey {
|
||||
CsvDb.DelHost(v.Host)
|
||||
}
|
||||
}
|
||||
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
|
||||
return CsvDb.DelTask(id)
|
||||
}
|
||||
|
||||
//get key by host from x
|
||||
func GetKeyByHost(host string) (h *HostList, t *ServerConfig, err error) {
|
||||
func GetKeyByHost(host string) (h *utils.HostList, t *utils.Client, err error) {
|
||||
for _, v := range CsvDb.Hosts {
|
||||
s := strings.Split(host, ":")
|
||||
if s[0] == v.Host {
|
||||
h = v
|
||||
t, err = CsvDb.GetTask(v.Vkey)
|
||||
t, err = CsvDb.GetClient(v.ClientId)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -174,22 +160,32 @@ func GetKeyByHost(host string) (h *HostList, t *ServerConfig, err error) {
|
||||
}
|
||||
|
||||
//get task list by page num
|
||||
func GetServerConfig(start, length int, typeVal string) ([]*ServerConfig, int) {
|
||||
list := make([]*ServerConfig, 0)
|
||||
func GetServerConfig(start, length int, typeVal string, clientId int) ([]*utils.ServerConfig, int) {
|
||||
list := make([]*utils.ServerConfig, 0)
|
||||
var cnt int
|
||||
for _, v := range CsvDb.Tasks {
|
||||
if v.Mode != typeVal {
|
||||
if (typeVal != "" && v.Mode != typeVal) || (typeVal == "" && clientId != v.ClientId) {
|
||||
continue
|
||||
}
|
||||
if v.UseClientCnf {
|
||||
v = utils.DeepCopyConfig(v)
|
||||
if c, err := CsvDb.GetClient(v.ClientId); err == nil {
|
||||
v.Compress = c.Cnf.Compress
|
||||
v.Mux = c.Cnf.Mux
|
||||
v.Crypt = c.Cnf.Crypt
|
||||
v.U = c.Cnf.U
|
||||
v.P = c.Cnf.P
|
||||
}
|
||||
}
|
||||
cnt++
|
||||
if start--; start < 0 {
|
||||
if length--; length > 0 {
|
||||
if _, ok := RunList[v.VerifyKey]; ok {
|
||||
if _, ok := RunList[v.Id]; ok {
|
||||
v.IsRun = 1
|
||||
} else {
|
||||
v.IsRun = 0
|
||||
}
|
||||
if s, ok := Bridge.SignalList[getverifyval(v.VerifyKey)]; ok {
|
||||
if s, ok := Bridge.SignalList[v.ClientId]; ok {
|
||||
if s.Len() > 0 {
|
||||
v.ClientStatus = 1
|
||||
} else {
|
||||
@@ -201,16 +197,91 @@ func GetServerConfig(start, length int, typeVal string) ([]*ServerConfig, int) {
|
||||
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)
|
||||
//获取客户端列表
|
||||
func GetClientList(start, length int) (list []*utils.Client, cnt int) {
|
||||
list, cnt = CsvDb.GetClientList(start, length)
|
||||
dealClientData(list)
|
||||
return
|
||||
}
|
||||
|
||||
func dealClientData(list []*utils.Client) {
|
||||
for _, v := range list {
|
||||
if _, ok := Bridge.SignalList[v.Id]; ok {
|
||||
v.IsConnect = true
|
||||
} else {
|
||||
v.IsConnect = false
|
||||
}
|
||||
v.Flow.InletFlow = 0
|
||||
v.Flow.ExportFlow = 0
|
||||
for _, h := range CsvDb.Hosts {
|
||||
if h.ClientId == v.Id {
|
||||
v.Flow.InletFlow += h.Flow.InletFlow
|
||||
v.Flow.ExportFlow += h.Flow.ExportFlow
|
||||
}
|
||||
}
|
||||
for _, t := range CsvDb.Tasks {
|
||||
if t.ClientId == v.Id {
|
||||
v.Flow.InletFlow += t.Flow.InletFlow
|
||||
v.Flow.ExportFlow += t.Flow.ExportFlow
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//根据客户端id删除其所属的所有隧道和域名
|
||||
func DelTunnelAndHostByClientId(clientId int) {
|
||||
for _, v := range CsvDb.Tasks {
|
||||
if v.ClientId == clientId {
|
||||
DelTask(v.Id)
|
||||
}
|
||||
}
|
||||
for _, v := range CsvDb.Hosts {
|
||||
if v.ClientId == clientId {
|
||||
CsvDb.DelHost(v.Host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//关闭客户端连接
|
||||
func DelClientConnect(clientId int) {
|
||||
Bridge.DelClientTunnel(clientId)
|
||||
Bridge.DelClientSignal(clientId)
|
||||
}
|
||||
|
||||
func GetDashboardData() map[string]int {
|
||||
data := make(map[string]int)
|
||||
data["hostCount"] = len(CsvDb.Hosts)
|
||||
data["clientCount"] = len(CsvDb.Clients)
|
||||
list := CsvDb.Clients
|
||||
dealClientData(list)
|
||||
c := 0
|
||||
var in, out int64
|
||||
for _, v := range list {
|
||||
if v.IsConnect {
|
||||
c += 1
|
||||
}
|
||||
in += v.Flow.InletFlow
|
||||
out += v.Flow.ExportFlow
|
||||
}
|
||||
data["clientOnlineCount"] = c
|
||||
data["inletFlowCount"] = int(in)
|
||||
data["exportFlowCount"] = int(out)
|
||||
for _, v := range CsvDb.Tasks {
|
||||
switch v.Mode {
|
||||
case "tunnelServer":
|
||||
data["tunnelServerCount"] += 1
|
||||
case "socks5Server":
|
||||
data["socks5ServerCount"] += 1
|
||||
case "httpProxyServer":
|
||||
data["httpProxyServerCount"] += 1
|
||||
case "udpServer":
|
||||
data["udpServerCount"] += 1
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
@@ -160,13 +160,14 @@ func (s *Sock5ModeServer) handleConnect(c net.Conn) {
|
||||
proxyConn, err := s.doConnect(c, connectMethod)
|
||||
defer func() {
|
||||
if s.config.Mux && proxyConn != nil {
|
||||
s.bridge.ReturnTunnel(proxyConn, getverifyval(s.config.VerifyKey))
|
||||
s.bridge.ReturnTunnel(proxyConn, s.config.ClientId)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
c.Close()
|
||||
} else {
|
||||
utils.ReplayWaitGroup(proxyConn.Conn, c, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
out, in := utils.ReplayWaitGroup(proxyConn.Conn, c, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
s.FlowAdd(in, out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,13 +198,14 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||
proxyConn, err := s.doConnect(c, associateMethod)
|
||||
defer func() {
|
||||
if s.config.Mux && proxyConn != nil {
|
||||
s.bridge.ReturnTunnel(proxyConn, getverifyval(s.config.VerifyKey))
|
||||
s.bridge.ReturnTunnel(proxyConn, s.config.ClientId)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
c.Close()
|
||||
} else {
|
||||
utils.ReplayWaitGroup(proxyConn.Conn, c, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
out, in := utils.ReplayWaitGroup(proxyConn.Conn, c, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
s.FlowAdd(in, out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +297,7 @@ func (s *Sock5ModeServer) Start() error {
|
||||
}
|
||||
log.Fatal("accept error: ", err)
|
||||
}
|
||||
s.ResetConfig()
|
||||
go s.handleConn(conn)
|
||||
}
|
||||
return nil
|
||||
@@ -306,7 +309,7 @@ func (s *Sock5ModeServer) Close() error {
|
||||
}
|
||||
|
||||
//new
|
||||
func NewSock5ModeServer(bridge *bridge.Tunnel, cnf *ServerConfig) *Sock5ModeServer {
|
||||
func NewSock5ModeServer(bridge *bridge.Tunnel, cnf *utils.ServerConfig) *Sock5ModeServer {
|
||||
s := new(Sock5ModeServer)
|
||||
s.bridge = bridge
|
||||
s.config = cnf
|
||||
|
@@ -12,33 +12,15 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
//server base struct
|
||||
type server struct {
|
||||
bridge *bridge.Tunnel
|
||||
config *ServerConfig
|
||||
}
|
||||
|
||||
func (s *server) GetTunnelAndWriteHost(connType string, cnf *ServerConfig, addr string) (*utils.Conn, error) {
|
||||
var err error
|
||||
link, err := s.bridge.GetTunnel(getverifyval(cnf.VerifyKey), cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = link.WriteHost(connType, addr); err != nil {
|
||||
link.Close()
|
||||
return nil, err
|
||||
}
|
||||
return link, nil
|
||||
}
|
||||
|
||||
type TunnelModeServer struct {
|
||||
server
|
||||
process process
|
||||
listener *net.TCPListener
|
||||
errorContent []byte
|
||||
process process
|
||||
listener *net.TCPListener
|
||||
}
|
||||
|
||||
//tcp|http|host
|
||||
func NewTunnelModeServer(process process, bridge *bridge.Tunnel, cnf *ServerConfig) *TunnelModeServer {
|
||||
func NewTunnelModeServer(process process, bridge *bridge.Tunnel, cnf *utils.ServerConfig) *TunnelModeServer {
|
||||
s := new(TunnelModeServer)
|
||||
s.bridge = bridge
|
||||
s.process = process
|
||||
@@ -49,6 +31,9 @@ func NewTunnelModeServer(process process, bridge *bridge.Tunnel, cnf *ServerConf
|
||||
//开始
|
||||
func (s *TunnelModeServer) Start() error {
|
||||
var err error
|
||||
if s.errorContent, err = utils.ReadAllFromFile(beego.AppPath + "/web/static/page/error.html"); err != nil {
|
||||
s.errorContent = []byte("easyProxy 404")
|
||||
}
|
||||
s.listener, err = net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), s.config.TcpPort, ""})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -62,6 +47,7 @@ func (s *TunnelModeServer) Start() error {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
s.ResetConfig()
|
||||
go s.process(utils.NewConn(conn), s)
|
||||
}
|
||||
return nil
|
||||
@@ -70,20 +56,25 @@ func (s *TunnelModeServer) Start() error {
|
||||
//权限认证
|
||||
func (s *TunnelModeServer) auth(r *http.Request, c *utils.Conn, u, p string) error {
|
||||
if u != "" && p != "" && !utils.CheckAuth(r, u, p) {
|
||||
c.Write([]byte(utils.Unauthorized_BYTES))
|
||||
c.Write([]byte(utils.UnauthorizedBytes))
|
||||
c.Close()
|
||||
return errors.New("401 Unauthorized")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TunnelModeServer) writeConnFail(c net.Conn) {
|
||||
c.Write([]byte(utils.ConnectionFailBytes))
|
||||
c.Write(s.errorContent)
|
||||
}
|
||||
|
||||
//与客户端建立通道
|
||||
func (s *TunnelModeServer) dealClient(c *utils.Conn, cnf *ServerConfig, addr string, method string, rb []byte) error {
|
||||
func (s *TunnelModeServer) dealClient(c *utils.Conn, cnf *utils.ServerConfig, addr string, method string, rb []byte) error {
|
||||
var link *utils.Conn
|
||||
var err error
|
||||
defer func() {
|
||||
if cnf.Mux && link != nil {
|
||||
s.bridge.ReturnTunnel(link, getverifyval(cnf.VerifyKey))
|
||||
s.bridge.ReturnTunnel(link, cnf.ClientId)
|
||||
}
|
||||
}()
|
||||
if link, err = s.GetTunnelAndWriteHost(utils.CONN_TCP, cnf, addr); err != nil {
|
||||
@@ -97,7 +88,8 @@ func (s *TunnelModeServer) dealClient(c *utils.Conn, cnf *ServerConfig, addr str
|
||||
} else if rb != nil {
|
||||
link.WriteTo(rb, cnf.CompressEncode, cnf.Crypt)
|
||||
}
|
||||
utils.ReplayWaitGroup(link.Conn, c.Conn, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
out, in := utils.ReplayWaitGroup(link.Conn, c.Conn, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
s.FlowAdd(in, out)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -139,7 +131,7 @@ func (s *HostServer) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewHostServer(cnf *ServerConfig) *HostServer {
|
||||
func NewHostServer(cnf *utils.ServerConfig) *HostServer {
|
||||
s := new(HostServer)
|
||||
s.config = cnf
|
||||
return s
|
||||
|
@@ -10,13 +10,12 @@ import (
|
||||
)
|
||||
|
||||
type UdpModeServer struct {
|
||||
bridge *bridge.Tunnel
|
||||
server
|
||||
listener *net.UDPConn
|
||||
udpMap map[string]*utils.Conn
|
||||
config *ServerConfig
|
||||
}
|
||||
|
||||
func NewUdpModeServer(bridge *bridge.Tunnel, cnf *ServerConfig) *UdpModeServer {
|
||||
func NewUdpModeServer(bridge *bridge.Tunnel, cnf *utils.ServerConfig) *UdpModeServer {
|
||||
s := new(UdpModeServer)
|
||||
s.bridge = bridge
|
||||
s.udpMap = make(map[string]*utils.Conn)
|
||||
@@ -40,6 +39,7 @@ func (s *UdpModeServer) Start() error {
|
||||
}
|
||||
continue
|
||||
}
|
||||
s.ResetConfig()
|
||||
go s.process(addr, data[:n])
|
||||
}
|
||||
return nil
|
||||
@@ -47,7 +47,7 @@ func (s *UdpModeServer) Start() error {
|
||||
|
||||
//TODO:效率问题有待解决
|
||||
func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
||||
conn, err := s.bridge.GetTunnel(getverifyval(s.config.VerifyKey), s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
conn, err := s.bridge.GetTunnel(s.config.ClientId, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
@@ -60,21 +60,22 @@ func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
||||
defer func() {
|
||||
if conn != nil && s.config.Mux {
|
||||
conn.WriteTo([]byte(utils.IO_EOF), s.config.CompressEncode, s.config.Crypt)
|
||||
s.bridge.ReturnTunnel(conn, getverifyval(s.config.VerifyKey))
|
||||
s.bridge.ReturnTunnel(conn, s.config.ClientId)
|
||||
} else {
|
||||
conn.Close()
|
||||
}
|
||||
}()
|
||||
if flag == utils.CONN_SUCCESS {
|
||||
conn.WriteTo(data, s.config.CompressEncode, s.config.Crypt)
|
||||
buf := make([]byte, 1024)
|
||||
//conn.conn.SetReadDeadline(time.Now().Add(time.Duration(time.Second * 3)))
|
||||
n, err := conn.ReadFrom(buf, s.config.CompressDecode, s.config.Crypt)
|
||||
in, _ := conn.WriteTo(data, s.config.CompressEncode, s.config.Crypt)
|
||||
buf := utils.BufPoolUdp.Get().([]byte)
|
||||
out, err := conn.ReadFrom(buf, s.config.CompressDecode, s.config.Crypt)
|
||||
if err != nil || err == io.EOF {
|
||||
log.Println("revieve error:", err)
|
||||
return
|
||||
}
|
||||
s.listener.WriteToUDP(buf[:n], addr)
|
||||
s.listener.WriteToUDP(buf[:out], addr)
|
||||
s.FlowAdd(int64(in), int64(out))
|
||||
utils.BufPoolUdp.Put(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user