mirror of
https://github.com/bee-san/RustScan.git
synced 2026-11-07 09:46:04 -10:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1078304ae | ||
|
|
22cbfc5826 | ||
|
|
c5091728a0 | ||
|
|
a9d729300c | ||
|
|
4f5dd20e85 | ||
|
|
499ff66f36 | ||
|
|
61b87243d9 | ||
|
|
e069991c8d | ||
|
|
85c1cbf445 | ||
|
|
e609b3617c |
No files matched your search
Generated
+16
@@ -774,6 +774,7 @@ dependencies = [
|
||||
"rlimit",
|
||||
"shell-words",
|
||||
"structopt",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -782,6 +783,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
|
||||
|
||||
[[package]]
|
||||
name = "shell-words"
|
||||
version = "1.0.0"
|
||||
@@ -874,6 +881,15 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.6.0"
|
||||
|
||||
+8
-2
@@ -16,8 +16,6 @@ exclude = [
|
||||
"rustscan-debbuilder/*",
|
||||
]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
colored = "2.0.0"
|
||||
structopt = "0.3.16"
|
||||
@@ -28,11 +26,19 @@ shell-words = "1.0.0"
|
||||
log = "0.4.0"
|
||||
env_logger = "0.7.1"
|
||||
dirs = "3.0.1"
|
||||
toml = "0.5.6"
|
||||
gcd = "2.0.1"
|
||||
rand = "0.7.3"
|
||||
colorful = "0.2.1"
|
||||
ansi_term = "0.12.1"
|
||||
ureq = "1.3.0"
|
||||
serde = "1.0.115"
|
||||
serde_derive = "1.0.115"
|
||||
|
||||
[package.metadata.deb]
|
||||
depends = "$auto, nmap"
|
||||
section = "rust"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
panic = 'abort'
|
||||
@@ -230,8 +230,7 @@ OPTIONS:
|
||||
-b, --batch-size <batch-size> The batch size for port scanning, it increases or slows the speed of scanning.
|
||||
Depends on the open file limit of your OS. If you do 65535 it will do every port
|
||||
at the same time. Although, your OS may not support this [default: 4500]
|
||||
-p, --ports <ports>... A list of comma separed ports to be scanned. Example: 80,443,8080. These ports will
|
||||
be scanned sequentially
|
||||
-p, --ports <ports>... A list of comma separed ports to be scanned. Example: 80,443,8080.
|
||||
-r, --range <range> A range of ports with format start-end. Example: 1-1000
|
||||
--scan-order <scan-order> The order of scanning to be performed. The "serial" option will scan ports in
|
||||
ascending order while the "random" option will scan ports randomly [default:
|
||||
@@ -341,6 +340,22 @@ To increase accuracy, the easiest way is to increase the timeout. The default is
|
||||
|
||||
Decreasing accuracy gives some speed bonus, but my testing found that batch size dramatically changed the speed whereas timeout did, but not so much.
|
||||
|
||||
## 🤖 Config File
|
||||
|
||||
RustScan uses a Config file to make things easier for you. And to also improve itself.
|
||||
The config file is used as the basis of the _adaptive learning_ mechanisms. This means that RustScan _learns_ from your scans and improves itself over time. (Don't worry, no bloated AI framework here 😉)
|
||||
|
||||
The config file should be placed in APPDIRS. To find this folder, run RustScan and look out for RustScan saying "couldn't find config at <location>". That location is where your config file should be.
|
||||
|
||||
Once you have this location, copy and paste this:
|
||||
|
||||
```toml
|
||||
|
||||
# The top ports
|
||||
[top_ports]
|
||||
80, 60, 443
|
||||
```
|
||||
|
||||
# 🎪 Community
|
||||
|
||||
Howdy Space Cow-Person 🤠🌌
|
||||
|
||||
+1004
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,28 @@
|
||||
FROM archlinux:latest
|
||||
|
||||
RUN yes | pacman -Syu
|
||||
RUN yes | pacman -S fakeroot binutils sudo make gcc gettext awk git
|
||||
|
||||
WORKDIR /opt
|
||||
RUN git clone https://aur.archlinux.org/yay-git.git
|
||||
|
||||
RUN useradd -m tecmint
|
||||
RUN passwd -d tecmint
|
||||
RUN printf 'tecmint ALL=(ALL) ALL\n' | tee -a /etc/sudoers
|
||||
|
||||
WORKDIR /opt/yay-git
|
||||
RUN chown -R tecmint /opt/yay-git
|
||||
USER tecmint
|
||||
RUN makepkg -si --noconfirm
|
||||
|
||||
# AUR
|
||||
RUN yay -S rustscan --noconfirm
|
||||
RUN rustscan 127.0.0.1 -q -b 250 -t 1
|
||||
RUN yay -R rustscan --noconfirm
|
||||
|
||||
# homebrew
|
||||
RUN yes | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
|
||||
ENV PATH="/home/linuxbrew/.linuxbrew/bin:${PATH}"
|
||||
RUN yes | brew tap brandonskerritt/rustscan
|
||||
RUN yes | brew install rustscan
|
||||
RUN rustscan 127.0.0.1 -q -b 250 -t 1
|
||||
File renamed without changes.
@@ -5,6 +5,7 @@ git pull --force
|
||||
|
||||
#amd64
|
||||
cargo deb
|
||||
yes | dpkg -i *.deb
|
||||
|
||||
#arm64
|
||||
rustup target add arm-unknown-linux-gnueabihf
|
||||
File renamed without changes.
+84
-9
@@ -13,11 +13,20 @@ use colorful::Colorful;
|
||||
use futures::executor::block_on;
|
||||
use rlimit::Resource;
|
||||
use rlimit::{getrlimit, setrlimit};
|
||||
use serde_derive::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::{net::IpAddr, net::ToSocketAddrs, time::Duration};
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
net::IpAddr,
|
||||
path::PathBuf,
|
||||
time::Duration,
|
||||
};
|
||||
use structopt::{clap::arg_enum, StructOpt};
|
||||
use ureq;
|
||||
|
||||
extern crate colorful;
|
||||
extern crate dirs;
|
||||
@@ -82,7 +91,6 @@ struct Opts {
|
||||
ips_or_hosts: Vec<String>,
|
||||
|
||||
/// A list of comma separed ports to be scanned. Example: 80,443,8080.
|
||||
/// These ports will be scanned sequentially.
|
||||
#[structopt(short, long, use_delimiter = true)]
|
||||
ports: Option<Vec<u16>>,
|
||||
|
||||
@@ -98,6 +106,10 @@ struct Opts {
|
||||
#[structopt(short, long)]
|
||||
accessible: bool,
|
||||
|
||||
///Config file usage
|
||||
#[structopt(short, long)]
|
||||
config: bool,
|
||||
|
||||
/// The batch size for port scanning, it increases or slows the speed of
|
||||
/// scanning. Depends on the open file limit of your OS. If you do 65535
|
||||
/// it will do every port at the same time. Although, your OS may not
|
||||
@@ -128,6 +140,11 @@ struct Opts {
|
||||
command: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ConfigFile {
|
||||
ip: IpAddr,
|
||||
}
|
||||
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
/// Faster Nmap scanning with Rust
|
||||
/// If you're looking for the actual scanning, check out the module Scanner
|
||||
@@ -150,6 +167,12 @@ fn main() {
|
||||
print_opening();
|
||||
}
|
||||
|
||||
/*
|
||||
TODO when releasing the new config file feature
|
||||
turn this on.
|
||||
if opts.config {
|
||||
let config = get_config_file();
|
||||
}*/
|
||||
let ips: Vec<IpAddr> = parse_ips(&opts);
|
||||
|
||||
if ips.is_empty() {
|
||||
@@ -246,21 +269,65 @@ Faster Nmap scanning with Rust."#;
|
||||
--------------------------------------"#;
|
||||
println!("{}", info.gradient(Color::Yellow).bold());
|
||||
funny_opening!();
|
||||
// println!("{}", loaded_config_file);
|
||||
}
|
||||
|
||||
fn get_config_file() {
|
||||
let result_get_location = get_location_config();
|
||||
let location = match result_get_location {
|
||||
Ok(path) => path,
|
||||
Err(_) => panic!("Your system does not have appdirs."),
|
||||
};
|
||||
info!("The location of config is {:?}", location);
|
||||
|
||||
detail!(format!("The config file is at {:?}", location));
|
||||
|
||||
load_and_parse_config_file(location);
|
||||
}
|
||||
|
||||
fn get_location_config() -> Result<std::path::PathBuf, &'static str> {
|
||||
info!("Getting location of config file");
|
||||
let config_path = match dirs::config_dir() {
|
||||
Some(mut path) => {
|
||||
path.push("rustscan");
|
||||
path.push("config.toml");
|
||||
path
|
||||
Ok(path)
|
||||
}
|
||||
None => panic!("Couldn't find config dir."),
|
||||
None => Err("Your system does not have APPDIRS"),
|
||||
};
|
||||
|
||||
detail!(format!(
|
||||
"{} {:?}",
|
||||
"The config file is expected to be at", config_path
|
||||
));
|
||||
config_path
|
||||
}
|
||||
|
||||
fn load_and_parse_config_file(config_path: PathBuf) -> ConfigFile {
|
||||
// Gets the file and returns the string of TOML
|
||||
// TODO quiet mode
|
||||
|
||||
let mut file = File::open(&config_path);
|
||||
let mut file: File = match file {
|
||||
Ok(result) => result,
|
||||
Err(_) => download_place_config_file(config_path),
|
||||
};
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).unwrap();
|
||||
let config: ConfigFile = toml::from_str(&contents).unwrap();
|
||||
|
||||
config
|
||||
}
|
||||
// Downloads config file
|
||||
// Places into Appdirs
|
||||
|
||||
fn download_place_config_file(config_location: PathBuf) -> std::fs::File {
|
||||
info!("Placing config file");
|
||||
let body = ureq::get("https://raw.githubusercontent.com/RustScan/RustScan/master/config.toml")
|
||||
.call()
|
||||
.into_string()
|
||||
.unwrap();
|
||||
|
||||
let mut file = File::create(config_location).unwrap();
|
||||
file.write(body.as_bytes()).unwrap();
|
||||
file
|
||||
}
|
||||
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
fn build_nmap_arguments<'a>(
|
||||
addr: &'a str,
|
||||
@@ -374,6 +441,7 @@ mod tests {
|
||||
timeout: 1_000,
|
||||
ulimit: Some(2_000),
|
||||
command: Vec::new(),
|
||||
config: false,
|
||||
accessible: false,
|
||||
scan_order: ScanOrder::Serial,
|
||||
};
|
||||
@@ -393,6 +461,7 @@ mod tests {
|
||||
timeout: 1_000,
|
||||
ulimit: Some(2_000),
|
||||
command: Vec::new(),
|
||||
config: false,
|
||||
accessible: false,
|
||||
scan_order: ScanOrder::Serial,
|
||||
};
|
||||
@@ -413,6 +482,7 @@ mod tests {
|
||||
timeout: 1_000,
|
||||
ulimit: Some(2_000),
|
||||
command: Vec::new(),
|
||||
config: false,
|
||||
accessible: false,
|
||||
scan_order: ScanOrder::Serial,
|
||||
};
|
||||
@@ -432,6 +502,7 @@ mod tests {
|
||||
timeout: 1_000,
|
||||
ulimit: Some(2_000),
|
||||
command: Vec::new(),
|
||||
config: false,
|
||||
accessible: false,
|
||||
scan_order: ScanOrder::Serial,
|
||||
};
|
||||
@@ -456,6 +527,7 @@ mod tests {
|
||||
timeout: 1_000,
|
||||
ulimit: None,
|
||||
command: Vec::new(),
|
||||
config: false,
|
||||
accessible: true,
|
||||
scan_order: ScanOrder::Serial,
|
||||
};
|
||||
@@ -478,6 +550,7 @@ mod tests {
|
||||
command: Vec::new(),
|
||||
accessible: false,
|
||||
scan_order: ScanOrder::Serial,
|
||||
config: false,
|
||||
};
|
||||
let ips = parse_ips(&opts);
|
||||
|
||||
@@ -497,6 +570,7 @@ mod tests {
|
||||
command: Vec::new(),
|
||||
accessible: false,
|
||||
scan_order: ScanOrder::Serial,
|
||||
config: false,
|
||||
};
|
||||
let ips = parse_ips(&opts);
|
||||
|
||||
@@ -516,6 +590,7 @@ mod tests {
|
||||
command: Vec::new(),
|
||||
accessible: false,
|
||||
scan_order: ScanOrder::Serial,
|
||||
config: false,
|
||||
};
|
||||
let ips = parse_ips(&opts);
|
||||
|
||||
|
||||
+31
-24
@@ -1,5 +1,7 @@
|
||||
mod range_iterator;
|
||||
use super::{PortRange, ScanOrder};
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use range_iterator::RangeIterator;
|
||||
|
||||
/// Represents options of port scanning.
|
||||
@@ -15,26 +17,27 @@ pub enum PortStrategy {
|
||||
impl PortStrategy {
|
||||
pub fn pick(range: Option<PortRange>, ports: Option<Vec<u16>>, order: ScanOrder) -> Self {
|
||||
match order {
|
||||
ScanOrder::Serial => match ports.is_none() {
|
||||
true => {
|
||||
let range = range.as_ref().unwrap();
|
||||
PortStrategy::Serial(SerialRange {
|
||||
start: range.start,
|
||||
end: range.end,
|
||||
})
|
||||
}
|
||||
false => PortStrategy::Manual(ports.unwrap()),
|
||||
},
|
||||
ScanOrder::Random => match ports.is_none() {
|
||||
true => {
|
||||
let range = range.as_ref().unwrap();
|
||||
PortStrategy::Random(RandomRange {
|
||||
start: range.start,
|
||||
end: range.end,
|
||||
})
|
||||
}
|
||||
false => PortStrategy::Manual(ports.unwrap()),
|
||||
},
|
||||
ScanOrder::Serial if ports.is_none() => {
|
||||
let range = range.as_ref().unwrap();
|
||||
PortStrategy::Serial(SerialRange {
|
||||
start: range.start,
|
||||
end: range.end,
|
||||
})
|
||||
}
|
||||
ScanOrder::Random if ports.is_none() => {
|
||||
let range = range.as_ref().unwrap();
|
||||
PortStrategy::Random(RandomRange {
|
||||
start: range.start,
|
||||
end: range.end,
|
||||
})
|
||||
}
|
||||
ScanOrder::Serial => PortStrategy::Manual(ports.unwrap()),
|
||||
ScanOrder::Random => {
|
||||
let mut rng = thread_rng();
|
||||
let mut ports = ports.unwrap();
|
||||
ports.shuffle(&mut rng);
|
||||
PortStrategy::Manual(ports)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,9 +124,13 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn random_strategy_with_ports_does_not_randomize_ports() {
|
||||
let strategy = PortStrategy::pick(None, Some(vec![80, 443]), ScanOrder::Random);
|
||||
let result = strategy.order();
|
||||
assert_eq!(vec![80, 443], result);
|
||||
fn random_strategy_with_ports() {
|
||||
let strategy = PortStrategy::pick(None, Some((1..10).collect()), ScanOrder::Random);
|
||||
let mut result = strategy.order();
|
||||
let expected_range = (1..10).into_iter().collect::<Vec<u16>>();
|
||||
assert_ne!(expected_range, result);
|
||||
|
||||
result.sort();
|
||||
assert_eq!(expected_range, result);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user