diff --git a/server/admin/server.go b/server/admin/server.go index b162755..0a02c61 100644 --- a/server/admin/server.go +++ b/server/admin/server.go @@ -25,6 +25,7 @@ func StartAdmin() { r.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { utils.SetSecureHeader(w) + w.Header().Set("Server", "AnyLinkAdminOpenSource") next.ServeHTTP(w, req) }) }) diff --git a/server/base/cfg.go b/server/base/cfg.go index de66643..8c2104b 100644 --- a/server/base/cfg.go +++ b/server/base/cfg.go @@ -70,6 +70,7 @@ type ServerConfig struct { Mtu int `json:"mtu"` DefaultDomain string `json:"default_domain"` + IdleTimeout int `json:"idle_timeout"` // in seconds SessionTimeout int `json:"session_timeout"` // in seconds // AuthTimeout int `json:"auth_timeout"` // in seconds AuditInterval int `json:"audit_interval"` // in seconds diff --git a/server/base/config.go b/server/base/config.go index 6f3fa8d..212f83c 100644 --- a/server/base/config.go +++ b/server/base/config.go @@ -57,6 +57,7 @@ var configs = []config{ {Typ: cfgInt, Name: "mobile_keepalive", Usage: "移动端keepalive接检测时间(秒)", ValInt: 7}, {Typ: cfgInt, Name: "mobile_dpd", Usage: "移动端死链接检测时间(秒)", ValInt: 15}, {Typ: cfgInt, Name: "mtu", Usage: "最大传输单元MTU", ValInt: 1460}, + {Typ: cfgInt, Name: "idle_timeout", Usage: "空闲链接超时时间(秒)-超时后断开链接,0关闭此功能", ValInt: 7200}, {Typ: cfgInt, Name: "session_timeout", Usage: "session过期时间(秒)-用于断线重连,0永不过期", 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 5ad3518..c409107 100644 --- a/server/conf/server-sample.toml +++ b/server/conf/server-sample.toml @@ -71,6 +71,7 @@ mtu = 1460 default_domain = "example.com" #default_domain = "example.com abc.example.com" +idle_timeout = 7200 #session过期时间,用于断线重连,0永不过期 session_timeout = 3600 auth_timeout = 0 diff --git a/server/dbdata/user_act_log.go b/server/dbdata/user_act_log.go index ac9c506..dfa039f 100644 --- a/server/dbdata/user_act_log.go +++ b/server/dbdata/user_act_log.go @@ -22,6 +22,7 @@ const ( UserLogoutTimeout = 3 // 用户超时登出 UserLogoutAdmin = 4 // 账号被管理员踢下线 UserLogoutExpire = 5 // 账号过期被踢下线 + UserIdleTimeout = 6 // 用户空闲链接超时 ) type UserActLogProcess struct { @@ -62,6 +63,7 @@ var ( UserLogoutTimeout: "Session过期被踢下线", UserLogoutAdmin: "账号被管理员踢下线", UserLogoutExpire: "账号过期被踢下线", + UserIdleTimeout: "用户空闲链接超时", }, } ) diff --git a/server/go.mod b/server/go.mod index 739ab53..1790474 100644 --- a/server/go.mod +++ b/server/go.mod @@ -33,7 +33,7 @@ require ( github.com/xhit/go-simple-mail/v2 v2.10.0 github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119 github.com/xuri/excelize/v2 v2.6.1 - go.uber.org/atomic v1.10.0 + go.uber.org/atomic v1.11.0 golang.org/x/crypto v0.8.0 golang.org/x/net v0.9.0 golang.org/x/text v0.9.0 diff --git a/server/go.sum b/server/go.sum index 6e01a42..7dad695 100644 --- a/server/go.sum +++ b/server/go.sum @@ -631,8 +631,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= diff --git a/server/handler/link_auth.go b/server/handler/link_auth.go index 9e3dd6f..15db11b 100644 --- a/server/handler/link_auth.go +++ b/server/handler/link_auth.go @@ -157,7 +157,7 @@ func tplRequest(typ int, w io.Writer, data RequestData) { if data.Banner != "" { buf := new(bytes.Buffer) - xml.EscapeText(buf, []byte(data.Banner)) + _ = xml.EscapeText(buf, []byte(data.Banner)) data.Banner = buf.String() } diff --git a/server/handler/link_cstp.go b/server/handler/link_cstp.go index ba947e7..fa4d601 100644 --- a/server/handler/link_cstp.go +++ b/server/handler/link_cstp.go @@ -21,10 +21,13 @@ func LinkCstp(conn net.Conn, bufRW *bufio.ReadWriter, cSess *sessdata.ConnSessio }() var ( - err error - n int - dataLen uint16 - dead = time.Duration(cSess.CstpDpd+5) * time.Second + err error + n int + dataLen uint16 + dead = time.Second * time.Duration(cSess.CstpDpd+5) + idle = time.Second * time.Duration(base.Cfg.IdleTimeout) + checkIdle = base.Cfg.IdleTimeout > 0 + lastTime time.Time ) go cstpWrite(conn, bufRW, cSess) @@ -55,9 +58,19 @@ func LinkCstp(conn net.Conn, bufRW *bufio.ReadWriter, cSess *sessdata.ConnSessio case 0x07: // KEEPALIVE // do nothing // base.Debug("recv keepalive", cSess.IpAddr) + // 判断超时时间 + if checkIdle { + lastTime = cSess.LastDataTime.Load() + if lastTime.Before(utils.NowSec().Add(-idle)) { + base.Warn("IdleTimeout", cSess.Username, cSess.IpAddr, "lastTime", lastTime) + sessdata.CloseSess(cSess.Sess.Token, dbdata.UserIdleTimeout) + return + } + } case 0x05: // DISCONNECT cSess.UserLogoutCode = dbdata.UserLogoutClient base.Debug("DISCONNECT", cSess.Username, cSess.IpAddr) + sessdata.CloseSess(cSess.Sess.Token, dbdata.UserLogoutClient) return case 0x03: // DPD-REQ // base.Debug("recv DPD-REQ", cSess.IpAddr) @@ -98,6 +111,8 @@ func LinkCstp(conn net.Conn, bufRW *bufio.ReadWriter, cSess *sessdata.ConnSessio if payloadIn(cSess, pl) { return } + // 只记录返回正确的数据时间 + cSess.LastDataTime.Store(utils.NowSec()) } } } diff --git a/server/handler/link_dtls.go b/server/handler/link_dtls.go index 34fe578..1888675 100644 --- a/server/handler/link_dtls.go +++ b/server/handler/link_dtls.go @@ -93,6 +93,8 @@ func LinkDtls(conn net.Conn, cSess *sessdata.ConnSession) { if payloadIn(cSess, pl) { return } + // 只记录返回正确的数据时间 + cSess.LastDataTime.Store(utils.NowSec()) } } diff --git a/server/handler/link_tunnel.go b/server/handler/link_tunnel.go index 3fd5b8b..3ddac98 100644 --- a/server/handler/link_tunnel.go +++ b/server/handler/link_tunnel.go @@ -136,7 +136,7 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { } HttpAddHeader(w, "X-CSTP-Split-Include", v.IpMask) } - // 不允许的路由 + // 不允许的路由 X-Cstp-Remote-Address-Ip4: for _, v := range cSess.Group.RouteExclude { HttpAddHeader(w, "X-CSTP-Split-Exclude", v.IpMask) } @@ -184,10 +184,9 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) hClone := w.Header().Clone() - headers := make([]byte, 0) - buf := bytes.NewBuffer(headers) + buf := &bytes.Buffer{} _ = hClone.Write(buf) - base.Debug(buf.String()) + base.Trace("LinkTunnel Response Header:", buf.String()) hj := w.(http.Hijacker) conn, bufRW, err := hj.Hijack() diff --git a/server/sessdata/ip_pool.go b/server/sessdata/ip_pool.go index 41dc773..e1971a5 100644 --- a/server/sessdata/ip_pool.go +++ b/server/sessdata/ip_pool.go @@ -89,10 +89,13 @@ func initIpPool() { // } // AcquireIp 获取动态ip -func AcquireIp(username, macAddr string, uniqueMac bool) net.IP { - base.Trace("AcquireIp:", username, macAddr, uniqueMac) +func AcquireIp(username, macAddr string, uniqueMac bool) (newIp net.IP) { + base.Trace("AcquireIp start:", username, macAddr, uniqueMac) ipPoolMux.Lock() - defer ipPoolMux.Unlock() + defer func() { + ipPoolMux.Unlock() + base.Trace("AcquireIp end:", username, macAddr, uniqueMac, newIp) + }() var ( err error diff --git a/server/sessdata/session.go b/server/sessdata/session.go index fc38928..8a55530 100644 --- a/server/sessdata/session.go +++ b/server/sessdata/session.go @@ -49,6 +49,7 @@ type ConnSession struct { BandwidthDownAll atomic2.Uint64 // 使用下行带宽总量 closeOnce sync.Once CloseChan chan struct{} + LastDataTime atomic2.Time // 最后数据传输时间 PayloadIn chan *Payload PayloadOutCstp chan *Payload // Cstp的数据 PayloadOutDtls chan *Payload // Dtls的数据 @@ -219,6 +220,7 @@ func (s *Session) NewConn() *ConnSession { PayloadOutDtls: make(chan *Payload, 64), dSess: &atomic.Value{}, } + cSess.LastDataTime.Store(time.Now()) dSess := &DtlsSession{ isActive: -1,