Compare commits

...
Author SHA1 Message Date
Brandon f1078304ae Merge branch 'master' into bee-add-config-file 2020-08-24 17:12:59 +01:00
Brandon 22cbfc5826 Merge pull request #159 from RustScan/bee-add-nmap-ports
updated config file to feature nmap top 1k ports
2020-08-24 16:49:13 +01:00
Brandon c5091728a0 Added config file functionality 2020-08-24 16:43:11 +01:00
Brandon a9d729300c Merge branch 'master' into bee-add-nmap-ports 2020-08-24 13:49:10 +01:00
Brandon 4f5dd20e85 Merge pull request #162 from RustScan/ba-reduce-binary-size
Reduce binary size from 2.4MB to 1.9MB
2020-08-24 12:48:45 +01:00
Bernardo Chaves 499ff66f36 Reduce binary size from 2.4MB to 1.9MB
By default, Cargo instructs compilation units to be compiled and optimized
in isolation. LTO instructs the linker to optimize at the link stage.
This can, for example, remove dead code and often times reduces binary size.

By default, when Rust code encounters a situation when it must call panic!(),
it unwinds the stack and produces a helpful backtrace. The unwinding code,
however, does require extra binary size. rustc can be instructed to abort
immediately rather than unwind, which removes the need for this extra unwinding code.

For more information see: https://github.com/johnthagen/min-sized-rust
2020-08-23 18:10:53 -04:00
Brandon 61b87243d9 Merge pull request #161 from RustScan/ba-refactor-port-strategy
Allow randomized order for manual ports
2020-08-22 22:27:37 +01:00
Bernardo Chaves e069991c8d Allow randomized order for manual ports
Before this change we would always scan manually specified ports in
sequential way, this is not the case anymore. This is an important
change since we are planning to introduce a config file with the top 1K
ports and we would like to scan those in a randomized way.
2020-08-21 13:09:41 -04:00
Brandon 85c1cbf445 Merge pull request #160 from RustScan/bee-remove-A
removed -A from nmap
2020-08-20 22:58:39 +01:00
Brandon 5551e64166 updated AUR package in readme 2020-08-20 00:40:41 +01:00
Brandon e0aa1423ad removed -A from nmap 2020-08-20 00:32:37 +01:00
Brandon e609b3617c updated config file to feature nmap top 1k ports 2020-08-20 00:05:45 +01:00
Brandon d0d8380296 Merge pull request #158 from RustScan/ba-add-port-and-range-options
Add --port and --range options
2020-08-19 16:26:39 +01:00
Brandon d66ad34f8c Merge branch 'master' into ba-add-port-and-range-options 2020-08-19 16:02:49 +01:00
Brandon 2670ec43df Merge pull request #156 from spenserblack/exclude-files
Exclude files
2020-08-19 00:05:59 +01:00
Bernardo Chaves 90d0b03ba7 Add --port and --range options
These options are mutually exclusive, this means that when a user
selects manual ports we will ignore ranges and vice-versa.

Manually specifying ports won't allow scan randomization for now.
2020-08-17 20:43:44 -04:00
Spenser Black 57eb3627b3 Use absolute image URLs instead of relative 2020-08-17 10:03:04 -04:00
Spenser Black 7e675b7557 Reduce crate size 2020-08-17 09:30:07 -04:00
Bernardo Araujo fdeaa05f23 Merge pull request #152 from RustScan/ba-add-host-resolution
Add host resolution
2020-08-16 18:35:40 -04:00
Bernardo Araujo 9fbf39f0cc Merge branch 'master' into ba-add-host-resolution 2020-08-16 18:11:27 -04:00
Ben (CMNatic) 14b6ea928d Merge pull request #155 from CMNatic/master
Updated README to use the rustscan dockerhub alpine image
2020-08-16 22:39:10 +01:00
Ben (CMNatic) 9452b1f922 Update README to add a disclaimer about the DockerHub Images
+ Instruct user to use the `alpine` image as it's considered the latest major release as per the release page

+ Formatting instructions
2020-08-16 22:37:51 +01:00
Ben (CMNatic) ed12888e81 Updated README to use the rustscan dockerhub alpine image
+ Added another step to clarify process for Docker as the build will fail if the user is not in the downloaded repo

