Modular 、Functional enhancement

This commit is contained in:
刘河
2019-04-08 17:01:08 +08:00
parent 0c87b4119a
commit 824b12a2f8
41 changed files with 754 additions and 242 deletions

View File

@@ -49,6 +49,10 @@ func (s *BaseController) Prepare() {
s.Data["allow_rate_limit"], _ = beego.AppConfig.Bool("allow_rate_limit")
s.Data["allow_connection_num_limit"], _ = beego.AppConfig.Bool("allow_connection_num_limit")
s.Data["allow_multi_ip"], _ = beego.AppConfig.Bool("allow_multi_ip")
s.Data["system_info_display"], _ = beego.AppConfig.Bool("system_info_display")
s.Data["allow_tunnel_num_limit"], _ = beego.AppConfig.Bool("allow_tunnel_num_limit")
s.Data["allow_local_proxy"], _ = beego.AppConfig.Bool("allow_local_proxy")
s.Data["allow_user_change_username"], _ = beego.AppConfig.Bool("allow_user_change_username")
}
//加载模板

View File

@@ -54,6 +54,7 @@ func (s *ClientController) Add() {
MaxConn: s.GetIntNoErr("max_conn"),
WebUserName: s.GetString("web_username"),
WebPassword: s.GetString("web_password"),
MaxTunnelNum: s.GetIntNoErr("max_tunnel"),
Flow: &file.Flow{
ExportFlow: 0,
InletFlow: 0,
@@ -116,13 +117,17 @@ func (s *ClientController) Edit() {
c.Flow.FlowLimit = int64(s.GetIntNoErr("flow_limit"))
c.RateLimit = s.GetIntNoErr("rate_limit")
c.MaxConn = s.GetIntNoErr("max_conn")
c.MaxTunnelNum = s.GetIntNoErr("max_tunnel")
}
c.Remark = s.GetString("remark")
c.Cnf.U = s.GetString("u")
c.Cnf.P = s.GetString("p")
c.Cnf.Compress = common.GetBoolByStr(s.GetString("compress"))
c.Cnf.Crypt = s.GetBoolNoErr("crypt")
c.WebUserName = s.GetString("web_username")
b, err := beego.AppConfig.Bool("allow_user_change_username")
if s.GetSession("isAdmin").(bool) || (err == nil && b) {
c.WebUserName = s.GetString("web_username")
}
c.WebPassword = s.GetString("web_password")
c.ConfigConnAllow = s.GetBoolNoErr("config_conn_allow")
if c.Rate != nil {

View File

@@ -93,7 +93,7 @@ func (s *IndexController) Add() {
Port: s.GetIntNoErr("port"),
ServerIp: s.GetString("server_ip"),
Mode: s.GetString("type"),
Target: &file.Target{TargetStr: s.GetString("target")},
Target: &file.Target{TargetStr: s.GetString("target"), LocalProxy: s.GetBoolNoErr("local_proxy")},
Id: int(file.GetDb().JsonDb.GetTaskId()),
Status: true,
Remark: s.GetString("remark"),
@@ -109,6 +109,9 @@ func (s *IndexController) Add() {
if t.Client, err = file.GetDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
s.AjaxErr(err.Error())
}
if t.Client.MaxTunnelNum != 0 && t.Client.GetTunnelNum() >= t.Client.MaxTunnelNum {
s.AjaxErr("The number of tunnels exceeds the limit")
}
if err := file.GetDb().NewTask(t); err != nil {
s.AjaxErr(err.Error())
}
@@ -166,6 +169,7 @@ func (s *IndexController) Edit() {
t.LocalPath = s.GetString("local_path")
t.StripPre = s.GetString("strip_pre")
t.Remark = s.GetString("remark")
t.Target.LocalProxy = s.GetBoolNoErr("local_proxy")
file.GetDb().UpdateTask(t)
server.StopServer(t.Id)
server.StartTask(t.Id)
@@ -244,7 +248,7 @@ func (s *IndexController) AddHost() {
h := &file.Host{
Id: int(file.GetDb().JsonDb.GetHostId()),
Host: s.GetString("host"),
Target: &file.Target{TargetStr: s.GetString("target")},
Target: &file.Target{TargetStr: s.GetString("target"), LocalProxy: s.GetBoolNoErr("local_proxy")},
HeaderChange: s.GetString("header"),
HostChange: s.GetString("hostchange"),
Remark: s.GetString("remark"),
@@ -304,6 +308,7 @@ func (s *IndexController) EditHost() {
h.Scheme = s.GetString("scheme")
h.KeyFilePath = s.GetString("key_file_path")
h.CertFilePath = s.GetString("cert_file_path")
h.Target.LocalProxy = s.GetBoolNoErr("local_proxy")
file.GetDb().JsonDb.StoreHostToJsonFile()
}
s.AjaxOk("modified success")

View File

@@ -13,6 +13,7 @@ type LoginController struct {
}
func (self *LoginController) Index() {
self.Data["register_allow"], _ = beego.AppConfig.Bool("allow_user_register")
self.TplName = "login/index.html"
}
func (self *LoginController) Verify() {
@@ -55,6 +56,37 @@ func (self *LoginController) Verify() {
}
self.ServeJSON()
}
func (self *LoginController) Register() {
if self.Ctx.Request.Method == "GET" {
self.TplName = "login/register.html"
} else {
if b, err := beego.AppConfig.Bool("allow_user_register"); err != nil || !b {
self.Data["json"] = map[string]interface{}{"status": 0, "msg": "register is not allow"}
self.ServeJSON()
return
}
if self.GetString("username") == "" || self.GetString("password") == "" || self.GetString("username") == beego.AppConfig.String("web_username") {
self.Data["json"] = map[string]interface{}{"status": 0, "msg": "please check your input"}
self.ServeJSON()
return
}
t := &file.Client{
Id: int(file.GetDb().JsonDb.GetClientId()),
Status: true,
Cnf: &file.Config{},
WebUserName: self.GetString("username"),
WebPassword: self.GetString("password"),
Flow: &file.Flow{},
}
if err := file.GetDb().NewClient(t); err != nil {
self.Data["json"] = map[string]interface{}{"status": 0, "msg": err.Error()}
} else {
self.Data["json"] = map[string]interface{}{"status": 1, "msg": "register success"}
}
self.ServeJSON()
}
}
func (self *LoginController) Out() {
self.SetSession("auth", false)
self.Redirect("/login/index", 302)

View File

@@ -39,6 +39,15 @@
placeholder="empty means to be unrestricted">
</div>
</div>
{{end}}
{{if eq true .allow_tunnel_num_limit}}
<div class="form-group" id="max_tunnel">
<label class="control-label col-sm-2" langtag="info-max-tunnel-num">客户端最大隧道数量</label>
<div class="col-sm-10">
<input class="form-control" type="text" name="max_tunnel"
placeholder="empty means to be unrestricted">
</div>
</div>
{{end}}
<div class="form-group" id="u">
<label class="control-label col-sm-2" langtag="info-web-auth-username">basic权限认证用户名</label>

View File

@@ -44,6 +44,15 @@
</div>
</div>
{{end}}
{{if eq true .allow_tunnel_num_limit}}
<div class="form-group" id="max_tunnel">
<label class="control-label col-sm-2" langtag="info-max-tunnel-num">客户端最大隧道数量</label>
<div class="col-sm-10">
<input class="form-control" value="{{.c.MaxTunnelNum}}" type="text" name="max_tunnel"
placeholder="empty means to be unrestricted">
</div>
</div>
{{end}}
{{end}}
<div class="form-group" id="u">
<label class="control-label col-sm-2" langtag="info-web-auth-username">basic权限认证用户名</label>
@@ -72,6 +81,7 @@
</div>
{{end}}
{{if eq true .allow_user_login}}
{{if or (eq true .allow_user_change_username) (eq true .isAdmin)}}
<div class="form-group" id="web_username">
<label class="control-label col-sm-2" langtag="info-client-web-username">web登陆用户名</label>
<div class="col-sm-10">
@@ -79,6 +89,7 @@
placeholder="empty means to be unrestricted">
</div>
</div>
{{end}}
<div class="form-group" id="web_password">
<label class="control-label col-sm-2" langtag="info-client-web-password">web登陆密码</label>
<div class="col-sm-10">

View File

@@ -127,6 +127,7 @@
+ '<b langtag="info-now-conn-num">当前连接数</b>' + row.NowConn + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-flow-limit">流量限制</b>' + row.Flow.FlowLimit + `m&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-rate-limit">带宽限制</b>' + row.RateLimit + `kb/s&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-max-tunnel-num">隧道数限制</b>' + row.MaxTunnelNum + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-client-web-username">web登陆用户名</b>' + row.WebUserName + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-client-web-password">web登陆密码</b>' + row.WebPassword + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp` + "<br/><br>"

View File

@@ -43,8 +43,20 @@
</div>
</div>
{{if eq true .allow_local_proxy}}
<div class="form-group" id="local_proxy">
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
<div class="col-sm-10">
<select class="form-control" name="local_proxy">
<option value="0">no</option>
<option value="1">yes</option>
</select>
</div>
</div>
{{end}}
<div class="form-group" id="target">
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
<label class="col-sm-2 control-label" langtag="info-target">目标(ip:端口)</label>
<div class="col-sm-10">
<textarea class="form-control" name="target" rows="4" placeholder="10.1.50.203:22
10.1.50.202:22"></textarea>
@@ -103,9 +115,9 @@
</div>
<script>
var arr = []
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "strip_pre", "local_path"]
arr["tcp"] = ["type", "port", "target", "compress", "u", "p", "tcp隧道模式提供一条tcp隧道适用于ssh、远程桌面等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的目标端口"]
arr["udp"] = ["type", "port", "target", "compress", "udp隧道模式提供一条udp隧道适用于dns、内网dns访问等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后访问公网服务器的设定端口则相当于访问内网目标地址的udp目标端口"]
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "strip_pre", "local_path", "local_proxy"]
arr["tcp"] = ["type", "port", "target", "compress", "u", "p", "local_proxy", "tcp隧道模式提供一条tcp隧道适用于ssh、远程桌面等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的目标端口"]
arr["udp"] = ["type", "port", "target", "compress", "local_proxy", "udp隧道模式提供一条udp隧道适用于dns、内网dns访问等添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后访问公网服务器的设定端口则相当于访问内网目标地址的udp目标端口"]
arr["socks5"] = ["type", "port", "compress", "u", "p", "socks5代理模式内网socks5代理配合proxifer可如同使用vpn一样访问内网设备或资源添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后在外网环境下本机配置socks5代理即访问内网设备或者资源 "]
arr["httpProxy"] = ["type", "port", "compress", "u", "p", " http代理模式内网http代理可访问内网网站添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后在外网环境下本机配置http代理即访问内网站点"]
arr["secret"] = ["type", "target", "compress", "password", "u", "p", " http代理模式内网http代理可访问内网网站添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后在外网环境下本机配置http代理即访问内网站点"]

View File

@@ -44,6 +44,17 @@
placeholder="such as 8024">
</div>
</div>
{{if eq true .allow_local_proxy}}
<div class="form-group" id="local_proxy">
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
<div class="col-sm-10">
<select class="form-control" name="local_proxy">
<option {{if eq false .t.Target.LocalProxy}}selected{{end}} value="0">no</option>
<option {{if eq true .t.Target.LocalProxy}}selected{{end}} value="1">yes</option>
</select>
</div>
</div>
{{end}}
<div class="form-group" id="target">
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
<div class="col-sm-10">
@@ -103,9 +114,9 @@
</div>
<script>
var arr = []
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "local_path", "strip_pre"]
arr["tcp"] = ["type", "port", "target", "u", "p", "compress"]
arr["udp"] = ["type", "port", "target", "compress"]
arr["all"] = ["type", "port", "compress", "u", "p", "target", "password", "local_path", "strip_pre", "local_proxy"]
arr["tcp"] = ["type", "port", "target", "u", "p", "compress", "local_proxy"]
arr["udp"] = ["type", "port", "target", "compress", "local_proxy"]
arr["socks5"] = ["type", "port", "compress", "u", "p"]
arr["httpProxy"] = ["type", "port", "compress", "u", "p"]
arr["secret"] = ["type", "target", "compress", "u", "p", "password"]

View File

@@ -56,6 +56,17 @@
placeholder="client id">
</div>
</div>
{{if eq true .allow_local_proxy}}
<div class="form-group" id="local_proxy">
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
<div class="col-sm-10">
<select class="form-control" name="local_proxy">
<option value="0">no</option>
<option value="1">yes</option>
</select>
</div>
</div>
{{end}}
<div class="form-group">
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
<div class="col-sm-10">

View File

@@ -59,6 +59,17 @@
placeholder="client id">
</div>
</div>
{{if eq true .allow_local_proxy}}
<div class="form-group" id="local_proxy">
<label class="control-label col-sm-2" langtag="info-local-proxy">是否代理为服务端本地</label>
<div class="col-sm-10">
<select class="form-control" name="local_proxy">
<option {{if eq false .h.Target.LocalProxy}}selected{{end}} value="0">no</option>
<option {{if eq true .h.Target.LocalProxy}}selected{{end}} value="1">yes</option>
</select>
</div>
</div>
{{end}}
<div class="form-group">
<label class="col-sm-2 control-label" langtag="info-target">内网目标(ip:端口)</label>
<div class="col-sm-10">

View File

@@ -242,7 +242,7 @@
</div>
</div>
{{if eq true .system_info_display}}
<div class="row">
<div class="col-lg-6">
<div class="ibox float-e-margins">
@@ -340,6 +340,7 @@
</div>
</div>
</div>
{{end}}
<div class="row">
<div class="col-lg-6">

View File

@@ -63,12 +63,19 @@
detailView: true,
smartDisplay: true, // 智能显示 pagination 和 cardview 等
detailFormatter: function (index, row, element) {
return '<b langtag="info-export-flow">出口流量</b>' + change(row.Flow.ExportFlow) + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-inlet-flow">入口流量</b>' + change(row.Flow.InletFlow) + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp` + "<br/><br>"
tmp = '<b langtag="info-export-flow">出口流量</b>' + change(row.Flow.ExportFlow) + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-inlet-flow">入口流量</b>' + change(row.Flow.InletFlow) + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-crypt">加密</b>' + row.Client.Cnf.Crypt + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-compress">压缩</b>' + row.Client.Cnf.Compress + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-web-auth-username">basic权限认证用户名</b>' + row.Client.Cnf.U + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
+ '<b langtag="info-web-auth-password">basic权限认证密码</b>' + row.Client.Cnf.P + `&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp`
if (row.Mode == "p2p") {
return tmp + "<br/><br>" + '<b langtag="info-command">访问端命令</b>' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -target=your target" + "</code>"
}
if (row.Mode = "secret") {
return tmp + "<br/><br>" + '<b langtag="info-command">访问端命令</b>' + "<code>./npc{{.win}} -server={{.ip}}:{{.p}} -vkey=" + row.Client.VerifyKey + " -type=" +{{.bridgeType}} +" -password=" + row.Password + " -local_type=secret" + "</code>"
}
return tmp
},
//表格的列
columns: [
@@ -112,13 +119,13 @@
field: 'Password',//域值
title: 'secret',//标题
visible: true,//false表示不显示
},
{
field: 'Status',//域值
title: 'setting',//内容
visible: true,//false表示不显示
formatter: function (value, row, index) {
if (value) {
return '<span class="badge badge-primary">open</span>'
@@ -131,7 +138,7 @@
field: 'RunStatus',//域值
title: 'run',//内容
visible: true,//false表示不显示
formatter: function (value, row, index) {
if (value) {
return '<span class="badge badge-primary">open</span>'
@@ -144,7 +151,7 @@
field: '',//域值
title: 'client',//内容
visible: true,//false表示不显示
formatter: function (value, row, index) {
if (row.Client.IsConnect) {
return '<span class="badge badge-primary">online</span>'
@@ -157,7 +164,7 @@
field: 'option',//域值
title: 'option',//内容
visible: true,//false表示不显示
formatter: function (value, row, index) {
btn_group = '<div class="btn-group">'
btn = `<button onclick="del(` + row.Id + `)" class="btn-danger"><i class="fa fa-trash"></i></button><button onclick="edit(` + row.Id + `)" class="btn-primary"><i class="fa fa-edit"></i></button></div>`

View File

@@ -48,6 +48,9 @@
<input name="password" type="password" class="form-control" placeholder="password" required="">
</div>
<button onclick="login()" class="btn btn-primary block full-width m-b">login</button>
{{if eq true .register_allow}}
<a class="btn btn-sm btn-white btn-block" href="/login/register">register</a>
{{end}}
</form>
</div>
</div>

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nps register</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/font-awesome/css/font-awesome.css" rel="stylesheet">
<link href="/static/css/style.css" rel="stylesheet">
</head>
<body class="gray-bg">
<div class="middle-box text-center loginscreen animated fadeInDown">
<div>
<div>
<h1 class="logo-name">NPS</h1>
</div>
<h3>register NPS</h3>
<form class="m-t" role="form" onsubmit="return false">
<div class="form-group">
<input type="text" class="form-control" placeholder="username" name="username" required="">
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="password" name="password" required="">
</div>
<button onclick="register()" type="submit" class="btn btn-primary block full-width m-b">register</button>
<a class="btn btn-sm btn-white btn-block" href="/login/index">login</a>
</form>
</div>
</div>
<script src="/static/js/jquery-2.1.1.js"></script>
<script>
function register() {
$.ajax({
type: "POST",
url: "/login/register",
data: $("form").serializeArray(),
success: function (res) {
alert(res.msg)
if (res.status) {
window.location.href = "/login/index"
}
}
})
return false
}
</script>
</body>
</html>