// Copyright 2022 E99p1ant. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package conf // ⚠️ 仅应由 "-ldflags" 注入。 var ( BuildTime string BuildCommit = "dev" // StaticVersion 静态资源缓存版本号:base.css 与主题 css 共用,改样式只改这一处。 StaticVersion = "20261020g" ) // 文本审核通道取值([security] text_censor_source)。定义在 conf 侧, // 让配置校验(conf.Init)与通道装配(internal/security/censor)共用同一份字面量。 const ( CensorSourceAuto = "auto" // 七牛优先、阿里云兜底(历史行为,留空同义) CensorSourceQiniu = "qiniu" CensorSourceAliyun = "aliyun" ) var ( App struct { Production bool `ini:"production"` ExternalURL string `ini:"external_url"` ICP string `ini:"icp"` DefaultLang string `ini:"default_lang"` // 站点默认语言(zh-CN/zh-TW/en/ja),留空回退简体中文 UptraceDSN string `ini:"uptrace_dsn"` QiniuAccessKey string `ini:"qiniu_access_key"` QiniuAccessSecret string `ini:"qiniu_access_secret"` AliyunAccessKey string `ini:"aliyun_access_key"` AliyunAccessKeySecret string `ini:"aliyun_access_key_secret"` SentryDSN string `ini:"sentry_dsn"` MaintenanceMode bool `ini:"maintenance_mode"` ShareBackground string `ini:"share_background"` FontPath string `ini:"font_path"` } // Theme 主题系统([theme] 段)。 // default :站点默认主题 slug,留空/非法回退内置 default(= 现在的外观)。 // available :启用哪些主题(逗号分隔),同时是箱主设置页的白名单; // 列了但缺少 css 文件的会被忽略并告警(见 internal/theme)。 Theme struct { Default string `ini:"default"` Available string `ini:"available"` } Security struct { EnableTextCensor bool `ini:"enable_text_censor"` IPBlacklist string `ini:"ip_blacklist"` IPBlacklistRedirectURL string `ini:"ip_blacklist_redirect_url"` // TrustProxy 为 true 时信任 CDN 权威客户端头 CF-Connecting-IP / EO-Client-IP // (以及受信代理设置的 X-Real-IP / X-Forwarded-For);否则一律用 RemoteAddr, // 防止伪造 header 绕过速率限制与 IP 黑名单。 TrustProxy bool `ini:"trust_proxy"` // TrustedProxies 逗号分隔的 IP / CIDR,仅限自己的反向代理 / LB。仅当 TCP 对端 // 落在该清单内才解析 X-Forwarded-For / X-Real-IP;留空则这两个头永不被信任 // (CDN 权威头仍会采用,前提是源站已由 Cloudflare Tunnel / 回源网段锁定, // 从而免于维护上游 CDN 的庞大 CIDR 清单)。 TrustedProxies string `ini:"trusted_proxies"` EnableAutoBan bool `ini:"enable_auto_ban"` // fail2ban 风格:检测到扫描特征后临时封禁来源 IP // BanTrackNotFound 是否把未注册路径的 404 计入封禁统计。默认 false:仅命中后台 // 扫描特征路径(KindSensitive)才统计,避免共享出口(CDN 边缘 / CGNAT)下 // 正常用户被 404 探测流量连坐误伤。 BanTrackNotFound bool `ini:"ban_track_notfound"` BanThresholdSensitive int `ini:"ban_threshold_sensitive"` // 窗口内敏感路径命中次数 BanThreshold404 int `ini:"ban_threshold_404"` // 窗口内 404 次数 BanWindowSeconds int `ini:"ban_window_seconds"` // 统计窗口(秒) BanDurationMinutes int `ini:"ban_duration_minutes"` // 封禁时长(分钟) // DefaultModerationStrictness 站点默认审核严格度(lax / standard / strict), // 仅对未单独设置档位的账号生效(见 moderation.StrictnessFor)。留空或非法值回退 // strict(最严档),保证升级不会放宽拦截;默认拦截面可能较升级前略有扩大, // 希望更少误伤则显式写 standard。 DefaultModerationStrictness string `ini:"default_moderation_strictness"` // TextCensorSource 文本审核通道:qiniu / aliyun(内容安全 2.0 TextModeration, // 个人实名账号即可开通)/ auto(默认,留空同义:七牛优先、阿里云复核)。 // 仅显式选定的通道会被调用,缺凭据时启动即报错(见 conf.Init)—— // 审核失败是 fail-closed(拒绝提交),会让发布与私信整站不可用且现象隐蔽。 TextCensorSource string `ini:"text_censor_source"` // EnableHoneypot 开启「虚假后台登录界面」蜜罐:扫描器探测后台路径时 // 返回一个仿 WordPress 的假登录页,并记录其提交的用户名/密码等破解信息。 // 仅在「无任何路由匹配」的路径上生效,与真实业务路由零交集。 EnableHoneypot bool `ini:"enable_honeypot"` // HoneypotPaths 追加自定义诱饵路径(逗号分隔),与内置清单并集。 HoneypotPaths string `ini:"honeypot_paths"` // HoneypotRetainDays 蜜罐命中记录的保留天数,到期自动清理。 // ⚠️ 键名是 honeypot_retain_days(没有 tion)。写成 honeypot_retention_days // 会被 ini 静默忽略 —— 现场踩过这个坑,表现为「自动清理未启用」。 // 缺省 30 天(见 sanitizeHoneypot);显式 <= 0 也回退 30。 // 要关闭自动清理请用 honeypot_auto_clean = false。 HoneypotRetainDays int `ini:"honeypot_retain_days"` // HoneypotAutoClean 是否启用蜜罐记录的后台自动保留期清理。 // 缺省 true:honeypot_hits 是只追加的审计表,写入完全由外部扫描流量驱动, // 没有自动清理的话表体积只增不减(这是「数据库被扫描撑爆」的真实路径)。 // 关闭后仍可手动执行 TamaBox honeypot prune。 // ⚠️ 缺省值靠 HasKey 判定(见 sanitizeHoneypot):ini 的 bool 解析是 // 「有键才赋值」,若只看零值就无法区分「未配置」与「显式关闭」。 HoneypotAutoClean bool `ini:"honeypot_auto_clean"` // HoneypotMaxRows 蜜罐命中记录的行数上限。缺省 200000(约 53 MB)。 // 显式写 0 表示不设上限(逃生口,会告警提醒表只增不减)。 // 保留期是时间维度的上界,但攻击者可以用海量源 IP 在保留期内把表撑爆, // 这是第二道闸。实测单行约 281 字节(含索引,常规 UA),20 万行约 53 MB。 HoneypotMaxRows int `ini:"honeypot_max_rows"` // HoneypotThreshold 窗口内蜜罐命中多少次即封禁。默认 1(一次即封): // 蜜罐路径与真实业务路由零交集,正常访客不可能命中,一次即足以判定扫描器。 // 缺省回退 1(见 sanitizeHoneypot)。 HoneypotThreshold int `ini:"honeypot_threshold"` // HoneypotBanMinutes 蜜罐封禁时长(分钟)。留空则复用 ban_duration_minutes。 HoneypotBanMinutes int `ini:"honeypot_ban_minutes"` SecurityAlertEmail string `ini:"security_alert_email"` // 触发封禁时告警收件人(留空不发送) } Server struct { Port int `ini:"port"` Listen string `ini:"listen"` // 绑定监听地址(含端口)。留空则默认 ":port"(监听所有网卡)。 Salt string `ini:"salt"` XSRFKey string `ini:"xsrf_key"` } Database struct { DSN string Type string `ini:"type"` User string `ini:"user"` Password string `ini:"password"` Host string `ini:"host"` Port uint `ini:"port"` Name string `ini:"name"` Schema string `ini:"schema"` DedupeUniqueFields bool `ini:"dedupe_unique_fields"` } Redis struct { Addr string `ini:"addr"` Password string `ini:"password"` } Recaptcha struct { CaptchaType string `ini:"captcha_type"` Domain string `ini:"domain"` SiteKey string `ini:"site_key"` ServerKey string `ini:"server_key"` TurnstileStyle bool `ini:"turnstile_style"` } Pixel struct { Host string `ini:"host"` } Upload struct { DefaultAvatarURL string `ini:"default_avatar"` DefaultBackground string `ini:"default_background"` DefaultBackgroundImageURL string `ini:"default_qrbackgroundimage"` AliyunEndpoint string `ini:"aliyun_endpoint"` AliyunAccessID string `ini:"aliyun_access_id"` AliyunAccessSecret string `ini:"aliyun_access_secret"` AliyunBucket string `ini:"aliyun_bucket"` AliyunBucketCDNHost string `ini:"aliyun_bucket_cdn_host"` ImageEndpoint string `ini:"image_endpoint"` ImageAccessID string `ini:"image_access_id"` ImageAccessSecret string `ini:"image_access_secret"` ImageBucket string `ini:"image_bucket"` ImageBucketCDNHost string `ini:"image_bucket_cdn_host"` } Mail struct { Account string `ini:"account"` Password string `ini:"password"` Port int `ini:"port"` SMTP string `ini:"smtp"` SkipTLSVerify bool `ini:"skip_tls_verify"` // 仅自签名 / 内网 SMTP 需要 } Service struct { Backends []struct { Prefix string `ini:"prefix"` ForwardURL string `ini:"forward_url"` } TLSInsecureSkipVerify bool `ini:"tls_insecure_skip_verify"` // 仅内网自签名后端需要 } )