Files
SamWaf/model/hosts.go
T
2026-05-12 17:00:04 +08:00

395 lines
20 KiB
Go
Raw 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 model
import (
"SamWaf/model/baseorm"
"encoding/json"
)
type Hosts struct {
baseorm.BaseOrm
Code string `gorm:"size:64" json:"code"` //唯一码
Host string `gorm:"size:255" json:"host"` //域名
Port int `json:"port"` //端口
Ssl int `json:"ssl"` //是否是ssl
GUARD_STATUS int `json:"guard_status"` //防御状态 1 是开启防御 0 是防御关闭
REMOTE_SYSTEM string `gorm:"size:50" json:"remote_system"` //是宝塔 phpstudy等
REMOTE_APP string `gorm:"size:100" json:"remote_app"` //是什么类型的应用
Remote_host string `gorm:"size:255" json:"remote_host"` //远端域名
Remote_port int `json:"remote_port"` //远端端口
Remote_ip string `gorm:"size:64" json:"remote_ip"` //远端指定IP
Certfile string `gorm:"type:text" json:"certfile"` //证书文件
Keyfile string `gorm:"type:text" json:"keyfile"` //密钥文件
REMARKS string `gorm:"size:500" json:"remarks"` //备注
GLOBAL_HOST int `json:"global_host"` //默认全局 1 全局 0非全局
DEFENSE_JSON string `gorm:"type:text" json:"defense_json"` //自身防御 json
START_STATUS int `json:"start_status"` //启动状态 如果是0 启动 ; 如果是1 不启动
EXCLUDE_URL_LOG string `gorm:"type:text" json:"exclude_url_log"` //排除的url开头的数据 换行隔开
IsEnableLoadBalance int `json:"is_enable_load_balance"` //是否激活负载 1 激活 非1 没有激活
LoadBalanceStage int `json:"load_balance_stage"` //负载策略
UnrestrictedPort int `json:"unrestricted_port"` //不限来源匹配端口 0 限制 1,不限制
BindSslId string `gorm:"size:64" json:"bind_ssl_id"` //绑定SSL的ID
AutoJumpHTTPS int `json:"auto_jump_https"` //是否自动跳转https 0 不自动 1 强制80跳转https
BindMoreHost string `gorm:"type:text" json:"bind_more_host"` //绑定多域名
IsTransBackDomain int `json:"is_trans_back_domain"` //是否传递后端域名到后端服务器侧
BindMorePort string `gorm:"size:255" json:"bind_more_port"` //是否绑定多个端口
IsEnableHttpAuthBase int `json:"is_enable_http_auth_base"` //是否 HTTPAuthBase 1 激活 非1 没有激活
HttpAuthBaseType string `gorm:"size:50" json:"http_auth_base_type"` //认证类型 authorization(默认Basic Auth) custom(自定义页面)
HttpAuthPathPrefix string `gorm:"size:255" json:"http_auth_path_prefix"` //HTTP认证路径前缀,用于隐藏系统特征,默认为随机生成
ResponseTimeOut int `json:"response_time_out"` //响应超时时间 默认60秒,为0则无限等待
HealthyJSON string `gorm:"type:text" json:"healthy_json"` //后端健康度检测 json
InsecureSkipVerify int `json:"insecure_skip_verify"` //是否开启后端https证书有效性验证 默认 0 是校验 1 是不校验
CaptchaJSON string `gorm:"type:text" json:"captcha_json"` //验证码配置 json
AntiLeechJSON string `gorm:"type:text" json:"anti_leech_json"` //防盗链配置 json
CacheJSON string `gorm:"type:text" json:"cache_json"` //缓存配置 json
StaticSiteJSON string `gorm:"type:text" json:"static_site_json"` //静态站点配置 json
TransportJSON string `gorm:"type:text" json:"transport_json"` //传输配置 json
DefaultEncoding string `gorm:"size:20" json:"default_encoding"` //默认编码 utf-8 或者 gbk auto字符串自动选择
LogOnlyMode int `json:"log_only_mode"` //仅记录模式 1开启 0关闭
CustomHeadersJSON string `gorm:"type:text" json:"custom_headers_json"` //自定义头信息配置 json
CustomResponseHeadersJSON string `gorm:"type:text" json:"custom_response_headers_json"` //自定义响应头信息配置 json
ResponseCompressJSON string `gorm:"type:text" json:"response_compress_json"` //响应压缩配置 json(Gzip/Brotli/Zstd)
IPMode string `gorm:"size:20" json:"ip_mode"` //IP提取模式: "nic" 网卡模式 或 "proxy" 代理模式
}
type HostsDefense struct {
DEFENSE_BOT int `json:"bot"` //防御-虚假BOT
DEFENSE_SQLI int `json:"sqli"` //防御-Sql注入
DEFENSE_XSS int `json:"xss"` //防御-xss攻击
DEFENSE_SCAN int `json:"scan"` //防御-scan工具扫描
DEFENSE_RCE int `json:"rce"` //防御-scan工具扫描
DEFENSE_SENSITIVE int `json:"sensitive"` //敏感词检测
DEFENSE_DIR_TRAVERSAL int `json:"traversal"` //目录穿越检测
DEFENSE_OWASP_SET int `json:"owaspset"` //OWASP集检测
}
// HealthyConfig 健康度检测
type HealthyConfig struct {
IsEnableHealthy int `json:"is_enable_healthy"` // 是否开启健康检查
FailCount int `json:"fail_count"` // 连续失败次数
SuccessCount int `json:"success_count"` // 连续成功次数
ResponseTime int `json:"response_time"` // 响应时间(秒)
CheckMethod string `json:"check_method"` // 检查方法 GET/HEAD
CheckPath string `json:"check_path"` // 检查路径
ExpectedCodes string `json:"expected_codes"` // 预期状态码
LastErrorReason string `json:"last_error_reason"` // 最后一次错误原因
}
// CaptchaConfig 验证码配置
type CaptchaConfig struct {
IsEnableCaptcha int `json:"is_enable_captcha"` // 是否开启验证码 1开启 0关闭
ExcludeURLs string `json:"exclude_urls"` // 排除验证码的URL列表
ExpireTime int `json:"expire_time"` // 验证通过后的有效期(小时)
IPMode string `json:"ip_mode"` // IP提取模式: "nic" 网卡模式 或 "proxy" 代理模式
EngineType string `json:"engine_type"` // 验证码引擎类型: 传统方式 "traditional",capJS工作量证明 "capJs"
PathPrefix string `json:"path_prefix"` // 验证码路径前缀,用于隐藏系统特征,默认为随机生成
CapJsConfig struct {
ChallengeCount int `json:"challengeCount,omitempty"` // Number of challenges to generate (default: 50)
ChallengeSize int `json:"challengeSize,omitempty"` // Size of each challenge in bytes (default: 32)
ChallengeDifficulty int `json:"challengeDifficulty,omitempty"` // Difficulty level (default: 4)
ExpiresMs int `json:"expiresMs,omitempty"` // Expiration time in milliseconds (default: 600000)
InfoTitle struct {
En string `json:"en,omitempty"` // English title
Zh string `json:"zh,omitempty"` // Chinese title
} `json:"infoTitle,omitempty"` // Multi-language info title
InfoText struct {
En string `json:"en,omitempty"` // English text
Zh string `json:"zh,omitempty"` // Chinese text
} `json:"infoText,omitempty"` // Multi-language info text
} `json:"cap_js_config"`
}
// ParseCaptchaConfig 解析验证码配置
func ParseCaptchaConfig(captchaJSON string) CaptchaConfig {
var config CaptchaConfig
// 设置默认值
config.IsEnableCaptcha = 0
config.ExcludeURLs = ""
config.ExpireTime = 24
config.IPMode = "nic" // 默认使用网卡模式
config.EngineType = "traditional" // 默认使用传统方式
// 初始化CapJsConfig默认值
config.CapJsConfig.ChallengeCount = 50 // 默认生成50个挑战
config.CapJsConfig.ChallengeSize = 32 // 默认每个挑战32字节
config.CapJsConfig.ChallengeDifficulty = 4 // 默认难度级别4
config.CapJsConfig.ExpiresMs = 600000 // 默认过期时间600秒(10分钟)
// 初始化InfoTitle默认值
config.CapJsConfig.InfoTitle.Zh = "安全验证"
config.CapJsConfig.InfoTitle.En = "Security Verification"
// 初始化InfoText默认值
config.CapJsConfig.InfoText.Zh = "为了确保您的访问安全,请完成以下验证"
config.CapJsConfig.InfoText.En = "To ensure the security of your access, please complete the following verification"
// 如果JSON不为空,则解析覆盖默认值
if captchaJSON != "" {
err := json.Unmarshal([]byte(captchaJSON), &config)
if err != nil {
// 解析失败时使用默认值,可以记录日志
return config
}
}
return config
}
// AntiLeechConfig 防盗链配置
type AntiLeechConfig struct {
IsEnableAntiLeech int `json:"is_enable_anti_leech"` // 是否开启防盗链 1开启 0关闭
FileTypes string `json:"file_types"` // 需要防盗链的文件类型,例如: gif|jpg|jpeg|png|bmp|swf
ValidReferers string `json:"valid_referers"` // 允许的引用来源列表,使用分号(;)分隔
Action string `json:"action"` // 对于非法引用的处理方式: redirect(重定向) 或 block(直接阻止)
RedirectURL string `json:"redirect_url"` // 重定向URL,当Action为redirect时使用
}
// CacheConfig 缓存配置
type CacheConfig struct {
IsEnableCache int `json:"is_enable_cache"` // 是否开启缓存 1开启 0关闭
CacheLocation string `json:"cache_location"` // 缓存位置: "memory"内存 或 "file"文件 或 "all"内存和文件
CacheDir string `json:"cache_dir"` // 缓存目录,当location为file时使用
MaxFileSizeMB float64 `json:"max_file_size_mb"` // 最大缓存文件大小(MB) 0 是不限制
MaxMemorySizeMB float64 `json:"max_memory_size_mb"` // 最大内存缓存大小(MB),当location为memory时使用 0 是不限制
}
// StaticSecurityHeader 静态站点安全响应头项
type StaticSecurityHeader struct {
HeaderName string `json:"header_name"` // 响应头名称
HeaderValue string `json:"header_value"` // 响应头值,留空则使用系统默认值
}
// StaticSiteConfig 静态站点配置
type StaticSiteConfig struct {
IsEnableStaticSite int `json:"is_enable_static_site"` // 是否开启静态站点 1开启 0关闭
StaticSitePath string `json:"static_site_path"` // 静态站点路径
StaticSitePrefix string `json:"static_site_prefix"` // 静态站点URL前缀,默认为"/"
SensitivePaths string `json:"sensitive_paths"` // 敏感路径列表,逗号分隔
SensitiveExtensions string `json:"sensitive_extensions"` // 敏感文件扩展名,逗号分隔
AllowedExtensions string `json:"allowed_extensions"` // 允许的文件扩展名白名单,逗号分隔
SensitivePatterns string `json:"sensitive_patterns"` // 敏感文件名模式(正则表达式),逗号分隔
// 安全响应头列表,数组为空则全部使用系统默认值;
// 某项 header_value 为空则该项也使用系统默认值
SecurityHeaders []StaticSecurityHeader `json:"security_headers"`
}
// ResponseCompressConfig 反代响应压缩(类似 nginx gzip / brotli / zstd)
type ResponseCompressConfig struct {
IsEnable int `json:"is_enable"` // 1 开启 0 关闭
Prefer string `json:"prefer"` // br_first | gzip_only | br_only | zstd_only
MinLength int `json:"min_length"` // 最小压缩字节数,0 表示用默认
IncludeTypes string `json:"include_types"` // 分号分隔 MIME 前缀或完整类型,空则用内置默认
IncludeExtensions string `json:"include_extensions"` // 分号分隔,如 .js;.css,与类型取并集
ExcludeExtensions string `json:"exclude_extensions"` // 分号或换行分隔后缀
ExcludePaths string `json:"exclude_paths"` // 换行或分号,URL 前缀匹配
CompressWhenStaticAssist int `json:"compress_when_static_assist"` // 1 时对静态协助响应也读体压缩
}
// TransportConfig 传输配置
type TransportConfig struct {
MaxIdleConns int `json:"max_idle_conns"` // 最大空闲连接数
MaxIdleConnsPerHost int `json:"max_idle_conns_per_host"` // 每个主机的最大空闲连接数
MaxConnsPerHost int `json:"max_conns_per_host"` // 每个主机的最大连接数
IdleConnTimeout int `json:"idle_conn_timeout"` // 空闲连接超时时间(秒)
TLSHandshakeTimeout int `json:"tls_handshake_timeout"` // TLS握手超时时间(秒)
ExpectContinueTimeout int `json:"expect_continue_timeout"` // Expect Continue超时时间(秒)
}
// CustomHeaderItem 自定义头信息项
type CustomHeaderItem struct {
HeaderName string `json:"header_name"` // 头信息名称
HeaderValue string `json:"header_value"` // 头信息值,支持内置变量
}
// CustomHeadersConfig 自定义头信息配置(用于请求头)
type CustomHeadersConfig struct {
IsEnableCustomHeaders int `json:"is_enable_custom_headers"` // 是否开启自定义头信息 1开启 0关闭
Headers []CustomHeaderItem `json:"headers"` // 自定义头信息列表
}
// CustomResponseHeaderRule 自定义响应头规则(类似 nginx location 块)
// MatchType 支持: global(全局) / prefix(路径前缀) / suffix(文件后缀) / exact(精确路径) / regex(正则)
// MergeMode 支持: merge(与全局规则合并,同名以本规则为准) / override(仅使用本规则,忽略全局)
type CustomResponseHeaderRule struct {
RuleName string `json:"rule_name"` // 规则名称,方便识别
MatchType string `json:"match_type"` // global / prefix / suffix / exact / regex
MatchValue string `json:"match_value"` // 匹配值;suffix 用分号分隔,如 ".mp4;.mp3;.webm"
Headers []CustomHeaderItem `json:"headers"` // 该规则的响应头列表
MergeMode string `json:"merge_mode"` // merge(默认) / override
}
// CustomResponseHeadersConfig 自定义响应头配置(V2 支持多规则路径匹配)
type CustomResponseHeadersConfig struct {
IsEnableCustomHeaders int `json:"is_enable_custom_headers"` // 是否开启 1开启 0关闭
Rules []CustomResponseHeaderRule `json:"rules"` // 规则列表(V2)
Headers []CustomHeaderItem `json:"headers,omitempty"` // 兼容旧版扁平列表
}
// defaultResponseCompressMimeTypes 与 nginx gzip_types 常见默认类似
var defaultResponseCompressMimeTypes = []string{
"text/html",
"text/plain",
"text/css",
"text/javascript",
"text/xml",
"application/json",
"application/javascript",
"application/x-javascript",
"application/xml",
"application/rss+xml",
"application/atom+xml",
"image/svg+xml",
}
// ParseResponseCompressConfig 解析响应压缩配置
func ParseResponseCompressConfig(jsonStr string) ResponseCompressConfig {
var c ResponseCompressConfig
c.IsEnable = 0
c.Prefer = "zstd_first"
c.MinLength = 256
c.CompressWhenStaticAssist = 0
if jsonStr == "" {
return c
}
if err := json.Unmarshal([]byte(jsonStr), &c); err != nil {
return ResponseCompressConfig{
IsEnable: 0, Prefer: "zstd_first", MinLength: 256, CompressWhenStaticAssist: 0,
}
}
if c.Prefer == "" {
c.Prefer = "zstd_first"
}
if c.MinLength <= 0 {
c.MinLength = 256
}
return c
}
// DefaultResponseCompressMimeTypes 返回内置默认 MIME 列表(供引擎匹配)
func DefaultResponseCompressMimeTypes() []string {
return append([]string(nil), defaultResponseCompressMimeTypes...)
}
// ParseTransportConfig 解析传输配置
func ParseTransportConfig(transportJSON string) TransportConfig {
var config TransportConfig
// 设置默认值
config.MaxIdleConns = 0
config.MaxIdleConnsPerHost = 0
config.MaxConnsPerHost = 0
config.IdleConnTimeout = 0
config.TLSHandshakeTimeout = 0
config.ExpectContinueTimeout = 0
// 如果JSON不为空,则解析覆盖默认值
if transportJSON != "" {
err := json.Unmarshal([]byte(transportJSON), &config)
if err != nil {
// 解析失败时使用默认值,可以记录日志
return config
}
}
return config
}
// ParseHostsDefense 解析防御配置
func ParseHostsDefense(defenseJSON string) HostsDefense {
var defense HostsDefense
// 设置默认值
defense.DEFENSE_BOT = 1
defense.DEFENSE_SQLI = 1
defense.DEFENSE_XSS = 1
defense.DEFENSE_SCAN = 1
defense.DEFENSE_RCE = 1
defense.DEFENSE_SENSITIVE = 1
defense.DEFENSE_DIR_TRAVERSAL = 1
defense.DEFENSE_OWASP_SET = 0
// 如果JSON不为空,则解析覆盖默认值
if defenseJSON != "" {
err := json.Unmarshal([]byte(defenseJSON), &defense)
if err != nil {
// 解析失败时使用默认值,可以记录日志
return defense
}
}
return defense
}
// ParseCustomHeadersConfig 解析自定义头信息配置
func ParseCustomHeadersConfig(customHeadersJSON string) CustomHeadersConfig {
var config CustomHeadersConfig
// 设置默认值
config.IsEnableCustomHeaders = 0
config.Headers = []CustomHeaderItem{}
// 如果JSON不为空,则解析覆盖默认值
if customHeadersJSON != "" {
err := json.Unmarshal([]byte(customHeadersJSON), &config)
if err != nil {
// 解析失败时使用默认值,可以记录日志
return config
}
}
return config
}
// ParseCustomResponseHeadersConfig 解析自定义响应头信息配置(支持 V2 多规则格式和旧版扁平格式)
// 旧格式(只有 headers 字段)会自动转换为一条 global 规则,保持向后兼容。
func ParseCustomResponseHeadersConfig(customResponseHeadersJSON string) CustomResponseHeadersConfig {
var config CustomResponseHeadersConfig
config.IsEnableCustomHeaders = 0
config.Rules = []CustomResponseHeaderRule{}
if customResponseHeadersJSON == "" {
return config
}
if err := json.Unmarshal([]byte(customResponseHeadersJSON), &config); err != nil {
return config
}
// 向后兼容:若 rules 为空但存在旧版 headers 字段,转换为一条 global 规则
if len(config.Rules) == 0 && len(config.Headers) > 0 {
config.Rules = []CustomResponseHeaderRule{
{
RuleName: "全局默认",
MatchType: "global",
MatchValue: "",
MergeMode: "merge",
Headers: config.Headers,
},
}
config.Headers = nil
}
// 为每条规则设置默认值
for i := range config.Rules {
if config.Rules[i].MatchType == "" {
config.Rules[i].MatchType = "global"
}
if config.Rules[i].MergeMode == "" {
config.Rules[i].MergeMode = "merge"
}
if config.Rules[i].Headers == nil {
config.Rules[i].Headers = []CustomHeaderItem{}
}
}
return config
}
// GetClientIPByMode 根据IP模式获取客户端IP
// ipMode: "nic" 网卡模式使用 NetSrcIp,"proxy" 代理模式使用 SRC_IP
// netSrcIp: 从网卡获取的IP (r.RemoteAddr)
// srcIP: 从代理头获取的IP (X-Forwarded-For等)
func GetClientIPByMode(ipMode string, netSrcIp string, srcIP string) string {
if ipMode == "proxy" {
return srcIP
}
// 默认使用网卡模式
return netSrcIp
}