Files
tamabox/internal/conf/static.go
T
2026-10-22 15:28:04 +08:00

201 lines
10 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.
// 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 = "20261022b"
)
// 文本审核通道取值([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"`
}
// Announcement 站内公告([announcement] 段)。解析与展示判定见 announcement.go。
Announcement announcementConfig
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(一次即封):
// 往假后台里填账号密码是证据最强的行为,抓到一次就足够。
// ⚠️ 它不作用于纯路径探测(GET 看一眼假登录页)—— 那类请求走常规
// ban_threshold_sensitive,否则扫描器 GET 一次就被封,永远走不到
// POST 提交凭据那一步,蜜罐也就拿不到字典。
// 缺省回退 1(见 sanitizeHoneypot)。
HoneypotThreshold int `ini:"honeypot_threshold"`
// HoneypotBanMinutes 蜜罐封禁时长(分钟)。缺省 1440(24 小时),
// 刻意远长于 ban_duration_minutes:命中蜜罐意味着对方已在提交账号密码,
// 证据强度高于单纯路径探测(见 DefaultHoneypotBanMinutes)。
// 显式 <= 0 表示回退 ban_duration_minutes。
HoneypotBanMinutes int `ini:"honeypot_ban_minutes"`
// HoneypotCredDir 凭据取证文件的存放目录。
//
// ⚠️ 捕获到的用户名/密码**不入库**,只追加到这个目录下的按天文件
// (creds-YYYY-MM-DD.jsonl,一行一条 JSON)。原因:明文账号密码一旦入库,
// 就会跟着进备份、主从复制和任何能连库的报表工具,事后无法彻底清除。
// 目录会被强制为 0700、文件 0600;留空使用默认 data/honeypot-creds。
// 目录不可写时只降级为「不保存凭据」,不会影响站点启动。
HoneypotCredDir string `ini:"honeypot_cred_dir"`
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"` // 仅内网自签名后端需要
}
)