zekroTJA / shinpuru

シンプル - Discord Bot with role selection, moderation, karma ranking, a starboard, code execution, raid alerting, backups, a web interface, twitch notifications and more!
https://shnp.de
MIT License
191 stars 36 forks source link

[PROPOSAL] Anti-Raid System #159

Closed voxain closed 4 years ago

voxain commented 4 years ago

This is a feature proposal that is fully open for discussion and suggestions. 😉

Introduction

As many of you may or may have not experienced, server raids are an ongoing trend on popular discord servers. But even if the highest levels of moderation restrictions can still cause problems: You can never prevent a bot from sending DMs to guild members or having a verified (fake) phone number.

Concept

To keep these events to a minimum here is a concept for an anti-Raid system. So in theory, when a new member joins, the bot will catch this event and check how old the discord account of the newly joined member is. If the account age is below 24h (this should also be customizable from the web interface) the account will be sent a Direct Message and banned instantly.

In that direct message, however, the user will find the reason for their fast ban and a link which will lead them to a new route on the web interface. The user will then be asked to login via discord's oAuth feature. After the authorization process has completed, the user will have to solve a captcha. If that captcha is resolved successfully, the user will then be redirected to a temporary discord invite, which expires after 1 use.

Customizable parameters

To ensure flexibility, there are a few things that should be customizable by admins: Value Suggested default value Description
Minimum account age 24h Every account which has been created within this timespan will be affected by the anti-raid mechanism.
Ban Message A quick, explaining but informative text The message users will receive before they are banned. This message of course has to contain the link.
Ignore Disabled DMs false If this setting is set to true, users who can't be DMed by the bot will not be affected by the system, since there is no way of informing them about what happened. However, these users should still be affected by default.
Captcha verification true If this feature is turned off, the user will not have to solve a captcha and will be instantly reinvited when authorizing on the dashboard. It should be customizable because it may already be enough to keep most bots out of the server, but easier for regular users to get back in if they were affected by the system.
Use temporary invite true Whether or not the bot should generate a temporary invite for each verified member. If not, the bot will generate one invite which will be used for all members - or provide admins with the possibility to choose the invite the bot will use - Maybe it would also be cool to be able to select a custom redirect URL.
lus commented 4 years ago

I see a problem with the DM-notification. Many people disabled direct messages from random people and so they won't get any notification. This would not be user friendly.

voxain commented 4 years ago

Many people disabled direct messages from random people

That's why I included the parameter "Ignore Disabled DMs" which can be turned on to prevent this. If it was turned off by default, raiding the server would be as easy as closing the bot's DMs which you possibly don't want -- but that should be decided by the user. After all, it's their decision if they even use the anti-raid system at all.

lus commented 4 years ago

Yeah, but if it's turned on, raiding would be pretty easy. If it's turned off, it wouldn't be user-friendly anymore. Maybe that needs a little overhaul.

voxain commented 4 years ago

@Lukaesebrot how would you do it differently? There is no way to do it. We can give admins the choice to exclude users who have their DMs disabled or it's their own bad luck. Strict moderation requires strict actions. Also, consider: If an account is less than 24h old, how high is the possibility that they've changed that setting?

zekroTJA commented 4 years ago

Well, without DMs, this concept is nearly impossible to realize. A bypas for that would be to automatically generate a channel which is not available for any users (admins excluded ofc) and which is only accessable with a specific, automatically generated role. When a user joins and the DM sending fails, the user will not be directly banned and instead of that, receive this role. Then, a mentioned message is sent into this channel. So the user is only able to see other members in this channel, which shall be only admins and other victims.

voxain commented 4 years ago

Since there's been some raids going on recently, i was thinking about this feature again. During ongoing raids, I've noticed that almost all of the used accounts were older than 24h, however that was just in some specific cases but it still was a thing. I was figuring, It'd be cool to have a feature included that just detects if a lot of new members are joining (lets just say by default, 10 members in 7 seconds), the bot should automatically raise the moderation level of the server. Of course, that value should be adjustable. Same goes for messages - If there's been more than, let's say, 10 messages per second for 3 seconds or more in one channel, the server's moderation level is raised by one (or the channel is locked).

