mirror of
https://github.com/pldubouilh/blockfast.git
synced 2026-08-27 20:36:34 -04:00
bubble up parsing errors
This commit is contained in:
Generated
+21
@@ -51,6 +51,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"linemux",
|
||||
"regex",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@@ -398,6 +399,26 @@ dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.12.0"
|
||||
|
||||
+2
-1
@@ -11,4 +11,5 @@ linemux = "0.2"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
|
||||
lazy_static = "1.4.0"
|
||||
regex = "1.5.4"
|
||||
clap = "2.33.3"
|
||||
clap = "2.33.3"
|
||||
thiserror = "1.0.26"
|
||||
|
||||
+38
-17
@@ -1,28 +1,30 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use crate::utils::Error;
|
||||
use lazy_static::lazy_static;
|
||||
use std::net::IpAddr;
|
||||
|
||||
// TODO: allow user-provided list
|
||||
// TODO: match different error-levels (10 404, but only 5 401, etc...)
|
||||
lazy_static! {
|
||||
static ref BAD_STATUSES: [&'static str; 2] = ["401", "429"];
|
||||
static ref BAD_STATUSES: [u32; 2] = [401, 429];
|
||||
}
|
||||
|
||||
pub fn parse(line: &str) -> Option<IpAddr> {
|
||||
pub fn parse(line: &str) -> Result<Option<IpAddr>, Error> {
|
||||
// TODO: Use a proper parser ?
|
||||
let elts: Vec<&str> = line.split_whitespace().collect();
|
||||
let ip = elts[0].parse::<IpAddr>().ok();
|
||||
let http_code = elts[elts.len() - 2] as &str;
|
||||
|
||||
BAD_STATUSES.iter().find_map(
|
||||
|bad_status| {
|
||||
if http_code == *bad_status {
|
||||
ip
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
let ip_str = elts[0];
|
||||
let ip = ip_str.parse::<IpAddr>().or(Err(Error::CantParse))?;
|
||||
|
||||
let http_code_str = elts[elts.len() - 2] as &str;
|
||||
let http_code = http_code_str.parse::<u32>().or(Err(Error::CantParse))?;
|
||||
|
||||
for status in BAD_STATUSES.iter() {
|
||||
if *status == http_code {
|
||||
return Ok(Some(ip));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -36,7 +38,10 @@ mod tests {
|
||||
"8.8.8.8 - p [25/Sep/2021:13:49:56 +0200] \"POST /some/rpc HTTP/2.0\" 429 923",
|
||||
];
|
||||
|
||||
vectors.iter().for_each(|e| assert!(parse(*e).is_some()))
|
||||
vectors.iter().for_each(|e| {
|
||||
let ret = parse(*e);
|
||||
assert!(ret.unwrap().is_some());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -46,6 +51,22 @@ mod tests {
|
||||
"8.8.8.8 - p [25/Sep/2021:13:49:56 +0200] \"POST /some/rpc HTTP/2.0\" 404 923",
|
||||
];
|
||||
|
||||
vectors.iter().for_each(|e| assert!(parse(*e).is_none()))
|
||||
vectors.iter().for_each(|e| {
|
||||
let ret = parse(*e);
|
||||
assert!(ret.unwrap().is_none());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed() {
|
||||
let vectors = [
|
||||
"8.8.8.8.8 - p [25/Sep/2021:13:49:56 +0200] \"POST /some/rpc HTTP/2.0\" 200 923",
|
||||
"8.8.8.8 - p [25/Sep/2021:13:49:56 +0200] \"POST /some/rpc HTTP/2.0\"",
|
||||
];
|
||||
|
||||
vectors.iter().for_each(|e| {
|
||||
let ret = parse(*e);
|
||||
assert!(ret.is_err());
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -6,6 +6,7 @@ mod utils;
|
||||
|
||||
mod jail;
|
||||
use crate::jail::Jail;
|
||||
use crate::utils::Error;
|
||||
|
||||
async fn run() -> Option<()> {
|
||||
let args = utils::cli().get_matches();
|
||||
@@ -36,12 +37,18 @@ async fn run() -> Option<()> {
|
||||
let payload = line.line();
|
||||
let path = line.source().display().to_string();
|
||||
|
||||
if do_sshd && path.ends_with(path_sshd) {
|
||||
sshd::parse(payload).and_then(|ip| jail.probe(ip));
|
||||
let res = if do_sshd && path.ends_with(path_sshd) {
|
||||
sshd::parse(payload)
|
||||
} else if do_clf && path.ends_with(path_clf) {
|
||||
clf::parse(payload).and_then(|ip| jail.probe(ip));
|
||||
clf::parse(payload)
|
||||
} else {
|
||||
eprintln!("! unknown logline: {}", path);
|
||||
Err(Error::UnknownError)
|
||||
};
|
||||
|
||||
if let Ok(Some(ip)) = res {
|
||||
jail.probe(ip);
|
||||
} else {
|
||||
eprintln!("! error processing logline: {}", path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+40
-8
@@ -1,7 +1,9 @@
|
||||
use crate::utils::Error;
|
||||
use std::net::IpAddr;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use std::str::FromStr;
|
||||
|
||||
struct Rule {
|
||||
matcher: String,
|
||||
@@ -15,7 +17,7 @@ lazy_static! {
|
||||
extractor: Regex::new(r"(from.)(.*)(.port)").unwrap(),
|
||||
},
|
||||
Rule {
|
||||
matcher: "Invalid user".to_string(),
|
||||
matcher: "Invalid user ".to_string(),
|
||||
extractor: Regex::new(r"(from.)(.*)").unwrap(),
|
||||
},
|
||||
Rule {
|
||||
@@ -25,16 +27,27 @@ lazy_static! {
|
||||
];
|
||||
}
|
||||
|
||||
pub fn parse(line: &str) -> Option<IpAddr> {
|
||||
let ret = SSHD_BAD.iter().find_map(|rule| {
|
||||
pub fn parse(line: &str) -> Result<Option<IpAddr>, Error> {
|
||||
let hits = SSHD_BAD.iter().find_map(|rule| {
|
||||
if line.contains(&rule.matcher) {
|
||||
rule.extractor.captures(line)?.get(2)
|
||||
rule.extractor.captures(line)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
});
|
||||
|
||||
ret.as_str().parse::<IpAddr>().ok()
|
||||
if hits.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let ip = hits
|
||||
.and_then(|c| c.get(2))
|
||||
.and_then(|m| IpAddr::from_str(m.as_str()).ok());
|
||||
|
||||
match ip {
|
||||
Some(ip) => Ok(Some(ip)),
|
||||
None => Err(Error::CantParse),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -49,7 +62,10 @@ mod tests {
|
||||
"Sep 26 06:25:32 livecompute sshd[23254]: Invalid user neal from 35.184.211.144"
|
||||
];
|
||||
|
||||
vectors.iter().for_each(|e| assert!(parse(*e).is_some()))
|
||||
vectors.iter().for_each(|e| {
|
||||
let ret = parse(*e);
|
||||
assert!(ret.unwrap().is_some());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -60,6 +76,22 @@ mod tests {
|
||||
"Sep 26 06:25:32 livecompute sshd[23254]: very good user neal from 35.184.211.144"
|
||||
];
|
||||
|
||||
vectors.iter().for_each(|e| assert!(parse(*e).is_none()))
|
||||
vectors.iter().for_each(|e| {
|
||||
let ret = parse(*e);
|
||||
assert!(ret.unwrap().is_none());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed() {
|
||||
let vectors = [
|
||||
"Sep 26 06:25:19 livecompute sshd[23246]: Failed password for root from 179.124.36.195.232 port 41883 ssh2",
|
||||
"Sep 26 06:26:14 livecompute sshd[23292]: pam_unix(sshd:auth): authentication failure; logname= u =0 tty=ssh ruser= rhost=",
|
||||
];
|
||||
|
||||
vectors.iter().for_each(|e| {
|
||||
let ret = parse(*e);
|
||||
assert!(ret.is_err());
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
use clap::{App, Arg};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum Error {
|
||||
#[error("cant parse")]
|
||||
CantParse,
|
||||
#[error("general error")]
|
||||
UnknownError,
|
||||
}
|
||||
|
||||
pub fn cli() -> App<'static, 'static> {
|
||||
App::new("ban internets scanner fast 🍶")
|
||||
.version("v0.0.1")
|
||||
|
||||
Reference in New Issue
Block a user