From 18f1113d33fbc916099e1e21048896b23390d6f9 Mon Sep 17 00:00:00 2001 From: Aine Date: Mon, 25 Sep 2023 21:59:23 +0300 Subject: [PATCH] add `pm banlist:auth` and `pm banlist:auto` --- README.md | 2 ++ bot/access.go | 50 +++++++++++++++++++++++++++++++++++++--- bot/command.go | 16 +++++++++++++ bot/command_admin.go | 54 ++++++++++++++++++++++++++++++++++++++++++++ bot/config/bot.go | 12 ++++++++++ smtp/manager.go | 3 ++- smtp/server.go | 6 ++--- 7 files changed, 136 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cfe0f65..a2a40e8 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,8 @@ If you want to change them - check available options in the help message (`!pm h * **`!pm greylist`** - Set automatic greylisting duration in minutes (0 - disabled) * **`!pm banlist`** - Enable/disable banlist and show current values +* **`!pm banlist:auth`** - Enable/disable automatic banning for invalid auth credentials +* **`!pm banlist:auto`** - Enable/disable automatic banning for invalid emails * **`!pm banlist:add`** - Ban an IP * **`!pm banlist:remove`** - Unban an IP * **`!pm banlist:reset`** - Reset banlist diff --git a/bot/access.go b/bot/access.go index 9eb2e0b..4a9b9d3 100644 --- a/bot/access.go +++ b/bot/access.go @@ -136,15 +136,59 @@ func (b *Bot) IsTrusted(addr net.Addr) bool { return false } -// Ban an address -func (b *Bot) Ban(addr net.Addr) { +// Ban an address automatically +func (b *Bot) BanAuto(addr net.Addr) { + if !b.cfg.GetBot().BanlistEnabled() { + return + } + + if !b.cfg.GetBot().BanlistAuto() { + return + } + + if b.IsTrusted(addr) { + return + } + b.log.Debug().Str("addr", addr.String()).Msg("attempting to automatically ban") + banlist := b.cfg.GetBanlist() + banlist.Add(addr) + err := b.cfg.SetBanlist(banlist) + if err != nil { + b.log.Error().Err(err).Str("addr", addr.String()).Msg("cannot update banlist") + } +} + +// Ban an address for incorrect auth automatically +func (b *Bot) BanAuth(addr net.Addr) { + if !b.cfg.GetBot().BanlistEnabled() { + return + } + + if !b.cfg.GetBot().BanlistAuth() { + return + } + + if b.IsTrusted(addr) { + return + } + b.log.Debug().Str("addr", addr.String()).Msg("attempting to automatically ban") + banlist := b.cfg.GetBanlist() + banlist.Add(addr) + err := b.cfg.SetBanlist(banlist) + if err != nil { + b.log.Error().Err(err).Str("addr", addr.String()).Msg("cannot update banlist") + } +} + +// Ban an address manually +func (b *Bot) BanManually(addr net.Addr) { if !b.cfg.GetBot().BanlistEnabled() { return } if b.IsTrusted(addr) { return } - b.log.Debug().Str("addr", addr.String()).Msg("attempting to ban") + b.log.Debug().Str("addr", addr.String()).Msg("attempting to manually ban") banlist := b.cfg.GetBanlist() banlist.Add(addr) err := b.cfg.SetBanlist(banlist) diff --git a/bot/command.go b/bot/command.go index 3a2142c..7948176 100644 --- a/bot/command.go +++ b/bot/command.go @@ -30,6 +30,8 @@ const ( commandSpamlistReset = "spam:reset" commandDelete = "delete" commandBanlist = "banlist" + commandBanlistAuto = "banlist:auto" + commandBanlistAuth = "banlist:auth" commandBanlistAdd = "banlist:add" commandBanlistRemove = "banlist:remove" commandBanlistReset = "banlist:reset" @@ -302,6 +304,16 @@ func (b *Bot) initCommands() commandList { description: "Enable/disable banlist and show current values", allowed: b.allowAdmin, }, + { + key: commandBanlistAuth, + description: "Enable/disable automatic banning of IP addresses when they try to auth with invalid credentials", + allowed: b.allowAdmin, + }, + { + key: commandBanlistAuto, + description: "Enable/disable automatic banning of IP addresses when they try to send invalid emails", + allowed: b.allowAdmin, + }, { key: commandBanlistAdd, description: "Ban an IP", @@ -387,6 +399,10 @@ func (b *Bot) handle(ctx context.Context) { b.runGreylist(ctx, commandSlice) case commandBanlist: b.runBanlist(ctx, commandSlice) + case commandBanlistAuth: + b.runBanlistAuth(ctx, commandSlice) + case commandBanlistAuto: + b.runBanlistAuto(ctx, commandSlice) case commandBanlistAdd: b.runBanlistAdd(ctx, commandSlice) case commandBanlistRemove: diff --git a/bot/command_admin.go b/bot/command_admin.go index ef82dfe..fcf936f 100644 --- a/bot/command_admin.go +++ b/bot/command_admin.go @@ -328,6 +328,60 @@ func (b *Bot) runBanlist(ctx context.Context, commandSlice []string) { b.SendNotice(ctx, evt.RoomID, "banlist has been updated") } +func (b *Bot) runBanlistAuth(ctx context.Context, commandSlice []string) { + evt := eventFromContext(ctx) + cfg := b.cfg.GetBot() + if len(commandSlice) < 2 { + var msg strings.Builder + msg.WriteString("Currently: `") + msg.WriteString(cfg.Get(config.BotBanlistAuth)) + msg.WriteString("`\n\n") + + if !cfg.BanlistAuth() { + msg.WriteString("To enable automatic banning for invalid credentials, send `") + msg.WriteString(b.prefix) + msg.WriteString(" banlist:auth true` (banlist itself must be enabled!)\n\n") + } + + b.SendNotice(ctx, evt.RoomID, msg.String()) + return + } + value := utils.SanitizeBoolString(commandSlice[1]) + cfg.Set(config.BotBanlistAuth, value) + err := b.cfg.SetBot(cfg) + if err != nil { + b.Error(ctx, evt.RoomID, "cannot set bot config: %v", err) + } + b.SendNotice(ctx, evt.RoomID, "auth banning has been updated") +} + +func (b *Bot) runBanlistAuto(ctx context.Context, commandSlice []string) { + evt := eventFromContext(ctx) + cfg := b.cfg.GetBot() + if len(commandSlice) < 2 { + var msg strings.Builder + msg.WriteString("Currently: `") + msg.WriteString(cfg.Get(config.BotBanlistAuto)) + msg.WriteString("`\n\n") + + if !cfg.BanlistAuto() { + msg.WriteString("To enable automatic banning for invalid emails, send `") + msg.WriteString(b.prefix) + msg.WriteString(" banlist:auto true` (banlist itself must be enabled!)\n\n") + } + + b.SendNotice(ctx, evt.RoomID, msg.String()) + return + } + value := utils.SanitizeBoolString(commandSlice[1]) + cfg.Set(config.BotBanlistAuto, value) + err := b.cfg.SetBot(cfg) + if err != nil { + b.Error(ctx, evt.RoomID, "cannot set bot config: %v", err) + } + b.SendNotice(ctx, evt.RoomID, "auto banning has been updated") +} + func (b *Bot) runBanlistAdd(ctx context.Context, commandSlice []string) { evt := eventFromContext(ctx) if len(commandSlice) < 2 { diff --git a/bot/config/bot.go b/bot/config/bot.go index ab4607e..c0adca0 100644 --- a/bot/config/bot.go +++ b/bot/config/bot.go @@ -21,6 +21,8 @@ const ( BotQueueBatch = "queue:batch" BotQueueRetries = "queue:retries" BotBanlistEnabled = "banlist:enabled" + BotBanlistAuto = "banlist:auto" + BotBanlistAuth = "banlist:auth" BotGreylist = "greylist" BotMautrix015Migration = "mautrix015migration" ) @@ -72,6 +74,16 @@ func (s Bot) BanlistEnabled() bool { return utils.Bool(s.Get(BotBanlistEnabled)) } +// BanlistAuto option +func (s Bot) BanlistAuto() bool { + return utils.Bool(s.Get(BotBanlistAuto)) +} + +// BanlistAuth option +func (s Bot) BanlistAuth() bool { + return utils.Bool(s.Get(BotBanlistAuth)) +} + // Greylist option (duration in minutes) func (s Bot) Greylist() int { return utils.Int(s.Get(BotGreylist)) diff --git a/smtp/manager.go b/smtp/manager.go index 84062dd..4a249e5 100644 --- a/smtp/manager.go +++ b/smtp/manager.go @@ -64,7 +64,8 @@ type matrixbot interface { IsGreylisted(net.Addr) bool IsBanned(net.Addr) bool IsTrusted(net.Addr) bool - Ban(net.Addr) + BanAuto(net.Addr) + BanAuth(net.Addr) GetMapping(string) (id.RoomID, bool) GetIFOptions(id.RoomID) email.IncomingFilteringOptions IncomingEmail(context.Context, *email.Email) error diff --git a/smtp/server.go b/smtp/server.go index d16509b..027c3b0 100644 --- a/smtp/server.go +++ b/smtp/server.go @@ -41,14 +41,14 @@ func (m *mailServer) Login(state *smtp.ConnectionState, username, password strin if !email.AddressValid(username) { m.log.Debug().Str("address", username).Msg("address is invalid") - m.bot.Ban(state.RemoteAddr) + m.bot.BanAuth(state.RemoteAddr) return nil, ErrBanned } roomID, allow := m.bot.AllowAuth(username, password) if !allow { m.log.Debug().Str("username", username).Msg("username or password is invalid") - m.bot.Ban(state.RemoteAddr) + m.bot.BanAuth(state.RemoteAddr) return nil, ErrBanned } @@ -77,7 +77,7 @@ func (m *mailServer) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, getRoomID: m.bot.GetMapping, getFilters: m.bot.GetIFOptions, receiveEmail: m.ReceiveEmail, - ban: m.bot.Ban, + ban: m.bot.BanAuto, greylisted: m.bot.IsGreylisted, trusted: m.bot.IsTrusted, log: m.log,