Of course, all the values should be adjustable, because in bigger servers, these could be the everyday cases.

zekroTJA commented 4 years ago

Thats a really good idea, but I need to look up first if you are able to change the servers moderation level via the bot API.

voxain commented 4 years ago

According to the Discord API docs, you can. I don't know if it's interpreted in the wrapper you're using.

zekroTJA commented 4 years ago

Okay, discordgo also supports updating guilds via this endpoint, so it should be possible to achive this approach: https://github.com/bwmarrin/discordgo/blob/v0.22.0/restapi.go#L615

I'll try to implement this as soon as I#ve figured out how to redesign the guild admin panel, because all of these new settings will not fit in the current guild settings spoiler. ^^

voxain commented 4 years ago

I may be able to provide you with an idea or two, just hit me up on discord if you need anything ^^

zekroTJA commented 4 years ago

Well, because I now have the time to work on this feature, I got some initial ideas how to implement the antiraid feature and what needs to be changed in detail to do so.

I) The Definition

First of all, I thought about how we define a "Raid", because, as @voxain mentioned above, we can not rely on data like account age or other stuff, because raided accounts can also be stolen accounts.

So, a "Raid" is defined as a flood of joins of new members to a guild in a relatively short time.

For example, 60 members join a guild with 1.000 members within 10 minutes, thats defined as a Raid.

II) Administrative Configurations

The following settings need to be implemented in order to configure the antiraid system by guild admins:

Key Type Description
enable bool Enables or disables the system.
regeneration_period int The ammount of seconds which is considered to be the normal, average rate of joining members.
burst int A maximum ammount of joins which can occur during a short period of time without triggering the system.

III) The Implementation

First of all, new database bindings need to be implemented to store the configurations of the antiraid system.

internal/core/database/database.go

type Database interface {
    // [...]

    SetAntiraidState(guildID string, state bool) error
    GetAntiraidState(guildID string) (bool, error)

    SetAntiraidRegeneration(guildID string, periodSecs int) error
    GetAntiraidRegeneration(guildID string) (int, error)

    SetAntiraidBurst(guildID string, burst int) error
    GetAntiraidBurst(guildID string) (int, error)

    // [...]
}

To modify these settings, new API endpoints needs to be created.

GET  /api/guilds/:guildID/settings/antiraid
POST /api/guilds/:guildID/settings/antiraid

And, of course, a new guild admin route in the web interface needs to be added for this purpose as well.

For actual detection of raids, a new discordgo listener is added which binds to the discordgo.GuildMemberAdd event. This listener instance holds a map of rate limiters with the guild ID as key and the rate limiter instance as value.

As rate limiters, the token bucket based rate limiters of the package github.com/zekroTJA/ratelimit are utilized for this purpose.

Everytime the GuildMemberAdd event fires, the configuration state of the antiraid system is checked for the guild ID where the event was fired. When the system is enabled, the listener checks for a limiter instance for the events guild ID. If there is no limiter instance available, a new instance is created using the values from settings. Otherwise, the limiter is checked if the limiters properties still match the guilds antiraid settings. If not, the limiters properties will be adjusted. Following, a token will be tried to be reserved from the limiter. When this was successful, the function returns. If the reservation fails, the antiraid system triggers.

On hitting the trigger, the servers verification level will be set to the highest level and the guilds admins are notified via DM. Also, after hitting the trigger, all IDs of members which join the guild in the next 24 hours are temporarily (another 24 hours, so 48 hours in total) stored and can be listed in the web interface.

voxain commented 4 years ago

Great work! What instantly comes to my mind (because you know, I love the Webinterface), It'd be great if there was a category "Raids" in which admins could see recent raids, the users which were affected by it, whether or not they have solved the captcha and a possibility to unban them if necessary.

Of course that is just an idea that pops to my mind now :)