mirror of https://github.com/ehang-io/nps
安装 守护进程优化 web修改
parent
74b262503e
commit
7af09a2f4c
|
@ -3,10 +3,12 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/cnlh/nps/server"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"github.com/cnlh/nps/server"
|
||||
_ "github.com/cnlh/nps/web/routers"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const VERSION = "v0.0.13"
|
||||
|
@ -26,12 +28,13 @@ var (
|
|||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
var test bool
|
||||
if len(os.Args) > 1 && os.Args[1] == "test" {
|
||||
test = true
|
||||
server.TestServerConfig()
|
||||
log.Println("test ok, no error")
|
||||
return
|
||||
}
|
||||
lib.InitDaemon("nps")
|
||||
if *logType == "stdout" || test {
|
||||
if *logType == "stdout" {
|
||||
lib.InitLogFile("nps", true)
|
||||
} else {
|
||||
lib.InitLogFile("nps", false)
|
||||
|
@ -61,7 +64,7 @@ func main() {
|
|||
Flow: &lib.Flow{},
|
||||
}
|
||||
c.Cnf.CompressDecode, c.Cnf.CompressEncode = lib.GetCompressType(c.Cnf.Compress)
|
||||
server.CsvDb.Clients[0] = c
|
||||
lib.GetCsvDb().Clients[0] = c
|
||||
task.Client = c
|
||||
}
|
||||
if *TcpPort == 0 {
|
||||
|
@ -75,7 +78,8 @@ func main() {
|
|||
lib.Println("服务端启动,监听tcp服务端端口:", *TcpPort)
|
||||
task.Config.CompressDecode, task.Config.CompressEncode = lib.GetCompressType(task.Config.Compress)
|
||||
if *rpMode != "webServer" {
|
||||
server.CsvDb.Tasks[0] = task
|
||||
lib.GetCsvDb().Tasks[0] = task
|
||||
}
|
||||
server.StartNewServer(*TcpPort, task, test)
|
||||
beego.LoadAppConfig("ini", filepath.Join(lib.GetRunPath(), "conf", "app.conf"))
|
||||
server.StartNewServer(*TcpPort, task)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
appname = nps
|
||||
|
||||
#web管理端口
|
||||
httpport = 8080
|
||||
httpport = 8081
|
||||
|
||||
#启动模式dev|pro
|
||||
runmode = dev
|
||||
|
@ -15,10 +15,10 @@ tcpport=8284
|
|||
#web api免验证IP地址
|
||||
authip=127.0.0.1
|
||||
|
||||
##http代理端口
|
||||
##http代理端口,为空则不启动
|
||||
httpProxyPort=80
|
||||
|
||||
##https代理端口
|
||||
##https代理端口,为空则不启动
|
||||
httpsProxyPort=
|
||||
|
||||
##certFile绝对路径
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1,ydiigrm4ghu7mym1,,true,,,0,,0,0
|
|
|
@ -0,0 +1 @@
|
|||
a.o.com,127.0.0.1:8081,1,,,测试
|
|
|
@ -0,0 +1,4 @@
|
|||
9001,tunnelServer,123.206.77.88:22,,,,1,0,0,0,1,1,true,测试tcp
|
||||
53,udpServer,114.114.114.114:53,,,,1,0,0,0,2,1,true,udp
|
||||
0,socks5Server,,,,,1,0,0,0,3,1,true,socks5
|
||||
9005,httpProxyServer,,,,,1,0,0,0,4,1,true,
|
|
BIN
image/web.png
BIN
image/web.png
Binary file not shown.
Before Width: | Height: | Size: 233 KiB After Width: | Height: | Size: 334 KiB |
|
@ -1,12 +1,11 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
@ -33,39 +32,75 @@ func InitDaemon(f string) {
|
|||
start(args, f)
|
||||
os.Exit(0)
|
||||
case "install":
|
||||
InstallNps()
|
||||
if f == "nps" {
|
||||
InstallNps()
|
||||
}
|
||||
os.Exit(0)
|
||||
case "status":
|
||||
if status(f) {
|
||||
log.Printf("%s is running", f)
|
||||
} else {
|
||||
log.Printf("%s is not running", f)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func status(f string) bool {
|
||||
var cmd *exec.Cmd
|
||||
b, err := ioutil.ReadFile(filepath.Join(GetPidPath(), f+".pid"))
|
||||
if err == nil {
|
||||
if !IsWindows() {
|
||||
cmd = exec.Command("/bin/sh", "-c", "ps -ax | awk '{ print $1 }' | grep "+string(b))
|
||||
} else {
|
||||
cmd = exec.Command("tasklist", )
|
||||
}
|
||||
out, _ := cmd.Output()
|
||||
if strings.Index(string(out), string(b)) > -1 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func start(osArgs []string, f string) {
|
||||
if status(f) {
|
||||
log.Printf(" %s is running", f)
|
||||
return
|
||||
}
|
||||
cmd := exec.Command(osArgs[0], osArgs[1:]...)
|
||||
cmd.Start()
|
||||
log.Println("执行启动成功")
|
||||
if cmd.Process.Pid > 0 {
|
||||
log.Println("start ok , pid:", cmd.Process.Pid, "config path:", GetRunPath())
|
||||
d1 := []byte(strconv.Itoa(cmd.Process.Pid))
|
||||
ioutil.WriteFile(beego.AppPath+"/"+f+".pid", d1, 0600)
|
||||
ioutil.WriteFile(filepath.Join(GetPidPath(), f+".pid"), d1, 0600)
|
||||
} else {
|
||||
log.Println("start error")
|
||||
}
|
||||
}
|
||||
|
||||
func stop(f string, p string) {
|
||||
if !status(f) {
|
||||
log.Printf(" %s is not running", f)
|
||||
return
|
||||
}
|
||||
var c *exec.Cmd
|
||||
var err error
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if IsWindows() {
|
||||
p := strings.Split(p, `\`)
|
||||
c = exec.Command("taskkill", "/F", "/IM", p[len(p)-1])
|
||||
case "linux", "darwin":
|
||||
b, err := ioutil.ReadFile(beego.AppPath + "/" + f + ".pid")
|
||||
} else {
|
||||
b, err := ioutil.ReadFile(filepath.Join(GetPidPath(), f+".pid"))
|
||||
if err == nil {
|
||||
c = exec.Command("/bin/bash", "-c", `kill -9 `+string(b))
|
||||
} else {
|
||||
log.Println("停止服务失败,pid文件不存在")
|
||||
log.Fatalln("stop error,PID file does not exist")
|
||||
}
|
||||
}
|
||||
err = c.Run()
|
||||
if err != nil {
|
||||
log.Println("停止服务失败,", err)
|
||||
log.Println("stop error,", err)
|
||||
} else {
|
||||
log.Println("停止服务成功")
|
||||
log.Println("stop ok")
|
||||
}
|
||||
}
|
||||
|
|
14
lib/file.go
14
lib/file.go
|
@ -3,8 +3,8 @@ package lib
|
|||
import (
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"github.com/astaxie/beego"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -37,7 +37,7 @@ func (s *Csv) Init() {
|
|||
|
||||
func (s *Csv) StoreTasksToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(beego.AppPath + "/conf/tasks.csv")
|
||||
csvFile, err := os.Create(filepath.Join(GetRunPath(), "conf", "tasks.csv"))
|
||||
if err != nil {
|
||||
Fatalf(err.Error())
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ func (s *Csv) openFile(path string) ([][]string, error) {
|
|||
}
|
||||
|
||||
func (s *Csv) LoadTaskFromCsv() {
|
||||
path := beego.AppPath + "/conf/tasks.csv"
|
||||
path := filepath.Join(GetRunPath(), "conf", "tasks.csv")
|
||||
records, err := s.openFile(path)
|
||||
if err != nil {
|
||||
Fatalln("配置文件打开错误:", path)
|
||||
|
@ -186,7 +186,7 @@ func (s *Csv) GetTask(id int) (v *Tunnel, err error) {
|
|||
|
||||
func (s *Csv) StoreHostToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(beego.AppPath + "/conf/hosts.csv")
|
||||
csvFile, err := os.Create(filepath.Join(GetRunPath(), "conf", "hosts.csv"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ func (s *Csv) StoreHostToCsv() {
|
|||
}
|
||||
|
||||
func (s *Csv) LoadClientFromCsv() {
|
||||
path := beego.AppPath + "/conf/clients.csv"
|
||||
path := filepath.Join(GetRunPath(), "conf", "clients.csv")
|
||||
records, err := s.openFile(path)
|
||||
if err != nil {
|
||||
Fatalln("配置文件打开错误:", path)
|
||||
|
@ -250,7 +250,7 @@ func (s *Csv) LoadClientFromCsv() {
|
|||
}
|
||||
|
||||
func (s *Csv) LoadHostFromCsv() {
|
||||
path := beego.AppPath + "/conf/hosts.csv"
|
||||
path := filepath.Join(GetRunPath(), "conf", "hosts.csv")
|
||||
records, err := s.openFile(path)
|
||||
if err != nil {
|
||||
Fatalln("配置文件打开错误:", path)
|
||||
|
@ -389,7 +389,7 @@ func (s *Csv) GetClient(id int) (v *Client, err error) {
|
|||
}
|
||||
func (s *Csv) StoreClientsToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(beego.AppPath + "/conf/clients.csv")
|
||||
csvFile, err := os.Create(filepath.Join(GetRunPath(), "conf", "clients.csv"))
|
||||
if err != nil {
|
||||
Fatalln(err.Error())
|
||||
}
|
||||
|
|
|
@ -7,34 +7,52 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InstallNps() {
|
||||
var path string
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
path = "C:/"
|
||||
case "linux", "darwin":
|
||||
path = "/etc/nps/"
|
||||
}
|
||||
if err := os.Mkdir(path, 0755); err != nil {
|
||||
log.Fatalf("创建目录%s失败:%s", path, err.Error())
|
||||
}
|
||||
path := GetInstallPath()
|
||||
MkidrDirAll(path, "conf", "web/static", "web/views")
|
||||
//复制文件到对应目录
|
||||
if err := CopyDir("./web", path); err != nil {
|
||||
if err := CopyDir(filepath.Join(GetAppPath(), "web", "views"), filepath.Join(path, "web", "views")); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
if err := CopyDir("./conf", path); err != nil {
|
||||
if err := CopyDir(filepath.Join(GetAppPath(), "web", "static"), filepath.Join(path, "web", "static")); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
if err := CopyDir(filepath.Join(GetAppPath(), "conf"), filepath.Join(path, "conf")); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
//linux加入到/etc/init.d
|
||||
|
||||
//windows处理
|
||||
if !IsWindows() {
|
||||
if _, err := copyFile(filepath.Join(GetAppPath(), "nps"), "/usr/bin/nps"); err != nil {
|
||||
if _, err := copyFile(filepath.Join(GetAppPath(), "nps"), "/usr/local/bin/nps"); err != nil {
|
||||
log.Fatalln(err)
|
||||
} else {
|
||||
os.Chmod("/usr/local/bin/nps", 0777)
|
||||
log.Println("Executable files have been copied to", "/usr/local/bin/nps")
|
||||
}
|
||||
} else {
|
||||
os.Chmod("/usr/bin/nps", 0777)
|
||||
log.Println("Executable files have been copied to", "/usr/bin/nps")
|
||||
}
|
||||
|
||||
//darwin处理
|
||||
}
|
||||
log.Println("install ok!")
|
||||
log.Println("Static files and configuration files in the current directory will be useless")
|
||||
log.Println("The new configuration file is located in", path, "you can edit them")
|
||||
if !IsWindows() {
|
||||
log.Println("You can start with nps test|start|stop|restart|status anywhere")
|
||||
} else {
|
||||
log.Println("You can copy executable files to any directory and start working with nps.exe test|start|stop|restart|status")
|
||||
}
|
||||
}
|
||||
func MkidrDirAll(path string, v ... string) {
|
||||
for _, item := range v {
|
||||
if err := os.MkdirAll(filepath.Join(path, item), 0755); err != nil {
|
||||
log.Fatalf("Failed to create directory %s error:%s", path, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CopyDir(srcPath string, destPath string) error {
|
||||
|
@ -44,39 +62,29 @@ func CopyDir(srcPath string, destPath string) error {
|
|||
return err
|
||||
} else {
|
||||
if !srcInfo.IsDir() {
|
||||
e := errors.New("srcPath不是一个正确的目录!")
|
||||
fmt.Println(e.Error())
|
||||
e := errors.New("SrcPath is not the right directory!")
|
||||
return e
|
||||
}
|
||||
}
|
||||
if destInfo, err := os.Stat(destPath); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return err
|
||||
} else {
|
||||
if !destInfo.IsDir() {
|
||||
e := errors.New("destInfo不是一个正确的目录!")
|
||||
fmt.Println(e.Error())
|
||||
e := errors.New("DestInfo is not the right directory!")
|
||||
return e
|
||||
}
|
||||
}
|
||||
//加上拷贝时间:不用可以去掉
|
||||
destPath = destPath + "_" + time.Now().Format("20060102150405")
|
||||
|
||||
err := filepath.Walk(srcPath, func(path string, f os.FileInfo, err error) error {
|
||||
if f == nil {
|
||||
return err
|
||||
}
|
||||
if !f.IsDir() {
|
||||
path := strings.Replace(path, "\\", "/", -1)
|
||||
destNewPath := strings.Replace(path, srcPath, destPath, -1)
|
||||
fmt.Println("复制文件:" + path + " 到 " + destNewPath)
|
||||
log.Println("copy file ::" + path + " to " + destNewPath)
|
||||
copyFile(path, destNewPath)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf(err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -84,32 +92,30 @@ func CopyDir(srcPath string, destPath string) error {
|
|||
func copyFile(src, dest string) (w int64, err error) {
|
||||
srcFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
defer srcFile.Close()
|
||||
//分割path目录
|
||||
destSplitPathDirs := strings.Split(dest, "/")
|
||||
destSplitPathDirs := strings.Split(dest, string(filepath.Separator))
|
||||
|
||||
//检测时候存在目录
|
||||
destSplitPath := ""
|
||||
for index, dir := range destSplitPathDirs {
|
||||
if index < len(destSplitPathDirs)-1 {
|
||||
destSplitPath = destSplitPath + dir + "/"
|
||||
destSplitPath = destSplitPath + dir + string(filepath.Separator)
|
||||
b, _ := pathExists(destSplitPath)
|
||||
if b == false {
|
||||
fmt.Println("创建目录:" + destSplitPath)
|
||||
log.Println("mkdir:" + destSplitPath)
|
||||
//创建目录
|
||||
err := os.Mkdir(destSplitPath, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dstFile, err := os.Create(dest)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
|
@ -12,9 +12,9 @@ var Log *log.Logger
|
|||
func InitLogFile(f string, isStdout bool) {
|
||||
var prefix string
|
||||
if !isStdout {
|
||||
logFile, err := os.OpenFile(beego.AppPath+"/"+f+"_log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
|
||||
logFile, err := os.OpenFile(filepath.Join(GetLogPath(), f+"_log.txt"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
|
||||
if err != nil {
|
||||
log.Fatalln("open file error !")
|
||||
log.Fatalln("open file error !", err)
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
prefix = "\r\n"
|
||||
|
|
61
lib/util.go
61
lib/util.go
|
@ -6,7 +6,9 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
@ -151,7 +153,6 @@ func ReadAllFromFile(filePath string) ([]byte, error) {
|
|||
return ioutil.ReadAll(f)
|
||||
}
|
||||
|
||||
|
||||
// FileExists reports whether the named file or directory exists.
|
||||
func FileExists(name string) bool {
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
|
@ -160,4 +161,60 @@ func FileExists(name string) bool {
|
|||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func GetRunPath() string {
|
||||
var path string
|
||||
if path = GetInstallPath(); !FileExists(path) {
|
||||
return "./"
|
||||
}
|
||||
return path
|
||||
}
|
||||
func GetInstallPath() string {
|
||||
var path string
|
||||
if IsWindows() {
|
||||
path = `C:\Program Files\nps`
|
||||
} else {
|
||||
path = "/etc/nps"
|
||||
}
|
||||
return path
|
||||
}
|
||||
func GetAppPath() string {
|
||||
if path, err := filepath.Abs(filepath.Dir(os.Args[0])); err == nil {
|
||||
return path
|
||||
}
|
||||
return os.Args[0]
|
||||
}
|
||||
func IsWindows() bool {
|
||||
if runtime.GOOS == "windows" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func GetLogPath() string {
|
||||
var path string
|
||||
if IsWindows() {
|
||||
path = "./"
|
||||
} else {
|
||||
path = "/tmp"
|
||||
}
|
||||
return path
|
||||
}
|
||||
func GetPidPath() string {
|
||||
var path string
|
||||
if IsWindows() {
|
||||
path = "./"
|
||||
} else {
|
||||
path = "/tmp"
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
func TestTcpPort(port int) bool {
|
||||
l, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), port, ""})
|
||||
defer l.Close()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ func (s *server) FlowAddHost(host *lib.Host, in, out int64) {
|
|||
//热更新配置
|
||||
func (s *server) ResetConfig() bool {
|
||||
//获取最新数据
|
||||
task, err := CsvDb.GetTask(s.task.Id)
|
||||
task, err := lib.GetCsvDb().GetTask(s.task.Id)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func (s *server) ResetConfig() bool {
|
|||
}
|
||||
s.task.UseClientCnf = task.UseClientCnf
|
||||
//使用客户端配置
|
||||
client, err := CsvDb.GetClient(s.task.Client.Id)
|
||||
client, err := lib.GetCsvDb().GetClient(s.task.Client.Id)
|
||||
if s.task.UseClientCnf {
|
||||
if err == nil {
|
||||
s.config.U = client.Cnf.U
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"github.com/astaxie/beego"
|
||||
"github.com/cnlh/nps/bridge"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
@ -44,14 +44,11 @@ func NewHttp(bridge *bridge.Bridge, c *lib.Tunnel) *httpServer {
|
|||
func (s *httpServer) Start() error {
|
||||
var err error
|
||||
var http, https *http.Server
|
||||
if s.errorContent, err = lib.ReadAllFromFile(beego.AppPath + "/web/static/page/error.html"); err != nil {
|
||||
if s.errorContent, err = lib.ReadAllFromFile(filepath.Join(lib.GetRunPath(), "web", "static", "page", "error.html")); err != nil {
|
||||
s.errorContent = []byte("easyProxy 404")
|
||||
}
|
||||
|
||||
if s.httpPort > 0 {
|
||||
if !s.TestTcpPort(s.httpPort) {
|
||||
lib.Fatalln("http端口", s.httpPort, "被占用!")
|
||||
}
|
||||
http = s.NewServer(s.httpPort)
|
||||
go func() {
|
||||
lib.Println("启动http监听,端口为", s.httpPort)
|
||||
|
@ -62,9 +59,6 @@ func (s *httpServer) Start() error {
|
|||
}()
|
||||
}
|
||||
if s.httpsPort > 0 {
|
||||
if !s.TestTcpPort(s.httpsPort) {
|
||||
lib.Fatalln("https端口", s.httpsPort, "被占用!")
|
||||
}
|
||||
if !lib.FileExists(s.pemPath) {
|
||||
lib.Fatalf("ssl certFile文件%s不存在", s.pemPath)
|
||||
}
|
||||
|
@ -80,7 +74,6 @@ func (s *httpServer) Start() error {
|
|||
}
|
||||
}()
|
||||
}
|
||||
startFinish <- true
|
||||
select {
|
||||
case <-s.stop:
|
||||
if http != nil {
|
||||
|
@ -90,7 +83,6 @@ func (s *httpServer) Start() error {
|
|||
https.Close()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -180,12 +172,3 @@ func (s *httpServer) NewServer(port int) *http.Server {
|
|||
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *httpServer) TestTcpPort(port int) bool {
|
||||
l, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), port, ""})
|
||||
defer l.Close()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import (
|
|||
"errors"
|
||||
"github.com/cnlh/nps/bridge"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
@ -13,7 +11,6 @@ import (
|
|||
var (
|
||||
Bridge *bridge.Bridge
|
||||
RunList map[int]interface{} //运行中的任务
|
||||
CsvDb = lib.GetCsvDb()
|
||||
startFinish chan bool
|
||||
)
|
||||
|
||||
|
@ -24,7 +21,7 @@ func init() {
|
|||
|
||||
//从csv文件中恢复任务
|
||||
func InitFromCsv() {
|
||||
for _, v := range CsvDb.Tasks {
|
||||
for _, v := range lib.GetCsvDb().Tasks {
|
||||
if v.Status {
|
||||
lib.Println("启动模式:", v.Mode, "监听端口:", v.TcpPort)
|
||||
AddTask(v)
|
||||
|
@ -33,31 +30,21 @@ func InitFromCsv() {
|
|||
}
|
||||
|
||||
//start a new server
|
||||
func StartNewServer(bridgePort int, cnf *lib.Tunnel, test bool) {
|
||||
go func() {
|
||||
Bridge = bridge.NewTunnel(bridgePort, RunList)
|
||||
if err := Bridge.StartTunnel(); err != nil {
|
||||
lib.Fatalln("服务端开启失败", err)
|
||||
}
|
||||
if svr := NewMode(Bridge, cnf); svr != nil {
|
||||
RunList[cnf.Id] = svr
|
||||
err := reflect.ValueOf(svr).MethodByName("Start").Call(nil)[0]
|
||||
if err.Interface() != nil {
|
||||
lib.Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
lib.Fatalln("启动模式不正确")
|
||||
}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-startFinish:
|
||||
if test {
|
||||
log.Println("测试完成,未发现错误")
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
func StartNewServer(bridgePort int, cnf *lib.Tunnel) {
|
||||
Bridge = bridge.NewTunnel(bridgePort, RunList)
|
||||
if err := Bridge.StartTunnel(); err != nil {
|
||||
lib.Fatalln("服务端开启失败", err)
|
||||
}
|
||||
if svr := NewMode(Bridge, cnf); svr != nil {
|
||||
RunList[cnf.Id] = svr
|
||||
err := reflect.ValueOf(svr).MethodByName("Start").Call(nil)[0]
|
||||
if err.Interface() != nil {
|
||||
lib.Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
lib.Fatalln("启动模式不正确")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//new a server by mode name
|
||||
|
@ -94,11 +81,11 @@ func NewMode(Bridge *bridge.Bridge, c *lib.Tunnel) interface{} {
|
|||
func StopServer(id int) error {
|
||||
if v, ok := RunList[id]; ok {
|
||||
reflect.ValueOf(v).MethodByName("Close").Call(nil)
|
||||
if t, err := CsvDb.GetTask(id); err != nil {
|
||||
if t, err := lib.GetCsvDb().GetTask(id); err != nil {
|
||||
return err
|
||||
} else {
|
||||
t.Status = false
|
||||
CsvDb.UpdateTask(t)
|
||||
lib.GetCsvDb().UpdateTask(t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -124,12 +111,12 @@ func AddTask(t *lib.Tunnel) error {
|
|||
|
||||
//start task
|
||||
func StartTask(id int) error {
|
||||
if t, err := CsvDb.GetTask(id); err != nil {
|
||||
if t, err := lib.GetCsvDb().GetTask(id); err != nil {
|
||||
return err
|
||||
} else {
|
||||
AddTask(t)
|
||||
t.Status = true
|
||||
CsvDb.UpdateTask(t)
|
||||
lib.GetCsvDb().UpdateTask(t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -139,12 +126,12 @@ func DelTask(id int) error {
|
|||
if err := StopServer(id); err != nil {
|
||||
return err
|
||||
}
|
||||
return CsvDb.DelTask(id)
|
||||
return lib.GetCsvDb().DelTask(id)
|
||||
}
|
||||
|
||||
//get key by host from x
|
||||
func GetInfoByHost(host string) (h *lib.Host, err error) {
|
||||
for _, v := range CsvDb.Hosts {
|
||||
for _, v := range lib.GetCsvDb().Hosts {
|
||||
s := strings.Split(host, ":")
|
||||
if s[0] == v.Host {
|
||||
h = v
|
||||
|
@ -159,7 +146,7 @@ func GetInfoByHost(host string) (h *lib.Host, err error) {
|
|||
func GetTunnel(start, length int, typeVal string, clientId int) ([]*lib.Tunnel, int) {
|
||||
list := make([]*lib.Tunnel, 0)
|
||||
var cnt int
|
||||
for _, v := range CsvDb.Tasks {
|
||||
for _, v := range lib.GetCsvDb().Tasks {
|
||||
if (typeVal != "" && v.Mode != typeVal) || (typeVal == "" && clientId != v.Client.Id) {
|
||||
continue
|
||||
}
|
||||
|
@ -185,7 +172,7 @@ func GetTunnel(start, length int, typeVal string, clientId int) ([]*lib.Tunnel,
|
|||
|
||||
//获取客户端列表
|
||||
func GetClientList(start, length int) (list []*lib.Client, cnt int) {
|
||||
list, cnt = CsvDb.GetClientList(start, length)
|
||||
list, cnt = lib.GetCsvDb().GetClientList(start, length)
|
||||
dealClientData(list)
|
||||
return
|
||||
}
|
||||
|
@ -199,13 +186,13 @@ func dealClientData(list []*lib.Client) {
|
|||
}
|
||||
v.Flow.InletFlow = 0
|
||||
v.Flow.ExportFlow = 0
|
||||
for _, h := range CsvDb.Hosts {
|
||||
for _, h := range lib.GetCsvDb().Hosts {
|
||||
if h.Client.Id == v.Id {
|
||||
v.Flow.InletFlow += h.Flow.InletFlow
|
||||
v.Flow.ExportFlow += h.Flow.ExportFlow
|
||||
}
|
||||
}
|
||||
for _, t := range CsvDb.Tasks {
|
||||
for _, t := range lib.GetCsvDb().Tasks {
|
||||
if t.Client.Id == v.Id {
|
||||
v.Flow.InletFlow += t.Flow.InletFlow
|
||||
v.Flow.ExportFlow += t.Flow.ExportFlow
|
||||
|
@ -217,14 +204,14 @@ func dealClientData(list []*lib.Client) {
|
|||
|
||||
//根据客户端id删除其所属的所有隧道和域名
|
||||
func DelTunnelAndHostByClientId(clientId int) {
|
||||
for _, v := range CsvDb.Tasks {
|
||||
for _, v := range lib.GetCsvDb().Tasks {
|
||||
if v.Client.Id == clientId {
|
||||
DelTask(v.Id)
|
||||
}
|
||||
}
|
||||
for _, v := range CsvDb.Hosts {
|
||||
for _, v := range lib.GetCsvDb().Hosts {
|
||||
if v.Client.Id == clientId {
|
||||
CsvDb.DelHost(v.Host)
|
||||
lib.GetCsvDb().DelHost(v.Host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,9 +223,9 @@ func DelClientConnect(clientId int) {
|
|||
|
||||
func GetDashboardData() map[string]int {
|
||||
data := make(map[string]int)
|
||||
data["hostCount"] = len(CsvDb.Hosts)
|
||||
data["clientCount"] = len(CsvDb.Clients)
|
||||
list := CsvDb.Clients
|
||||
data["hostCount"] = len(lib.GetCsvDb().Hosts)
|
||||
data["clientCount"] = len(lib.GetCsvDb().Clients)
|
||||
list := lib.GetCsvDb().Clients
|
||||
dealClientData(list)
|
||||
c := 0
|
||||
var in, out int64
|
||||
|
@ -252,7 +239,7 @@ func GetDashboardData() map[string]int {
|
|||
data["clientOnlineCount"] = c
|
||||
data["inletFlowCount"] = int(in)
|
||||
data["exportFlowCount"] = int(out)
|
||||
for _, v := range CsvDb.Tasks {
|
||||
for _, v := range lib.GetCsvDb().Tasks {
|
||||
switch v.Mode {
|
||||
case "tunnelServer":
|
||||
data["tunnelServerCount"] += 1
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/cnlh/nps/bridge"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -71,10 +72,14 @@ type WebServer struct {
|
|||
|
||||
//开始
|
||||
func (s *WebServer) Start() error {
|
||||
p, _ := beego.AppConfig.Int("httpport")
|
||||
if !lib.TestTcpPort(p) {
|
||||
lib.Fatalln("web管理端口", p, "被占用!")
|
||||
}
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
lib.Println("web管理启动,访问端口为", beego.AppConfig.String("httpport"))
|
||||
beego.SetViewsPath(beego.AppPath + "/web/views")
|
||||
beego.SetStaticPath("/static", beego.AppPath+"/web/static")
|
||||
beego.SetStaticPath("/static", filepath.Join(lib.GetRunPath(), "web", "static"))
|
||||
beego.SetViewsPath(filepath.Join(lib.GetRunPath(), "web", "views"))
|
||||
beego.Run()
|
||||
return errors.New("web管理启动失败")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func TestServerConfig() {
|
||||
var postArr []int
|
||||
for _, v := range lib.GetCsvDb().Tasks {
|
||||
isInArr(&postArr, v.TcpPort, v.Remark)
|
||||
}
|
||||
p, err := beego.AppConfig.Int("httpport")
|
||||
if err != nil {
|
||||
log.Fatalln("Getting web management port error :", err)
|
||||
} else {
|
||||
isInArr(&postArr, p, "WebmManagement port")
|
||||
}
|
||||
if p := beego.AppConfig.String("httpProxyPort"); p != "" {
|
||||
if port, err := strconv.Atoi(p); err != nil {
|
||||
log.Fatalln("get http port error:", err)
|
||||
} else {
|
||||
isInArr(&postArr, port, "https port")
|
||||
}
|
||||
}
|
||||
if p := beego.AppConfig.String("httpsProxyPort"); p != "" {
|
||||
if port, err := strconv.Atoi(p); err != nil {
|
||||
log.Fatalln("get https port error", err)
|
||||
} else {
|
||||
if !lib.FileExists(beego.AppConfig.String("pemPath")) {
|
||||
log.Fatalf("ssl certFile %s is not exist", beego.AppConfig.String("pemPath"))
|
||||
}
|
||||
if !lib.FileExists(beego.AppConfig.String("ketPath")) {
|
||||
log.Fatalf("ssl keyFile %s is not exist", beego.AppConfig.String("pemPath"))
|
||||
}
|
||||
isInArr(&postArr, port, "http port")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isInArr(arr *[]int, val int, remark string) {
|
||||
for _, v := range *arr {
|
||||
if v == val {
|
||||
log.Fatalf("the port %d is reused,remark: %s", val, remark)
|
||||
}
|
||||
}
|
||||
if !lib.TestTcpPort(val) {
|
||||
log.Fatalf("open the %d port error ,remark: %s", val, remark)
|
||||
}
|
||||
*arr = append(*arr, val)
|
||||
return
|
||||
}
|
|
@ -2,8 +2,8 @@ package controllers
|
|||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/cnlh/nps/server"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"github.com/cnlh/nps/server"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/cnlh/nps/server"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"github.com/cnlh/nps/server"
|
||||
)
|
||||
|
||||
type ClientController struct {
|
||||
|
@ -30,7 +30,7 @@ func (s *ClientController) Add() {
|
|||
} else {
|
||||
t := &lib.Client{
|
||||
VerifyKey: lib.GetRandomString(16),
|
||||
Id: server.CsvDb.GetClientId(),
|
||||
Id: lib.GetCsvDb().GetClientId(),
|
||||
Status: true,
|
||||
Remark: s.GetString("remark"),
|
||||
Cnf: &lib.Config{
|
||||
|
@ -50,7 +50,7 @@ func (s *ClientController) Add() {
|
|||
t.Rate = lib.NewRate(int64(t.RateLimit * 1024))
|
||||
t.Rate.Start()
|
||||
}
|
||||
server.CsvDb.NewClient(t)
|
||||
lib.GetCsvDb().NewClient(t)
|
||||
s.AjaxOk("添加成功")
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func (s *ClientController) GetClient() {
|
|||
if s.Ctx.Request.Method == "POST" {
|
||||
id := s.GetIntNoErr("id")
|
||||
data := make(map[string]interface{})
|
||||
if c, err := server.CsvDb.GetClient(id); err != nil {
|
||||
if c, err := lib.GetCsvDb().GetClient(id); err != nil {
|
||||
data["code"] = 0
|
||||
} else {
|
||||
data["code"] = 1
|
||||
|
@ -74,7 +74,7 @@ func (s *ClientController) Edit() {
|
|||
id := s.GetIntNoErr("id")
|
||||
if s.Ctx.Request.Method == "GET" {
|
||||
s.Data["menu"] = "client"
|
||||
if c, err := server.CsvDb.GetClient(id); err != nil {
|
||||
if c, err := lib.GetCsvDb().GetClient(id); err != nil {
|
||||
s.error()
|
||||
} else {
|
||||
s.Data["c"] = c
|
||||
|
@ -82,7 +82,7 @@ func (s *ClientController) Edit() {
|
|||
s.SetInfo("修改")
|
||||
s.display()
|
||||
} else {
|
||||
if c, err := server.CsvDb.GetClient(id); err != nil {
|
||||
if c, err := lib.GetCsvDb().GetClient(id); err != nil {
|
||||
s.error()
|
||||
} else {
|
||||
c.Remark = s.GetString("remark")
|
||||
|
@ -101,7 +101,7 @@ func (s *ClientController) Edit() {
|
|||
} else {
|
||||
c.Rate = nil
|
||||
}
|
||||
server.CsvDb.UpdateClient(c)
|
||||
lib.GetCsvDb().UpdateClient(c)
|
||||
}
|
||||
s.AjaxOk("修改成功")
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ func (s *ClientController) Edit() {
|
|||
//更改状态
|
||||
func (s *ClientController) ChangeStatus() {
|
||||
id := s.GetIntNoErr("id")
|
||||
if client, err := server.CsvDb.GetClient(id); err == nil {
|
||||
if client, err := lib.GetCsvDb().GetClient(id); err == nil {
|
||||
client.Status = s.GetBoolNoErr("status")
|
||||
if client.Status == false {
|
||||
server.DelClientConnect(client.Id)
|
||||
|
@ -123,7 +123,7 @@ func (s *ClientController) ChangeStatus() {
|
|||
//删除客户端
|
||||
func (s *ClientController) Del() {
|
||||
id := s.GetIntNoErr("id")
|
||||
if err := server.CsvDb.DelClient(id); err != nil {
|
||||
if err := lib.GetCsvDb().DelClient(id); err != nil {
|
||||
s.AjaxErr("删除失败")
|
||||
}
|
||||
server.DelTunnelAndHostByClientId(id)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/cnlh/nps/server"
|
||||
"github.com/cnlh/nps/lib"
|
||||
"github.com/cnlh/nps/server"
|
||||
)
|
||||
|
||||
type IndexController struct {
|
||||
|
@ -82,17 +82,17 @@ func (s *IndexController) Add() {
|
|||
Compress: s.GetString("compress"),
|
||||
Crypt: s.GetBoolNoErr("crypt"),
|
||||
},
|
||||
Id: server.CsvDb.GetTaskId(),
|
||||
Id: lib.GetCsvDb().GetTaskId(),
|
||||
UseClientCnf: s.GetBoolNoErr("use_client"),
|
||||
Status: true,
|
||||
Remark: s.GetString("remark"),
|
||||
Flow: &lib.Flow{},
|
||||
}
|
||||
var err error
|
||||
if t.Client, err = server.CsvDb.GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
if t.Client, err = lib.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
s.AjaxErr(err.Error())
|
||||
}
|
||||
server.CsvDb.NewTask(t)
|
||||
lib.GetCsvDb().NewTask(t)
|
||||
if err := server.AddTask(t); err != nil {
|
||||
s.AjaxErr(err.Error())
|
||||
} else {
|
||||
|
@ -103,7 +103,7 @@ func (s *IndexController) Add() {
|
|||
func (s *IndexController) GetOneTunnel() {
|
||||
id := s.GetIntNoErr("id")
|
||||
data := make(map[string]interface{})
|
||||
if t, err := server.CsvDb.GetTask(id); err != nil {
|
||||
if t, err := lib.GetCsvDb().GetTask(id); err != nil {
|
||||
data["code"] = 0
|
||||
} else {
|
||||
data["code"] = 1
|
||||
|
@ -115,7 +115,7 @@ func (s *IndexController) GetOneTunnel() {
|
|||
func (s *IndexController) Edit() {
|
||||
id := s.GetIntNoErr("id")
|
||||
if s.Ctx.Request.Method == "GET" {
|
||||
if t, err := server.CsvDb.GetTask(id); err != nil {
|
||||
if t, err := lib.GetCsvDb().GetTask(id); err != nil {
|
||||
s.error()
|
||||
} else {
|
||||
s.Data["t"] = t
|
||||
|
@ -123,7 +123,7 @@ func (s *IndexController) Edit() {
|
|||
s.SetInfo("修改")
|
||||
s.display()
|
||||
} else {
|
||||
if t, err := server.CsvDb.GetTask(id); err != nil {
|
||||
if t, err := lib.GetCsvDb().GetTask(id); err != nil {
|
||||
s.error()
|
||||
} else {
|
||||
t.TcpPort = s.GetIntNoErr("port")
|
||||
|
@ -137,10 +137,10 @@ func (s *IndexController) Edit() {
|
|||
t.Config.Crypt = s.GetBoolNoErr("crypt")
|
||||
t.UseClientCnf = s.GetBoolNoErr("use_client")
|
||||
t.Remark = s.GetString("remark")
|
||||
if t.Client, err = server.CsvDb.GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
if t.Client, err = lib.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
s.AjaxErr("修改失败")
|
||||
}
|
||||
server.CsvDb.UpdateTask(t)
|
||||
lib.GetCsvDb().UpdateTask(t)
|
||||
}
|
||||
s.AjaxOk("修改成功")
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ func (s *IndexController) HostList() {
|
|||
} else {
|
||||
start, length := s.GetAjaxParams()
|
||||
clientId := s.GetIntNoErr("client_id")
|
||||
list, cnt := server.CsvDb.GetHost(start, length, clientId)
|
||||
list, cnt := lib.GetCsvDb().GetHost(start, length, clientId)
|
||||
s.AjaxTable(list, cnt, cnt)
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func (s *IndexController) GetHost() {
|
|||
|
||||
func (s *IndexController) DelHost() {
|
||||
host := s.GetString("host")
|
||||
if err := server.CsvDb.DelHost(host); err != nil {
|
||||
if err := lib.GetCsvDb().DelHost(host); err != nil {
|
||||
s.AjaxErr("删除失败")
|
||||
}
|
||||
s.AjaxOk("删除成功")
|
||||
|
@ -222,10 +222,10 @@ func (s *IndexController) AddHost() {
|
|||
Flow: &lib.Flow{},
|
||||
}
|
||||
var err error
|
||||
if h.Client, err = server.CsvDb.GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
if h.Client, err = lib.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
s.AjaxErr("添加失败")
|
||||
}
|
||||
server.CsvDb.NewHost(h)
|
||||
lib.GetCsvDb().NewHost(h)
|
||||
s.AjaxOk("添加成功")
|
||||
}
|
||||
}
|
||||
|
@ -251,9 +251,9 @@ func (s *IndexController) EditHost() {
|
|||
h.HostChange = s.GetString("hostchange")
|
||||
h.Remark = s.GetString("remark")
|
||||
h.TargetArr = nil
|
||||
server.CsvDb.UpdateHost(h)
|
||||
lib.GetCsvDb().UpdateHost(h)
|
||||
var err error
|
||||
if h.Client, err = server.CsvDb.GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
if h.Client, err = lib.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||
s.AjaxErr("修改失败")
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
<div class="row tile">
|
||||
<div class="col-md-6 col-md-auto">
|
||||
<div>
|
||||
<h3 class="tile-title">添加</h3>
|
||||
<h3 class="tile-title">修改</h3>
|
||||
<div class="tile-body">
|
||||
<form>
|
||||
<input type="hidden" name="id" value="{{.c.Id}}">
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
<div class="row tile">
|
||||
<div class="col-lg-12">
|
||||
<div class="bs-component">
|
||||
<div class="alert alert-dismissible alert-success">
|
||||
<button class="close" type="button" data-dismiss="alert">×</button>
|
||||
<span id="info"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-md-auto">
|
||||
<div>
|
||||
<h3 class="tile-title">添加</h3>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="row tile">
|
||||
<div class="col-md-6 col-md-auto">
|
||||
<div>
|
||||
<h3 class="tile-title">添加</h3>
|
||||
<h3 class="tile-title">修改</h3>
|
||||
<div class="tile-body">
|
||||
<form>
|
||||
<input type="hidden" name="id" value="{{.t.Id}}">
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label">内网目标</label>
|
||||
<textarea class="form-control" rows="4" type="text" name="target"
|
||||
placeholder="内网隧道目标,例如10.1.50.203:22,换行分隔"></textarea>
|
||||
placeholder="内网隧道目标,例如10.1.50.203:22,如需负载均衡多个地址换行分隔"></textarea>
|
||||
</div>
|
||||
<div class="form-group" id="header">
|
||||
<label class="control-label">header头修改(冒号分隔,多个请换行填写)</label>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="col-md-3">
|
||||
<div class="widget-small warning coloured-icon"><i class="icon fa fa-html5 fa-3x"></i>
|
||||
<div class="info">
|
||||
<h4>HTTP端口</h4>
|
||||
<h4>客户端连接端口</h4>
|
||||
<p><b>{{.p}}</b></p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,69 +36,95 @@
|
|||
<div class="col-md-6">
|
||||
<div class="tile">
|
||||
<h3 class="tile-title">流量</h3>
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<canvas class="embed-responsive-item" id="flow"></canvas>
|
||||
</div>
|
||||
<div id="flow" style="width: 600px;height:400px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="tile">
|
||||
<h3 class="tile-title">代理类型</h3>
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<canvas class="embed-responsive-item" id="types"></canvas>
|
||||
</div>
|
||||
<div id="tj" style="width: 600px;height:400px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var pdataFlow = [
|
||||
{
|
||||
value: {{.data.inletFlowCount}},
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "入口流量"
|
||||
option = {
|
||||
title : {
|
||||
x:'center'
|
||||
},
|
||||
{
|
||||
value: {{.data.exportFlowCount}},
|
||||
color: "#FDB45C",
|
||||
highlight: "#FFC870",
|
||||
label: "出口流量"
|
||||
}
|
||||
]
|
||||
var pdataTypes = [
|
||||
{
|
||||
value: {{.data.tunnelServerCount}},
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "tcp隧道"
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function (p) {
|
||||
return p.seriesName + "<br>" + p.name + ":" + change(p.data.value);
|
||||
},
|
||||
},
|
||||
{
|
||||
value: {{.data.socks5ServerCount}},
|
||||
color: "#85FEAA",
|
||||
highlight: "#85FEAA",
|
||||
label: "socks5隧道"
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: ['入口流量', '出口流量']
|
||||
},
|
||||
{
|
||||
value: {{.data.httpProxyServerCount}},
|
||||
color: "#4B653C",
|
||||
highlight: "#4B653C",
|
||||
label: "http代理"
|
||||
series : [
|
||||
{
|
||||
name: '类型 统计',
|
||||
type: 'pie',
|
||||
radius : '55%',
|
||||
center: ['50%', '60%'],
|
||||
data:[
|
||||
{value:{{.data.inletFlowCount}}, name: '入口流量'},
|
||||
{value:{{.data.exportFlowCount}}, name: '出口流量'},
|
||||
],
|
||||
itemStyle: {
|
||||
emphasis: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var myChart = echarts.init(document.getElementById('flow'));
|
||||
myChart.setOption(option);
|
||||
|
||||
|
||||
option = {
|
||||
title : {
|
||||
x:'center'
|
||||
},
|
||||
{
|
||||
value: {{.data.udpServerCount}},
|
||||
color: "#90653C",
|
||||
highlight: "#90653C",
|
||||
label: "udp代理"
|
||||
tooltip : {
|
||||
trigger: 'item',
|
||||
formatter: "{a} <br/>{b} : {c} ({d}%)"
|
||||
},
|
||||
{
|
||||
value: {{.data.hostCount}},
|
||||
color: "#FDB45C",
|
||||
highlight: "#FDB45C",
|
||||
label: "域名解析"
|
||||
}
|
||||
]
|
||||
var ctxp = $("#flow").get(0).getContext("2d");
|
||||
var pieChart = new Chart(ctxp).Pie(pdataFlow);
|
||||
var ctxd = $("#types").get(0).getContext("2d");
|
||||
var doughnutChart = new Chart(ctxd).Doughnut(pdataTypes);
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: ['tcp隧道数','socks5隧道数','http代理隧道数','udp隧道数','域名解析数']
|
||||
},
|
||||
series : [
|
||||
{
|
||||
name: '类型 统计',
|
||||
type: 'pie',
|
||||
radius : '55%',
|
||||
center: ['50%', '60%'],
|
||||
data:[
|
||||
{value:{{.data.tunnelServerCount}}, name:'tcp隧道数'},
|
||||
{value:{{.data.socks5ServerCount}}, name:'socks5隧道数'},
|
||||
{value:{{.data.httpProxyServerCount}}, name:'http隧道数'},
|
||||
{value:{{.data.udpServerCount}}, name:'udp隧道数'},
|
||||
{value:{{.data.hostCount}}, name:'域名解析数'}
|
||||
],
|
||||
itemStyle: {
|
||||
emphasis: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var myChart = echarts.init(document.getElementById('tj'));
|
||||
myChart.setOption(option);
|
||||
|
||||
</script>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="/static/css/main.css">
|
||||
<!-- Font-icon css-->
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/font-awesome.min.css">
|
||||
<title>easyProxy内网穿透</title>
|
||||
<title>nps内网穿透</title>
|
||||
</head>
|
||||
<body>
|
||||
<section class="material-half-bg">
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<meta name="description"
|
||||
content="Vali is a responsive and free admin theme built with Bootstrap 4, SASS and PUG.js. It's fully customizable and modular.">
|
||||
<link rel="shortcut icon" href="/static/img/favicon.ico">
|
||||
<title>easyProxy内网穿透</title>
|
||||
<title>nps内网穿透</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
@ -61,7 +61,7 @@
|
|||
|
||||
<script type="text/javascript" src="/static/js/datatables.min.js"></script>
|
||||
<script src="/static/js/main.js"></script>
|
||||
<script src="/static/js/chart.js"></script>
|
||||
<script src="/static/js/echarts.min.js"></script>
|
||||
<main class="app-content">
|
||||
<div class="app-title">
|
||||
<div>
|
||||
|
|
Loading…
Reference in New Issue