mirror of
https://github.com/bee-san/RustScan.git
synced 2026-11-07 17:02:04 -10:00
Compare commits
38
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf56da5aaf | ||
|
|
4f36218ffe | ||
|
|
65f7db7a07 | ||
|
|
9645c58760 | ||
|
|
7e8771fc3b | ||
|
|
37ef19f798 | ||
|
|
f57bd6f395 | ||
|
|
661f9f4774 | ||
|
|
8d1075127f | ||
|
|
5e382948b6 | ||
|
|
da325a94ac | ||
|
|
f1741f376c | ||
|
|
756ec0a8a5 | ||
|
|
bfe8e775cf | ||
|
|
9e4f5855aa | ||
|
|
8c9e5b57a3 | ||
|
|
d2ad8ab756 | ||
|
|
6ac61a40ae | ||
|
|
ea2a13b021 | ||
|
|
b8fc25c76b | ||
|
|
9894942b24 | ||
|
|
83d544ca9f | ||
|
|
fd0ea4ddce | ||
|
|
8ce275e240 | ||
|
|
0affe5ec0f | ||
|
|
4d67440865 | ||
|
|
ed3276c3a8 | ||
|
|
2218e00783 | ||
|
|
0b2972460b | ||
|
|
9cc9d02eb7 | ||
|
|
803d9c4508 | ||
|
|
41b3f31cfd | ||
|
|
12d4954815 | ||
|
|
26df0b9877 | ||
|
|
4ec0b73b5c | ||
|
|
15786dea5c | ||
|
|
b633df020f | ||
|
|
c2bb178d6a |
No files matched your search
@@ -36,6 +36,26 @@
|
||||
"ideas",
|
||||
"example"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "bernardoamc",
|
||||
"name": "Bernardo Araujo",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/428984?v=4",
|
||||
"profile": "http://bernardoamc.github.io/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"bug",
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Isona",
|
||||
"name": "Izzy Whistlecroft",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/11759523?v=4",
|
||||
"profile": "https://github.com/Isona",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,32 @@
|
||||
on: [push, pull_request]
|
||||
|
||||
name: Continuous integration
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: check
|
||||
|
||||
test:
|
||||
name: Test Suite
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
+1
-1
@@ -30,7 +30,6 @@ Cargo.lock
|
||||
*.sig
|
||||
|
||||
pkg/
|
||||
src/
|
||||
|
||||
### Rust ###
|
||||
# Generated by Cargo
|
||||
@@ -45,3 +44,4 @@ Cargo.lock
|
||||
**/*.rs.bk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/rust,archlinuxpackages
|
||||
*.deb
|
||||
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at brandon@skerritt.blog. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
+1
-1
@@ -16,10 +16,10 @@ readme="README.md"
|
||||
[dependencies]
|
||||
colored = "1.9.3"
|
||||
clap = "2.33.0"
|
||||
rayon = "1.3.1"
|
||||
async-std = "1.6.2"
|
||||
futures = "0.3"
|
||||
rlimit = "0.3.0"
|
||||
|
||||
[package.metadata.deb]
|
||||
depends = "$auto, nmap"
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# Maintainer: Bee <[email protected]>
|
||||
pkgname=rustscan-bin
|
||||
pkgver=1.1.0
|
||||
pkgrel=1
|
||||
pkgdesc="Faster Nmap Scanning with Rust"
|
||||
url="https://github.com/brandonskerritt/rustscan"
|
||||
license=("MIT")
|
||||
arch=("x86_64")
|
||||
provides=("rustscan")
|
||||
depends=('rustup')
|
||||
|
||||
package() {
|
||||
rustup toolchain install stable && cargo install rustscan
|
||||
}
|
||||
@@ -20,7 +20,8 @@
|
||||
# 🤔 What is this?
|
||||
1. Find ports quickly using Rustscan (**8 seconds at its fastest**).
|
||||
2. Automatically runs `nmap` on those ports.
|
||||
3. Profit???
|
||||
3. ???
|
||||
4. Profit!
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
@@ -90,6 +91,8 @@ The most universal way is to use `cargo`, Rust's built in package manager (think
|
||||
|
||||
If you face any issues at all, please leave a GitHub issue. I have only tested this on Linux, so there may be issues for Mac OS or Windows.
|
||||
|
||||
Note: sometimes Rust doesn't add Cargo to the path. Please see [this issue](https://github.com/rust-lang/rustup/issues/2436) for how to fix that.
|
||||
|
||||
## 🖥️ Debian / Kali
|
||||
|
||||
Download the .deb file from the releases page:
|
||||
@@ -139,12 +142,15 @@ rustscan -h
|
||||
RustScan 1.2.0
|
||||
Bee https://github.com/brandonskerritt
|
||||
Fast Port Scanner built in Rust
|
||||
WARNING Do not use this program against sensitive infrastructure. The specified server may not be able to handle this
|
||||
many socket connections at once.
|
||||
|
||||
USAGE:
|
||||
rustscan [OPTIONS] <ip> [command]...
|
||||
rustscan [FLAGS] [OPTIONS] <ip> [command]...
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-q, --quiet Quiet mode. Only output the ports. No Nmap. Useful for grep or outputting to a file.
|
||||
-V, --version Prints version information
|
||||
|
||||
OPTIONS:
|
||||
@@ -152,6 +158,7 @@ OPTIONS:
|
||||
-b, --batch <b> Increases speed of scanning. The batch size for port scanning. Depends on your open file limit
|
||||
of OS. If you do 65535 it will do every port at the same time. Although, your OS may not
|
||||
support this. [default: 4500]
|
||||
-u, --ulimit <u> Automatically ups the ULIMIT with the value you provided.
|
||||
|
||||
ARGS:
|
||||
<ip> The IP address to scan
|
||||
@@ -263,7 +270,7 @@ Ciphey is an automated decryption tool using artifical intelligence & natural la
|
||||
[Check it out here!](https://github.com/ciphey/ciphey)
|
||||
## Contributors ✨
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
@@ -276,6 +283,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center"><a href="https://skerritt.blog"><img src="https://avatars3.githubusercontent.com/u/10378052?v=4" width="100px;" alt=""/><br /><sub><b>Brandon</b></sub></a><br /><a href="#infra-brandonskerritt" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/brandonskerritt/RustScan/commits?author=brandonskerritt" title="Tests">⚠️</a> <a href="https://github.com/brandonskerritt/RustScan/commits?author=brandonskerritt" title="Code">💻</a> <a href="#design-brandonskerritt" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://sakiir.ovh"><img src="https://avatars1.githubusercontent.com/u/9950578?v=4" width="100px;" alt=""/><br /><sub><b>SakiiR</b></sub></a><br /><a href="https://github.com/brandonskerritt/RustScan/commits?author=SakiiR" title="Code">💻</a> <a href="https://github.com/brandonskerritt/RustScan/issues?q=author%3ASakiiR" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://github.com/smackhack"><img src="https://avatars2.githubusercontent.com/u/48143394?v=4" width="100px;" alt=""/><br /><sub><b>smackhack</b></sub></a><br /><a href="#ideas-smackhack" title="Ideas, Planning, & Feedback">🤔</a> <a href="#example-smackhack" title="Examples">💡</a></td>
|
||||
<td align="center"><a href="http://bernardoamc.github.io/"><img src="https://avatars0.githubusercontent.com/u/428984?v=4" width="100px;" alt=""/><br /><sub><b>Bernardo Araujo</b></sub></a><br /><a href="https://github.com/brandonskerritt/RustScan/commits?author=bernardoamc" title="Code">💻</a> <a href="https://github.com/brandonskerritt/RustScan/issues?q=author%3Abernardoamc" title="Bug reports">🐛</a> <a href="#design-bernardoamc" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/Isona"><img src="https://avatars2.githubusercontent.com/u/11759523?v=4" width="100px;" alt=""/><br /><sub><b>Izzy Whistlecroft</b></sub></a><br /><a href="https://github.com/brandonskerritt/RustScan/issues?q=author%3AIsona" title="Bug reports">🐛</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
+3
-6
@@ -1,9 +1,6 @@
|
||||
This is my first Rust project! As such, I expect there are many, many bugs involved or things that can be sped up.
|
||||
|
||||
In particular, here is my roadmap:
|
||||
* Tokio async
|
||||
* Better UX
|
||||
* Optimised code
|
||||
If you're looking to get involved, we make use of Good First Issues / Help Wanted tags. Click this link to see all the issues we could use help with!
|
||||
[https://github.com/brandonskerritt/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22](https://github.com/brandonskerritt/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
|
||||
|
||||
Please leave issues / pull requests, I'd love to learn more about this amazing language :)
|
||||
Please leave issues / pull requests, I'd love to learn more about this amazing language :)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+38
-123
@@ -1,18 +1,15 @@
|
||||
use async_std::io;
|
||||
use async_std::net::TcpStream;
|
||||
mod scanner;
|
||||
use scanner::Scanner;
|
||||
|
||||
use clap::{App, Arg, AppSettings};
|
||||
use colored::*;
|
||||
use std::process::{exit, Command};
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
net::{SocketAddr, Shutdown},
|
||||
io::ErrorKind, convert::TryInto,
|
||||
};
|
||||
use async_std::prelude::*;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use std::process::{exit, Command};
|
||||
use std::convert::TryInto;
|
||||
use futures::executor::block_on;
|
||||
use rlimit::Resource;
|
||||
use rlimit::{setrlimit, getrlimit};
|
||||
|
||||
/// Faster Nmap scanning with Rust
|
||||
fn main() {
|
||||
let matches = App::new("RustScan")
|
||||
@@ -20,7 +17,7 @@ fn main() {
|
||||
.about("Fast Port Scanner built in Rust\nWARNING Do not use this program against sensitive infrastructure. The specified server may not be able to handle this many socket connections at once.")
|
||||
.version("1.2.0")
|
||||
.setting(AppSettings::TrailingVarArg)
|
||||
|
||||
|
||||
// IP address is a required argument
|
||||
.arg(Arg::with_name("ip")
|
||||
.required(true)
|
||||
@@ -57,14 +54,14 @@ fn main() {
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
|
||||
|
||||
let ip = matches.value_of("ip").unwrap_or("None");
|
||||
let ulimit_arg = matches.value_of("u").unwrap_or("None");
|
||||
let quiet = if matches.is_present("q") { true } else { false };
|
||||
let command_matches= matches.values_of("command");
|
||||
let command_run: String = match command_matches {
|
||||
// We use the user supplied args
|
||||
Some(x) => {
|
||||
Some(_x) => {
|
||||
// TODO x is the same as below, use that instead
|
||||
matches.values_of("command").unwrap().collect::<Vec<_>>().join(" ")
|
||||
}
|
||||
@@ -78,23 +75,30 @@ fn main() {
|
||||
.unwrap_or("None")
|
||||
.parse::<u64>()
|
||||
.unwrap();
|
||||
|
||||
|
||||
if !quiet {
|
||||
print_opening();
|
||||
}
|
||||
|
||||
|
||||
// checks ulimit
|
||||
|
||||
|
||||
// change ulimit size
|
||||
if !(ulimit_arg == "None") {
|
||||
let limit = ulimit_arg.parse::<u64>().unwrap();
|
||||
if !quiet{
|
||||
println!("Automatically upping ulimit to {}", ulimit_arg);
|
||||
}
|
||||
setrlimit(Resource::NOFILE, limit, limit);
|
||||
let uresult = setrlimit(Resource::NOFILE, limit, limit);
|
||||
|
||||
match uresult {
|
||||
Ok(_) => {}
|
||||
Err(_) => {println!("ERROR. Failed to set Ulimit.")}
|
||||
}
|
||||
}
|
||||
|
||||
let (x, _) = getrlimit(Resource::NOFILE).unwrap();
|
||||
|
||||
|
||||
let (x, _) = getrlimit(Resource::NOFILE).unwrap();
|
||||
|
||||
// if maximum limit is lower than batch size
|
||||
// automatically re-adjust the batch size
|
||||
@@ -106,7 +110,7 @@ fn main() {
|
||||
// if the OS supports high file limits like 8000
|
||||
// but the user selected a batch size higher than this
|
||||
// reduce to a lower number
|
||||
// basically, ubuntu is 8000
|
||||
// basically, ubuntu is 8000
|
||||
// but i can only get it to work on < 5k in testing
|
||||
// 5k is default, so 3000 seems safe
|
||||
if x > 8000{
|
||||
@@ -130,7 +134,6 @@ fn main() {
|
||||
}
|
||||
// the user has asked to automatically up the ulimit
|
||||
|
||||
|
||||
// gets timeout
|
||||
let duration_timeout =
|
||||
matches
|
||||
@@ -139,26 +142,17 @@ fn main() {
|
||||
.parse::<u64>()
|
||||
.unwrap();
|
||||
|
||||
|
||||
|
||||
// 65535 + 1 because of 0 indexing
|
||||
let test = run_batched(ip.to_string(), 1, 65536, Duration::from_millis(duration_timeout,), batch_size.try_into().unwrap(), quiet);
|
||||
let reports_fullsult = block_on(test);
|
||||
|
||||
let scanner = Scanner::new(ip, 1, 65536, batch_size.try_into().unwrap(), Duration::from_millis(duration_timeout), quiet);
|
||||
let scan_result = block_on(scanner.run());
|
||||
|
||||
// prints ports and places them into nmap string
|
||||
let mut nmap_str_ports: Vec<String> = Vec::new();
|
||||
let nmap_str_ports: Vec<String> = scan_result.into_iter().map(|port| port.to_string()).collect();
|
||||
|
||||
// makes vector of open ports
|
||||
for i in reports_fullsult.iter() {
|
||||
// appends it to port
|
||||
nmap_str_ports.push(i.to_string());
|
||||
}
|
||||
|
||||
// if no ports are found, suggest running with less
|
||||
// if no ports are found, suggest running with less
|
||||
if nmap_str_ports.is_empty() {
|
||||
panic!("{} Looks like I didn't find any open ports. This is usually caused by a high batch size.
|
||||
\n*I used {} threads, consider lowering to {} with {} or a comfortable number lfor your system.
|
||||
\n*I used {} threads, consider lowering to {} with {} or a comfortable number lfor your system.
|
||||
\n Alternatively, increase the timeout if your ping is high. Rustscan -T 2000 for 2000 second timeout.", "ERROR".red(), batch_size, (batch_size / 2).to_string().green(), "'rustscan -b <batch_size> <ip address>'".green());
|
||||
}
|
||||
|
||||
@@ -170,7 +164,6 @@ fn main() {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// nmap port style is 80,443. Comma seperated with no spaces.
|
||||
let ports_str = nmap_str_ports.join(",");
|
||||
|
||||
@@ -180,106 +173,28 @@ fn main() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let string_format = format!("{} {} {} {} {}", command_run, "-vvv", "-p", &ports_str, ip);
|
||||
let string_format = format!("{} {} {} {} {} {}", command_run, "-Pn", "-vvv", "-p", &ports_str, ip);
|
||||
if !quiet{
|
||||
println!("The Nmap command to be run is {}", string_format);
|
||||
}
|
||||
let command_list = string_format.split_whitespace();
|
||||
let vec = command_list.collect::<Vec<&str>>();
|
||||
|
||||
// Runs the nmap command and spawns it as a process.
|
||||
Command::new("nmap")
|
||||
let mut child = Command::new("nmap")
|
||||
.args(&vec)
|
||||
.spawn()
|
||||
.expect("failed to execute process");
|
||||
}
|
||||
.expect("failed to execute nmap process");
|
||||
|
||||
pub async fn run_batched(
|
||||
host: String,
|
||||
port_start: u32,
|
||||
port_end: u32,
|
||||
timeout: Duration,
|
||||
batch: u32,
|
||||
quiet: bool,
|
||||
) -> Vec<u32> {
|
||||
// run the scans in batches
|
||||
let mut begin = port_start;
|
||||
let mut end = begin + batch;
|
||||
let mut all_addrs: std::vec::Vec<u32> = Vec::new();
|
||||
|
||||
while end <= port_end {
|
||||
let mut batch_addrs = execute(host.clone(), begin, end, timeout, quiet).await;
|
||||
all_addrs.append(&mut batch_addrs);
|
||||
begin = end+1;
|
||||
end += batch;
|
||||
}
|
||||
all_addrs
|
||||
}
|
||||
async fn execute(
|
||||
host: String,
|
||||
port_start: u32,
|
||||
port_end: u32,
|
||||
timeout: Duration,
|
||||
quiet: bool,
|
||||
) -> Vec<u32> {
|
||||
// runs a scan against a range of ports
|
||||
let mut ftrs = FuturesUnordered::new();
|
||||
// TODO can I make this async?
|
||||
for port in port_start..port_end {
|
||||
ftrs.push(try_connect(host.clone(), port, timeout, quiet));
|
||||
}
|
||||
|
||||
let mut open_addrs: Vec<u32> = Vec::new();
|
||||
// TODO can I make this async?
|
||||
while let Some(result) = ftrs.next().await {
|
||||
match result {
|
||||
Ok(addr) => open_addrs.push(addr),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
open_addrs
|
||||
}
|
||||
|
||||
async fn try_connect(host: String, port: u32, timeout: Duration, quiet: bool) -> io::Result<u32> {
|
||||
let addr = host.to_string() + ":" + &port.to_string();
|
||||
match addr.parse() {
|
||||
Ok(sock_addr) => match connect(sock_addr, timeout).await {
|
||||
Ok(stream_result) => {
|
||||
match stream_result.shutdown(Shutdown::Both) {
|
||||
_ => {}
|
||||
}
|
||||
if !quiet {
|
||||
println!("Open {}", port.to_string().purple());
|
||||
}
|
||||
|
||||
Ok(port)
|
||||
}
|
||||
Err(e) => match e.kind() {
|
||||
ErrorKind::Other => {
|
||||
eprintln!("{:?}", e); // in case we get too many open files
|
||||
panic!("Too many open files. Please reduce batch size. The default is 5000. Try -b 2500.");
|
||||
Err(e)
|
||||
}
|
||||
_ => Err(io::Error::new(io::ErrorKind::Other, e.to_string())),
|
||||
},
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Unable to convert to socket address {:?}", e);
|
||||
panic!("Unable to convert to socket address");
|
||||
Err(io::Error::new(io::ErrorKind::Other, e.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn connect(addr: SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
||||
let stream = io::timeout(timeout, async move { TcpStream::connect(addr).await }).await?;
|
||||
Ok(stream)
|
||||
child.wait().expect("failed to wait on nmap process");
|
||||
}
|
||||
|
||||
fn print_opening() {
|
||||
let s = "
|
||||
_____ _ _____
|
||||
| __ \\ | | / ____|
|
||||
| |__) | _ ___| |_| (___ ___ __ _ _ __
|
||||
| _ / | | / __| __|\\___ \\ / __/ _` | '_ \\
|
||||
_____ _ _____
|
||||
| __ \\ | | / ____|
|
||||
| |__) | _ ___| |_| (___ ___ __ _ _ __
|
||||
| _ / | | / __| __|\\___ \\ / __/ _` | '_ \\
|
||||
| | \\ \\ |_| \\__ \\ |_ ____) | (_| (_| | | | |
|
||||
|_| \\_\\__,_|___/\\__|_____/ \\___\\__,_|_| |_|
|
||||
Faster nmap scanning with rust.";
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
use async_std::io;
|
||||
use async_std::net::TcpStream;
|
||||
use colored::*;
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
net::{SocketAddr, Shutdown},
|
||||
io::ErrorKind,
|
||||
};
|
||||
use async_std::prelude::*;
|
||||
use futures::stream::FuturesUnordered;
|
||||
|
||||
pub struct Scanner {
|
||||
host: String,
|
||||
start: u64,
|
||||
end: u64,
|
||||
batch_size: u64,
|
||||
timeout: Duration,
|
||||
quiet: bool,
|
||||
}
|
||||
|
||||
impl Scanner {
|
||||
pub fn new(host: &str, start: u64, end: u64, batch_size: u64, timeout: Duration, quiet: bool) -> Self {
|
||||
Self {
|
||||
host: host.to_owned(),
|
||||
start,
|
||||
end,
|
||||
batch_size,
|
||||
timeout,
|
||||
quiet
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&self) -> Vec<u64> {
|
||||
let ports: Vec<u64> = (self.start..self.end).collect();
|
||||
let mut open_ports: std::vec::Vec<u64> = Vec::new();
|
||||
|
||||
for range in ports.chunks(self.batch_size as usize) {
|
||||
let mut ports = self.scan_range(range).await;
|
||||
open_ports.append(&mut ports);
|
||||
}
|
||||
|
||||
open_ports
|
||||
}
|
||||
|
||||
async fn scan_range(&self, range: &[u64]) -> Vec<u64> {
|
||||
let mut ftrs = FuturesUnordered::new();
|
||||
|
||||
for port in range {
|
||||
ftrs.push(self.scan_port(port));
|
||||
}
|
||||
|
||||
let mut open_ports: Vec<u64> = Vec::new();
|
||||
while let Some(result) = ftrs.next().await {
|
||||
match result {
|
||||
Ok(port) => open_ports.push(port),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
open_ports
|
||||
}
|
||||
|
||||
async fn scan_port(&self, port: &u64) -> io::Result<u64> {
|
||||
let addr = format!("{}:{}", self.host , port);
|
||||
|
||||
match addr.parse() {
|
||||
Ok(sock_addr) => match self.connect(sock_addr).await {
|
||||
Ok(stream_result) => {
|
||||
match stream_result.shutdown(Shutdown::Both) {
|
||||
_ => {}
|
||||
}
|
||||
if !self.quiet {
|
||||
println!("Open {}", port.to_string().purple());
|
||||
}
|
||||
|
||||
Ok(*port)
|
||||
}
|
||||
Err(e) => match e.kind() {
|
||||
ErrorKind::Other => {
|
||||
eprintln!("{:?}", e); // in case we get too many open files
|
||||
panic!("Too many open files. Please reduce batch size. The default is 5000. Try -b 2500.");
|
||||
}
|
||||
_ => Err(io::Error::new(io::ErrorKind::Other, e.to_string())),
|
||||
},
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Unable to convert to socket address {:?}", e);
|
||||
panic!("Unable to convert to socket address");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn connect(&self, addr: SocketAddr) -> io::Result<TcpStream> {
|
||||
let stream = io::timeout(self.timeout, async move { TcpStream::connect(addr).await }).await?;
|
||||
Ok(stream)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user