+ DockerHub has CI with master branch and two images tags `latest` and `alpine` where `alpine` is tagged on feature releases (currently 1.7.1)
2020-08-16 22:28:57 +01:00
Bernardo Chaves f68abcb955 Add host resolution
For now if we can establish a socket on port 80 we can infer the IP of the
host. This might change in the future if we start considering other
ports like 443.
2020-08-16 11:52:11 -04:00
Brandon 4c91e8fb40 Merge pull request #153 from andy5995/docs
docs: fix typo in README.md, link to GitHub flow in contributing doc
2020-08-15 11:08:03 +01:00
andy5995 1d3e831066 docs: fix typo in README.md, link to GitHub flow in contributing doc 2020-08-15 02:05:20 -05:00
dependabot-preview[bot] ff6b1c40db Merge pull request #151 from RustScan/dependabot/cargo/async-std-1.6.3 2020-08-15 00:58:44 +00:00
dependabot-preview[bot] 5573d91a7b Bump async-std from 1.6.2 to 1.6.3
Bumps [async-std](https://github.com/async-rs/async-std) from 1.6.2 to 1.6.3.
- [Release notes](https://github.com/async-rs/async-std/releases)
- [Changelog](https://github.com/async-rs/async-std/blob/master/CHANGELOG.md)
- [Commits](https://github.com/async-rs/async-std/commits/v1.6.3)

Signed-off-by: dependabot-preview[bot] <[email protected]>
2020-08-14 08:38:10 +00:00
Brandon a8e56eec4b Merge pull request #149 from RustScan/all-contributors/add-cmnatic
docs: add cmnatic as a contributor
2020-08-13 22:56:14 +01:00
Brandon fb75c9d332 Merge branch 'master' into all-contributors/add-cmnatic 2020-08-13 22:43:56 +01:00
Ben (CMNatic) 581ec27cb5 Merge pull request #148 from CMNatic/master
Updated README to include instructions on building the new Dockerfile
2020-08-13 20:25:05 +01:00
allcontributors[bot] 9673c8807d docs: update .all-contributorsrc [skip ci] 2020-08-13 19:24:12 +00:00
allcontributors[bot] 78818d6bc7 docs: update README.md [skip ci] 2020-08-13 19:24:11 +00:00
Ben (CMNatic) d0ff597be6 Updated README to include instructions on building the new Dockerfile 2020-08-13 20:11:58 +01:00
Ben (CMNatic) 516ebe367a Merge pull request #118 from Hydragyrum/feature/create-alpine-based-dockerfile
Feature/create alpine based dockerfile
2020-08-13 19:41:52 +01:00
Ben (CMNatic) 1e9660e4ff Merge branch 'master' into feature/create-alpine-based-dockerfile 2020-08-13 19:32:13 +01:00
Brandon 7b4dda5a19 Merge pull request #147 from RustScan/dependabot/cargo/rlimit-0.4.0
Bump rlimit from 0.3.0 to 0.4.0
2020-08-13 11:40:23 +01:00
dependabot-preview[bot] a20b71191d Bump rlimit from 0.3.0 to 0.4.0
Bumps [rlimit](https://github.com/Nugine/rlimit) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/Nugine/rlimit/releases)
- [Commits](https://github.com/Nugine/rlimit/compare/v0.3.0...v0.4.0)

Signed-off-by: dependabot-preview[bot] <[email protected]>
2020-08-13 08:36:23 +00:00
Brandon 18c5dd69e5 Merge pull request #145 from RustScan/all-contributors/add-TGotwig
docs: add TGotwig as a contributor
2020-08-11 19:45:15 +01:00
Brandon 090264ac26 Merge branch 'master' into all-contributors/add-TGotwig 2020-08-11 19:32:11 +01:00
Bernardo Araujo 702681606f Merge pull request #146 from RustScan/bee-fix-spelling
fixed spelling mistake
2020-08-10 20:59:20 -04:00
Brandon c58ac613c9 fixed spelling mistake 2020-08-11 01:47:25 +01:00
allcontributors[bot] 59bb72426d docs: update .all-contributorsrc [skip ci] 2020-08-10 19:57:32 +00:00
allcontributors[bot] f48590c238 docs: update README.md [skip ci] 2020-08-10 19:57:31 +00:00
Adam Bertrand 8b363571f1 Merge branch 'master' into feature/create-alpine-based-dockerfile 2020-08-05 21:52:34 +02:00
Hydragyrum 0fa11f6e51 Add a non-privileged user to run rustscan 2020-08-05 18:53:06 +02:00
Adam Bertrand d423f34e7a Merge branch 'master' into feature/create-alpine-based-dockerfile 2020-08-05 18:25:54 +02:00
Hydragyrum e17f9d0bb1 Add newline to dockerfile 2020-08-04 23:18:12 +02:00
Hydragyrum 3329428766 Create a basic Alpine-Based Dockerfile 2020-08-04 23:17:30 +02:00
14 changed files with 1593 additions and 110 deletions

No files matched your search

+20
View File
@@ -86,6 +86,15 @@
"code"
]
},
{
"login": "TGotwig",
"name": "Thomas Gotwig",
"avatar_url": "https://avatars0.githubusercontent.com/u/30773779?v=4",
"profile": "https://tgotwig.me",
"contributions": [
"platform"
]
},
{
"login": "remigourdon",
"name": "Rémi Gourdon",
@@ -95,6 +104,17 @@
"doc",
"code"
]
},
{
"login": "cmnatic",
"name": "Ben (CMNatic)",
"avatar_url": "https://avatars3.githubusercontent.com/u/4163116?v=4",
"profile": "https://cmnatic.co.uk",
"contributions": [
"code",
"doc",
"design"
]
}
],
"contributorsPerLine": 7,
Generated
+106 -31
View File
@@ -51,16 +51,63 @@ dependencies = [
]
[[package]]
name = "async-std"
version = "1.6.2"
name = "async-executor"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00d68a33ebc8b57800847d00787307f84a562224a14db069b0acefe4c2abbf5d"
checksum = "90f47c78ea98277cb1f5e6f60ba4fc762f5eafe9f6511bc2f7dfd8b75c225650"
dependencies = [
"async-io",
"futures-lite",
"multitask",
"parking 1.0.6",
"scoped-tls",
"waker-fn",
]
[[package]]
name = "async-io"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae22a338d28c75b53702b66f77979062cb29675db376d99e451af4fa79dedb3"
dependencies = [
"cfg-if",
"concurrent-queue",
"futures-lite",
"libc",
"once_cell",
"parking 2.0.0",
"polling",
"socket2",
"vec-arena",
"wepoll-sys-stjepang",
"winapi",
]
[[package]]
name = "async-mutex"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20e85981fc34e84cdff3fc2c9219189752633fdc538a06df8b5ac45b68a4f3a9"
dependencies = [
"event-listener",
]
[[package]]
name = "async-std"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c8da367da62b8ff2313c406c9ac091c1b31d67a165becdd2de380d846260f7"
dependencies = [
"async-executor",
"async-io",
"async-mutex",
"async-task",
"blocking",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
"futures-lite",
"kv-log-macro",
"log",
"memchr",
@@ -69,7 +116,6 @@ dependencies = [
"pin-project-lite",
"pin-utils",
"slab",
"smol",
"wasm-bindgen-futures",
]
@@ -127,15 +173,14 @@ dependencies = [
[[package]]
name = "blocking"
version = "0.4.7"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2468ff7bf85066b4a3678fede6fe66db31846d753ff0adfbfab2c6a6e81612b"
checksum = "76e94bf99b692f54c9d05f97454d3faf11134523fe5b180564a3fb6ed63bcc0a"
dependencies = [
"async-channel",
"atomic-waker",
"futures-lite",
"once_cell",
"parking",
"waker-fn",
]
@@ -324,7 +369,7 @@ dependencies = [
"futures-core",
"futures-io",
"memchr",
"parking",
"parking 1.0.6",
"pin-project-lite",
"waker-fn",
]
@@ -465,6 +510,17 @@ version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "multitask"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c09c35271e7dcdb5f709779111f2c8e8ab8e06c1b587c1c6a9e179d865aaa5b4"
dependencies = [
"async-task",
"concurrent-queue",
"fastrand",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
@@ -487,6 +543,12 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb300f271742d4a2a66c01b6b2fa0c83dfebd2e0bf11addb879a3547b4ed87c"
[[package]]
name = "parking"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
[[package]]
name = "pin-project"
version = "0.4.23"
@@ -519,6 +581,18 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "polling"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d83023eb990619815bb41b45625b02da62b00d0f24b0a08aae37697b3f6c94"
dependencies = [
"cfg-if",
"libc",
"wepoll-sys-stjepang",
"winapi",
]
[[package]]
name = "ppv-lite86"
version = "0.2.8"
@@ -663,9 +737,9 @@ checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "rlimit"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d26e65e82a1e2628c5f209ec12f4508fa50e644bd2f264138e60129d61eae8"
checksum = "49b02d62c38353a6fce45c25ca19783e25dd5f495ca681c674a4ee15aa4c1536"
dependencies = [
"cfg-if",
"libc",
@@ -700,6 +774,7 @@ dependencies = [
"rlimit",
"shell-words",
"structopt",
"toml",
]
[[package]]
@@ -708,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"
@@ -720,27 +801,6 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smol"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "620cbb3c6e34da57d3a248cda0cd01cd5848164dc062e764e65d06fe3ea7aed5"
dependencies = [
"async-task",
"blocking",
"concurrent-queue",
"fastrand",
"futures-io",
"futures-util",
"libc",
"once_cell",
"scoped-tls",
"slab",
"socket2",
"wepoll-sys-stjepang",
"winapi",
]
[[package]]
name = "socket2"
version = "0.3.12"
@@ -821,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"
@@ -839,6 +908,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vec-arena"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17dfb54bf57c9043f4616cb03dab30eff012cc26631b797d8354b916708db919"
[[package]]
name = "vec_map"
version = "0.8.2"
+15 -4
View File
@@ -10,24 +10,35 @@ license = "MIT"
keywords = ["port", "scanning", "nmap"]
categories = ["command-line-utilities"]
readme="README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
exclude = [
".github/*",
"pictures/*",
"rustscan-debbuilder/*",
]
[dependencies]
colored = "2.0.0"
structopt = "0.3.16"
async-std = "1.6.2"
async-std = "1.6.3"
futures = "0.3"
rlimit = "0.3.0"
rlimit = "0.4.0"
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'
+22
View File
@@ -0,0 +1,22 @@
FROM rust:alpine as builder
RUN apk update && \
apk add build-base && \
rm -rf /var/cache/apk/*
WORKDIR /usr/src/rustscan
COPY . .
RUN cargo install --path .
FROM alpine
LABEL author="Hydragyrum <https://github.com/Hydragyrum>"
RUN ulimit -n 100000 && \
apk update && \
apk add \
nmap nmap-scripts wget \
&& \
rm -rf /var/cache/apk/*
COPY --from=builder /usr/local/cargo/bin/rustscan /usr/local/bin/rustscan
RUN addgroup -S rustscan && \
adduser -S -G rustscan rustscan
USER rustscan
ENTRYPOINT ["/usr/local/bin/rustscan"]
+67 -21
View File
@@ -5,13 +5,13 @@
<a href="https://github.com/RustScan/RustScan#-usage">Usage Guide</a>
⬅️
<br>
<img src="pictures/rustscan.png">
<img src="https://github.com/RustScan/RustScan/blob/master/pictures/rustscan.png?raw=true">
</p>
<p align="center">
<u><b> Turns a 17 minutes Nmap scan into 19 seconds. </b></u><br> Find all open ports <b>fast</b> with RustScan, automatically pipe them into Nmap.
</p>
<p align="center">
<img alt="AUR version" src="https://img.shields.io/aur/version/rustscan-bin">
<img alt="AUR version" src="https://img.shields.io/aur/version/rustscan">
<img src="https://img.shields.io/badge/Built%20with-Rust-Purple">
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/w/brandonskerritt/rustscan">
<img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/rustscan/rustscan/total?label=GitHub%20Downloads">
@@ -23,8 +23,8 @@
| <p align="center"><a href="https://hub.docker.com/r/cmnatic/rustscan">🐋 Docker (Recommended) </a></p> | <p align="center"><a href="https://github.com/RustScan/RustScan/releases">👩‍💻 Kali / Debian </p> | <p align="center"><a href="https://aur.archlinux.org/packages/rustscan/">🏗️ Arch </a></p> | <p align="center"><a href="https://crates.io/crates/rustscan">🔧 Cargo (Universal) </a></p> |
| ---- | ---- | ---- | --- |
| <p align="center"><img src="pictures/docker.png" /></p> | <p align="center"><img src="pictures/kali.png" /></p> | <p align="center"><img src="pictures/arch.png" /></p> | <p align="center"><img src="pictures/rust.png" /></p>
| `docker pull cmnatic/rustscan:debian-buster` <p>[Usage](https://github.com/RustScan/RustScan#docker-whale) | [Read the install guide](https://github.com/brandonskerritt/RustScan/blob/master/README.md#%EF%B8%8F-debian--kali) | `yay -S rustscan` | `cargo install rustscan`
| <p align="center"><img src="https://github.com/RustScan/RustScan/blob/master/pictures/docker.png?raw=true" /></p> | <p align="center"><img src="https://github.com/RustScan/RustScan/blob/master/pictures/kali.png?raw=true" /></p> | <p align="center"><img src="https://github.com/RustScan/RustScan/blob/master/pictures/arch.png?raw=true" /></p> | <p align="center"><img src="https://github.com/RustScan/RustScan/blob/master/pictures/rust.png?raw=true" /></p>
| `docker pull rustscan/rustscan:alpine` <p>[Usage](https://github.com/RustScan/RustScan#docker-whale) | [Read the install guide](https://github.com/brandonskerritt/RustScan/blob/master/README.md#%EF%B8%8F-debian--kali) | `yay -S rustscan` | `cargo install rustscan`
<hr>
@@ -42,8 +42,8 @@
</tr>
<tr>
<th>Gif</th>
<td><img src="pictures/with_rustscan.gif" alt="The guy she tells you not to worry about"></td>
<td><img src="pictures/without_rustscan.gif" alt="You"></td>
<td><img src="https://github.com/RustScan/RustScan/blob/master/pictures/with_rustscan.gif?raw=true" alt="The guy she tells you not to worry about"></td>
<td><img src="https://github.com/RustScan/RustScan/blob/master/pictures/without_rustscan.gif?raw=true" alt="You"></td>
</tr>
<tr>
<th>Time</th>
@@ -79,7 +79,7 @@ RustScans **only** job is to reduce the friction between finding open ports and
# 🔭 Why RustScan?
Why spend time running fast scans and manually copying the ports, or waiting for a 20 minute scan to finish when you can just do all 65k ports in less than a minute?
![gif](pictures/8seconds.gif)
![gif](https://github.com/RustScan/RustScan/blob/master/pictures/8seconds.gif?raw=true)
**RustScan running in 8 seconds and finding all open ports out of 65k.**
@@ -122,22 +122,32 @@ Docker is the recommended way of installing RustScan. This is because:
To install Docker, [follow their guide](https://docs.docker.com/engine/install/).
**Once Docker is installed, run this command against the IP you want to target.**
**Once Docker is installed, you can either build your own image using the `Dockerfile` (alpine) provided in the repo, or alternatively, use the published Docker image like below (most convenient)**
Please see our [DockerHub](https://hub.docker.com/repository/docker/rustscan/rustscan) for further info, however, note that we have two Docker images:
```
rustscan/rustscan:alpine
rustscan/rustscan:latest
```
We strongly recommend using the `alpine` tag, as this is the latest major - stable - release of RustScan. This READMDE uses the `alpine` image by default, however, note that the`latest` image is considered experimental.
#### To get started:
Simply run this command against the IP you want to target:
```
docker run -it --rm --name rustscan cmnatic/rustscan:debian-buster rustscan 127.0.0.1
docker run -it --rm --name rustscan rustscan/rustscan:alpine <rustscan arguments here> <ip address to scan>
```
Note: this will scan the Docker's localhost, not your own.
This will download the Docker image.
Once done, you will no longer need to re-download the image (except when RustScan updates) and can use RustScan like a normal application.
You will have to run this command every time, so we suggest aliasing it to something memorable.
```
alias rustscan='docker run -it --rm --name rustscan cmnatic/rustscan:debian-buster rustscan'
alias rustscan='docker run -it --rm --name rustscan rustscan/rustscan:alpine <rustscan arguments here> <ip address to scan>'
```
Then we can:
@@ -146,6 +156,23 @@ Then we can:
rustscan 127.0.0.1 -t 500 -b 1500 -- -A
```
#### To build your own image:
Download the repo:
```
git clone https://github.com/RustScan/RustScan.git
```
Ensure you navigate to the download location of the repo:
```
cd /path/to/download/RustScan
```
Build away!
```
docker build -t <yourimagename> .
```
## 🍺 HomeBrew
**Note for Mac users** Mac OS has a very, very small ulimit size. This will negatively impact RustScan by a significant amount. Please use the Docker container, or tell RustScan to up the ulimit size on every run.
@@ -186,13 +213,12 @@ rustscan -h
```
```
rustscan 1.7.1
Fast Port Scanner built in Rust. WARNING Do not use this program against sensitive infrastructure since the specified
server may not be able to handle this many socket connections at once. - Discord https://discord.gg/GFrQsGy - GitHub
https://github.com/RustScan/RustScan
USAGE:
rustscan [FLAGS] [OPTIONS] <ips>... [-- <command>...]
rustscan [FLAGS] [OPTIONS] <ips-or-hosts>... [-- <command>...]
FLAGS:
-a, --accessible
@@ -204,6 +230,8 @@ 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.
-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:
serial] [possible values: Serial, Random]
@@ -211,11 +239,11 @@ OPTIONS:
-u, --ulimit <ulimit> Automatically ups the ULIMIT with the value you provided
ARGS:
<ips>... A list of comma separated IP addresses to be scanned
<command>... The Nmap arguments to run. To use the argument -A, end RustScan's args with '-- -A'. Example:
'rustscan -T 1500 127.0.0.1 -- -A -sC'. This command adds -Pn -vvv -p $PORTS automatically to
nmap. For things like --script '(safe and vuln)' enclose it in quotations marks \"'(safe and
vuln)'\"")
<ips-or-hosts>... A list of comma separated IP addresses or hosts to be scanned
<command>... The Nmap arguments to run. To use the argument -A, end RustScan's args with '-- -A'.
Example: 'rustscan -T 1500 127.0.0.1 -- -A -sC'. This command adds -Pn -vvv -p $PORTS
automatically to nmap. For things like --script '(safe and vuln)' enclose it in quotations
marks \"'(safe and vuln)'\"")
```
The format is `rustscan -b 500 -T 1500 192.168.0.1` to scan 192.168.0.1 with 500 batch size with a timeout of 1500ms. The timeout is how long RustScan waits for a response until it assumes the port is closed.
@@ -240,7 +268,7 @@ You can also use both of these at the same time, to make it as slow or as fast a
**Please** do not use this tool against sensitive servers. It is designed mainly for Capture the Flag events, not real world servers with sensitive data.
## 🚨 Thread Paniced at Main: Too Many Open Files
## 🚨 Thread Panicked at Main: Too Many Open Files
This is the most common error found in RustScan.
The open file limit is how many open sockets you can have at any given time.
@@ -312,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 🤠🌌
@@ -353,7 +397,7 @@ Please read the [contributing.md file](contributing.md)
## Contributors ✨
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-11-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
@@ -373,7 +417,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
</tr>
<tr>
<td align="center"><a href="https://github.com/Atul9"><img src="https://avatars1.githubusercontent.com/u/3390330?v=4" width="100px;" alt=""/><br /><sub><b>Atul Bhosale</b></sub></a><br /><a href="https://github.com/RustScan/RustScan/commits?author=Atul9" title="Code">💻</a></td>
<td align="center"><a href="https://tgotwig.me"><img src="https://avatars0.githubusercontent.com/u/30773779?v=4" width="100px;" alt=""/><br /><sub><b>Thomas Gotwig</b></sub></a><br /><a href="#platform-TGotwig" title="Packaging/porting to new platform">📦</a></td>
<td align="center"><a href="https://github.com/remigourdon"><img src="https://avatars3.githubusercontent.com/u/2874133?v=4" width="100px;" alt=""/><br /><sub><b>Rémi Gourdon</b></sub></a><br /><a href="https://github.com/RustScan/RustScan/commits?author=remigourdon" title="Documentation">📖</a> <a href="https://github.com/RustScan/RustScan/commits?author=remigourdon" title="Code">💻</a></td>
<td align="center"><a href="https://cmnatic.co.uk"><img src="https://avatars3.githubusercontent.com/u/4163116?v=4" width="100px;" alt=""/><br /><sub><b>Ben (CMNatic)</b></sub></a><br /><a href="https://github.com/RustScan/RustScan/commits?author=cmnatic" title="Code">💻</a> <a href="https://github.com/RustScan/RustScan/commits?author=cmnatic" title="Documentation">📖</a> <a href="#design-cmnatic" title="Design">🎨</a></td>
</tr>
</table>
+1004
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -8,7 +8,7 @@ TL;DR if you abuse members of our community you will be **perma-banned** with no
RustScan has 2 major labels for GitHub issues you should look at:
* Good First issue
These are issues for newcomers to open source!
These are issues for newcomers to open source!
[https://github.com/RustScan/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22](https://github.com/RustScan/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
* Help wanted
These are issues that aren't really for newcomers, but we could still do wiht help!
@@ -16,7 +16,7 @@ These are issues that aren't really for newcomers, but we could still do wiht he
If you want to, solve the issue or comment on the issue for help.
The flow for contributing to open source software is:
The [flow for contributing](https://guides.github.com/introduction/flow/) to open source software is:
* Fork the repo
* Make changes
* Pull request to the repo
+28
View File
@@ -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.
+237 -24
View File
@@ -13,10 +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::{net::IpAddr, time::Duration};
use std::str::FromStr;
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;
@@ -39,6 +49,35 @@ arg_enum! {
}
}
#[derive(Debug)]
pub struct PortRange {
start: u16,
end: u16,
}
fn parse_range(input: &str) -> Result<PortRange, String> {
let range = input
.split("-")
.map(|x| x.parse::<u16>())
.collect::<Result<Vec<u16>, std::num::ParseIntError>>();
if range.is_err() {
return Err(String::from(
"the range format must be 'start-end'. Example: 1-1000.",
));
}
match range.unwrap().as_slice() {
[start, end] => Ok(PortRange {
start: *start,
end: *end,
}),
_ => Err(String::from(
"the range format must be 'start-end'. Example: 1-1000.",
)),
}
}
#[derive(StructOpt, Debug)]
#[structopt(name = "rustscan", setting = structopt::clap::AppSettings::TrailingVarArg)]
/// Fast Port Scanner built in Rust.
@@ -47,9 +86,17 @@ arg_enum! {
/// - Discord https://discord.gg/GFrQsGy
/// - GitHub https://github.com/RustScan/RustScan
struct Opts {
/// A list of comma separated IP addresses to be scanned.
#[structopt(use_delimiter = true, parse(try_from_str), required = true)]
ips: Vec<IpAddr>,
/// A list of comma separated IP addresses or hosts to be scanned.
#[structopt(use_delimiter = true, required = true)]
ips_or_hosts: Vec<String>,
/// A list of comma separed ports to be scanned. Example: 80,443,8080.
#[structopt(short, long, use_delimiter = true)]
ports: Option<Vec<u16>>,
/// A range of ports with format start-end. Example: 1-1000.
#[structopt(short, long, conflicts_with = "ports", parse(try_from_str = parse_range))]
range: Option<PortRange>,
///Quiet mode. Only output the ports. No Nmap. Useful for grep or outputting to a file.
#[structopt(short, long)]
@@ -59,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
@@ -89,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
@@ -96,22 +152,43 @@ fn main() {
env_logger::init();
info!("Starting up");
let opts = Opts::from_args();
let mut opts = Opts::from_args();
if opts.ports.is_none() && opts.range.is_none() {
opts.range = Some(PortRange {
start: LOWEST_PORT_NUMBER,
end: TOP_PORT_NUMBER,
});
}
info!("Mains() `opts` arguments are {:?}", opts);
if !opts.quiet && !opts.accessible {
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() {
warning!("No IPs could be resolved, aborting scan.", false);
std::process::exit(1);
}
let ulimit: rlimit::rlim = adjust_ulimit_size(&opts);
let batch_size: u16 = infer_batch_size(&opts, ulimit);
let scanner = Scanner::new(
&opts.ips,
&ips,
batch_size,
Duration::from_millis(opts.timeout.into()),
opts.quiet,
PortStrategy::pick(LOWEST_PORT_NUMBER, TOP_PORT_NUMBER, opts.scan_order),
PortStrategy::pick(opts.range, opts.ports, opts.scan_order),
);
let scan_result = block_on(scanner.run());
@@ -124,7 +201,7 @@ fn main() {
.push(socket.port());
}
for ip in opts.ips {
for ip in ips {
if ports_per_ip.contains_key(&ip) {
continue;
}
@@ -134,7 +211,7 @@ fn main() {
let x = format!("{} Looks like I didn't find any open ports for {:?}. This is usually caused by a high batch size.
\n*I used {} batch size, consider lowering to {} with {} or a comfortable number for your system.
\n Alternatively, increase the timeout if your ping is high. Rustscan -T 2000 for 2000 second timeout.\n",
\n Alternatively, increase the timeout if your ping is high. Rustscan -t 2000 for 2000 second timeout.\n",
"ERROR",
ip,
opts.batch_size,
@@ -192,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,
@@ -215,7 +336,6 @@ fn build_nmap_arguments<'a>(
is_ipv6: bool,
) -> Vec<&'a str> {
let mut arguments: Vec<&str> = user_args.iter().map(AsRef::as_ref).collect();
arguments.push("-A");
arguments.push("-vvv");
if is_ipv6 {
@@ -229,6 +349,25 @@ fn build_nmap_arguments<'a>(
arguments
}
fn parse_ips(opts: &Opts) -> Vec<IpAddr> {
let mut ips: Vec<IpAddr> = Vec::new();
for ip_or_host in &opts.ips_or_hosts {
match IpAddr::from_str(ip_or_host) {
Ok(ip) => ips.push(ip),
_ => match format!("{}:{}", &ip_or_host, 80).to_socket_addrs() {
Ok(mut iter) => ips.push(iter.nth(0).unwrap().ip()),
_ => {
let failed_to_resolve = format!("Host {:?} could not be resolved.", ip_or_host);
warning!(failed_to_resolve, opts.quiet);
}
},
}
}
ips
}
fn adjust_ulimit_size(opts: &Opts) -> rlimit::rlim {
if opts.ulimit.is_some() {
let limit: rlimit::rlim = opts.ulimit.unwrap();
@@ -289,18 +428,20 @@ fn infer_batch_size(opts: &Opts, ulimit: rlimit::rlim) -> u16 {
#[cfg(test)]
mod tests {
use crate::{adjust_ulimit_size, infer_batch_size, print_opening, Opts, ScanOrder};
use std::{net::IpAddr, str::FromStr};
use crate::{adjust_ulimit_size, infer_batch_size, parse_ips, print_opening, Opts, ScanOrder};
#[test]
fn batch_size_lowered() {
let opts = Opts {
ips: vec![IpAddr::from_str("127.0.0.1").unwrap()],
ips_or_hosts: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
config: false,
accessible: false,
scan_order: ScanOrder::Serial,
};
@@ -312,12 +453,15 @@ mod tests {
#[test]
fn batch_size_lowered_average_size() {
let opts = Opts {
ips: vec![IpAddr::from_str("127.0.0.1").unwrap()],
ips_or_hosts: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
config: false,
accessible: false,
scan_order: ScanOrder::Serial,
};
@@ -330,12 +474,15 @@ mod tests {
// because ulimit and batch size are same size, batch size is lowered
// to ULIMIT - 100
let opts = Opts {
ips: vec![IpAddr::from_str("127.0.0.1").unwrap()],
ips_or_hosts: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
config: false,
accessible: false,
scan_order: ScanOrder::Serial,
};
@@ -347,12 +494,15 @@ mod tests {
fn batch_size_adjusted_2000() {
// ulimit == batch_size
let opts = Opts {
ips: vec![IpAddr::from_str("127.0.0.1").unwrap()],
ips_or_hosts: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
config: false,
accessible: false,
scan_order: ScanOrder::Serial,
};
@@ -369,12 +519,15 @@ mod tests {
#[test]
fn test_high_ulimit_no_quiet_mode() {
let opts = Opts {
ips: vec![IpAddr::from_str("127.0.0.1").unwrap()],
ips_or_hosts: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: false,
batch_size: 10,
timeout: 1_000,
ulimit: None,
command: Vec::new(),
config: false,
accessible: true,
scan_order: ScanOrder::Serial,
};
@@ -383,4 +536,64 @@ mod tests {
assert!(1 == 1);
}
#[test]
fn parse_correct_ips_or_hosts() {
let opts = Opts {
ips_or_hosts: vec!["127.0.0.1".to_owned(), "google.com".to_owned()],
ports: None,
range: None,
quiet: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
accessible: false,
scan_order: ScanOrder::Serial,
config: false,
};
let ips = parse_ips(&opts);
assert_eq!(2, ips.len());
}
#[test]
fn parse_correct_and_incorrect_ips_or_hosts() {
let opts = Opts {
ips_or_hosts: vec!["127.0.0.1".to_owned(), "im_wrong".to_owned()],
ports: None,
range: None,
quiet: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
accessible: false,
scan_order: ScanOrder::Serial,
config: false,
};
let ips = parse_ips(&opts);
assert_eq!(1, ips.len());
}
#[test]
fn parse_incorrect_ips_or_hosts() {
let opts = Opts {
ips_or_hosts: vec!["im_wrong".to_owned(), "300.10.1.1".to_owned()],
ports: None,
range: None,
quiet: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
accessible: false,
scan_order: ScanOrder::Serial,
config: false,
};
let ips = parse_ips(&opts);
assert_eq!(0, ips.len());
}
}
+53 -10
View File
@@ -1,5 +1,7 @@
mod range_iterator;
use super::ScanOrder;
use super::{PortRange, ScanOrder};
use rand::seq::SliceRandom;
use rand::thread_rng;
use range_iterator::RangeIterator;
/// Represents options of port scanning.
@@ -7,20 +9,41 @@ use range_iterator::RangeIterator;
/// Right now all these options involve ranges, but in the future
/// it will also contain custom lists of ports.
pub enum PortStrategy {
Manual(Vec<u16>),
Serial(SerialRange),
Random(RandomRange),
}
impl PortStrategy {
pub fn pick(start: u16, end: u16, scan_type: ScanOrder) -> Self {
match scan_type {
ScanOrder::Serial => PortStrategy::Serial(SerialRange { start, end }),
ScanOrder::Random => PortStrategy::Random(RandomRange { start, end }),
pub fn pick(range: Option<PortRange>, ports: Option<Vec<u16>>, order: ScanOrder) -> Self {
match order {
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)
}
}
}
pub fn order(&self) -> Vec<u16> {
match self {
PortStrategy::Manual(ports) => ports.to_vec(),
PortStrategy::Serial(range) => range.generate(),
PortStrategy::Random(range) => range.generate(),
}
@@ -71,18 +94,20 @@ impl RangeOrder for RandomRange {
#[cfg(test)]
mod tests {
use super::PortStrategy;
use crate::ScanOrder;
use crate::{PortRange, ScanOrder};
#[test]
fn serial_strategy() {
let strategy = PortStrategy::pick(1, 100, ScanOrder::Serial);
fn serial_strategy_with_range() {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Serial);
let result = strategy.order();
let expected_range = (1..100).into_iter().collect::<Vec<u16>>();
assert_eq!(expected_range, result);
}
#[test]
fn random_strategy() {
let strategy = PortStrategy::pick(1, 100, ScanOrder::Random);
fn random_strategy_with_range() {
let range = PortRange { start: 1, end: 100 };
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let mut result = strategy.order();
let expected_range = (1..100).into_iter().collect::<Vec<u16>>();
assert_ne!(expected_range, result);
@@ -90,4 +115,22 @@ mod tests {
result.sort();
assert_eq!(expected_range, result);
}
#[test]
fn serial_strategy_with_ports() {
let strategy = PortStrategy::pick(None, Some(vec![80, 443]), ScanOrder::Serial);
let result = strategy.order();
assert_eq!(vec![80, 443], result);
}
#[test]
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);
}
}
+38 -18
View File
@@ -12,14 +12,14 @@ use std::{
};
/// The class for the scanner
/// Host is data type IpAddr and is the host address
/// IP is data type IpAddr and is the IP address
/// start & end is where the port scan starts and ends
/// batch_size is how many ports at a time should be scanned
/// Timeout is the time RustScan should wait before declaring a port closed. As datatype Duration.
/// Quiet is whether or not RustScan should print things, or wait until the end to print only open ports.
#[cfg(not(tarpaulin_include))]
pub struct Scanner {
hosts: Vec<IpAddr>,
ips: Vec<IpAddr>,
batch_size: u16,
timeout: Duration,
quiet: bool,
@@ -28,7 +28,7 @@ pub struct Scanner {
impl Scanner {
pub fn new(
hosts: &[IpAddr],
ips: &[IpAddr],
batch_size: u16,
timeout: Duration,
quiet: bool,
@@ -39,7 +39,7 @@ impl Scanner {
timeout,
quiet,
port_strategy,
hosts: hosts.iter().map(|host| host.to_owned()).collect(),
ips: ips.iter().map(|ip| ip.to_owned()).collect(),
}
}
@@ -48,10 +48,10 @@ impl Scanner {
/// Returns all open ports as Vec<u16>
pub async fn run(&self) -> Vec<SocketAddr> {
let ports: Vec<u16> = self.port_strategy.order();
let batch_per_host: usize = self.batch_size as usize / self.hosts.len();
let batch_per_ip: usize = self.batch_size as usize / self.ips.len();
let mut open_sockets: Vec<SocketAddr> = Vec::new();
for batch in ports.chunks(batch_per_host) {
for batch in ports.chunks(batch_per_ip) {
let mut sockets = self.scan_ports(batch).await;
open_sockets.append(&mut sockets);
}
@@ -64,8 +64,8 @@ impl Scanner {
async fn scan_ports(&self, ports: &[u16]) -> Vec<SocketAddr> {
let mut ftrs = FuturesUnordered::new();
for port in ports {
for host in &self.hosts {
ftrs.push(self.scan_socket(SocketAddr::new(*host, *port)));
for ip in &self.ips {
ftrs.push(self.scan_socket(SocketAddr::new(*ip, *port)));
}
}
@@ -91,7 +91,7 @@ impl Scanner {
///
/// self.scan_port(10:u16)
///
/// Note: `self` must contain `self.host`.
/// Note: `self` must contain `self.ip`.
async fn scan_socket(&self, socket: SocketAddr) -> io::Result<SocketAddr> {
match self.connect(socket).await {
Ok(x) => {
@@ -119,9 +119,9 @@ impl Scanner {
/// # Example
///
/// let port: u16 = 80
/// // Host is an IpAddr type
/// let host = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
/// let socket = SocketAddr::new(host, port);
/// // ip is an IpAddr type
/// let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
/// let socket = SocketAddr::new(ip, port);
/// self.connect(socket)
/// // returns Result which is either Ok(stream) for port is open, or Er for port is closed.
/// // Timeout occurs after self.timeout seconds
@@ -139,7 +139,7 @@ impl Scanner {
#[cfg(test)]
mod tests {
use super::*;
use crate::ScanOrder;
use crate::{PortRange, ScanOrder};
use async_std::task::block_on;
use std::{net::IpAddr, time::Duration};
@@ -147,7 +147,11 @@ mod tests {
fn scanner_runs() {
// Makes sure the program still runs and doesn't panic
let addrs = vec!["127.0.0.1".parse::<IpAddr>().unwrap()];
let strategy = PortStrategy::pick(1, 1_000, ScanOrder::Random);
let range = PortRange {
start: 1,
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
block_on(scanner.run());
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
@@ -157,7 +161,11 @@ mod tests {
fn ipv6_scanner_runs() {
// Makes sure the program still runs and doesn't panic
let addrs = vec!["::1".parse::<IpAddr>().unwrap()];
let strategy = PortStrategy::pick(1, 1_000, ScanOrder::Random);
let range = PortRange {
start: 1,
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
block_on(scanner.run());
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
@@ -166,7 +174,11 @@ mod tests {
#[test]
fn quad_zero_scanner_runs() {
let addrs = vec!["0.0.0.0".parse::<IpAddr>().unwrap()];
let strategy = PortStrategy::pick(1, 1_000, ScanOrder::Random);
let range = PortRange {
start: 1,
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
block_on(scanner.run());
assert_eq!(1, 1);
@@ -174,7 +186,11 @@ mod tests {
#[test]
fn google_dns_runs() {
let addrs = vec!["8.8.8.8".parse::<IpAddr>().unwrap()];
let strategy = PortStrategy::pick(400, 445, ScanOrder::Random);
let range = PortRange {
start: 400,
end: 445,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
block_on(scanner.run());
assert_eq!(1, 1);
@@ -185,7 +201,11 @@ mod tests {
let addrs = vec!["8.8.8.8".parse::<IpAddr>().unwrap()];
// mac should have this automatically scaled down
let strategy = PortStrategy::pick(400, 600, ScanOrder::Random);
let range = PortRange {
start: 400,
end: 600,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
block_on(scanner.run());
assert_eq!(1, 1);