mirror of
https://github.com/mikedilger/chorus.git
synced 2026-05-03 06:51:42 +00:00
Ban for 60 seconds after 3 errors, adjust ban times
This commit is contained in:
parent
b85cd9297c
commit
dbf7313d2b
@ -109,6 +109,9 @@ pub enum ChorusError {
|
|||||||
// Filter is underspecified
|
// Filter is underspecified
|
||||||
Scraper,
|
Scraper,
|
||||||
|
|
||||||
|
// Too many errors
|
||||||
|
TooManyErrors,
|
||||||
|
|
||||||
// URL Parse
|
// URL Parse
|
||||||
UrlParse(url::ParseError),
|
UrlParse(url::ParseError),
|
||||||
|
|
||||||
@ -166,6 +169,7 @@ impl std::fmt::Display for ChorusError {
|
|||||||
ChorusError::Rustls(e) => write!(f, "{e}"),
|
ChorusError::Rustls(e) => write!(f, "{e}"),
|
||||||
ChorusError::Tungstenite(e) => write!(f, "{e}"),
|
ChorusError::Tungstenite(e) => write!(f, "{e}"),
|
||||||
ChorusError::Scraper => write!(f, "Filter is underspecified. Scrapers are not allowed"),
|
ChorusError::Scraper => write!(f, "Filter is underspecified. Scrapers are not allowed"),
|
||||||
|
ChorusError::TooManyErrors => write!(f, "Too many errors"),
|
||||||
ChorusError::UrlParse(e) => write!(f, "{e}"),
|
ChorusError::UrlParse(e) => write!(f, "{e}"),
|
||||||
ChorusError::Utf8(e) => write!(f, "{e}"),
|
ChorusError::Utf8(e) => write!(f, "{e}"),
|
||||||
ChorusError::Utf8Error => write!(f, "UTF-8 error"),
|
ChorusError::Utf8Error => write!(f, "UTF-8 error"),
|
||||||
|
|||||||
@ -49,3 +49,14 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Globals {
|
||||||
|
pub async fn ban(ipaddr: std::net::IpAddr, seconds: u64) {
|
||||||
|
let mut until = Time::now();
|
||||||
|
until.0 += seconds;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
53
src/main.rs
53
src/main.rs
@ -12,7 +12,7 @@ pub mod web;
|
|||||||
|
|
||||||
use crate::config::{Config, FriendlyConfig};
|
use crate::config::{Config, FriendlyConfig};
|
||||||
use crate::error::{ChorusError, Error};
|
use crate::error::{ChorusError, Error};
|
||||||
use crate::globals::GLOBALS;
|
use crate::globals::{Globals, GLOBALS};
|
||||||
use crate::reply::NostrReply;
|
use crate::reply::NostrReply;
|
||||||
use crate::store::Store;
|
use crate::store::Store;
|
||||||
use crate::tls::MaybeTlsStream;
|
use crate::tls::MaybeTlsStream;
|
||||||
@ -251,6 +251,7 @@ async fn handle_http_request(
|
|||||||
websocket,
|
websocket,
|
||||||
challenge: TextNonce::new().into_string(),
|
challenge: TextNonce::new().into_string(),
|
||||||
user: None,
|
user: None,
|
||||||
|
errcount: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Increment count of active websockets
|
// Increment count of active websockets
|
||||||
@ -262,17 +263,26 @@ async fn handle_http_request(
|
|||||||
old_num_websockets + 1
|
old_num_websockets + 1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Everybody gets a 4-second ban on disconnect to prevent
|
||||||
|
// rapid reconnection
|
||||||
|
let mut ban_seconds: u64 = 4;
|
||||||
|
|
||||||
// Handle the websocket
|
// Handle the websocket
|
||||||
if let Err(e) = ws_service.handle_websocket_stream().await {
|
if let Err(e) = ws_service.handle_websocket_stream().await {
|
||||||
if matches!(
|
match e.inner {
|
||||||
e.inner,
|
|
||||||
ChorusError::Tungstenite(tungstenite::error::Error::Protocol(
|
ChorusError::Tungstenite(tungstenite::error::Error::Protocol(
|
||||||
tungstenite::error::ProtocolError::ResetWithoutClosingHandshake
|
tungstenite::error::ProtocolError::ResetWithoutClosingHandshake,
|
||||||
))
|
)) => {
|
||||||
) {
|
// So they disconnected ungracefully.
|
||||||
// Swallow the boring error
|
// No big deal, no extra ban for that.
|
||||||
} else {
|
}
|
||||||
log::error!("{}: {}", peer, e);
|
ChorusError::TooManyErrors => {
|
||||||
|
ban_seconds = 60;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
log::error!("{}: {}", peer, e);
|
||||||
|
ban_seconds = 15;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,14 +295,8 @@ async fn handle_http_request(
|
|||||||
old_num_websockets - 1
|
old_num_websockets - 1
|
||||||
);
|
);
|
||||||
|
|
||||||
// Everybody gets a 4 second ban on disconnect, to prevent rapid reconnection
|
// Ban for the appropriate duration
|
||||||
let ipaddr = peer.ip();
|
Globals::ban(peer.ip(), ban_seconds).await;
|
||||||
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) => {
|
Err(e) => {
|
||||||
log::error!("{}", e);
|
log::error!("{}", e);
|
||||||
@ -321,6 +325,7 @@ struct WebSocketService {
|
|||||||
pub websocket: WebSocketStream<Upgraded>,
|
pub websocket: WebSocketStream<Upgraded>,
|
||||||
pub challenge: String,
|
pub challenge: String,
|
||||||
pub user: Option<Pubkey>,
|
pub user: Option<Pubkey>,
|
||||||
|
pub errcount: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebSocketService {
|
impl WebSocketService {
|
||||||
@ -392,13 +397,21 @@ impl WebSocketService {
|
|||||||
async fn handle_websocket_message(&mut self, message: Message) -> Result<(), Error> {
|
async fn handle_websocket_message(&mut self, message: Message) -> Result<(), Error> {
|
||||||
match message {
|
match message {
|
||||||
Message::Text(msg) => {
|
Message::Text(msg) => {
|
||||||
log::debug!("{}: <= {}", self.peer, msg);
|
log::trace!("{}: <= {}", self.peer, msg);
|
||||||
// This is defined in nostr.rs
|
// This is defined in nostr.rs
|
||||||
if let Err(e) = self.handle_nostr_message(&msg).await {
|
if let Err(e) = self.handle_nostr_message(&msg).await {
|
||||||
log::error!("{e}");
|
self.errcount += 1;
|
||||||
log::error!("msg was {}", msg);
|
log::error!("{}: {e}", self.peer);
|
||||||
|
log::error!("{}: msg was {}", self.peer, msg);
|
||||||
let reply = NostrReply::Notice(format!("error: {}", e));
|
let reply = NostrReply::Notice(format!("error: {}", e));
|
||||||
self.websocket.send(Message::text(reply.as_json())).await?;
|
self.websocket.send(Message::text(reply.as_json())).await?;
|
||||||
|
if self.errcount > 3 {
|
||||||
|
let reply = NostrReply::Notice(
|
||||||
|
"Too many errors (3). Banned for 60 seconds.".into(),
|
||||||
|
);
|
||||||
|
self.websocket.send(Message::text(reply.as_json())).await?;
|
||||||
|
return Err(ChorusError::TooManyErrors.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Binary(msg) => {
|
Message::Binary(msg) => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user