mirror of
https://github.com/Astatin3/rust-scan-mc.git
synced 2026-06-09 00:18:02 -06:00
Add timestamp and rescan
This commit is contained in:
@@ -20,3 +20,4 @@ craftping = "0.7.0"
|
|||||||
sha256 = "1.6.0"
|
sha256 = "1.6.0"
|
||||||
rayon = "1.10.0"
|
rayon = "1.10.0"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
|
chrono = "0.4.40"
|
||||||
|
|||||||
+83
-41
@@ -1,5 +1,11 @@
|
|||||||
use std::{collections::HashMap, net::IpAddr, sync::Arc, time::Instant};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
net::IpAddr,
|
||||||
|
sync::Arc,
|
||||||
|
time::{Duration, Instant, UNIX_EPOCH},
|
||||||
|
};
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rocksdb::{Cache, ColumnFamily, DB, IteratorMode, Options, WriteBatch};
|
use rocksdb::{Cache, ColumnFamily, DB, IteratorMode, Options, WriteBatch};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -11,6 +17,7 @@ const BLOCK_CACHE_SIZE_MB: usize = 512; // 512MB block cache
|
|||||||
const WRITE_BUFFER_SIZE_MB: usize = 64; // 64MB write buffer
|
const WRITE_BUFFER_SIZE_MB: usize = 64; // 64MB write buffer
|
||||||
const NUM_PARALLEL_THREADS: usize = 8; // Number of threads for parallel operations
|
const NUM_PARALLEL_THREADS: usize = 8; // Number of threads for parallel operations
|
||||||
const BATCH_SIZE: usize = 1000; // Batch size for writes
|
const BATCH_SIZE: usize = 1000; // Batch size for writes
|
||||||
|
pub const EPOCH_2025: u32 = 1735689600; // So i don't have to use u64
|
||||||
|
|
||||||
pub struct ResultDatabase {
|
pub struct ResultDatabase {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
@@ -22,6 +29,7 @@ pub struct ResultDatabase {
|
|||||||
pub struct DatabaseResult {
|
pub struct DatabaseResult {
|
||||||
pub ip: String,
|
pub ip: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
|
pub time_scanned: u32,
|
||||||
|
|
||||||
pub version: String,
|
pub version: String,
|
||||||
pub protocol: u32,
|
pub protocol: u32,
|
||||||
@@ -45,9 +53,10 @@ impl DatabaseResult {
|
|||||||
let mut str = "".to_string();
|
let mut str = "".to_string();
|
||||||
|
|
||||||
str += format!(
|
str += format!(
|
||||||
"\n{}\n- ports: [{}]\n- version: [{}]\n- protocol: [{}]\n- max_players: [{}]\n- online_players: [{}]\n- players_list: [{:?}]\n- description: [{}]\n- icon_hash: [{}]\n- mod_info: [{:?}]\n- forge_data: [{:?}]\n- enforces_secure_chat: [{:?}]\n- previews_chat: [{:?}]",
|
"\n{}:{}\n- Last scanned: {}\n- version: [{}]\n- protocol: [{}]\n- max_players: [{}]\n- online_players: [{}]\n- players_list: [{:?}]\n- description: [{}]\n- icon_hash: [{}]\n- mod_info: [{:?}]\n- forge_data: [{:?}]\n- enforces_secure_chat: [{:?}]\n- previews_chat: [{:?}]",
|
||||||
self.ip,
|
self.ip,
|
||||||
self.port,
|
self.port,
|
||||||
|
DateTime::<Utc>::from(UNIX_EPOCH + Duration::from_secs((self.time_scanned + EPOCH_2025) as u64)).format("%Y-%m-%d %H:%M:%S.%f").to_string(),
|
||||||
self.version,
|
self.version,
|
||||||
self.protocol,
|
self.protocol,
|
||||||
self.max_players,
|
self.max_players,
|
||||||
@@ -163,6 +172,7 @@ impl ResultDatabase {
|
|||||||
|
|
||||||
let column_families = vec![
|
let column_families = vec![
|
||||||
"addr".to_string(),
|
"addr".to_string(),
|
||||||
|
"time".to_string(),
|
||||||
"version".to_string(),
|
"version".to_string(),
|
||||||
"protocol".to_string(),
|
"protocol".to_string(),
|
||||||
"max_players".to_string(),
|
"max_players".to_string(),
|
||||||
@@ -245,17 +255,18 @@ impl ResultDatabase {
|
|||||||
let db = Arc::new(DB::open_cf(&self.options, &self.path, &self.columns)?);
|
let db = Arc::new(DB::open_cf(&self.options, &self.path, &self.columns)?);
|
||||||
|
|
||||||
let cf_addr = db.cf_handle(&self.columns[0]).unwrap();
|
let cf_addr = db.cf_handle(&self.columns[0]).unwrap();
|
||||||
let cf_version = db.cf_handle(&self.columns[1]).unwrap();
|
let cf_time = db.cf_handle(&self.columns[1]).unwrap();
|
||||||
let cf_protocol = db.cf_handle(&self.columns[2]).unwrap();
|
let cf_version = db.cf_handle(&self.columns[2]).unwrap();
|
||||||
let cf_max_players = db.cf_handle(&self.columns[3]).unwrap();
|
let cf_protocol = db.cf_handle(&self.columns[3]).unwrap();
|
||||||
let cf_online_players = db.cf_handle(&self.columns[4]).unwrap();
|
let cf_max_players = db.cf_handle(&self.columns[4]).unwrap();
|
||||||
let cf_players_list = db.cf_handle(&self.columns[5]).unwrap();
|
let cf_online_players = db.cf_handle(&self.columns[5]).unwrap();
|
||||||
let cf_description = db.cf_handle(&self.columns[6]).unwrap();
|
let cf_players_list = db.cf_handle(&self.columns[6]).unwrap();
|
||||||
let cf_icon_hash = db.cf_handle(&self.columns[7]).unwrap();
|
let cf_description = db.cf_handle(&self.columns[7]).unwrap();
|
||||||
let cf_mod_info = db.cf_handle(&self.columns[8]).unwrap();
|
let cf_icon_hash = db.cf_handle(&self.columns[8]).unwrap();
|
||||||
let cf_forge_data = db.cf_handle(&self.columns[9]).unwrap();
|
let cf_mod_info = db.cf_handle(&self.columns[9]).unwrap();
|
||||||
let cf_enforces_secure_chat = db.cf_handle(&self.columns[10]).unwrap();
|
let cf_forge_data = db.cf_handle(&self.columns[10]).unwrap();
|
||||||
let cf_previews_chat = db.cf_handle(&self.columns[11]).unwrap();
|
let cf_enforces_secure_chat = db.cf_handle(&self.columns[11]).unwrap();
|
||||||
|
let cf_previews_chat = db.cf_handle(&self.columns[12]).unwrap();
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let length = string_rows.len();
|
let length = string_rows.len();
|
||||||
@@ -282,6 +293,7 @@ impl ResultDatabase {
|
|||||||
let key = key.as_bytes();
|
let key = key.as_bytes();
|
||||||
|
|
||||||
batch.put_cf(cf_addr, key, key);
|
batch.put_cf(cf_addr, key, key);
|
||||||
|
batch.put_cf(cf_time, key, row.time_scanned.to_string().as_bytes());
|
||||||
batch.put_cf(cf_version, key, row.version.as_bytes());
|
batch.put_cf(cf_version, key, row.version.as_bytes());
|
||||||
batch.put_cf(cf_protocol, key, row.protocol.to_string().as_bytes());
|
batch.put_cf(cf_protocol, key, row.protocol.to_string().as_bytes());
|
||||||
batch.put_cf(cf_max_players, key, row.max_players.to_string().as_bytes());
|
batch.put_cf(cf_max_players, key, row.max_players.to_string().as_bytes());
|
||||||
@@ -368,6 +380,7 @@ impl ResultDatabase {
|
|||||||
db.cf_handle(&self.columns[9]).unwrap(),
|
db.cf_handle(&self.columns[9]).unwrap(),
|
||||||
db.cf_handle(&self.columns[10]).unwrap(),
|
db.cf_handle(&self.columns[10]).unwrap(),
|
||||||
db.cf_handle(&self.columns[11]).unwrap(),
|
db.cf_handle(&self.columns[11]).unwrap(),
|
||||||
|
db.cf_handle(&self.columns[12]).unwrap(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return self.fetch_row(&db, row, &cfs);
|
return self.fetch_row(&db, row, &cfs);
|
||||||
@@ -413,6 +426,7 @@ impl ResultDatabase {
|
|||||||
db.cf_handle(&self.columns[9]).unwrap(),
|
db.cf_handle(&self.columns[9]).unwrap(),
|
||||||
db.cf_handle(&self.columns[10]).unwrap(),
|
db.cf_handle(&self.columns[10]).unwrap(),
|
||||||
db.cf_handle(&self.columns[11]).unwrap(),
|
db.cf_handle(&self.columns[11]).unwrap(),
|
||||||
|
db.cf_handle(&self.columns[12]).unwrap(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut matching_keys: Vec<DatabaseResult> = Vec::new();
|
let mut matching_keys: Vec<DatabaseResult> = Vec::new();
|
||||||
@@ -457,6 +471,7 @@ impl ResultDatabase {
|
|||||||
db.cf_handle(&self.columns[9]).unwrap(),
|
db.cf_handle(&self.columns[9]).unwrap(),
|
||||||
db.cf_handle(&self.columns[10]).unwrap(),
|
db.cf_handle(&self.columns[10]).unwrap(),
|
||||||
db.cf_handle(&self.columns[11]).unwrap(),
|
db.cf_handle(&self.columns[11]).unwrap(),
|
||||||
|
db.cf_handle(&self.columns[12]).unwrap(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut matching_keys: Vec<DatabaseResult> = Vec::new();
|
let mut matching_keys: Vec<DatabaseResult> = Vec::new();
|
||||||
@@ -490,7 +505,7 @@ impl ResultDatabase {
|
|||||||
if queries.len() == 1 {
|
if queries.len() == 1 {
|
||||||
// Return host if results include host
|
// Return host if results include host
|
||||||
match queries[0] {
|
match queries[0] {
|
||||||
QueryDataType::Host(row, port) => {
|
QueryDataType::Addr(row, port) => {
|
||||||
return Ok(vec![
|
return Ok(vec![
|
||||||
self.get_row_by_host(
|
self.get_row_by_host(
|
||||||
format!("{}:{}", row.to_string().as_str(), port).as_str(),
|
format!("{}:{}", row.to_string().as_str(), port).as_str(),
|
||||||
@@ -517,6 +532,7 @@ impl ResultDatabase {
|
|||||||
db.cf_handle(&self.columns[9]).unwrap(),
|
db.cf_handle(&self.columns[9]).unwrap(),
|
||||||
db.cf_handle(&self.columns[10]).unwrap(),
|
db.cf_handle(&self.columns[10]).unwrap(),
|
||||||
db.cf_handle(&self.columns[11]).unwrap(),
|
db.cf_handle(&self.columns[11]).unwrap(),
|
||||||
|
db.cf_handle(&self.columns[12]).unwrap(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let matching_key_bytes = search_parallel(&db, queries, &cfs);
|
let matching_key_bytes = search_parallel(&db, queries, &cfs);
|
||||||
@@ -545,34 +561,38 @@ impl ResultDatabase {
|
|||||||
.to_string()
|
.to_string()
|
||||||
.parse::<u16>()
|
.parse::<u16>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
version: self.row_to_string(db, row_id, &cfs[1]),
|
time_scanned: self
|
||||||
protocol: self
|
.row_to_string(db, row_id, &cfs[1])
|
||||||
.row_to_string(db, row_id, &cfs[2])
|
|
||||||
.parse::<u32>()
|
.parse::<u32>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
max_players: self
|
version: self.row_to_string(db, row_id, &cfs[2]),
|
||||||
|
protocol: self
|
||||||
.row_to_string(db, row_id, &cfs[3])
|
.row_to_string(db, row_id, &cfs[3])
|
||||||
.parse::<u32>()
|
.parse::<u32>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
online_players: self
|
max_players: self
|
||||||
.row_to_string(db, row_id, &cfs[4])
|
.row_to_string(db, row_id, &cfs[4])
|
||||||
.parse::<u32>()
|
.parse::<u32>()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
online_players: self
|
||||||
|
.row_to_string(db, row_id, &cfs[5])
|
||||||
|
.parse::<u32>()
|
||||||
|
.unwrap(),
|
||||||
players_list: DatabaseResult::decode_players_list(
|
players_list: DatabaseResult::decode_players_list(
|
||||||
self.row_to_string(db, row_id, &cfs[5]),
|
self.row_to_string(db, row_id, &cfs[6]),
|
||||||
),
|
),
|
||||||
description: self.row_to_string(db, row_id, &cfs[6]),
|
description: self.row_to_string(db, row_id, &cfs[7]),
|
||||||
icon_hash: self.row_to_string(db, row_id, &cfs[7]),
|
icon_hash: self.row_to_string(db, row_id, &cfs[8]),
|
||||||
mod_info: DatabaseResult::decode_mod_info(self.row_to_string(db, row_id, &cfs[8])),
|
mod_info: DatabaseResult::decode_mod_info(self.row_to_string(db, row_id, &cfs[9])),
|
||||||
forge_data: DatabaseResult::decode_forge_data(
|
forge_data: DatabaseResult::decode_forge_data(
|
||||||
self.row_to_string(db, row_id, &cfs[9]),
|
|
||||||
),
|
|
||||||
enforces_secure_chat: DatabaseResult::decode_option_bool(
|
|
||||||
self.row_to_string(db, row_id, &cfs[10]),
|
self.row_to_string(db, row_id, &cfs[10]),
|
||||||
),
|
),
|
||||||
previews_chat: DatabaseResult::decode_option_bool(
|
enforces_secure_chat: DatabaseResult::decode_option_bool(
|
||||||
self.row_to_string(db, row_id, &cfs[11]),
|
self.row_to_string(db, row_id, &cfs[11]),
|
||||||
),
|
),
|
||||||
|
previews_chat: DatabaseResult::decode_option_bool(
|
||||||
|
self.row_to_string(db, row_id, &cfs[12]),
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -589,7 +609,10 @@ impl ResultDatabase {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum QueryDataType {
|
pub enum QueryDataType {
|
||||||
Host(IpAddr, u16),
|
Addr(IpAddr, u16),
|
||||||
|
Host(QueryType, String),
|
||||||
|
Port(QueryType, u32),
|
||||||
|
ScanTime(QueryType, u32),
|
||||||
Version(QueryType, String),
|
Version(QueryType, String),
|
||||||
Protocol(QueryType, u32),
|
Protocol(QueryType, u32),
|
||||||
MaxPlayers(QueryType, u32),
|
MaxPlayers(QueryType, u32),
|
||||||
@@ -690,19 +713,24 @@ pub fn search_parallel(
|
|||||||
) -> Vec<Vec<u8>> {
|
) -> Vec<Vec<u8>> {
|
||||||
// Get column family handles
|
// Get column family handles
|
||||||
let cf_addr = cfs[0];
|
let cf_addr = cfs[0];
|
||||||
let cf_version = cfs[1];
|
let cf_scan_time = cfs[1];
|
||||||
let cf_protocol = cfs[2];
|
let cf_version = cfs[2];
|
||||||
let cf_max_players = cfs[3];
|
let cf_protocol = cfs[3];
|
||||||
let cf_online_players = cfs[4];
|
let cf_max_players = cfs[4];
|
||||||
let cf_players_list = cfs[5];
|
let cf_online_players = cfs[5];
|
||||||
let cf_description = cfs[6];
|
let cf_players_list = cfs[6];
|
||||||
let cf_icon_hash = cfs[7];
|
let cf_description = cfs[7];
|
||||||
let cf_mod_info = cfs[8];
|
let cf_icon_hash = cfs[8];
|
||||||
let cf_forge_data = cfs[9];
|
let cf_mod_info = cfs[9];
|
||||||
let cf_secure_chat = cfs[10];
|
let cf_forge_data = cfs[10];
|
||||||
let cf_previews_chat = cfs[11];
|
let cf_secure_chat = cfs[11];
|
||||||
|
let cf_previews_chat = cfs[12];
|
||||||
|
|
||||||
// Partition queries by type
|
// Partition queries by type
|
||||||
|
let mut host_queries = Vec::new();
|
||||||
|
let mut port_queries = Vec::new();
|
||||||
|
|
||||||
|
let mut time_queries = Vec::new();
|
||||||
let mut version_queries = Vec::new();
|
let mut version_queries = Vec::new();
|
||||||
let mut protocol_queries = Vec::new();
|
let mut protocol_queries = Vec::new();
|
||||||
let mut max_players_queries = Vec::new();
|
let mut max_players_queries = Vec::new();
|
||||||
@@ -717,6 +745,9 @@ pub fn search_parallel(
|
|||||||
|
|
||||||
for q in queries {
|
for q in queries {
|
||||||
match q {
|
match q {
|
||||||
|
QueryDataType::Host(_, _) => host_queries.push(q),
|
||||||
|
QueryDataType::Port(_, _) => port_queries.push(q),
|
||||||
|
QueryDataType::ScanTime(_, _) => time_queries.push(q),
|
||||||
QueryDataType::Version(_, _) => version_queries.push(q),
|
QueryDataType::Version(_, _) => version_queries.push(q),
|
||||||
QueryDataType::Protocol(_, _) => protocol_queries.push(q),
|
QueryDataType::Protocol(_, _) => protocol_queries.push(q),
|
||||||
QueryDataType::MaxPlayers(_, _) => max_players_queries.push(q),
|
QueryDataType::MaxPlayers(_, _) => max_players_queries.push(q),
|
||||||
@@ -771,7 +802,14 @@ pub fn search_parallel(
|
|||||||
if let Some(bytes) = bytes {
|
if let Some(bytes) = bytes {
|
||||||
if let Ok(data) = std::str::from_utf8(&bytes) {
|
if let Ok(data) = std::str::from_utf8(&bytes) {
|
||||||
queries.iter().all(|query| match query {
|
queries.iter().all(|query| match query {
|
||||||
QueryDataType::Host(_, _) => false,
|
QueryDataType::Addr(_, _) => false,
|
||||||
|
QueryDataType::Host(qt, test) => {
|
||||||
|
match_string_comparison(qt, test, data.split(":").nth(0).unwrap_or(""))
|
||||||
|
}
|
||||||
|
QueryDataType::Port(qt, test) => {
|
||||||
|
match_num_comparison(qt, test, data.split(":").nth(1).unwrap_or(""))
|
||||||
|
}
|
||||||
|
QueryDataType::ScanTime(qt, test) => match_num_comparison(qt, test, data),
|
||||||
QueryDataType::Version(qt, test) => match_string_comparison(qt, test, data),
|
QueryDataType::Version(qt, test) => match_string_comparison(qt, test, data),
|
||||||
QueryDataType::Protocol(qt, test) => match_num_comparison(qt, test, data),
|
QueryDataType::Protocol(qt, test) => match_num_comparison(qt, test, data),
|
||||||
QueryDataType::MaxPlayers(qt, test) => match_num_comparison(qt, test, data),
|
QueryDataType::MaxPlayers(qt, test) => match_num_comparison(qt, test, data),
|
||||||
@@ -814,7 +852,11 @@ pub fn search_parallel(
|
|||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.filter(|key| {
|
.filter(|key| {
|
||||||
// Check port queries
|
// Check port queries
|
||||||
(version_queries.is_empty() || loop_queries(db, cf_version, key, &version_queries))
|
(host_queries.is_empty() || loop_queries(db, cf_addr, key, &host_queries))
|
||||||
|
&& (port_queries.is_empty() || loop_queries(db, cf_addr, key, &port_queries))
|
||||||
|
&& (time_queries.is_empty() || loop_queries(db, cf_scan_time, key, &time_queries))
|
||||||
|
&& (version_queries.is_empty()
|
||||||
|
|| loop_queries(db, cf_version, key, &version_queries))
|
||||||
&& (protocol_queries.is_empty()
|
&& (protocol_queries.is_empty()
|
||||||
|| loop_queries(db, cf_protocol, key, &protocol_queries))
|
|| loop_queries(db, cf_protocol, key, &protocol_queries))
|
||||||
&& (max_players_queries.is_empty()
|
&& (max_players_queries.is_empty()
|
||||||
|
|||||||
+53
@@ -2,10 +2,12 @@ use std::{
|
|||||||
cmp::min,
|
cmp::min,
|
||||||
env,
|
env,
|
||||||
net::IpAddr,
|
net::IpAddr,
|
||||||
|
str::FromStr,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use parse_ip_range::parse_ip_targets;
|
use parse_ip_range::parse_ip_targets;
|
||||||
|
use rand::{rng, seq::SliceRandom};
|
||||||
use untitled::{
|
use untitled::{
|
||||||
database::ResultDatabase, online_scan, parse_ip_range, port_scan::tcp_scan, query,
|
database::ResultDatabase, online_scan, parse_ip_range, port_scan::tcp_scan, query,
|
||||||
service_scan::service_scan::scan_services,
|
service_scan::service_scan::scan_services,
|
||||||
@@ -35,6 +37,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let _ = scan(database, args[2].to_string());
|
let _ = scan(database, args[2].to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"rescan" => rescan(database, args)?,
|
||||||
// "search" => {
|
// "search" => {
|
||||||
// if args.len() != 4 {
|
// if args.len() != 4 {
|
||||||
// println!("Invalid Usage!");
|
// println!("Invalid Usage!");
|
||||||
@@ -180,6 +183,56 @@ fn scan(database: ResultDatabase, arg: String) -> Result<(), Box<dyn std::error:
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rescan(database: ResultDatabase, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let start = Instant::now();
|
||||||
|
if let Ok(query) = query::search(args[2..].join(" ")) {
|
||||||
|
let results = database.search(query);
|
||||||
|
if let Ok(results) = results {
|
||||||
|
let len = results.len();
|
||||||
|
|
||||||
|
let mut hosts: Vec<IpAddr> = Vec::new();
|
||||||
|
|
||||||
|
for result in results {
|
||||||
|
println!("{}", result.to_string());
|
||||||
|
hosts.push(IpAddr::from_str(result.ip.as_str()).unwrap());
|
||||||
|
}
|
||||||
|
println!("{} results in {}ms", len, start.elapsed().as_millis());
|
||||||
|
|
||||||
|
hosts.sort();
|
||||||
|
hosts.dedup();
|
||||||
|
hosts.shuffle(&mut rng());
|
||||||
|
|
||||||
|
let chunks = hosts.chunks(BATCH_SIZE);
|
||||||
|
let num_chunks = chunks.len();
|
||||||
|
for (i, hosts) in chunks.enumerate() {
|
||||||
|
let hosts = hosts.to_vec();
|
||||||
|
let length = hosts.len();
|
||||||
|
|
||||||
|
println!("Scanning chunk {}/{} ({} hosts)", i + 1, num_chunks, length);
|
||||||
|
|
||||||
|
let up_hosts: Vec<IpAddr> = online_scan::ping_scanner::ping_scan(hosts).unwrap();
|
||||||
|
let up_len = up_hosts.len();
|
||||||
|
println!(
|
||||||
|
"Finished Pinging! {} Scanned, {} Up",
|
||||||
|
length,
|
||||||
|
up_hosts.len()
|
||||||
|
);
|
||||||
|
|
||||||
|
let tcp_results =
|
||||||
|
tcp_scan::tcp_scan(up_hosts, PORTS_1.to_vec(), Duration::from_secs(3));
|
||||||
|
println!("Finished port scan");
|
||||||
|
|
||||||
|
let service_results =
|
||||||
|
scan_services(tcp_results, min(50, up_len), Duration::from_secs(1));
|
||||||
|
println!("Finished service scan");
|
||||||
|
let _ = database.add_data_row(service_results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// fn search(database: ResultDatabase, search_type: String, arg: String) {
|
// fn search(database: ResultDatabase, search_type: String, arg: String) {
|
||||||
// match search_type.as_str() {
|
// match search_type.as_str() {
|
||||||
// "host" => {
|
// "host" => {
|
||||||
|
|||||||
+16
-2
@@ -10,12 +10,12 @@ fn try_parse_host(query: &str) -> Option<QueryDataType> {
|
|||||||
let ip = IpAddr::from_str(split.nth(0).unwrap());
|
let ip = IpAddr::from_str(split.nth(0).unwrap());
|
||||||
if let Some(port) = &split.nth(1) {
|
if let Some(port) = &split.nth(1) {
|
||||||
if let (Ok(ip), Ok(port)) = (ip, port.parse::<u16>()) {
|
if let (Ok(ip), Ok(port)) = (ip, port.parse::<u16>()) {
|
||||||
return Some(QueryDataType::Host(ip, port));
|
return Some(QueryDataType::Addr(ip, port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(ip) = IpAddr::from_str(&query) {
|
if let Ok(ip) = IpAddr::from_str(&query) {
|
||||||
return Some(QueryDataType::Host(ip, 25565));
|
return Some(QueryDataType::Addr(ip, 25565));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
@@ -67,6 +67,20 @@ pub fn search(query: String) -> Result<Vec<QueryDataType>, Box<dyn std::error::E
|
|||||||
}
|
}
|
||||||
|
|
||||||
(match tag.as_str() {
|
(match tag.as_str() {
|
||||||
|
"port" => {
|
||||||
|
results.push(QueryDataType::Port(
|
||||||
|
get_equals_type_num(&delim),
|
||||||
|
data.parse::<u32>().expect("Error parsing port"),
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
"scantime" => {
|
||||||
|
results.push(QueryDataType::ScanTime(
|
||||||
|
get_equals_type_num(&delim),
|
||||||
|
data.parse::<u32>().expect("Error parsing time"),
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
"version" => {
|
"version" => {
|
||||||
results.push(QueryDataType::Version(get_equals_type_str(&delim), data));
|
results.push(QueryDataType::Version(get_equals_type_str(&delim), data));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ use serde_json::json;
|
|||||||
use sha256::digest;
|
use sha256::digest;
|
||||||
use std::{
|
use std::{
|
||||||
net::{IpAddr, SocketAddr, TcpStream},
|
net::{IpAddr, SocketAddr, TcpStream},
|
||||||
time::Duration,
|
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::database::DatabaseResult;
|
use crate::database::{DatabaseResult, EPOCH_2025};
|
||||||
|
|
||||||
pub fn scan(
|
pub fn scan(
|
||||||
ip: IpAddr,
|
ip: IpAddr,
|
||||||
@@ -30,6 +30,11 @@ pub fn scan(
|
|||||||
Ok(DatabaseResult {
|
Ok(DatabaseResult {
|
||||||
ip: ip.to_string(),
|
ip: ip.to_string(),
|
||||||
port: port as u16,
|
port: port as u16,
|
||||||
|
time_scanned: (SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs()
|
||||||
|
- EPOCH_2025 as u64) as u32,
|
||||||
version: pong.version,
|
version: pong.version,
|
||||||
protocol: pong.protocol as u32,
|
protocol: pong.protocol as u32,
|
||||||
max_players: pong.max_players as u32,
|
max_players: pong.max_players as u32,
|
||||||
|
|||||||
Reference in New Issue
Block a user