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>
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
- BYTE/S
-
-
-
-
-
-
+
+
+ BYTE/S
+
+
+
+
+
+
-
-
- 输入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,