IP banning

This commit is contained in:
Mike Dilger 2024-02-19 12:36:07 +13:00
parent ca0dee2285
commit b76ea99b60
2 changed files with 24 additions and 1 deletions

View File

@ -1,7 +1,10 @@
use crate::config::{Config, FriendlyConfig};
use crate::store::Store;
use crate::types::Time;
use hyper::server::conn::Http;
use lazy_static::lazy_static;
use std::collections::HashMap;
use std::net::IpAddr;
use std::sync::atomic::AtomicUsize;
use std::sync::OnceLock;
use tokio::sync::broadcast::Sender as BroadcastSender;
@ -22,6 +25,7 @@ pub struct Globals {
pub num_clients: AtomicUsize,
pub shutting_down: WatchSender<bool>,
pub banlist: RwLock<HashMap<IpAddr, Time>>,
}
lazy_static! {
@ -41,6 +45,7 @@ lazy_static! {
new_events,
num_clients: AtomicUsize::new(0),
shutting_down,
banlist: RwLock::new(HashMap::new()),
}
};
}

View File

@ -16,7 +16,7 @@ use crate::globals::GLOBALS;
use crate::reply::NostrReply;
use crate::store::Store;
use crate::tls::MaybeTlsStream;
use crate::types::{OwnedFilter, Pubkey};
use crate::types::{OwnedFilter, Pubkey, Time};
use futures::{sink::SinkExt, stream::StreamExt};
use hyper::service::Service;
use hyper::upgrade::Upgraded;
@ -102,6 +102,15 @@ async fn main() -> Result<(), Error> {
// Accepts network connections and spawn a task to serve each one
v = listener.accept() => {
let (tcp_stream, peer_addr) = v?;
let ipaddr = peer_addr.ip();
if let Some(ban_until) = GLOBALS.banlist.read().await.get(&ipaddr) {
let now = Time::now();
if *ban_until > now {
log::debug!("{peer_addr}: Blocking reconnection until {ban_until}");
continue;
}
}
if let Some(tls_acceptor) = &maybe_tls_acceptor {
let tls_acceptor_clone = tls_acceptor.clone();
@ -275,6 +284,15 @@ async fn handle_http_request(
peer,
old_num_websockets - 1
);
// Everybody gets a 4 second ban on disconnect, to prevent rapid reconnection
let ipaddr = peer.ip();
let mut until = Time::now();
until.0 += 4;
if let Some(current_ban) = GLOBALS.banlist.read().await.get(&ipaddr) {
until.0 = current_ban.0.max(until.0);
}
GLOBALS.banlist.write().await.insert(ipaddr, until);
}
Err(e) => {
log::error!("{}", e);