-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spam Filtering/Prevention #24
Comments
Honestly, I feel like we could mod the WebSocket message handler to include some rate limiting checks. As for rate limiting, I'm thinking we do limiting by:
use std::collections::VecDeque;
use std::time::{Duration, Instant};
const TIME_WINDOW: Duration = Duration::from_secs(60); // 1 minute window
const MESSAGE_LIMIT: usize = 10; // 10 messages per window Obv we should maybe change the values but this is just maybe how we'd get started on it. Thoughts?? |
I noticed you've added |
Hey sorry for the late reply, this took a little bit of thinking so here we go. This whole idea is borrowed from a sliding window algo I found recently: https://www.geeksforgeeks.org/window-sliding-technique/ The thought process is to give each user will have their own VecDeque to track the timestamps of their messages. VecDeque will store the timestamps of each message. We'll have to store it in a message_timestamps variable. We can prob just create a struct for users to keep track of the timestamps. struct User {
message_timestamps: VecDeque<Instant>,
} When a user sends a message, the current time (Instant) is added to the end of the VecDeque. Using a push_back method to achieve this like this: fn add_message(&mut self, timestamp: Instant) {
self.message_timestamps.push_back(timestamp);
} To maintain the data structure, we'll have to remove timestamps eventually that get outside of the current time window. (60 seconds or whatever we choose, given by the TIME_WINDOW const). We can prob achieve this by removing elements from the beginning of the Deque. We'll use pop_front until all timestamps are within our time window. Something like this: fn remove_old_messages(&mut self, current_time: Instant) {
while let Some(&old_timestamp) = self.message_timestamps.front() {
if current_time.duration_since(old_timestamp) > TIME_WINDOW {
self.message_timestamps.pop_front();
} else {
break;
}
}
} For rate limiting checks, we'll count the number of timestamps in our Dequeue and see if it goes over the limit. Obv if the limit is gone over, we'll have to temporarily stop messages. We can figure out consequences for spamming. As for implementation, fn can_send_message(&self) -> bool {
self.message_timestamps.len() < MESSAGE_LIMIT
} Before a message finally gets processed, we want to call remove_old_messages to update the tracking algo. Then we'll have to check can_send_message if they can send a message or needs to be limited. fn handle_new_message(&mut self, timestamp: Instant) -> bool {
self.remove_old_messages(timestamp);
if self.can_send_message() {
self.add_message(timestamp);
true // Allow message. YAY
} else {
false // Reject message and drop it :(
}
} |
Genius! I assume we'll have to create a Vec of open connections, probably using the User struct to hold that connection. I think that's a good idea, and it should work in practice. I'll have to see what we can do with |
To prevent sockpuppeting, a user should only be allowed to have one session per device. |
This will be doable in the future once #44 and #38 are complete. Should be as simple as giving each session a cookie to store in local storage, and then checking for that cookie on each tab. If user has cookie, then don't open a new session. Am not sure about how secure that would be though. |
Sliding window algo will be very easy to do once #38 is complete. |
This algorithm is now possible, and should be written in the call to |
We need to figure out a way to somehow limit the number of messages from a single user. There's several ways we could implement this, but we definitely want to avoid putting it in the frontend.
The text was updated successfully, but these errors were encountered: