Skip to content

[Proposal] Update flood protection logic #1559

@HumorBaby

Description

@HumorBaby

Flood-prevention measures need to be refactored.

Proposed minimum changes:

  • Move logic into irc.Bot.write
  • Calculate writing backoff (penalty) based on an adequately massaged message (e.g., post-truncation)

Background

RFC 1459 spec on flood control of clients:

8.10 Flood control of clients

   With a large network of interconnected IRC servers, it is quite easy
   for any single client attached to the network to supply a continuous
   stream of messages that result in not only flooding the network, but
   also degrading the level of service provided to others.  Rather than
   require every 'victim' to be provide their own protection, flood
   protection was written into the server and is applied to all clients
   except services.  The current algorithm is as follows:

        * check to see if client's `message timer' is less than
          current time (set to be equal if it is);

        * read any data present from the client;

        * while the timer is less than ten seconds ahead of the current
          time, parse any present messages and penalize the client by
          2 seconds for each message;

   which in essence means that the client may send 1 message every 2
   seconds without being adversely affected.

Current bot layout: (I may have missed some 😯)

** = flood-prevention logic is here
+----------------+    +---------------+    +-------------+
|  Sopel.action  +--->+ **Sopel.say** +--->+             |
|  Sopel.msg     |    +---------------+    |             |    +---------------+    +--------------------------+
|  Sopel.reply   |                         | Sopel.write +--->+ irc.Bot.write +--->+ asynchat.async_chat.send |
+----------------+    +---------------+    |             |    +---------------+    +--------------------------+
                      | Sopel.notice  +--->+             |            .
                      | Sopel.part    |    +-------------+           /|\
                      | Sopel.join    |                               |
                      | Sopel.kick ?  |                               |
                      +---------------+                         +-----------+ 
                                                                | CAP,NICK, |
                                                                | PASS,...  |
                                                                +-----------+

Rationale

A few reasons this change is needed:

  1. The current logic calculates a penalty based on the untruncated message. This led to the fiasco of .dice denial of service #1550 (comment) and .py denial of service #1551.
    • The penalty should be based only on the actual part of the message that is being sent to the server.
  2. All the methods that don't use Sopel.say currently, bypass flood-prevention logic.

Future plans

Potential additional changes:

  • Add configurable backoff
  • Add a configurable maximum penalty
  • Allow message burst (with a configurable number and subsequent delays)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions