Compare commits

...
Author SHA1 Message Date
Brandon b64aa19d61 Added more boundary tests for scanners mod.rs 2020-10-03 02:36:25 +01:00
Brandon 81ad00dc29 1.10.0 release 2020-09-29 00:29:58 +01:00
Bee 64cac6e0fa Added DNS lookup using Google DNS, refactored IP code (#246)
* Added DNS lookup using Google DNS, refactored IP code

* fixed comments & cargo fmt

* Fixed code review comments, added tests, removed unwrap() panics

* Added assertion to test
2020-09-28 21:19:55 +01:00
dependabot-preview[bot] 739e9716fc Bump structopt from 0.3.17 to 0.3.18 (#243)
Bumps [structopt](https://github.com/TeXitoi/structopt) from 0.3.17 to 0.3.18.
- [Release notes](https://github.com/TeXitoi/structopt/releases)
- [Changelog](https://github.com/TeXitoi/structopt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TeXitoi/structopt/compare/v0.3.17...v0.3.18)

Signed-off-by: dependabot-preview[bot] <[email protected]>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-24 13:38:47 +01:00
7 changed files with 843 additions and 41 deletions

No files matched your search

Generated
+695 -14
View File
File diff suppressed because it is too large. Load diff
+8 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "rustscan"
version = "1.9.0"
version = "1.10.0"
authors = ["Bee <[email protected]>"]
edition = "2018"
description = "Faster Nmap Scanning with Rust"
@@ -18,7 +18,7 @@ exclude = [
[dependencies]
colored = "2.0.0"
structopt = "0.3.17"
structopt = "0.3.18"
async-std = "1.6.4"
futures = "0.3"
rlimit = "0.4.0"
@@ -35,6 +35,8 @@ serde = "1.0.116"
serde_derive = "1.0.116"
cidr-utils = "0.5.0"
itertools = "0.9.0"
trust-dns-resolver = { version = "0.19.5"}
criterion = "0.3"
[package.metadata.deb]
depends = "$auto, nmap"
@@ -43,3 +45,7 @@ section = "rust"
[profile.release]
lto = true
panic = 'abort'
[[bench]]
name = "main"
harness = false
+9
View File
@@ -0,0 +1,9 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rustscan::*;
pub fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
+6
View File
@@ -0,0 +1,6 @@
127.0.0.1
google.com
example.com
66666666666666.666666666666666666.66666666666666666.6666666666
....
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.radiatorFixtures
+80 -24
View File
@@ -26,8 +26,9 @@ use std::io::prelude::*;
use std::io::BufReader;
use std::net::ToSocketAddrs;
use std::process::Command;
use std::str::FromStr;
use std::{net::IpAddr, time::Duration};
use trust_dns_resolver::config::*;
use trust_dns_resolver::Resolver;
extern crate colorful;
extern crate dirs;
@@ -208,9 +209,54 @@ fn build_nmap_arguments<'a>(
arguments
}
/// Goes through all possible IP inputs (files or via argparsing)
/// Parses the string(s) into IPs
fn parse_addresses(opts: &Opts) -> Vec<IpAddr> {
let mut ips: Vec<IpAddr> = Vec::new();
let resolver = &Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
for ip_or_host in &opts.addresses {
match read_ips_from_file(ip_or_host.to_owned(), &resolver) {
Ok(x) => ips.extend(x),
_ => match parse_to_ip(ip_or_host.to_owned(), &resolver) {
Ok(x) => ips.extend(x),
_ => {
warning!(
format!("Host {:?} could not be resolved.", ip_or_host),
opts.greppable,
opts.accessible
);
}
},
}
}
ips
}
/// Uses DNS to get the IPS assiocated with host
fn resolve_ips_from_host(
source: &String,
resolver: &Resolver,
) -> Result<Vec<IpAddr>, std::io::Error> {
let mut ips: Vec<std::net::IpAddr> = Vec::new();
match resolver.lookup_ip(&source) {
Ok(x) => {
for ip in x.iter() {
ips.push(ip);
}
}
_ => (),
};
return Ok(ips);
}
#[cfg(not(tarpaulin_include))]
/// Parses an input file of IPs and uses those
fn read_ips_from_file(ips: String) -> Result<Vec<std::net::IpAddr>, std::io::Error> {
fn read_ips_from_file(
ips: String,
resolver: &Resolver,
) -> Result<Vec<std::net::IpAddr>, std::io::Error> {
// if we cannot open it as a file, it is not a file so move on
let file = File::open(ips)?;
let reader = BufReader::new(file);
@@ -218,37 +264,39 @@ fn read_ips_from_file(ips: String) -> Result<Vec<std::net::IpAddr>, std::io::Err
let mut ips: Vec<std::net::IpAddr> = Vec::new();
for str_ip in reader.lines() {
match IpAddr::from_str(&str_ip.unwrap()) {
Ok(x) => ips.push(x),
Err(y) => panic!("File does not contain valid IP address. Error at {}", y),
match str_ip {
Ok(x) => match parse_to_ip(x, resolver) {
Ok(result) => ips.extend(result),
Err(e) => {
debug!("{} is not a valid IP or host", e);
}
},
Err(_) => {
debug!("Line in file is not valid");
}
}
}
Ok(ips)
}
fn parse_addresses(opts: &Opts) -> Vec<IpAddr> {
/// Given a string, parse it as an host, IP address, or CIDR.
/// This allows us to pass files as hosts or cidr or IPs easily
/// Call this everytime you have a possible IP_or_host
fn parse_to_ip(address: String, resolver: &Resolver) -> Result<Vec<IpAddr>, std::io::Error> {
let mut ips: Vec<IpAddr> = Vec::new();
for ip_or_host in &opts.addresses {
match IpCidr::from_str(ip_or_host) {
Ok(cidr) => cidr.iter().for_each(|ip| ips.push(ip)),
_ => match format!("{}:{}", &ip_or_host, 80).to_socket_addrs() {
Ok(mut iter) => ips.push(iter.nth(0).unwrap().ip()),
_ => match read_ips_from_file(ip_or_host.to_owned()) {
Ok(x) => ips.extend(x),
_ => {
warning!(
format!("Host {:?} could not be resolved.", ip_or_host),
opts.greppable,
opts.accessible
);
}
},
match IpCidr::from_str(&address) {
Ok(cidr) => cidr.iter().for_each(|ip| ips.push(ip)),
_ => match format!("{}:{}", &address, 80).to_socket_addrs() {
Ok(mut iter) => ips.push(iter.nth(0).unwrap().ip()),
_ => match resolve_ips_from_host(&address, resolver) {
Ok(hosts) => ips.extend(hosts),
_ => (),
},
}
}
},
};
ips
Ok(ips)
}
fn adjust_ulimit_size(opts: &Opts) -> rlimit::rlim {
@@ -419,4 +467,12 @@ mod tests {
assert_eq!(ips.is_empty(), true);
}
#[test]
fn parse_hosts_file_and_incorrect_hosts() {
// Host file contains IP, Hosts, incorrect IPs, incorrect hosts
let mut opts = Opts::default();
opts.addresses = vec!["fixtures/hosts.txt".to_owned()];
let ips = parse_addresses(&opts);
assert_eq!(ips.len(), 3);
}
}
+45
View File
@@ -232,4 +232,49 @@ mod tests {
block_on(scanner.run());
assert_eq!(1, 1);
}
#[test]
fn scanner_runs_serial() {
let addrs = vec!["8.8.8.8".parse::<IpAddr>().unwrap()];
let range = PortRange {
start: 400,
end: 600,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Serial);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
assert_eq!(1, 1);
}
#[test]
fn scanner_doesnt_run_no_range() {
let addrs = vec!["8.8.8.8".parse::<IpAddr>().unwrap()];
let range = PortRange { start: 0, end: 0 };
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Serial);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
assert_eq!(1, 1);
}
#[test]
fn scanner_doesnt_run_high_range() {
let addrs = vec!["127.0.0.1".parse::<IpAddr>().unwrap()];
let range = PortRange {
start: 1,
end: 65535,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Serial);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
assert_eq!(1, 1);
}
#[test]
fn scanner_doesnt_run_backwards_range() {
let addrs = vec!["127.0.0.1".parse::<IpAddr>().unwrap()];
let range = PortRange { start: 10, end: 1 };
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Serial);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
assert_eq!(1, 1);
}
}