feat: 新增 SMTP/IMAP/POP3 协议调用日志(含攻击分析筛选)
- 每个连接记录一条日志:协议、端口、来源 IP、用户名、成功/失败、 失败原因(密码错误/IP封禁/中继被拒/发件人伪造/未认证发信等)、 操作摘要、消息数与会话时长 - 管理后台新增「协议日志」页:按协议/状态/IP/用户名/时间筛选, 今日与历史成功/失败统计卡片,分页查看,可手动清理 - 后台每 6 小时自动清理超出 protocol_log_keep_days(默认30天) 的日志;新增 [web] protocol_log_keep_days 配置项 - 修复 POP3 认证既有 bug:handleUSER 丢弃邮箱域名导致 PASS 永远失败 - 新增 store 单测、SMTP/POP3 端到端测试与模板渲染测试
This commit is contained in:
30 files changed
+1233
-59
No files matched your search
+1
-1
@@ -46,7 +46,7 @@ func InitDB(cfg config.DatabaseConfig, storageCfg config.StorageConfig) (*gorm.D
|
||||
}
|
||||
|
||||
// Auto-migrate all models
|
||||
if err := db.AutoMigrate(&User{}, &Domain{}, &Message{}, &Attachment{}, &BanEntry{}, &OutboundMessage{}); err != nil {
|
||||
if err := db.AutoMigrate(&User{}, &Domain{}, &Message{}, &Attachment{}, &BanEntry{}, &OutboundMessage{}, &ProtocolLog{}); err != nil {
|
||||
return nil, fmt.Errorf("数据库迁移失败: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,34 @@ type BanEntry struct {
|
||||
// TableName specifies the table name for BanEntry.
|
||||
func (BanEntry) TableName() string { return "ban_entries" }
|
||||
|
||||
// Protocol log statuses.
|
||||
const (
|
||||
ProtocolSMTP = "smtp"
|
||||
ProtocolIMAP = "imap"
|
||||
ProtocolPOP3 = "pop3"
|
||||
)
|
||||
|
||||
// ProtocolLog records one SMTP/IMAP/POP3 connection session: auth result,
|
||||
// failure reason and source IP, for admin analysis of attacks/abuse.
|
||||
type ProtocolLog struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Protocol string `gorm:"size:16;index;not null" json:"protocol"` // smtp | imap | pop3
|
||||
Port int `json:"port"` // 25/465/587/143/993/110/995
|
||||
ClientIP string `gorm:"size:64;index;not null" json:"client_ip"`
|
||||
Username string `gorm:"size:255;index" json:"username"`
|
||||
Success bool `gorm:"index" json:"success"`
|
||||
FailReason string `gorm:"size:512" json:"fail_reason"`
|
||||
Detail string `gorm:"size:2048" json:"detail"`
|
||||
MsgCount int `json:"msg_count"`
|
||||
DurationMs int64 `json:"duration_ms"`
|
||||
CreatedAt time.Time `gorm:"index" json:"created_at"`
|
||||
}
|
||||
|
||||
// TableName specifies the table name for ProtocolLog.
|
||||
func (ProtocolLog) TableName() string {
|
||||
return "protocol_logs"
|
||||
}
|
||||
|
||||
// Attachment represents a file attached to an email message.
|
||||
type Attachment struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
|
||||
Reference in New Issue
Block a user