Files
2025-12-10 15:38:55 +08:00

144 lines
4.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package waftunnelengine
import (
"SamWaf/common/zlog"
"SamWaf/model"
"fmt"
"strconv"
"strings"
"time"
)
// TimeRange 时间范围结构
type TimeRange struct {
Start time.Time // 开始时间
End time.Time // 结束时间
}
// ParseTimeRanges 解析时间范围字符串
// 格式: "08:00-10:00;11:00-12:00"
// 返回: TimeRange 切片和错误信息
func ParseTimeRanges(timeRangesStr string) ([]TimeRange, error) {
// 如果为空,返回空切片(表示无限制)
if strings.TrimSpace(timeRangesStr) == "" {
return []TimeRange{}, nil
}
var ranges []TimeRange
// 按分号分割多个时间段
parts := strings.Split(timeRangesStr, ";")
for _, part := range parts {
part = strings.TrimSpace(part)
if part == "" {
continue
}
// 按减号分割开始和结束时间
timeParts := strings.Split(part, "-")
if len(timeParts) != 2 {
return nil, fmt.Errorf("无效的时间范围格式: %s, 应为 HH:MM-HH:MM", part)
}
startStr := strings.TrimSpace(timeParts[0])
endStr := strings.TrimSpace(timeParts[1])
// 解析开始时间
startTime, err := parseTime(startStr)
if err != nil {
return nil, fmt.Errorf("解析开始时间失败 %s: %v", startStr, err)
}
// 解析结束时间
endTime, err := parseTime(endStr)
if err != nil {
return nil, fmt.Errorf("解析结束时间失败 %s: %v", endStr, err)
}
ranges = append(ranges, TimeRange{
Start: startTime,
End: endTime,
})
}
return ranges, nil
}
// parseTime 解析时间字符串 HH:MM
func parseTime(timeStr string) (time.Time, error) {
parts := strings.Split(timeStr, ":")
if len(parts) != 2 {
return time.Time{}, fmt.Errorf("无效的时间格式: %s, 应为 HH:MM", timeStr)
}
hour, err := strconv.Atoi(parts[0])
if err != nil || hour < 0 || hour > 23 {
return time.Time{}, fmt.Errorf("无效的小时: %s", parts[0])
}
minute, err := strconv.Atoi(parts[1])
if err != nil || minute < 0 || minute > 59 {
return time.Time{}, fmt.Errorf("无效的分钟: %s", parts[1])
}
// 使用今天的日期,只关注时间部分
now := time.Now()
return time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, now.Location()), nil
}
// IsTimeAllowed 检查当前时间是否在允许的时间范围内
func IsTimeAllowed(timeRanges []TimeRange, currentTime time.Time) bool {
// 如果没有时间限制,总是允许
if len(timeRanges) == 0 {
return true
}
// 只比较时分,忽略日期
currentHour := currentTime.Hour()
currentMinute := currentTime.Minute()
currentTimeOfDay := currentHour*60 + currentMinute // 转换为分钟数
for _, tr := range timeRanges {
startTimeOfDay := tr.Start.Hour()*60 + tr.Start.Minute()
endTimeOfDay := tr.End.Hour()*60 + tr.End.Minute()
// 处理跨午夜的情况(例如 23:00-01:00
if endTimeOfDay < startTimeOfDay {
// 跨午夜:当前时间在开始时间之后或结束时间之前
if currentTimeOfDay >= startTimeOfDay || currentTimeOfDay <= endTimeOfDay {
return true
}
} else {
// 正常情况:当前时间在开始和结束时间之间
if currentTimeOfDay >= startTimeOfDay && currentTimeOfDay <= endTimeOfDay {
return true
}
}
}
return false
}
// CheckTimeAccess 检查隧道的时间访问权限
func CheckTimeAccess(protocol string, clientIP string, clientPort string, serverPort string, tunnel model.Tunnel) bool {
// 解析时间范围
timeRanges, err := ParseTimeRanges(tunnel.AllowedTimeRanges)
if err != nil {
zlog.Error(fmt.Sprintf("解析时间范围失败 [协议:%s 客户端IP:%s 客户端端口:%s 服务端口:%s 错误:%s]",
protocol, clientIP, clientPort, serverPort, err.Error()))
// 解析失败时,为了安全起见,拒绝访问
return false
}
// 检查当前时间是否允许访问
currentTime := time.Now()
allowed := IsTimeAllowed(timeRanges, currentTime)
if !allowed {
zlog.Warn(fmt.Sprintf("%s连接被时间限制拒绝 [客户端IP:%s 客户端端口:%s 服务端口:%s 当前时间:%s 允许时间段:%s]",
protocol, clientIP, clientPort, serverPort, currentTime.Format("15:04"), tunnel.AllowedTimeRanges))
}
return allowed
}