线上(box.shiroko.one/_/tamakyi)两个现象来自同一处:`--tb-navbar` 是实色,
顶栏那条带(y=20..80)把从右上角长出来的花枝齐刷刷切掉一段。
第一版顺手改成 transparent —— 花枝完整了,但顶栏"消失":导航失去依托,
文字直接压在花纹上。用户当场否掉,要求半透明。
- 顶栏:`rgba(253,246,248,0.72)` / 深色 `rgba(34,26,30,0.72)`,配
`.uk-navbar-container{backdrop-filter:blur(12px)}`(令牌只能是颜色,模糊写在规则里)。
0.72 有依据:导航文字 #6d555d 纯底 6.34:1,最坏情况(深花瓣在顶栏后面)压平后 5.08:1。
- 花枝 top -16px → 26px:顶栏半透明后,700~760px 宽度下枝头正好压在「登录」上(截图确认)。
- 手机底栏 #tb-mobile-utils 在 base.css 写死 rgba(255,255,255,.92),粉底上是一条白杠,
主题里改成同色系 0.92。
- 新增 TestNavbarNotFullyTransparent:拦 `transparent` / `rgba(...,0)` / `#rrggbb00`,
并说明"这不是审美偏好,是踩过之后立的规矩"。变异验证过(改回 transparent 立即 FAIL)。
约定同时写进 static/css/themes/_scaffold.css 的令牌说明。
- StaticVersion 20261022b → 20261022c:css 改了不提版本号,浏览器拿着旧样式,
现象就是"改了但线上没变"。
201 lines
10 KiB
Go
201 lines
10 KiB
Go
// 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 = "20261022c"
|
||
)
|
||
|
||
// 文本审核通道取值([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"` // 仅内网自签名后端需要
|
||
}
|
||
)
|