From 522be82a31ebbf6b2e9acd5a56021d8bce539973 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 May 2022 17:14:50 +0800 Subject: [PATCH 01/28] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9F=9F=E5=90=8D?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=8B=86=E5=88=86=E9=9A=A7=E9=81=93=EF=BC=88?= =?UTF-8?q?=E5=9F=9F=E5=90=8D=E8=B7=AF=E7=94=B1=E5=8A=9F=E8=83=BD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/group.go | 40 +++++ server/dbdata/tables.go | 26 ++-- server/handler/link_tunnel.go | 47 +++++- web/src/pages/group/List.vue | 271 ++++++++++++++++++---------------- 4 files changed, 241 insertions(+), 143 deletions(-) diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 252f3f8..1eed65f 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "net" + "regexp" + "strings" "time" "github.com/bjdgyc/anylink/base" @@ -127,6 +129,20 @@ func SetGroup(g *Group) error { } } g.ClientDns = clientDns + // 域名拆分隧道,不能同时填写 + if g.DsIncludeDomains != "" && g.DsExcludeDomains != "" { + return errors.New("包含/排除域名不能同时填写") + } + // 校验包含域名的格式 + err = CheckDomainNames(g.DsIncludeDomains) + if err != nil { + return errors.New("包含域名有误:" + err.Error()) + } + // 校验排除域名的格式 + err = CheckDomainNames(g.DsExcludeDomains) + if err != nil { + return errors.New("排除域名有误:" + err.Error()) + } g.UpdatedAt = time.Now() if g.Id > 0 { @@ -149,3 +165,27 @@ func parseIpNet(s string) (string, *net.IPNet, error) { return ipMask, ipNet, nil } +func CheckDomainNames(domains string) error { + if domains == "" { + return nil + } + str_slice := strings.Split(domains, ",") + for _, val := range str_slice { + if val == "" { + return errors.New(val + " 请以逗号分隔域名") + } + if !ValidateDomainName(val) { + return errors.New(val + " 域名有误") + } + } + return nil +} + +func ValidateDomainName(domain string) bool { + pos := strings.LastIndex(domain, ".") + if pos != -1 && len(domain[pos+1:]) < 2 { + return false + } + RegExp := regexp.MustCompile(`^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$`) + return RegExp.MatchString(domain) +} diff --git a/server/dbdata/tables.go b/server/dbdata/tables.go index 48df52e..a0ffea2 100644 --- a/server/dbdata/tables.go +++ b/server/dbdata/tables.go @@ -6,18 +6,20 @@ import ( ) type Group struct { - Id int `json:"id" xorm:"pk autoincr not null"` - Name string `json:"name" xorm:"varchar(60) not null unique"` - Note string `json:"note" xorm:"varchar(255)"` - AllowLan bool `json:"allow_lan" xorm:"Bool"` - ClientDns []ValData `json:"client_dns" xorm:"Text"` - RouteInclude []ValData `json:"route_include" xorm:"Text"` - RouteExclude []ValData `json:"route_exclude" xorm:"Text"` - LinkAcl []GroupLinkAcl `json:"link_acl" xorm:"Text"` - Bandwidth int `json:"bandwidth" xorm:"Int"` // 带宽限制 - Status int8 `json:"status" xorm:"Int"` // 1正常 - CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` - UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` + Id int `json:"id" xorm:"pk autoincr not null"` + Name string `json:"name" xorm:"varchar(60) not null unique"` + Note string `json:"note" xorm:"varchar(255)"` + AllowLan bool `json:"allow_lan" xorm:"Bool"` + ClientDns []ValData `json:"client_dns" xorm:"Text"` + RouteInclude []ValData `json:"route_include" xorm:"Text"` + RouteExclude []ValData `json:"route_exclude" xorm:"Text"` + DsExcludeDomains string `json:"ds_exclude_domains" xorm:"Text"` + DsIncludeDomains string `json:"ds_include_domains" xorm:"Text"` + LinkAcl []GroupLinkAcl `json:"link_acl" xorm:"Text"` + Bandwidth int `json:"bandwidth" xorm:"Int"` // 带宽限制 + Status int8 `json:"status" xorm:"Int"` // 1正常 + CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` + UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` } type User struct { diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index a43cb5f..295a19c 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "strings" + "text/template" "github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/dbdata" @@ -118,7 +119,6 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { for _, v := range cSess.Group.RouteExclude { HttpAddHeader(w, "X-CSTP-Split-Exclude", v.IpMask) } - HttpSetHeader(w, "X-CSTP-Lease-Duration", fmt.Sprintf("%d", base.Cfg.IpLease)) // ip地址租期 HttpSetHeader(w, "X-CSTP-Session-Timeout", "none") HttpSetHeader(w, "X-CSTP-Session-Timeout-Alert-Interval", "60") @@ -153,7 +153,11 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { HttpSetHeader(w, "X-CSTP-Disable-Always-On-VPN", "false") HttpSetHeader(w, "X-CSTP-Client-Bypass-Protocol", "false") HttpSetHeader(w, "X-CSTP-TCP-Keepalive", "false") - // HttpSetHeader(w, "X-CSTP-Post-Auth-XML", ``) + // 设置域名拆分隧道(移动端不支持) + if mobile != "mobile" { + SetPostAuthXml(cSess.Group, w) + } + w.WriteHeader(http.StatusOK) hClone := w.Header().Clone() @@ -187,3 +191,42 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { go LinkCstp(conn, bufRW, cSess) } + +// 设置域名拆分隧道 +func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error { + if g.DsExcludeDomains == "" && g.DsIncludeDomains == "" { + return nil + } + tmpl, err := template.New("post_auth_xml").Parse(ds_domains_xml) + if err != nil { + return err + } + var result bytes.Buffer + _ = tmpl.Execute(&result, g) + if err != nil { + return err + } + if result.String() != "" { + HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) + base.Info(result.String()) + } + return nil +} + +var ds_domains_xml = ` + + + + + + {{if .DsExcludeDomains}} + + {{end}} + {{if .DsIncludeDomains}} + + {{end}} + + + + +` \ No newline at end of file diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index 2fbb4b3..77fa358 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -152,143 +152,155 @@ center> - - - + + + + + - - - + + + - - - + + + - - - - - - - - - + + + + + + + + + - - - 输入IP格式如: 192.168.0.10 - - - - - - - - - - - - - - - - + + + 输入IP格式如: 192.168.0.10 + + + + + + + + + + + + + + + + + + + 启用 + 停用 + + + - - - 输入CIDR格式如: 192.168.1.0/24 - - - - - - - - - - - - - - - - + + + + 输入CIDR格式如: 192.168.1.0/24 + + + + + + + + + + + + + + + + - - - 输入CIDR格式如: 192.168.2.0/24 - - - - - - - - - - - - - - - - + + + 输入CIDR格式如: 192.168.2.0/24 + + + + + + + + + + + + + + + + + + + + + 输入CIDR格式如: 192.168.3.0/24 端口0表示所有端口 + + + + - - - 输入CIDR格式如: 192.168.3.0/24 端口0表示所有端口 - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - 启用 - 停用 - - - - - - 保存 - 取消 - - + + + + + + + + + + 保存 + 取消 + + @@ -313,6 +325,7 @@ export default { page: 1, tableData: [], count: 10, + activeTab : "general", ruleForm: { bandwidth: 0, From 625e4eecf40499066c3786273147b5766e0a9cdf Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 May 2022 09:16:43 +0800 Subject: [PATCH 02/28] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/link_tunnel.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index 295a19c..f1ef464 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -202,14 +202,11 @@ func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error { return err } var result bytes.Buffer - _ = tmpl.Execute(&result, g) + err = tmpl.Execute(&result, g) if err != nil { return err } - if result.String() != "" { - HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) - base.Info(result.String()) - } + HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) return nil } @@ -229,4 +226,4 @@ var ds_domains_xml = ` -` \ No newline at end of file +` From 2964b34087dfcbce25958ef6966e67287302e4c0 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 May 2022 09:37:35 +0800 Subject: [PATCH 03/28] =?UTF-8?q?=E5=BC=B9=E5=87=BA=E7=AA=97=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=98=BE=E7=A4=BA=E7=AC=AC=E4=B8=80=E4=B8=AA=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/pages/group/List.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index 77fa358..fa19975 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -375,6 +375,7 @@ export default { handleEdit(row) { !this.$refs['ruleForm'] || this.$refs['ruleForm'].resetFields(); console.log(row) + this.activeTab = "general" this.user_edit_dialog = true if (!row) { return; From 90aa6c272d9ddd5cd285fd436683aa9fcbccbd58 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 May 2022 13:40:35 +0800 Subject: [PATCH 04/28] =?UTF-8?q?=E5=B0=86ds=5Fdomains=5Fxml=E8=BF=81?= =?UTF-8?q?=E7=A7=BB=E8=87=B3link=5Fauth.go?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/link_auth.go | 17 +++++++++++++++++ server/handler/link_tunnel.go | 18 ------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/server/handler/link_auth.go b/server/handler/link_auth.go index 6c98138..a148dae 100644 --- a/server/handler/link_auth.go +++ b/server/handler/link_auth.go @@ -221,3 +221,20 @@ var auth_profile = ` ` +var ds_domains_xml = ` + + + + + + {{if .DsExcludeDomains}} + + {{end}} + {{if .DsIncludeDomains}} + + {{end}} + + + + +` diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index f1ef464..52aac12 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -209,21 +209,3 @@ func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error { HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) return nil } - -var ds_domains_xml = ` - - - - - - {{if .DsExcludeDomains}} - - {{end}} - {{if .DsIncludeDomains}} - - {{end}} - - - - -` From f6996363e305a278cadb0f654d16f6cc6cb63e28 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 May 2022 14:04:24 +0800 Subject: [PATCH 05/28] =?UTF-8?q?dynamic-split-exclude-domains=E5=92=8Cdyn?= =?UTF-8?q?amic-split-include-domains=E4=B8=8D=E8=83=BD=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E5=87=BA=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/link_auth.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/handler/link_auth.go b/server/handler/link_auth.go index a148dae..d1740af 100644 --- a/server/handler/link_auth.go +++ b/server/handler/link_auth.go @@ -229,11 +229,10 @@ var ds_domains_xml = ` {{if .DsExcludeDomains}} - {{end}} - {{if .DsIncludeDomains}} + {{else if .DsIncludeDomains}} {{end}} - + From f325970089bc067691e816b33c483c784f3679b1 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 30 May 2022 14:40:27 +0800 Subject: [PATCH 06/28] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9F=9F=E5=90=8D?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=8B=86=E5=88=86=E9=9A=A7=E9=81=93=EF=BC=88?= =?UTF-8?q?=E5=9F=9F=E5=90=8D=E8=B7=AF=E7=94=B1=E5=8A=9F=E8=83=BD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/group.go | 40 +++++ server/dbdata/tables.go | 26 ++-- server/handler/link_tunnel.go | 47 +++++- web/src/pages/group/List.vue | 271 ++++++++++++++++++---------------- 4 files changed, 241 insertions(+), 143 deletions(-) diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 252f3f8..1eed65f 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -4,6 +4,8 @@ import ( "errors" "fmt" "net" + "regexp" + "strings" "time" "github.com/bjdgyc/anylink/base" @@ -127,6 +129,20 @@ func SetGroup(g *Group) error { } } g.ClientDns = clientDns + // 域名拆分隧道,不能同时填写 + if g.DsIncludeDomains != "" && g.DsExcludeDomains != "" { + return errors.New("包含/排除域名不能同时填写") + } + // 校验包含域名的格式 + err = CheckDomainNames(g.DsIncludeDomains) + if err != nil { + return errors.New("包含域名有误:" + err.Error()) + } + // 校验排除域名的格式 + err = CheckDomainNames(g.DsExcludeDomains) + if err != nil { + return errors.New("排除域名有误:" + err.Error()) + } g.UpdatedAt = time.Now() if g.Id > 0 { @@ -149,3 +165,27 @@ func parseIpNet(s string) (string, *net.IPNet, error) { return ipMask, ipNet, nil } +func CheckDomainNames(domains string) error { + if domains == "" { + return nil + } + str_slice := strings.Split(domains, ",") + for _, val := range str_slice { + if val == "" { + return errors.New(val + " 请以逗号分隔域名") + } + if !ValidateDomainName(val) { + return errors.New(val + " 域名有误") + } + } + return nil +} + +func ValidateDomainName(domain string) bool { + pos := strings.LastIndex(domain, ".") + if pos != -1 && len(domain[pos+1:]) < 2 { + return false + } + RegExp := regexp.MustCompile(`^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$`) + return RegExp.MatchString(domain) +} diff --git a/server/dbdata/tables.go b/server/dbdata/tables.go index 48df52e..a0ffea2 100644 --- a/server/dbdata/tables.go +++ b/server/dbdata/tables.go @@ -6,18 +6,20 @@ import ( ) type Group struct { - Id int `json:"id" xorm:"pk autoincr not null"` - Name string `json:"name" xorm:"varchar(60) not null unique"` - Note string `json:"note" xorm:"varchar(255)"` - AllowLan bool `json:"allow_lan" xorm:"Bool"` - ClientDns []ValData `json:"client_dns" xorm:"Text"` - RouteInclude []ValData `json:"route_include" xorm:"Text"` - RouteExclude []ValData `json:"route_exclude" xorm:"Text"` - LinkAcl []GroupLinkAcl `json:"link_acl" xorm:"Text"` - Bandwidth int `json:"bandwidth" xorm:"Int"` // 带宽限制 - Status int8 `json:"status" xorm:"Int"` // 1正常 - CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` - UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` + Id int `json:"id" xorm:"pk autoincr not null"` + Name string `json:"name" xorm:"varchar(60) not null unique"` + Note string `json:"note" xorm:"varchar(255)"` + AllowLan bool `json:"allow_lan" xorm:"Bool"` + ClientDns []ValData `json:"client_dns" xorm:"Text"` + RouteInclude []ValData `json:"route_include" xorm:"Text"` + RouteExclude []ValData `json:"route_exclude" xorm:"Text"` + DsExcludeDomains string `json:"ds_exclude_domains" xorm:"Text"` + DsIncludeDomains string `json:"ds_include_domains" xorm:"Text"` + LinkAcl []GroupLinkAcl `json:"link_acl" xorm:"Text"` + Bandwidth int `json:"bandwidth" xorm:"Int"` // 带宽限制 + Status int8 `json:"status" xorm:"Int"` // 1正常 + CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` + UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` } type User struct { diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index a43cb5f..295a19c 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "strings" + "text/template" "github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/dbdata" @@ -118,7 +119,6 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { for _, v := range cSess.Group.RouteExclude { HttpAddHeader(w, "X-CSTP-Split-Exclude", v.IpMask) } - HttpSetHeader(w, "X-CSTP-Lease-Duration", fmt.Sprintf("%d", base.Cfg.IpLease)) // ip地址租期 HttpSetHeader(w, "X-CSTP-Session-Timeout", "none") HttpSetHeader(w, "X-CSTP-Session-Timeout-Alert-Interval", "60") @@ -153,7 +153,11 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { HttpSetHeader(w, "X-CSTP-Disable-Always-On-VPN", "false") HttpSetHeader(w, "X-CSTP-Client-Bypass-Protocol", "false") HttpSetHeader(w, "X-CSTP-TCP-Keepalive", "false") - // HttpSetHeader(w, "X-CSTP-Post-Auth-XML", ``) + // 设置域名拆分隧道(移动端不支持) + if mobile != "mobile" { + SetPostAuthXml(cSess.Group, w) + } + w.WriteHeader(http.StatusOK) hClone := w.Header().Clone() @@ -187,3 +191,42 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { go LinkCstp(conn, bufRW, cSess) } + +// 设置域名拆分隧道 +func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error { + if g.DsExcludeDomains == "" && g.DsIncludeDomains == "" { + return nil + } + tmpl, err := template.New("post_auth_xml").Parse(ds_domains_xml) + if err != nil { + return err + } + var result bytes.Buffer + _ = tmpl.Execute(&result, g) + if err != nil { + return err + } + if result.String() != "" { + HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) + base.Info(result.String()) + } + return nil +} + +var ds_domains_xml = ` + + + + + + {{if .DsExcludeDomains}} + + {{end}} + {{if .DsIncludeDomains}} + + {{end}} + + + + +` \ No newline at end of file diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index 2fbb4b3..77fa358 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -152,143 +152,155 @@ center> - - - + + + + + - - - + + + - - - + + + - - - - - - - - - + + + + + + + + + - - - 输入IP格式如: 192.168.0.10 - - - - - - - - - - - - - - - - + + + 输入IP格式如: 192.168.0.10 + + + + + + + + + + + + + + + + + + + 启用 + 停用 + + + - - - 输入CIDR格式如: 192.168.1.0/24 - - - - - - - - - - - - - - - - + + + + 输入CIDR格式如: 192.168.1.0/24 + + + + + + + + + + + + + + + + - - - 输入CIDR格式如: 192.168.2.0/24 - - - - - - - - - - - - - - - - + + + 输入CIDR格式如: 192.168.2.0/24 + + + + + + + + + + + + + + + + + + + + + 输入CIDR格式如: 192.168.3.0/24 端口0表示所有端口 + + + + - - - 输入CIDR格式如: 192.168.3.0/24 端口0表示所有端口 - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - 启用 - 停用 - - - - - - 保存 - 取消 - - + + + + + + + + + + 保存 + 取消 + + @@ -313,6 +325,7 @@ export default { page: 1, tableData: [], count: 10, + activeTab : "general", ruleForm: { bandwidth: 0, From cde46c5765108c1ddb2206c8afac1c6a081851a7 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 30 May 2022 14:41:38 +0800 Subject: [PATCH 07/28] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/link_tunnel.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index 295a19c..f1ef464 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -202,14 +202,11 @@ func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error { return err } var result bytes.Buffer - _ = tmpl.Execute(&result, g) + err = tmpl.Execute(&result, g) if err != nil { return err } - if result.String() != "" { - HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) - base.Info(result.String()) - } + HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) return nil } @@ -229,4 +226,4 @@ var ds_domains_xml = ` -` \ No newline at end of file +` From 3de75285de6ce78be1e3d717560b4c226f1a76be Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 30 May 2022 14:41:49 +0800 Subject: [PATCH 08/28] =?UTF-8?q?=E5=BC=B9=E5=87=BA=E7=AA=97=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=98=BE=E7=A4=BA=E7=AC=AC=E4=B8=80=E4=B8=AA=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/pages/group/List.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index 77fa358..fa19975 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -375,6 +375,7 @@ export default { handleEdit(row) { !this.$refs['ruleForm'] || this.$refs['ruleForm'].resetFields(); console.log(row) + this.activeTab = "general" this.user_edit_dialog = true if (!row) { return; From a0830f0440e22195fa58cb85e491561bffb00af0 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 30 May 2022 14:41:59 +0800 Subject: [PATCH 09/28] =?UTF-8?q?=E5=B0=86ds=5Fdomains=5Fxml=E8=BF=81?= =?UTF-8?q?=E7=A7=BB=E8=87=B3link=5Fauth.go?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/link_auth.go | 17 +++++++++++++++++ server/handler/link_tunnel.go | 18 ------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/server/handler/link_auth.go b/server/handler/link_auth.go index 6c98138..a148dae 100644 --- a/server/handler/link_auth.go +++ b/server/handler/link_auth.go @@ -221,3 +221,20 @@ var auth_profile = ` ` +var ds_domains_xml = ` + + + + + + {{if .DsExcludeDomains}} + + {{end}} + {{if .DsIncludeDomains}} + + {{end}} + + + + +` diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index f1ef464..52aac12 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -209,21 +209,3 @@ func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error { HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) return nil } - -var ds_domains_xml = ` - - - - - - {{if .DsExcludeDomains}} - - {{end}} - {{if .DsIncludeDomains}} - - {{end}} - - - - -` From 9d5b9c4dedf8ac73137caa4e23d71c0ee575e519 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 30 May 2022 14:42:08 +0800 Subject: [PATCH 10/28] =?UTF-8?q?dynamic-split-exclude-domains=E5=92=8Cdyn?= =?UTF-8?q?amic-split-include-domains=E4=B8=8D=E8=83=BD=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E5=87=BA=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/handler/link_auth.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/handler/link_auth.go b/server/handler/link_auth.go index a148dae..d1740af 100644 --- a/server/handler/link_auth.go +++ b/server/handler/link_auth.go @@ -229,11 +229,10 @@ var ds_domains_xml = ` {{if .DsExcludeDomains}} - {{end}} - {{if .DsIncludeDomains}} + {{else if .DsIncludeDomains}} {{end}} - + From 3e491d33c6c9200f71e0fb6c3610e7b15dcc48ab Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Tue, 31 May 2022 13:12:30 +0800 Subject: [PATCH 11/28] =?UTF-8?q?=E5=9F=9F=E5=90=8D=E5=90=8E=E7=BC=80?= =?UTF-8?q?=E5=8F=AA=E8=83=BD=E4=B8=BA=E5=AD=97=E6=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/group.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 1eed65f..28e42a0 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -182,10 +182,6 @@ func CheckDomainNames(domains string) error { } func ValidateDomainName(domain string) bool { - pos := strings.LastIndex(domain, ".") - if pos != -1 && len(domain[pos+1:]) < 2 { - return false - } - RegExp := regexp.MustCompile(`^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$`) + RegExp := regexp.MustCompile(`^([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+[A-Za-z]{2,18}$`) return RegExp.MatchString(domain) } From d4f266de66319bf43b17d493cd4c5e2f8a9cb4c1 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Tue, 31 May 2022 19:14:25 +0800 Subject: [PATCH 12/28] =?UTF-8?q?=E8=BF=87=E6=BB=A4=E9=A6=96=E5=B0=BE?= =?UTF-8?q?=E7=9A=84=E7=A9=BA=E7=99=BD=E7=AC=A6=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E5=A4=A7=E5=AE=B6=E4=B9=A0=E6=83=AF=E6=80=A7=E6=8C=89=E4=BA=86?= =?UTF-8?q?=E5=9B=9E=E8=BD=A6=E9=94=AE=E8=80=8C=E5=AF=BC=E8=87=B4=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/group.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 28e42a0..872a2a0 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -130,6 +130,8 @@ func SetGroup(g *Group) error { } g.ClientDns = clientDns // 域名拆分隧道,不能同时填写 + g.DsIncludeDomains = strings.TrimSpace(g.DsIncludeDomains) + g.DsExcludeDomains = strings.TrimSpace(g.DsExcludeDomains) if g.DsIncludeDomains != "" && g.DsExcludeDomains != "" { return errors.New("包含/排除域名不能同时填写") } From e9c55a08530835ff06d7b1be3e8cd19aee7cae2a Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Thu, 2 Jun 2022 17:58:22 +0800 Subject: [PATCH 13/28] =?UTF-8?q?=E6=96=B0=E5=A2=9Eradius=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/admin/api_group.go | 4 ++- server/dbdata/group.go | 70 +++++++++++++++++++++++++++++------- server/dbdata/tables.go | 29 +++++++-------- server/dbdata/user.go | 53 +++++++++++++++++++++++++++ server/go.mod | 1 + web/src/pages/group/List.vue | 52 +++++++++++++++++++-------- 6 files changed, 168 insertions(+), 41 deletions(-) diff --git a/server/admin/api_group.go b/server/admin/api_group.go index 17fbdb7..dd440e1 100644 --- a/server/admin/api_group.go +++ b/server/admin/api_group.go @@ -62,7 +62,9 @@ func GroupDetail(w http.ResponseWriter, r *http.Request) { RespError(w, RespInternalErr, err) return } - + if len(data.Auth) == 0 { + data.Auth["type"] = "local" + } RespSucess(w, data) } diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 872a2a0..d39d476 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -1,6 +1,7 @@ package dbdata import ( + "encoding/json" "errors" "fmt" "net" @@ -32,19 +33,27 @@ type ValData struct { Note string `json:"note"` } +type AuthRadius struct { + Addr string `json:"addr"` + Secret string `json:"secret"` +} + // type Group struct { -// Id int `json:"id" xorm:"pk autoincr not null"` -// Name string `json:"name" xorm:"not null unique"` -// Note string `json:"note"` -// AllowLan bool `json:"allow_lan"` -// ClientDns []ValData `json:"client_dns"` -// RouteInclude []ValData `json:"route_include"` -// RouteExclude []ValData `json:"route_exclude"` -// LinkAcl []GroupLinkAcl `json:"link_acl"` -// Bandwidth int `json:"bandwidth"` // 带宽限制 -// Status int8 `json:"status"` // 1正常 -// CreatedAt time.Time `json:"created_at"` -// UpdatedAt time.Time `json:"updated_at"` +// Id int `json:"id" xorm:"pk autoincr not null"` +// Name string `json:"name" xorm:"varchar(60) not null unique"` +// Note string `json:"note" xorm:"varchar(255)"` +// AllowLan bool `json:"allow_lan" xorm:"Bool"` +// ClientDns []ValData `json:"client_dns" xorm:"Text"` +// RouteInclude []ValData `json:"route_include" xorm:"Text"` +// RouteExclude []ValData `json:"route_exclude" xorm:"Text"` +// DsExcludeDomains string `json:"ds_exclude_domains" xorm:"Text"` +// DsIncludeDomains string `json:"ds_include_domains" xorm:"Text"` +// LinkAcl []GroupLinkAcl `json:"link_acl" xorm:"Text"` +// Bandwidth int `json:"bandwidth" xorm:"Int"` // 带宽限制 +// Auth map[string]interface{} `json:"auth" xorm:"not null default '{}' varchar(255)"` // 认证方式 +// Status int8 `json:"status" xorm:"Int"` // 1正常 +// CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` +// UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` // } func GetGroupNames() []string { @@ -145,6 +154,20 @@ func SetGroup(g *Group) error { if err != nil { return errors.New("排除域名有误:" + err.Error()) } + // 处理认证类型 + switch g.Auth["type"] { + case "local": + g.Auth = map[string]interface{}{ + "type": g.Auth["type"], + } + case "radius": + err = checkRadiusData(g.Auth) + if err != nil { + return err + } + default: + return errors.New("未知的认证类型") + } g.UpdatedAt = time.Now() if g.Id > 0 { @@ -167,6 +190,24 @@ func parseIpNet(s string) (string, *net.IPNet, error) { return ipMask, ipNet, nil } + +func checkRadiusData(auth map[string]interface{}) error { + radisConf := AuthRadius{} + bodyBytes, err := json.Marshal(auth["radius"]) + if err != nil { + return errors.New("Radius的密钥/服务器地址填写有误") + } + json.Unmarshal(bodyBytes, &radisConf) + if !ValidateIpPort(radisConf.Addr) { + return errors.New("Radius的服务器地址填写有误") + } + // freeradius官网最大8000字符, 这里限制800 + if len(radisConf.Secret) < 8 || len(radisConf.Secret) > 800 { + return errors.New("Radius的密钥长度需在8~800个字符之间") + } + return nil +} + func CheckDomainNames(domains string) error { if domains == "" { return nil @@ -187,3 +228,8 @@ func ValidateDomainName(domain string) bool { RegExp := regexp.MustCompile(`^([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+[A-Za-z]{2,18}$`) return RegExp.MatchString(domain) } + +func ValidateIpPort(addr string) bool { + RegExp := regexp.MustCompile(`^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$$`) + return RegExp.MatchString(addr) +} diff --git a/server/dbdata/tables.go b/server/dbdata/tables.go index a0ffea2..9dd2b5d 100644 --- a/server/dbdata/tables.go +++ b/server/dbdata/tables.go @@ -6,20 +6,21 @@ import ( ) type Group struct { - Id int `json:"id" xorm:"pk autoincr not null"` - Name string `json:"name" xorm:"varchar(60) not null unique"` - Note string `json:"note" xorm:"varchar(255)"` - AllowLan bool `json:"allow_lan" xorm:"Bool"` - ClientDns []ValData `json:"client_dns" xorm:"Text"` - RouteInclude []ValData `json:"route_include" xorm:"Text"` - RouteExclude []ValData `json:"route_exclude" xorm:"Text"` - DsExcludeDomains string `json:"ds_exclude_domains" xorm:"Text"` - DsIncludeDomains string `json:"ds_include_domains" xorm:"Text"` - LinkAcl []GroupLinkAcl `json:"link_acl" xorm:"Text"` - Bandwidth int `json:"bandwidth" xorm:"Int"` // 带宽限制 - Status int8 `json:"status" xorm:"Int"` // 1正常 - CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` - UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` + Id int `json:"id" xorm:"pk autoincr not null"` + Name string `json:"name" xorm:"varchar(60) not null unique"` + Note string `json:"note" xorm:"varchar(255)"` + AllowLan bool `json:"allow_lan" xorm:"Bool"` + ClientDns []ValData `json:"client_dns" xorm:"Text"` + RouteInclude []ValData `json:"route_include" xorm:"Text"` + RouteExclude []ValData `json:"route_exclude" xorm:"Text"` + DsExcludeDomains string `json:"ds_exclude_domains" xorm:"Text"` + DsIncludeDomains string `json:"ds_include_domains" xorm:"Text"` + LinkAcl []GroupLinkAcl `json:"link_acl" xorm:"Text"` + Bandwidth int `json:"bandwidth" xorm:"Int"` // 带宽限制 + Auth map[string]interface{} `json:"auth" xorm:"not null default '{}' varchar(255)"` // 认证方式 + Status int8 `json:"status" xorm:"Int"` // 1正常 + CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` + UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` } type User struct { diff --git a/server/dbdata/user.go b/server/dbdata/user.go index 5fbb2d7..c513e63 100644 --- a/server/dbdata/user.go +++ b/server/dbdata/user.go @@ -1,13 +1,18 @@ package dbdata import ( + "context" + "encoding/json" "errors" "fmt" "sync" "time" + "github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/pkg/utils" "github.com/xlzd/gotp" + "layeh.com/radius" + "layeh.com/radius/rfc2865" ) // type User struct { @@ -68,6 +73,38 @@ func SetUser(v *User) error { // 验证用户登陆信息 func CheckUser(name, pwd, group string) error { + // 获取登入的group数据 + groupData := &Group{} + err := One("Name", group, groupData) + if err != nil { + return fmt.Errorf("%s %s", name, "No用户组") + } + if len(groupData.Auth) == 0 { + groupData.Auth["type"] = "local" + } + base.Debug(name + " auth type: " + fmt.Sprintf("%s", groupData.Auth["type"])) + switch groupData.Auth["type"] { + case "local": + return checkLocalUser(name, pwd, group) + case "radius": + radisConf := AuthRadius{} + bodyBytes, err := json.Marshal(groupData.Auth["radius"]) + if err != nil { + fmt.Errorf("%s %s", name, "Radius出现Marshal错误") + } + err = json.Unmarshal(bodyBytes, &radisConf) + if err != nil { + fmt.Errorf("%s %s", name, "Radius出现Unmarshal错误") + } + return checkRadiusUser(name, pwd, radisConf) + default: + return fmt.Errorf("%s %s", name, "无效的认证类型") + } + return nil +} + +// 验证本地用户登陆信息 +func checkLocalUser(name, pwd, group string) error { // TODO 严重问题 // return nil @@ -108,6 +145,22 @@ func CheckUser(name, pwd, group string) error { return nil } +func checkRadiusUser(name string, pwd string, raduisConf AuthRadius) error { + packet := radius.New(radius.CodeAccessRequest, []byte(raduisConf.Secret)) + rfc2865.UserName_SetString(packet, name) + rfc2865.UserPassword_SetString(packet, pwd) + ctx, done := context.WithTimeout(context.Background(), 3*time.Second) + defer done() + response, err := radius.Exchange(ctx, packet, raduisConf.Addr) + if err != nil { + return fmt.Errorf("%s %s", name, "Radius服务器连接异常, 请检测服务器和端口") + } + if response.Code != radius.CodeAccessAccept { + return fmt.Errorf("%s %s", name, "Radius:用户名或密码错误") + } + return nil +} + var ( userOtpMux = sync.Mutex{} userOtp = map[string]time.Time{} diff --git a/server/go.mod b/server/go.mod index f46c1b3..4f3d552 100644 --- a/server/go.mod +++ b/server/go.mod @@ -25,6 +25,7 @@ require ( golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac + layeh.com/radius v0.0.0-20210819152912-ad72663a72ab xorm.io/xorm v1.2.2 ) diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index fa19975..8524c53 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -207,6 +207,25 @@ + + + + 本地 + Radius + + + + + + + + + + + + + + @@ -300,7 +319,7 @@ 保存 取消 - + @@ -318,7 +337,8 @@ export default { this.$emit('update:route_name', ['用户组信息', '用户组列表']) }, mounted() { - this.getData(1) + this.getData(1); + this.setAuthData(); }, data() { return { @@ -335,21 +355,17 @@ export default { route_include: [{val: 'all', note: '默认全局代理'}], route_exclude: [], link_acl: [], + auth : {"type":'local'} }, rules: { name: [ - {required: true, message: '请输入用户名', trigger: 'blur'}, + {required: true, message: '请输入组名', trigger: 'blur'}, {max: 30, message: '长度小于 30 个字符', trigger: 'blur'} ], bandwidth: [ - {required: true, message: '请输入用户姓名', trigger: 'blur'}, - {type: 'number', message: '年龄必须为数字值'} + {required: true, message: '请输入带宽限制', trigger: 'blur'}, + {type: 'number', message: '带宽限制必须为数字值'} ], - email: [ - {required: true, message: '请输入用户邮箱', trigger: 'blur'}, - {type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change']} - ], - status: [ {required: true} ], @@ -357,6 +373,14 @@ export default { } }, methods: { + setAuthData(row) { + var defAuthData = {"type":'local', + "radius":{"addr":"", "secret":""}, + } + if (this.ruleForm.auth.type == "local" || !row) { + this.ruleForm.auth = defAuthData; + } + }, handleDel(row) { axios.post('/group/del?id=' + row.id).then(resp => { const rdata = resp.data; @@ -378,15 +402,16 @@ export default { this.activeTab = "general" this.user_edit_dialog = true if (!row) { + this.setAuthData(row) return; } - axios.get('/group/detail', { params: { id: row.id, } }).then(resp => { - this.ruleForm = resp.data.data + this.ruleForm = resp.data.data; + this.setAuthData(resp.data.data); }).catch(error => { this.$message.error('哦,请求出错'); console.log(error); @@ -426,12 +451,11 @@ export default { arr.push({val: "", action: "allow", port: 0}); }, submitForm(formName) { - this.$refs[formName].validate((valid) => { + this.$refs[formName].validate((valid, obj) => { if (!valid) { console.log('error submit!!'); return false; } - axios.post('/group/set', this.ruleForm).then(resp => { const rdata = resp.data; if (rdata.code === 0) { From a450fe3eef21eae62c1e32de637e2696ba03e459 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Thu, 2 Jun 2022 20:50:00 +0800 Subject: [PATCH 14/28] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtest=E6=9C=AA=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/group.go | 14 +++++++++----- server/dbdata/user.go | 5 ++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/server/dbdata/group.go b/server/dbdata/group.go index d39d476..831c194 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -154,19 +154,23 @@ func SetGroup(g *Group) error { if err != nil { return errors.New("排除域名有误:" + err.Error()) } - // 处理认证类型 + // 处理认证方式的逻辑 + defAuth := map[string]interface{}{ + "type": "local", + } + if len(g.Auth) == 0 { + g.Auth = defAuth + } switch g.Auth["type"] { case "local": - g.Auth = map[string]interface{}{ - "type": g.Auth["type"], - } + g.Auth = defAuth case "radius": err = checkRadiusData(g.Auth) if err != nil { return err } default: - return errors.New("未知的认证类型") + return errors.New("#" + fmt.Sprintf("%s", g.Auth["type"]) + "#未知的认证类型") } g.UpdatedAt = time.Now() diff --git a/server/dbdata/user.go b/server/dbdata/user.go index c513e63..5f634f7 100644 --- a/server/dbdata/user.go +++ b/server/dbdata/user.go @@ -8,7 +8,6 @@ import ( "sync" "time" - "github.com/bjdgyc/anylink/base" "github.com/bjdgyc/anylink/pkg/utils" "github.com/xlzd/gotp" "layeh.com/radius" @@ -79,12 +78,12 @@ func CheckUser(name, pwd, group string) error { if err != nil { return fmt.Errorf("%s %s", name, "No用户组") } + // 初始化Auth if len(groupData.Auth) == 0 { groupData.Auth["type"] = "local" } - base.Debug(name + " auth type: " + fmt.Sprintf("%s", groupData.Auth["type"])) switch groupData.Auth["type"] { - case "local": + case "", "local": return checkLocalUser(name, pwd, group) case "radius": radisConf := AuthRadius{} From c38f1e9b8c811384f25482e663b99998a3c1b60d Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Fri, 3 Jun 2022 07:26:41 +0800 Subject: [PATCH 15/28] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/group.go | 6 +++--- server/dbdata/user.go | 30 +++++++++++++++++------------- web/src/pages/group/List.vue | 2 +- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 831c194..4effbd2 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -205,9 +205,9 @@ func checkRadiusData(auth map[string]interface{}) error { if !ValidateIpPort(radisConf.Addr) { return errors.New("Radius的服务器地址填写有误") } - // freeradius官网最大8000字符, 这里限制800 - if len(radisConf.Secret) < 8 || len(radisConf.Secret) > 800 { - return errors.New("Radius的密钥长度需在8~800个字符之间") + // freeradius官网最大8000字符, 这里限制200 + if len(radisConf.Secret) < 8 || len(radisConf.Secret) > 200 { + return errors.New("Radius的密钥长度需在8~200个字符之间") } return nil } diff --git a/server/dbdata/user.go b/server/dbdata/user.go index 5f634f7..3db7461 100644 --- a/server/dbdata/user.go +++ b/server/dbdata/user.go @@ -86,16 +86,7 @@ func CheckUser(name, pwd, group string) error { case "", "local": return checkLocalUser(name, pwd, group) case "radius": - radisConf := AuthRadius{} - bodyBytes, err := json.Marshal(groupData.Auth["radius"]) - if err != nil { - fmt.Errorf("%s %s", name, "Radius出现Marshal错误") - } - err = json.Unmarshal(bodyBytes, &radisConf) - if err != nil { - fmt.Errorf("%s %s", name, "Radius出现Unmarshal错误") - } - return checkRadiusUser(name, pwd, radisConf) + return checkRadiusUser(name, pwd, groupData.Auth) default: return fmt.Errorf("%s %s", name, "无效的认证类型") } @@ -144,13 +135,26 @@ func checkLocalUser(name, pwd, group string) error { return nil } -func checkRadiusUser(name string, pwd string, raduisConf AuthRadius) error { - packet := radius.New(radius.CodeAccessRequest, []byte(raduisConf.Secret)) +func checkRadiusUser(name string, pwd string, auth map[string]interface{}) error { + if _, ok := auth["radius"]; !ok { + fmt.Errorf("%s %s", name, "Radius的radius值不存在") + } + radiusConf := AuthRadius{} + bodyBytes, err := json.Marshal(auth["radius"]) + if err != nil { + fmt.Errorf("%s %s", name, "Radius Marshal出现错误") + } + err = json.Unmarshal(bodyBytes, &radiusConf) + if err != nil { + fmt.Errorf("%s %s", name, "Radius Unmarshal出现错误") + } + // radius认证时,设置超时3秒 + packet := radius.New(radius.CodeAccessRequest, []byte(radiusConf.Secret)) rfc2865.UserName_SetString(packet, name) rfc2865.UserPassword_SetString(packet, pwd) ctx, done := context.WithTimeout(context.Background(), 3*time.Second) defer done() - response, err := radius.Exchange(ctx, packet, raduisConf.Addr) + response, err := radius.Exchange(ctx, packet, radiusConf.Addr) if err != nil { return fmt.Errorf("%s %s", name, "Radius服务器连接异常, 请检测服务器和端口") } diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index 8524c53..446584d 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -451,7 +451,7 @@ export default { arr.push({val: "", action: "allow", port: 0}); }, submitForm(formName) { - this.$refs[formName].validate((valid, obj) => { + this.$refs[formName].validate((valid) => { if (!valid) { console.log('error submit!!'); return false; From b06c035cce7fb3cc48e220c2c9f4d185de97f3aa Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 6 Jun 2022 21:25:19 +0800 Subject: [PATCH 16/28] =?UTF-8?q?1.=E9=87=8D=E6=9E=84=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E7=9A=84=E4=BB=A3=E7=A0=81,=E6=96=B9?= =?UTF-8?q?=E4=BE=BF=E6=9C=AA=E6=9D=A5=E6=89=A9=E5=B1=95=202.=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/group.go | 45 ++++-------------- server/dbdata/group_test.go | 19 +++++++- server/dbdata/user.go | 50 ++++---------------- server/dbdata/user_test.go | 18 ++++++++ server/dbdata/userauth.go | 15 ++++++ server/dbdata/userauth_radius.go | 78 ++++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 76 deletions(-) create mode 100644 server/dbdata/userauth.go create mode 100644 server/dbdata/userauth_radius.go diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 4effbd2..52524d1 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -1,7 +1,6 @@ package dbdata import ( - "encoding/json" "errors" "fmt" "net" @@ -33,11 +32,6 @@ type ValData struct { Note string `json:"note"` } -type AuthRadius struct { - Addr string `json:"addr"` - Secret string `json:"secret"` -} - // type Group struct { // Id int `json:"id" xorm:"pk autoincr not null"` // Name string `json:"name" xorm:"varchar(60) not null unique"` @@ -154,23 +148,26 @@ func SetGroup(g *Group) error { if err != nil { return errors.New("排除域名有误:" + err.Error()) } - // 处理认证方式的逻辑 + // 处理登入方式的逻辑 defAuth := map[string]interface{}{ "type": "local", } if len(g.Auth) == 0 { g.Auth = defAuth } - switch g.Auth["type"] { - case "local": + authType := g.Auth["type"].(string) + if authType == "local" { g.Auth = defAuth - case "radius": - err = checkRadiusData(g.Auth) + } else { + _, ok := authRegistry[authType] + if !ok { + return errors.New("未知的认证方式: " + fmt.Sprintf("%s", g.Auth["type"])) + } + auth := makeInstance(authType).(IUserAuth) + err = auth.checkData(g.Auth) if err != nil { return err } - default: - return errors.New("#" + fmt.Sprintf("%s", g.Auth["type"]) + "#未知的认证类型") } g.UpdatedAt = time.Now() @@ -195,23 +192,6 @@ func parseIpNet(s string) (string, *net.IPNet, error) { return ipMask, ipNet, nil } -func checkRadiusData(auth map[string]interface{}) error { - radisConf := AuthRadius{} - bodyBytes, err := json.Marshal(auth["radius"]) - if err != nil { - return errors.New("Radius的密钥/服务器地址填写有误") - } - json.Unmarshal(bodyBytes, &radisConf) - if !ValidateIpPort(radisConf.Addr) { - return errors.New("Radius的服务器地址填写有误") - } - // freeradius官网最大8000字符, 这里限制200 - if len(radisConf.Secret) < 8 || len(radisConf.Secret) > 200 { - return errors.New("Radius的密钥长度需在8~200个字符之间") - } - return nil -} - func CheckDomainNames(domains string) error { if domains == "" { return nil @@ -232,8 +212,3 @@ func ValidateDomainName(domain string) bool { RegExp := regexp.MustCompile(`^([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+[A-Za-z]{2,18}$`) return RegExp.MatchString(domain) } - -func ValidateIpPort(addr string) bool { - RegExp := regexp.MustCompile(`^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$$`) - return RegExp.MatchString(addr) -} diff --git a/server/dbdata/group_test.go b/server/dbdata/group_test.go index ee1dee1..7d27c7f 100644 --- a/server/dbdata/group_test.go +++ b/server/dbdata/group_test.go @@ -24,8 +24,25 @@ func TestGetGroupNames(t *testing.T) { err = SetGroup(&g3) ast.Nil(err) + authData := map[string]interface{}{ + "type": "radius", + "radius": map[string]string{ + "addr": "192.168.8.12:1044", + "secret": "43214132", + }, + } + g4 := Group{Name: "g4", ClientDns: []ValData{{Val: "114.114.114.114"}}, Auth: authData} + err = SetGroup(&g4) + ast.Nil(err) + g5 := Group{Name: "g5", ClientDns: []ValData{{Val: "114.114.114.114"}}, DsIncludeDomains: "baidu.com,163.com"} + err = SetGroup(&g5) + ast.Nil(err) + g6 := Group{Name: "g6", ClientDns: []ValData{{Val: "114.114.114.114"}}, DsExcludeDomains: "com.cn,qq.com"} + err = SetGroup(&g6) + ast.Nil(err) + // 判断所有数据 - gAll := []string{"g1", "g2", "g3"} + gAll := []string{"g1", "g2", "g3", "g4", "g5", "g6"} gs := GetGroupNames() for _, v := range gs { ast.Equal(true, utils.InArrStr(gAll, v)) diff --git a/server/dbdata/user.go b/server/dbdata/user.go index 3db7461..6add617 100644 --- a/server/dbdata/user.go +++ b/server/dbdata/user.go @@ -1,8 +1,6 @@ package dbdata import ( - "context" - "encoding/json" "errors" "fmt" "sync" @@ -10,8 +8,6 @@ import ( "github.com/bjdgyc/anylink/pkg/utils" "github.com/xlzd/gotp" - "layeh.com/radius" - "layeh.com/radius/rfc2865" ) // type User struct { @@ -82,15 +78,18 @@ func CheckUser(name, pwd, group string) error { if len(groupData.Auth) == 0 { groupData.Auth["type"] = "local" } - switch groupData.Auth["type"] { - case "", "local": + authType := groupData.Auth["type"].(string) + // 本地认证方式 + if authType == "local" { return checkLocalUser(name, pwd, group) - case "radius": - return checkRadiusUser(name, pwd, groupData.Auth) - default: - return fmt.Errorf("%s %s", name, "无效的认证类型") } - return nil + // 其它认证方式, 支持自定义 + _, ok := authRegistry[authType] + if !ok { + return fmt.Errorf("%s %s", "未知的认证方式: ", authType) + } + auth := makeInstance(authType).(IUserAuth) + return auth.checkUser(name, pwd, groupData.Auth) } // 验证本地用户登陆信息 @@ -135,35 +134,6 @@ func checkLocalUser(name, pwd, group string) error { return nil } -func checkRadiusUser(name string, pwd string, auth map[string]interface{}) error { - if _, ok := auth["radius"]; !ok { - fmt.Errorf("%s %s", name, "Radius的radius值不存在") - } - radiusConf := AuthRadius{} - bodyBytes, err := json.Marshal(auth["radius"]) - if err != nil { - fmt.Errorf("%s %s", name, "Radius Marshal出现错误") - } - err = json.Unmarshal(bodyBytes, &radiusConf) - if err != nil { - fmt.Errorf("%s %s", name, "Radius Unmarshal出现错误") - } - // radius认证时,设置超时3秒 - packet := radius.New(radius.CodeAccessRequest, []byte(radiusConf.Secret)) - rfc2865.UserName_SetString(packet, name) - rfc2865.UserPassword_SetString(packet, pwd) - ctx, done := context.WithTimeout(context.Background(), 3*time.Second) - defer done() - response, err := radius.Exchange(ctx, packet, radiusConf.Addr) - if err != nil { - return fmt.Errorf("%s %s", name, "Radius服务器连接异常, 请检测服务器和端口") - } - if response.Code != radius.CodeAccessAccept { - return fmt.Errorf("%s %s", name, "Radius:用户名或密码错误") - } - return nil -} - var ( userOtpMux = sync.Mutex{} userOtp = map[string]time.Time{} diff --git a/server/dbdata/user_test.go b/server/dbdata/user_test.go index e076672..545ca45 100644 --- a/server/dbdata/user_test.go +++ b/server/dbdata/user_test.go @@ -40,4 +40,22 @@ func TestCheckUser(t *testing.T) { _ = SetUser(&u) err = CheckUser("aaa", u.PinCode, group) ast.Nil(err) + + // 添加一个radius组 + group2 := "group2" + authData := map[string]interface{}{ + "type": "radius", + "radius": map[string]string{ + "addr": "192.168.1.12:1044", + "secret": "43214132", + }, + } + g2 := Group{Name: group2, Status: 1, ClientDns: dns, RouteInclude: route, Auth: authData} + err = SetGroup(&g2) + ast.Nil(err) + err = CheckUser("aaa", "bbbbbbb", group2) + if ast.NotNil(err) { + ast.Equal("aaa Radius服务器连接异常, 请检测服务器和端口", err.Error()) + + } } diff --git a/server/dbdata/userauth.go b/server/dbdata/userauth.go new file mode 100644 index 0000000..44ac09b --- /dev/null +++ b/server/dbdata/userauth.go @@ -0,0 +1,15 @@ +package dbdata + +import "reflect" + +var authRegistry = make(map[string]reflect.Type) + +type IUserAuth interface { + checkData(authData map[string]interface{}) error + checkUser(name string, pwd string, authData map[string]interface{}) error +} + +func makeInstance(name string) interface{} { + v := reflect.New(authRegistry[name]).Elem() + return v.Interface() +} diff --git a/server/dbdata/userauth_radius.go b/server/dbdata/userauth_radius.go new file mode 100644 index 0000000..13b627d --- /dev/null +++ b/server/dbdata/userauth_radius.go @@ -0,0 +1,78 @@ +package dbdata + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "reflect" + "regexp" + "time" + + "layeh.com/radius" + "layeh.com/radius/rfc2865" +) + +type AuthRadius struct { + Addr string `json:"addr"` + Secret string `json:"secret"` +} + +func init() { + authRegistry["radius"] = reflect.TypeOf(AuthRadius{}) +} + +func (auth AuthRadius) checkData(authData map[string]interface{}) error { + authType := authData["type"].(string) + bodyBytes, err := json.Marshal(authData[authType]) + if err != nil { + return errors.New("Radius的密钥/服务器地址填写有误") + } + json.Unmarshal(bodyBytes, &auth) + if !ValidateIpPort(auth.Addr) { + return errors.New("Radius的服务器地址填写有误") + } + // freeradius官网最大8000字符, 这里限制200 + if len(auth.Secret) < 8 || len(auth.Secret) > 200 { + return errors.New("Radius的密钥长度需在8~200个字符之间") + } + return nil +} + +func (auth AuthRadius) checkUser(name string, pwd string, authData map[string]interface{}) error { + pl := len(pwd) + if name == "" || pl < 1 { + return fmt.Errorf("%s %s", name, "密码错误") + } + authType := authData["type"].(string) + if _, ok := authData[authType]; !ok { + return fmt.Errorf("%s %s", name, "Radius的radius值不存在") + } + bodyBytes, err := json.Marshal(authData[authType]) + if err != nil { + return fmt.Errorf("%s %s", name, "Radius Marshal出现错误") + } + err = json.Unmarshal(bodyBytes, &auth) + if err != nil { + return fmt.Errorf("%s %s", name, "Radius Unmarshal出现错误") + } + // radius认证时,设置超时3秒 + packet := radius.New(radius.CodeAccessRequest, []byte(auth.Secret)) + rfc2865.UserName_SetString(packet, name) + rfc2865.UserPassword_SetString(packet, pwd) + ctx, done := context.WithTimeout(context.Background(), 3*time.Second) + defer done() + response, err := radius.Exchange(ctx, packet, auth.Addr) + if err != nil { + return fmt.Errorf("%s %s", name, "Radius服务器连接异常, 请检测服务器和端口") + } + if response.Code != radius.CodeAccessAccept { + return fmt.Errorf("%s %s", name, "Radius:用户名或密码错误") + } + return nil +} + +func ValidateIpPort(addr string) bool { + RegExp := regexp.MustCompile(`^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$$`) + return RegExp.MatchString(addr) +} From f46a30488ac0ac435c55658301828e70e86d2cde Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 6 Jun 2022 21:34:51 +0800 Subject: [PATCH 17/28] =?UTF-8?q?=E8=BF=81=E7=A7=BBValidateIpPort=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/userauth.go | 10 +++++++++- server/dbdata/userauth_radius.go | 6 ------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/server/dbdata/userauth.go b/server/dbdata/userauth.go index 44ac09b..190e863 100644 --- a/server/dbdata/userauth.go +++ b/server/dbdata/userauth.go @@ -1,6 +1,9 @@ package dbdata -import "reflect" +import ( + "reflect" + "regexp" +) var authRegistry = make(map[string]reflect.Type) @@ -13,3 +16,8 @@ func makeInstance(name string) interface{} { v := reflect.New(authRegistry[name]).Elem() return v.Interface() } + +func ValidateIpPort(addr string) bool { + RegExp := regexp.MustCompile(`^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$$`) + return RegExp.MatchString(addr) +} diff --git a/server/dbdata/userauth_radius.go b/server/dbdata/userauth_radius.go index 13b627d..ef6691e 100644 --- a/server/dbdata/userauth_radius.go +++ b/server/dbdata/userauth_radius.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "reflect" - "regexp" "time" "layeh.com/radius" @@ -71,8 +70,3 @@ func (auth AuthRadius) checkUser(name string, pwd string, authData map[string]in } return nil } - -func ValidateIpPort(addr string) bool { - RegExp := regexp.MustCompile(`^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$$`) - return RegExp.MatchString(addr) -} From 8ede613488a8fdb5cb90962e0b049d91ffecc583 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Tue, 7 Jun 2022 09:46:45 +0800 Subject: [PATCH 18/28] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=BB=84=E5=81=9C=E7=94=A8=E6=97=B6=E7=9A=84=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20+=20=E4=BC=98=E5=8C=96IUserAuth=E7=9A=84ch?= =?UTF-8?q?eckUser=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/user.go | 16 +++++----------- server/dbdata/userauth.go | 2 +- server/dbdata/userauth_radius.go | 8 ++++---- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/server/dbdata/user.go b/server/dbdata/user.go index 6add617..7834013 100644 --- a/server/dbdata/user.go +++ b/server/dbdata/user.go @@ -66,13 +66,13 @@ func SetUser(v *User) error { return err } -// 验证用户登陆信息 +// 验证用户登录信息 func CheckUser(name, pwd, group string) error { // 获取登入的group数据 groupData := &Group{} err := One("Name", group, groupData) - if err != nil { - return fmt.Errorf("%s %s", name, "No用户组") + if err != nil || groupData.Status != 1 { + return fmt.Errorf("%s - %s", name, "用户组错误") } // 初始化Auth if len(groupData.Auth) == 0 { @@ -89,10 +89,10 @@ func CheckUser(name, pwd, group string) error { return fmt.Errorf("%s %s", "未知的认证方式: ", authType) } auth := makeInstance(authType).(IUserAuth) - return auth.checkUser(name, pwd, groupData.Auth) + return auth.checkUser(name, pwd, groupData) } -// 验证本地用户登陆信息 +// 验证本地用户登录信息 func checkLocalUser(name, pwd, group string) error { // TODO 严重问题 // return nil @@ -110,12 +110,6 @@ func checkLocalUser(name, pwd, group string) error { if !utils.InArrStr(v.Groups, group) { return fmt.Errorf("%s %s", name, "用户组错误") } - groupData := &Group{} - err = One("Name", group, groupData) - if err != nil || groupData.Status != 1 { - return fmt.Errorf("%s - %s", name, "用户组错误") - } - // 判断otp信息 pinCode := pwd if !v.DisableOtp { diff --git a/server/dbdata/userauth.go b/server/dbdata/userauth.go index 190e863..fbc3eb5 100644 --- a/server/dbdata/userauth.go +++ b/server/dbdata/userauth.go @@ -9,7 +9,7 @@ var authRegistry = make(map[string]reflect.Type) type IUserAuth interface { checkData(authData map[string]interface{}) error - checkUser(name string, pwd string, authData map[string]interface{}) error + checkUser(name, pwd string, g *Group) error } func makeInstance(name string) interface{} { diff --git a/server/dbdata/userauth_radius.go b/server/dbdata/userauth_radius.go index ef6691e..4d15eb1 100644 --- a/server/dbdata/userauth_radius.go +++ b/server/dbdata/userauth_radius.go @@ -38,16 +38,16 @@ func (auth AuthRadius) checkData(authData map[string]interface{}) error { return nil } -func (auth AuthRadius) checkUser(name string, pwd string, authData map[string]interface{}) error { +func (auth AuthRadius) checkUser(name, pwd string, g *Group) error { pl := len(pwd) if name == "" || pl < 1 { return fmt.Errorf("%s %s", name, "密码错误") } - authType := authData["type"].(string) - if _, ok := authData[authType]; !ok { + authType := g.Auth["type"].(string) + if _, ok := g.Auth[authType]; !ok { return fmt.Errorf("%s %s", name, "Radius的radius值不存在") } - bodyBytes, err := json.Marshal(authData[authType]) + bodyBytes, err := json.Marshal(g.Auth[authType]) if err != nil { return fmt.Errorf("%s %s", name, "Radius Marshal出现错误") } From e24aa2d900208975c8202ef6cd67d34f431b4ed8 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 13 Jun 2022 18:31:32 +0800 Subject: [PATCH 19/28] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=AD=96=E7=95=A5=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/admin/api_policy.go | 98 ++++++++ server/admin/server.go | 4 + server/dbdata/db.go | 2 +- server/dbdata/group.go | 2 +- server/dbdata/policy.go | 101 +++++++++ server/dbdata/tables.go | 14 ++ server/dbdata/user_test.go | 8 + server/handler/link_tunnel.go | 17 ++ web/src/layout/LayoutAside.vue | 1 + web/src/pages/user/Policy.vue | 402 +++++++++++++++++++++++++++++++++ web/src/plugins/router.js | 1 + 11 files changed, 648 insertions(+), 2 deletions(-) create mode 100644 server/admin/api_policy.go create mode 100644 server/dbdata/policy.go create mode 100644 web/src/pages/user/Policy.vue diff --git a/server/admin/api_policy.go b/server/admin/api_policy.go new file mode 100644 index 0000000..a4934c9 --- /dev/null +++ b/server/admin/api_policy.go @@ -0,0 +1,98 @@ +package admin + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "strconv" + + "github.com/bjdgyc/anylink/dbdata" +) + +func PolicyList(w http.ResponseWriter, r *http.Request) { + _ = r.ParseForm() + pageS := r.FormValue("page") + page, _ := strconv.Atoi(pageS) + if page < 1 { + page = 1 + } + + var pageSize = dbdata.PageSize + + count := dbdata.CountAll(&dbdata.Policy{}) + + var datas []dbdata.Policy + err := dbdata.Find(&datas, pageSize, page) + if err != nil { + RespError(w, RespInternalErr, err) + return + } + + data := map[string]interface{}{ + "count": count, + "page_size": pageSize, + "datas": datas, + } + + RespSucess(w, data) +} + +func PolicyDetail(w http.ResponseWriter, r *http.Request) { + _ = r.ParseForm() + idS := r.FormValue("id") + id, _ := strconv.Atoi(idS) + if id < 1 { + RespError(w, RespParamErr, "Id错误") + return + } + + var data dbdata.Policy + err := dbdata.One("Id", id, &data) + if err != nil { + RespError(w, RespInternalErr, err) + return + } + + RespSucess(w, data) +} + +func PolicySet(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + RespError(w, RespInternalErr, err) + return + } + defer r.Body.Close() + v := &dbdata.Policy{} + err = json.Unmarshal(body, v) + if err != nil { + RespError(w, RespInternalErr, err) + return + } + + err = dbdata.SetPolicy(v) + if err != nil { + RespError(w, RespInternalErr, err) + return + } + + RespSucess(w, nil) +} + +func PolicyDel(w http.ResponseWriter, r *http.Request) { + _ = r.ParseForm() + idS := r.FormValue("id") + id, _ := strconv.Atoi(idS) + if id < 1 { + RespError(w, RespParamErr, "Id错误") + return + } + + data := dbdata.Policy{Id: id} + err := dbdata.Del(&data) + if err != nil { + RespError(w, RespInternalErr, err) + return + } + RespSucess(w, nil) +} diff --git a/server/admin/server.go b/server/admin/server.go index 98f3b20..75b6ac9 100644 --- a/server/admin/server.go +++ b/server/admin/server.go @@ -52,6 +52,10 @@ func StartAdmin() { r.HandleFunc("/user/ip_map/detail", UserIpMapDetail) r.HandleFunc("/user/ip_map/set", UserIpMapSet) r.HandleFunc("/user/ip_map/del", UserIpMapDel) + r.HandleFunc("/user/policy/list", PolicyList) + r.HandleFunc("/user/policy/detail", PolicyDetail) + r.HandleFunc("/user/policy/set", PolicySet) + r.HandleFunc("/user/policy/del", PolicyDel) r.HandleFunc("/group/list", GroupList) r.HandleFunc("/group/names", GroupNames) diff --git a/server/dbdata/db.go b/server/dbdata/db.go index b6f9263..994651b 100644 --- a/server/dbdata/db.go +++ b/server/dbdata/db.go @@ -25,7 +25,7 @@ func initDb() { } // 初始化数据库 - err = xdb.Sync2(&User{}, &Setting{}, &Group{}, &IpMap{}, &AccessAudit{}) + err = xdb.Sync2(&User{}, &Setting{}, &Group{}, &IpMap{}, &AccessAudit{}, &Policy{}) if err != nil { base.Fatal(err) } diff --git a/server/dbdata/group.go b/server/dbdata/group.go index 52524d1..112805d 100644 --- a/server/dbdata/group.go +++ b/server/dbdata/group.go @@ -161,7 +161,7 @@ func SetGroup(g *Group) error { } else { _, ok := authRegistry[authType] if !ok { - return errors.New("未知的认证方式: " + fmt.Sprintf("%s", g.Auth["type"])) + return errors.New("未知的认证方式: " + authType) } auth := makeInstance(authType).(IUserAuth) err = auth.checkData(g.Auth) diff --git a/server/dbdata/policy.go b/server/dbdata/policy.go new file mode 100644 index 0000000..a6e6ad5 --- /dev/null +++ b/server/dbdata/policy.go @@ -0,0 +1,101 @@ +package dbdata + +import ( + "errors" + "net" + "strings" + "time" +) + +func GetPolicy(Username string) *Policy { + policyData := &Policy{} + err := One("Username", Username, policyData) + if err != nil { + return policyData + } + return policyData +} + +func SetPolicy(p *Policy) error { + var err error + if p.Username == "" { + return errors.New("用户名错误") + } + + // 包含路由 + routeInclude := []ValData{} + for _, v := range p.RouteInclude { + if v.Val != "" { + if v.Val == All { + routeInclude = append(routeInclude, v) + continue + } + + ipMask, _, err := parseIpNet(v.Val) + if err != nil { + return errors.New("RouteInclude 错误" + err.Error()) + } + + v.IpMask = ipMask + routeInclude = append(routeInclude, v) + } + } + p.RouteInclude = routeInclude + // 包含路由 + routeExclude := []ValData{} + for _, v := range p.RouteExclude { + if v.Val != "" { + ipMask, _, err := parseIpNet(v.Val) + if err != nil { + return errors.New("RouteExclude 错误" + err.Error()) + } + v.IpMask = ipMask + routeExclude = append(routeExclude, v) + } + } + p.RouteExclude = routeExclude + + // DNS 判断 + clientDns := []ValData{} + for _, v := range p.ClientDns { + if v.Val != "" { + ip := net.ParseIP(v.Val) + if ip.String() != v.Val { + return errors.New("DNS IP 错误") + } + clientDns = append(clientDns, v) + } + } + if len(routeInclude) == 0 || (len(routeInclude) == 1 && routeInclude[0].Val == "all") { + if len(clientDns) == 0 { + return errors.New("默认路由,必须设置一个DNS") + } + } + p.ClientDns = clientDns + + // 域名拆分隧道,不能同时填写 + p.DsIncludeDomains = strings.TrimSpace(p.DsIncludeDomains) + p.DsExcludeDomains = strings.TrimSpace(p.DsExcludeDomains) + if p.DsIncludeDomains != "" && p.DsExcludeDomains != "" { + return errors.New("包含/排除域名不能同时填写") + } + // 校验包含域名的格式 + err = CheckDomainNames(p.DsIncludeDomains) + if err != nil { + return errors.New("包含域名有误:" + err.Error()) + } + // 校验排除域名的格式 + err = CheckDomainNames(p.DsExcludeDomains) + if err != nil { + return errors.New("排除域名有误:" + err.Error()) + } + + p.UpdatedAt = time.Now() + if p.Id > 0 { + err = Set(p) + } else { + err = Add(p) + } + + return err +} diff --git a/server/dbdata/tables.go b/server/dbdata/tables.go index 9dd2b5d..56b2dbe 100644 --- a/server/dbdata/tables.go +++ b/server/dbdata/tables.go @@ -68,3 +68,17 @@ type AccessAudit struct { DstPort uint16 `json:"dst_port" xorm:"not null"` CreatedAt time.Time `json:"created_at" xorm:"DateTime"` } + +type Policy struct { + Id int `json:"id" xorm:"pk autoincr not null"` + Username string `json:"username" xorm:"varchar(60) not null unique"` + AllowLan bool `json:"allow_lan" xorm:"Bool"` + ClientDns []ValData `json:"client_dns" xorm:"Text"` + RouteInclude []ValData `json:"route_include" xorm:"Text"` + RouteExclude []ValData `json:"route_exclude" xorm:"Text"` + DsExcludeDomains string `json:"ds_exclude_domains" xorm:"Text"` + DsIncludeDomains string `json:"ds_include_domains" xorm:"Text"` + Status int8 `json:"status" xorm:"Int"` // 1正常 0 禁用 + CreatedAt time.Time `json:"created_at" xorm:"DateTime created"` + UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"` +} diff --git a/server/dbdata/user_test.go b/server/dbdata/user_test.go index 545ca45..8e46dcc 100644 --- a/server/dbdata/user_test.go +++ b/server/dbdata/user_test.go @@ -58,4 +58,12 @@ func TestCheckUser(t *testing.T) { ast.Equal("aaa Radius服务器连接异常, 请检测服务器和端口", err.Error()) } + // 添加用户策略 + dns2 := []ValData{{Val: "8.8.8.8"}} + route2 := []ValData{{Val: "192.168.2.1/24"}} + p1 := Policy{Username: "aaa", Status: 1, ClientDns: dns2, RouteInclude: route2} + err = SetPolicy(&p1) + ast.Nil(err) + err = CheckUser("aaa", u.PinCode, group) + ast.Nil(err) } diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index 52aac12..42bf87f 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -100,6 +100,9 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { //HttpSetHeader(w, "X-CSTP-Default-Domain", cSess.LocalIp) HttpSetHeader(w, "X-CSTP-Base-MTU", cstpBaseMtu) + // 设置用户策略 + SetUserPolicy(sess.Username, cSess.Group) + // 允许本地LAN访问vpn网络,必须放在路由的第一个 if cSess.Group.AllowLan { HttpSetHeader(w, "X-CSTP-Split-Exclude", "0.0.0.0/255.255.255.255") @@ -209,3 +212,17 @@ func SetPostAuthXml(g *dbdata.Group, w http.ResponseWriter) error { HttpSetHeader(w, "X-CSTP-Post-Auth-XML", result.String()) return nil } + +// 设置用户策略, 覆盖Group的属性值 +func SetUserPolicy(username string, g *dbdata.Group) { + userPolicy := dbdata.GetPolicy(username) + if userPolicy.Id != 0 && userPolicy.Status == 1 { + base.Debug(username + " use UserPolicy") + g.AllowLan = userPolicy.AllowLan + g.ClientDns = userPolicy.ClientDns + g.RouteInclude = userPolicy.RouteInclude + g.RouteExclude = userPolicy.RouteExclude + g.DsExcludeDomains = userPolicy.DsExcludeDomains + g.DsIncludeDomains = userPolicy.DsIncludeDomains + } +} diff --git a/web/src/layout/LayoutAside.vue b/web/src/layout/LayoutAside.vue index fb2973c..fbb82dd 100644 --- a/web/src/layout/LayoutAside.vue +++ b/web/src/layout/LayoutAside.vue @@ -42,6 +42,7 @@ 用户列表 + 用户策略 在线用户 IP映射 diff --git a/web/src/pages/user/Policy.vue b/web/src/pages/user/Policy.vue new file mode 100644 index 0000000..e009fad --- /dev/null +++ b/web/src/pages/user/Policy.vue @@ -0,0 +1,402 @@ + + + + + diff --git a/web/src/plugins/router.js b/web/src/plugins/router.js index f574b08..07b42e5 100644 --- a/web/src/plugins/router.js +++ b/web/src/plugins/router.js @@ -20,6 +20,7 @@ const routes = [ {path: 'set/audit', component: () => import('@/pages/set/Audit')}, {path: 'user/list', component: () => import('@/pages/user/List')}, + {path: 'user/policy', component: () => import('@/pages/user/Policy')}, {path: 'user/online', component: () => import('@/pages/user/Online')}, {path: 'user/ip_map', component: () => import('@/pages/user/IpMap')}, From 68076f58eb5ca51d57a371a270be0af71c6d57b4 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Mon, 13 Jun 2022 18:35:24 +0800 Subject: [PATCH 20/28] =?UTF-8?q?=E4=BF=AE=E6=94=B9SetPolicy=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/dbdata/policy.go b/server/dbdata/policy.go index a6e6ad5..9777804 100644 --- a/server/dbdata/policy.go +++ b/server/dbdata/policy.go @@ -41,7 +41,7 @@ func SetPolicy(p *Policy) error { } } p.RouteInclude = routeInclude - // 包含路由 + // 排除路由 routeExclude := []ValData{} for _, v := range p.RouteExclude { if v.Val != "" { From 6a997bfd467aae907353c32b535e956d80612a0e Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Tue, 14 Jun 2022 09:23:38 +0800 Subject: [PATCH 21/28] =?UTF-8?q?=E6=8F=90=E4=BA=A4policy=5Ftest.go?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/dbdata/policy_test.go | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 server/dbdata/policy_test.go diff --git a/server/dbdata/policy_test.go b/server/dbdata/policy_test.go new file mode 100644 index 0000000..e2dd409 --- /dev/null +++ b/server/dbdata/policy_test.go @@ -0,0 +1,45 @@ +package dbdata + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetPolicy(t *testing.T) { + ast := assert.New(t) + + preIpData() + defer closeIpdata() + + // 添加 Policy + p1 := Policy{Username: "a1", ClientDns: []ValData{{Val: "114.114.114.114"}}, DsExcludeDomains: "baidu.com,163.com"} + err := SetPolicy(&p1) + ast.Nil(err) + + p2 := Policy{Username: "a2", ClientDns: []ValData{{Val: "114.114.114.114"}}, DsExcludeDomains: "com.cn,qq.com"} + err = SetPolicy(&p2) + ast.Nil(err) + + route := []ValData{{Val: "192.168.1.1/24"}} + p3 := Policy{Username: "a3", ClientDns: []ValData{{Val: "114.114.114.114"}}, RouteInclude: route, DsExcludeDomains: "com.cn,qq.com"} + err = SetPolicy(&p3) + ast.Nil(err) + // 判断 IpMask + ast.Equal(p3.RouteInclude[0].IpMask, "192.168.1.1/255.255.255.0") + + route2 := []ValData{{Val: "192.168.2.1/24"}} + p4 := Policy{Username: "a4", ClientDns: []ValData{{Val: "114.114.114.114"}}, RouteExclude: route2, DsIncludeDomains: "com.cn,qq.com"} + err = SetPolicy(&p4) + ast.Nil(err) + // 判断 IpMask + ast.Equal(p4.RouteExclude[0].IpMask, "192.168.2.1/255.255.255.0") + + // 判断所有数据 + var userPolicy *Policy + pAll := []string{"a1", "a2", "a3", "a4"} + for _, v := range pAll { + userPolicy = GetPolicy(v) + ast.NotEqual(userPolicy.Id, 0, "user policy id is zero") + } +} From 54f7a59a917d3b16b25340b62294b969e28d3f10 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Tue, 14 Jun 2022 14:40:19 +0800 Subject: [PATCH 22/28] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mtu=E7=9A=84=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/base/cfg.go | 1 + server/base/config.go | 1 + server/conf/server-sample.toml | 4 ++++ server/sessdata/session.go | 5 ++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/server/base/cfg.go b/server/base/cfg.go index 49a9c92..5690f08 100644 --- a/server/base/cfg.go +++ b/server/base/cfg.go @@ -66,6 +66,7 @@ type ServerConfig struct { CstpDpd int `json:"cstp_dpd"` // Dead peer detection in seconds MobileKeepalive int `json:"mobile_keepalive"` MobileDpd int `json:"mobile_dpd"` + Mtu int `json:"mtu"` SessionTimeout int `json:"session_timeout"` // in seconds // AuthTimeout int `json:"auth_timeout"` // in seconds diff --git a/server/base/config.go b/server/base/config.go index b7edc7b..bdb6dc1 100644 --- a/server/base/config.go +++ b/server/base/config.go @@ -54,6 +54,7 @@ var configs = []config{ {Typ: cfgInt, Name: "cstp_dpd", Usage: "死链接检测时间(秒)", ValInt: 30}, {Typ: cfgInt, Name: "mobile_keepalive", Usage: "移动端keepalive接检测时间(秒)", ValInt: 50}, {Typ: cfgInt, Name: "mobile_dpd", Usage: "移动端死链接检测时间(秒)", ValInt: 60}, + {Typ: cfgInt, Name: "mtu", Usage: "最大传输单元MTU", ValInt: 1460}, {Typ: cfgInt, Name: "session_timeout", Usage: "session过期时间(秒)", ValInt: 3600}, // {Typ: cfgInt, Name: "auth_timeout", Usage: "auth_timeout", ValInt: 0}, {Typ: cfgInt, Name: "audit_interval", Usage: "审计去重间隔(秒),-1关闭", ValInt: -1}, diff --git a/server/conf/server-sample.toml b/server/conf/server-sample.toml index 402e03f..13a8835 100644 --- a/server/conf/server-sample.toml +++ b/server/conf/server-sample.toml @@ -60,6 +60,10 @@ cstp_keepalive = 20 cstp_dpd = 30 mobile_keepalive = 40 mobile_dpd = 50 + +#设置最大传输单元 +mtu = 1460 + #session过期时间,用于断线重连,0永不过期 session_timeout = 3600 auth_timeout = 0 diff --git a/server/sessdata/session.go b/server/sessdata/session.go index 97d6e3e..f165247 100644 --- a/server/sessdata/session.go +++ b/server/sessdata/session.go @@ -294,9 +294,12 @@ func (cs *ConnSession) ratePeriod() { } } -const MaxMtu = 1460 +var MaxMtu = 1460 func (cs *ConnSession) SetMtu(mtu string) { + if base.Cfg.Mtu > 0 { + MaxMtu = base.Cfg.Mtu + } cs.Mtu = MaxMtu mi, err := strconv.Atoi(mtu) From 7f1e769377d359672d35b06140345c6a5797debc Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Wed, 15 Jun 2022 09:37:37 +0800 Subject: [PATCH 23/28] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=BB=84=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E9=A1=B5=E7=9A=84=E8=B7=AF=E7=94=B1=E5=88=97=E5=8F=AA?= =?UTF-8?q?=E6=98=BE=E7=A4=BA5=E6=9D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/pages/group/List.vue | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index 446584d..6ce97bd 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -65,7 +65,8 @@ label="路由包含" width="200"> @@ -74,7 +75,8 @@ label="路由排除" width="200"> @@ -83,9 +85,10 @@ label="LINK-ACL" min-width="200"> From 04d025c68b675ace90ebe2e828ba11117c136df6 Mon Sep 17 00:00:00 2001 From: bjdgyc Date: Wed, 15 Jun 2022 11:35:20 +0800 Subject: [PATCH 24/28] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +++++++++++++--------- doc/README.md | 20 +++++++++++++------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index f269afa..2622f03 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,16 @@ AnyLink 服务端仅在 CentOS 7、Ubuntu 18.04 测试通过,如需要安装 ![online](doc/screenshot/online.jpg) +## Donate + +> 如果您觉得 anylink 对你有帮助,欢迎给我们打赏,也是帮助 anylink 更好的发展。 +> +> [查看打赏列表](doc/README.md) + +

+ +

+ ## Installation > 没有编程基础的同学建议直接下载 release 包,从下面的地址下载 anylink-deploy.tar.gz @@ -78,12 +88,15 @@ sudo ./anylink - [x] 支持 [proxy protocol v1](http://www.haproxy.org/download/2.2/doc/proxy-protocol.txt) 协议 - [x] 用户组支持 - [x] 多用户支持 +- [x] 用户策略支持 - [x] TOTP 令牌支持 - [x] TOTP 令牌开关 - [x] 流量速率限制 - [x] 后台管理界面 - [x] 访问权限管理 - [x] IP 访问审计功能 +- [x] 域名动态拆分隧道(域名路由功能) +- [x] radius认证支持 - [ ] 基于 ipvtap 设备的桥接访问模式 ## Config @@ -268,15 +281,6 @@ sh bridge-init.sh docker build -t anylink . ``` -## Donate - -> 如果您觉得 anylink 对你有帮助,欢迎给我们打赏,也是帮助 anylink 更好的发展。 -> -> [查看打赏列表](doc/README.md) - -

- -

## 常见问题 diff --git a/doc/README.md b/doc/README.md index 64d5e58..6366342 100644 --- a/doc/README.md +++ b/doc/README.md @@ -10,11 +10,17 @@ > 感谢以下同学的打赏,AnyLink 有你更美好! -| 昵称 | 主页 | -| -------- | ---------------------------- | -| 代码oo8 | | -| 甘磊 | https://github.com/ganlei333 | -| Oo@ | https://github.com/chooop | -| 虚极静笃 | | -| Ficapy | | +| 昵称 | 主页 | +| -- | ---------------------------- | +| 代码oo8 | | +| 甘磊 | https://github.com/ganlei333 | +| Oo@ | https://github.com/chooop | +| 虚极静笃 | | +| 请喝可乐 | | +| 加油加油 | | +| 李建 | | +| lanbin | | +| 乐在东途 | | + + From 2b9c0fdca830567fc2ca31ee208ee04c77d0c8d7 Mon Sep 17 00:00:00 2001 From: bjdgyc Date: Wed, 15 Jun 2022 11:47:14 +0800 Subject: [PATCH 25/28] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- build.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d1b58eb..cec779e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ COPY --from=builder_node /web/ui /anylink/server/ui #TODO 本地打包时使用镜像 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories RUN apk add --no-cache git gcc musl-dev -RUN cd /anylink/server;go build -o anylink -ldflags "-X main.CommitId=$(git rev-parse HEAD)" \ +RUN cd /anylink/server;go mod tidy;go build -o anylink -ldflags "-X main.CommitId=$(git rev-parse HEAD)" \ && /anylink/server/anylink tool -v # anylink diff --git a/build.sh b/build.sh index 2b57fd5..76acaf5 100644 --- a/build.sh +++ b/build.sh @@ -31,6 +31,7 @@ rm -rf ui cp -rf $cpath/web/ui . #国内可替换源加快速度 export GOPROXY=https://goproxy.io +go mod tidy go build -v -o anylink -ldflags "-X main.CommitId=$(git rev-parse HEAD)" RETVAL $? From f208be9126a1a33a915b8dbcc55fa74ed12d4de7 Mon Sep 17 00:00:00 2001 From: bjdgyc Date: Wed, 15 Jun 2022 11:52:09 +0800 Subject: [PATCH 26/28] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20go=20sum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/go.sum | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/go.sum b/server/go.sum index 06fafa4..089a38c 100644 --- a/server/go.sum +++ b/server/go.sum @@ -565,6 +565,7 @@ golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -964,6 +965,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +layeh.com/radius v0.0.0-20210819152912-ad72663a72ab h1:05KeMI4s7jEdIfHb7QCjUr5X2BRA0gjLZLZEmmjGNc4= +layeh.com/radius v0.0.0-20210819152912-ad72663a72ab/go.mod h1:pFWM9De99EY9TPVyHIyA56QmoRViVck/x41WFkUlc9A= lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.33.6 h1:r63dgSzVzRxUpAJFPQWHy1QeZeY1ydNENUDaBx1GqYc= From 4b36577b0034b2e3ab7dc946db7e2a8f09d7d629 Mon Sep 17 00:00:00 2001 From: lanrenwo Date: Wed, 15 Jun 2022 22:42:20 +0800 Subject: [PATCH 27/28] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=BB=84=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E9=A1=B5=E7=9A=84=E8=B7=AF=E7=94=B1=E5=88=97=E5=8F=AA?= =?UTF-8?q?=E6=98=BE=E7=A4=BA5=E6=9D=A1=EF=BC=8C=E8=B6=85=E8=BF=87?= =?UTF-8?q?=E5=88=99=E6=98=BE=E7=A4=BA=E6=9B=B4=E5=A4=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/pages/group/List.vue | 46 ++++++++++++++++++++++++++--------- web/src/pages/user/Policy.vue | 33 +++++++++++++++++++------ 2 files changed, 61 insertions(+), 18 deletions(-) diff --git a/web/src/pages/group/List.vue b/web/src/pages/group/List.vue index 6ce97bd..7a1b08b 100644 --- a/web/src/pages/group/List.vue +++ b/web/src/pages/group/List.vue @@ -1,7 +1,6 @@