Compare commits

...

19 Commits
v0.1.1 ... main

Author SHA1 Message Date
Justine Pelletreau
befd6c862b Added timeout on http
All checks were successful
Rust-build / build (push) Successful in 16m6s
2023-07-22 22:04:50 +02:00
95d726987f Update README.md
Some checks reported warnings
Rust-build / build (push) Has been cancelled
2023-07-22 21:55:04 +02:00
Justine Pelletreau
75f2ae0655 Better dockerfile
Some checks reported warnings
Rust-build / build (push) Has been cancelled
2023-07-22 21:23:53 +02:00
Justine Pelletreau
dc2854faad Update README
Some checks reported warnings
Rust-build / build (push) Has been cancelled
2023-07-22 20:10:36 +02:00
Justine Pelletreau
3db7162612 Revised workflow
Some checks reported warnings
Rust-build / build (push) Has been cancelled
2023-07-22 19:45:44 +02:00
Justine Pelletreau
c51d855d9c Added dockerfile
Some checks reported warnings
Rust-build / build (push) Has been cancelled
2023-07-22 19:44:50 +02:00
Justine Pelletreau
3a34230b0a Removed actions
All checks were successful
Rust-build / build (push) Successful in 1m57s
2023-07-22 19:19:07 +02:00
Justine Pelletreau
04198fb28e Added release action
Some checks failed
Rust-build / build (push) Failing after 2m7s
2023-07-22 19:12:04 +02:00
Justine Pelletreau
dd430b1b2c Prettier resultsé
All checks were successful
Rust-build / build (push) Successful in 2m19s
2023-07-22 18:56:21 +02:00
53c405b7a6 Update README.md
All checks were successful
Rust-build / build (push) Successful in 2m6s
2023-07-22 13:52:42 +02:00
Justine Pelletreau
c4462fcbca Added http mode and results
All checks were successful
Rust-build / build (push) Successful in 2m39s
2023-07-22 13:48:36 +02:00
Justine Pelletreau
5476327560 Added build action
All checks were successful
Rust-build / build (push) Successful in 1m18s
2023-07-17 12:05:56 +02:00
Justine Pelletreau
8f08f1784c Revert "Revert "Added banner and separated files""
Some checks failed
GitHub Actions Demo / Explore-GitHub-Actions (push) Failing after 2s
This reverts commit b5457c34ac32f3935959dc4483c3c8fd39a9baf8.
2023-07-15 20:10:33 +02:00
Justine Pelletreau
b5457c34ac Revert "Added banner and separated files"
Some checks failed
GitHub Actions Demo / Explore-GitHub-Actions (push) Failing after 3s
This reverts commit 96ad617804add17ee4b97d3e155e799d4b739425.
2023-07-15 20:09:24 +02:00
Justine Pelletreau
4b5f095a9b Actions update
Some checks failed
GitHub Actions Demo / Explore-GitHub-Actions (push) Failing after 12s
2023-07-15 20:07:48 +02:00
Justine Pelletreau
237e46bc5d testing actions
Some checks reported warnings
GitHub Actions Demo / Explore-GitHub-Actions (push) Has been cancelled
2023-07-15 20:05:42 +02:00
Justine Pelletreau
78c1fe3f09 Removed badge from readme 2023-07-15 20:03:23 +02:00
Justine Pelletreau
5378d6b105 Added actions 2023-07-15 20:02:01 +02:00
Justine Pelletreau
96ad617804 Added banner and separated files 2023-07-15 10:52:43 +02:00
9 changed files with 1276 additions and 121 deletions

View File

@ -0,0 +1,57 @@
name: Rust-build
on:
push:
branches:
- "main"
jobs:
build:
runs-on: ubuntu-latest
container:
image: catthehacker/ubuntu:act-latest
steps:
- name: Check-out
uses: actions/checkout@v3
- name: Install stable toolchain
uses: https://github.com/actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Run cargo check
uses: https://github.com/actions-rs/cargo@v1
with:
command: check
- name: Test
run: cargo test
- name: Build
run: cargo build --release
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to registry
uses: docker/login-action@v2
with:
registry: gitea.squi.fr
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
env:
ACTIONS_RUNTIME_TOKEN: '' # See https://gitea.com/gitea/act_runner/issues/119
with:
context: .
file: ./Dockerfile
platforms: |
linux/amd64
linux/arm64
push: true
tags: gitea.squi.fr/justine/portnut:latest

754
Cargo.lock generated
View File

@ -2,6 +2,21 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.0.2" version = "1.0.2"
@ -71,18 +86,63 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.3.3" version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
[[package]]
name = "bumpalo"
version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "bytes"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.79" version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.3.11" version = "4.3.11"
@ -130,6 +190,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "encoding_rs"
version = "0.8.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.1" version = "0.3.1"
@ -151,12 +220,118 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures-channel"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.25",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "futures-task"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-util"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [
"futures-core",
"futures-io",
"futures-macro",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gimli"
version = "0.27.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
[[package]] [[package]]
name = "glob" name = "glob"
version = "0.3.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
@ -178,6 +353,104 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]]
name = "http"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "hyper"
version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]]
name = "hyper-rustls"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
dependencies = [
"futures-util",
"http",
"hyper",
"rustls",
"tokio",
"tokio-rustls",
]
[[package]]
name = "idna"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "ipnet"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6"
[[package]] [[package]]
name = "ipnetwork" name = "ipnetwork"
version = "0.20.0" version = "0.20.0"
@ -198,6 +471,21 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "js-sys"
version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [
"wasm-bindgen",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.147" version = "0.2.147"
@ -210,24 +498,93 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
[[package]]
name = "log"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.5.0" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]] [[package]]
name = "no-std-net" name = "no-std-net"
version = "0.6.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi 0.3.2",
"libc",
]
[[package]]
name = "object"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.18.0" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "percent-encoding"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pin-project-lite"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "pnet" name = "pnet"
version = "0.33.0" version = "0.33.0"
@ -321,11 +678,12 @@ dependencies = [
[[package]] [[package]]
name = "portnut" name = "portnut"
version = "0.1.0" version = "0.1.2"
dependencies = [ dependencies = [
"atty", "atty",
"clap", "clap",
"pnet", "pnet",
"reqwest",
] ]
[[package]] [[package]]
@ -375,6 +733,66 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
[[package]]
name = "reqwest"
version = "0.11.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
"hyper-rustls",
"ipnet",
"js-sys",
"log",
"mime",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-rustls",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"webpki-roots",
"winreg",
]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.4" version = "0.38.4"
@ -388,12 +806,107 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "rustls"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b19faa85ecb5197342b54f987b142fb3e30d0c90da40f80ef4fa9a726e6676ed"
dependencies = [
"log",
"ring",
"rustls-webpki",
"sct",
]
[[package]]
name = "rustls-pemfile"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2"
dependencies = [
"base64",
]
[[package]]
name = "rustls-webpki"
version = "0.101.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.171" version = "1.0.171"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9"
[[package]]
name = "serde_json"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "slab"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
dependencies = [
"autocfg",
]
[[package]]
name = "socket2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
@ -422,18 +935,248 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
dependencies = [
"autocfg",
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
"socket2",
"windows-sys",
]
[[package]]
name = "tokio-rustls"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
name = "tower-service"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if",
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
dependencies = [
"once_cell",
]
[[package]]
name = "try-lock"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "unicode-bidi"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.10" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "url"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]] [[package]]
name = "utf8parse" name = "utf8parse"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
"try-lock",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.25",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.25",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]]
name = "web-sys"
version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
dependencies = [
"webpki",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -521,3 +1264,12 @@ name = "windows_x86_64_msvc"
version = "0.48.0" version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winreg"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [
"winapi",
]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "portnut" name = "portnut"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -9,3 +9,4 @@ edition = "2021"
atty = "0.2.14" atty = "0.2.14"
clap = { version = "4.3.11", features = ["derive"] } clap = { version = "4.3.11", features = ["derive"] }
pnet = "0.33.0" pnet = "0.33.0"
reqwest = { version = "0.11", default-features = false, features = ["blocking", "rustls-tls"] }

15
Dockerfile Normal file
View File

@ -0,0 +1,15 @@
FROM rust:slim-buster AS builder
RUN mkdir -p /opt/portnut
COPY --chown=root --chmod=0755 ./src /opt/portnut/src
COPY --chown=root --chmod=0755 ./Cargo.toml /opt/portnut/Cargo.toml
RUN apt update
#RUN apt install libssl-dev openssl pkg-config -y
WORKDIR /opt/portnut
RUN cargo build --release
RUN cp target/release/portnut /bin/portnut
FROM debian:stable-slim
WORKDIR /opt/
COPY --from=builder /opt/portnut/target/release/portnut .
ENTRYPOINT ["/opt/portnut"]
CMD [ "" ]

View File

@ -1,15 +1,20 @@
# Portnut # Portnut
[![Build Status](http://drone.sq.lan/api/badges/Rust/Portnut/status.svg)](http://drone.sq.lan/Rust/Portnut) Portnut is a port stressing / scanning multithreaded utility. It can handle raw TCP and HTTP.
# TODO # TODO
* Read the answer and count the number of answers received.
* Make a distributed version that allows stressing from multiple computers at the same time * Make a distributed version that allows stressing from multiple computers at the same time
* Return more stats (low 1%, high 1%)
# Install # Install
Go to the releases page and download the latest version. Go to the releases page and download the latest version.
Give it execution rights and simply launch it. Give it execution rights and simply launch it.
# Building
Prerequisite to building reqwest:
> apt install libssl-dev
# Usage # Usage
Portnut is a tcp port scanner / stresser. Portnut is a tcp port scanner / stresser.
@ -17,37 +22,101 @@ Portnut is a tcp port scanner / stresser.
The scanning function simply tries to connect to the tcp ports given. The scanning function simply tries to connect to the tcp ports given.
The stressing function sends a payload every 10 milliseconds, to every ports given at the same time. The payload can be passed via a pipe (optionnal). The stressing function sends a payload every 10 milliseconds, to every ports given at the same time. The payload can be passed via a pipe (optionnal).
## Scan
``` ```
1637 justine@portnut > target/release/portnut -a 127.0.0.1 -w 3 -p 8080,22 2347 justine > portnut tcpscan -a 127.0.0.1 -p 8080,8090
Scanning 127.0.0.1 ____ ____ ____ _______ ____ ________
TCP/8080 => REJECT / __ \/ __ \/ __ \/_ __/ | / / / / /_ __/
TCP/22 => REJECT / /_/ / / / / /_/ / / / / |/ / / / / / /
/ ____/ /_/ / _, _/ / / / /| / /_/ / / /
/_/ \____/_/ |_| /_/ /_/ |_/\____/ /_/
Scanning 127.0.0.1
TCP/8080 => ACCEPT
TCP/8090 => REJECT
2351 justine > portnut tcpscan -a 127.0.0.1 -p 8080,8090 --range
____ ____ ____ _______ ____ ________
/ __ \/ __ \/ __ \/_ __/ | / / / / /_ __/
/ /_/ / / / / /_/ / / / / |/ / / / / / /
/ ____/ /_/ / _, _/ / / / /| / /_/ / / /
/_/ \____/_/ |_| /_/ /_/ |_/\____/ /_/
Scanning 127.0.0.1
TCP/8080 => ACCEPT
TCP/8081 => REJECT
TCP/8082 => REJECT
TCP/8083 => REJECT
TCP/8084 => REJECT
TCP/8085 => REJECT
TCP/8086 => REJECT
TCP/8087 => REJECT
TCP/8088 => REJECT
TCP/8089 => REJECT
```
## TCP Stress
TCP Stress can be applied to a port, a list of port, or a range of port.
Stressing allows sending a payload (via -p/--payload or via a pipe), sending, and waiting for an answer.
```
2356 justine > portnut tcpstress -a 127.0.0.1 -p 8080 -d 2
____ ____ ____ _______ ____ ________
/ __ \/ __ \/ __ \/_ __/ | / / / / /_ __/
/ /_/ / / / / /_/ / / / / |/ / / / / / /
/ ____/ /_/ / _, _/ / / / /| / /_/ / / /
/_/ \____/_/ |_| /_/ /_/ |_/\____/ /_/
#First scan the ports, and stress the available ones.
1738 justine@portnut > echo "GET / HTTP/1.1" | target/release/portnut -a 127.0.0.1 -p 8080 -w 30 -s -c 100
Scanning 127.0.0.1 Scanning 127.0.0.1
TCP/8080 => ACCEPT TCP/8080 => ACCEPT
Stressing 127.0.0.1 using 100 concurrent threads per port for 30s Stressing 127.0.0.1 using 5 concurrent threads per port for 2s
TOTAL 20
OK 20
NOK 0
Got 100% of OK
Mean answer time : 512ms
```
## HTTP Stress
HTTP stress performs a GET on the given address.
``` ```
1257 justine > portnut httpstress -a http://localhost:8080 --duration 5
____ ____ ____ _______ ____ ________
/ __ \/ __ \/ __ \/_ __/ | / / / / /_ __/
/ /_/ / / / / /_/ / / / / |/ / / / / / /
/ ____/ /_/ / _, _/ / / / /| / /_/ / / /
/_/ \____/_/ |_| /_/ /_/ |_/\____/ /_/
Threads starting their 5s run...
over !
TOTAL 809
OK 809
NOK 0
Got 100% of OK
Mean answer time : 5ms
```
## More ?
See the help : See the help :
``` ```
justine@portnut > target/release/portnut -h A simple TCP/HTTP port scanner / stresser. If stressing, you can pass a payload via a pipe
A simple TCP port scanner / stresser. If stressing, you can pass a payload via a pipe
Usage: portnut [OPTIONS] --address <ADDRESS> Usage: portnut [OPTIONS] --address <ADDRESS> --ports <PORTS>... <MODE>
Arguments:
<MODE> Mode of use : either tcpstress, tcpscan or httpstress
Options: Options:
-a, --address <ADDRESS> IP address or hostname to scan -a, --address <ADDRESS> IP address or hostname to scan - or url if using http
-t, --timeout <TIMEOUT> Timeout for each connection in seconds [default: 1] -t, --timeout <TIMEOUT> Timeout for each connection in seconds [default: 1]
-w, --wait <WAIT> Number of milliseconds to wait in between scans when scanning OR duration of stress when stress testing (in seconds) [default: 30] -w, --wait <WAIT> Number of milliseconds to wait in between scans or requests [default: 30]
-d, --duration <DURATION> Duration of tcp stress test in seconds, default 30 [default: 30]
-p, --ports <PORTS>... Ports to stress / scan, separated by commas (22,80) -p, --ports <PORTS>... Ports to stress / scan, separated by commas (22,80)
-r, --range Set this flag to treat the ports as a range rather than a list -r, --range Set this flag to treat the ports as a range rather than a list
-s, --stress Set this flag to stress the ports instead of scanning them -s, --stress Set this flag to stress the ports instead of scanning them
-c, --cthreads <CTHREADS> How many threads per port when stressing (Concurrent Threads) [default: 5] -c, --cthreads <CTHREADS> How many threads per port when stressing (Concurrent Threads) [default: 5]
-h, --help Print help -h, --help Print help
-V, --version Print version -V, --version Print version
``` ```

70
src/http.rs Normal file
View File

@ -0,0 +1,70 @@
use std::thread;
use reqwest;
use std::time::{Duration, Instant};
use std::sync::mpsc;
use crate::results::*;
pub fn http_stress(url: String, interval: Duration, sleep: Duration, threads: u32, timeout: Duration) -> std::io::Result<()> {
let mut handles = vec![];
let (tx, rx) = mpsc::channel();
println!("Threads starting their {:?} run...", interval);
for _i in 0..=threads {
let add = url.clone();
let end_time = Instant::now() + interval;
let wait = sleep.clone();
let tx2 = tx.clone();
let delay = timeout.clone();
handles.push(thread::spawn( move || {
loop {
if Instant::now() >= end_time { break; }
let b4 = Instant::now();
let client = reqwest::blocking::Client::new();
let resp = client.get(add.clone()).timeout(delay).send();
let time = Instant::now() - b4;
match resp {
Ok(_) => {
let myres = StressResult { time: time, ok: true, rtype: ResType::Http };
let _ = tx2.send(myres);
//println!("Got an answer for {} in {:?} in thread {}", add, time, i);
},
Err(_) => {
let myres = StressResult { time: time, ok: false, rtype: ResType::Http };
let _ = tx2.send(myres);
//println!("No answer for {} after {:?} in thread {}", add, time, i);
},
}
thread::sleep(wait);
}
drop(tx2);
}));
}
drop(tx);
for handle in handles {
let _ = handle.join();
}
println!("over !");
//Showing Results
//Somehow iterating over never ends
let mut res: Vec<StressResult> = vec![];
for r in rx.try_iter() {
res.push(r);
}
let lres = ListOfResults { results: res, restype: ResType::Http };
lres.show_info();
Ok(())
}

View File

@ -1,11 +1,17 @@
use clap::Parser; use clap::Parser;
use std::io::prelude::*;
use std::io::{self, Read}; use std::io::{self, Read};
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::time::{Duration, Instant};
use std::thread;
use atty::Stream; use atty::Stream;
use std::io::BufReader; use std::time::{Duration};
mod tcp;
use tcp::tcp_scan;
use tcp::tcp_stress;
mod http;
use http::http_stress;
mod results;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
@ -13,8 +19,11 @@ fn main() -> std::io::Result<()> {
let address = args.address; let address = args.address;
let timeout = Duration::from_secs(args.timeout); let timeout = Duration::from_secs(args.timeout);
let sleep = Duration::from_millis(args.wait); let sleep = Duration::from_millis(args.wait);
let duration = Duration::from_secs(args.duration);
let ports = handle_ports(args.ports.clone(), &args.range); let ports = handle_ports(args.ports.clone(), &args.range);
let threads = args.cthreads; let threads = args.cthreads;
print_banner();
//Reading the payload from stdin (if applicable) //Reading the payload from stdin (if applicable)
let mut payload = String::new(); let mut payload = String::new();
@ -26,13 +35,26 @@ fn main() -> std::io::Result<()> {
payload = "SAKAMOTO".to_string(); payload = "SAKAMOTO".to_string();
} }
if args.stress { match args.mode.as_str() {
tcp_stress(payload, address, timeout, sleep, ports, threads)?; "tcpstress" => {
} else { println!("===== TCP STRESS TEST =====");
tcp_scan(address, timeout, sleep, ports)?; tcp_stress(payload, address, timeout, duration, ports, threads)?;
return Ok(());
}
"tcpscan" => {
println!("===== TCP SCAN =====");
tcp_scan(address, timeout, sleep, ports)?;
return Ok(());
}
"httpstress" => {
println!("===== HTTP STRESS TEST =====");
http_stress(address, duration, sleep, threads, timeout)?;
return Ok(());
}
_ => {
panic!("Mode unkown ! See the help.");
}
} }
Ok(())
} }
//Returns a correct list of ports, according to range. //Returns a correct list of ports, according to range.
@ -50,115 +72,47 @@ fn handle_ports(ports: Vec<u32>, range: &bool) -> Vec<u32> {
} }
} }
fn print_banner() {
let lines = [
" ____ ____ ____ _______ ____ ________",
" / __ \\/ __ \\/ __ \\/_ __/ | / / / / /_ __/",
" / /_/ / / / / /_/ / / / / |/ / / / / / / ",
" / ____/ /_/ / _, _/ / / / /| / /_/ / / / ",
"/_/ \\____/_/ |_| /_/ /_/ |_/\\____/ /_/ ",
];
for line in lines {
///Scan the ports on address by attempting a tcp connection. println!("{}", line);
fn tcp_scan(address: String, timeout: Duration, sleep: Duration, ports: Vec<u32>) -> std::io::Result<()> {
println!("Scanning {}", address);
for i in ports {
let socket = resolve_add(&address.as_str(), &i);
match TcpStream::connect_timeout(&socket, timeout) {
Ok(mut _s) => {
println!("TCP/{} => ACCEPT", i);
//s.write(b"Some padding")?;
}
Err(_) => {
println!("TCP/{} => REJECT", i);
}
}
thread::sleep(sleep.clone());
//stream.write(b"Some great padding")?;
//stream.read(&mut [0; 128])?;
} }
Ok(()) println!("");
} }
///Takes either an hostname or an IP address and port, and resolve to a socket address.
///DNS recordings can lead to multiple entries : we take the first one.
fn resolve_add(host: &str, port: &u32) -> SocketAddr {
let details = format!("{}:{}", host, port);
let server: Vec<_> = details
.to_socket_addrs()
.expect("Can't resolve your address")
.collect();
return server[0];
}
///Try to stress the remote machine by attempting to every given port at once and sending payload
fn tcp_stress(payload: String, address: String, timeout: Duration, interval: Duration, ports: Vec<u32>, threads: u32) -> std::io::Result<()> {
let mut handles = vec![];
for port in ports {
tcp_scan(address.clone(), timeout, interval, vec![port])?;
let mut threads_left = threads;
loop {
let add = address.clone();
let pay = payload.clone();
let int = interval * 1000;
let end_time = Instant::now() + int;
//pay.push_str("\r\n");
handles.push(thread::spawn( move || {
let socket = resolve_add(&add.as_str(), &port);
loop {
//Check if it is time to stop
if Instant::now() >= end_time { break; }
match TcpStream::connect_timeout(&socket, timeout) {
Ok(mut s) => {
//Remote port answers
//Writing
s.write_all(pay.as_bytes()).unwrap();
s.flush().unwrap();
//Reading ///A simple TCP/HTTP port scanner / stresser.
s.set_read_timeout(Some(Duration::from_millis(500))).unwrap();
let mut reader = BufReader::new(s.try_clone().unwrap());
let mut answer = String::new();
let count = reader.read_line(&mut answer).unwrap_or(0);
if count > 0 {
println!("Read {} bytes for port {} -> {}", count, &port, answer);
}
//Sleeping
thread::sleep(Duration::from_millis(10));
},
Err(_) => (),
}
}
}));
*&mut threads_left -=1;
if threads_left == 0 { break; }
}
}
println!("\nStressing {} using {} concurrent threads per port for {:?} \n", address, threads, interval * 1000);
for handle in handles {
let _ = handle.join();
}
Ok(())
}
///A simple TCP port scanner / stresser.
///If stressing, you can pass a payload via a pipe. ///If stressing, you can pass a payload via a pipe.
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)] #[command(author = "Squip", version, long_about = None)]
struct Args { struct Args {
///IP address or hostname to scan ///Mode of use : either tcpstress, tcpscan or httpstress
mode: String,
///IP address or hostname to scan - or url if using http
///ex of address : 127.0.0.1
///ex of url : http://example.org
#[arg(short, long)] #[arg(short, long)]
address: String, address: String,
///Timeout for each connection in seconds ///Timeout for each connection in seconds, default 30
#[arg(short, long, default_value_t = 1)] #[arg(short, long, default_value_t = 30)]
timeout: u64, timeout: u64,
///Number of milliseconds to wait in between scans when scanning ///Number of milliseconds to wait in between scans or requests
///OR duration of stress when stress testing (in seconds)
#[arg(short, long, default_value_t = 30)] #[arg(short, long, default_value_t = 30)]
wait: u64, wait: u64,
///Duration of tcp stress test in seconds, default 30
#[arg(short, long, default_value_t = 30)]
duration: u64,
///Ports to stress / scan, separated by commas (22,80) ///Ports to stress / scan, separated by commas (22,80)
#[arg(short, long, value_parser, num_args=1.., value_delimiter=',')] #[arg(short, long, value_parser, num_args=0.., value_delimiter=',')]
ports: Vec<u32>, ports: Vec<u32>,
///Set this flag to treat the ports as a range rather than a list ///Set this flag to treat the ports as a range rather than a list
#[arg(long, short, action, default_value_t = false)] #[arg(long, short, action, default_value_t = false)]

111
src/results.rs Normal file
View File

@ -0,0 +1,111 @@
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct StressResult {
///How long did it take
pub time: Duration,
///Did we get an answer
pub ok: bool,
pub rtype: ResType,
}
#[derive(Debug, Clone)]
pub enum ResType {
Tcp(u32),
Http,
}
#[derive(Debug, Clone)]
pub struct ListOfResults {
pub results: Vec<StressResult>,
pub restype: ResType,
}
impl ListOfResults {
fn compute_ratio(&self) {
let mut ok: u64 = 0;
let mut nok: u64 = 0;
for r in self.results.clone() {
if r.ok == true {
*&mut ok += 1;
} else {
*&mut nok += 1;
}
}
let mut compute = ok + nok;
println!("TOTAL {}\n\tOK {}\n\tNOK {}", compute, ok, nok);
if compute < 1 { compute = 1; }
compute = ok * 100 / compute;
println!("Got {}% of OK\n", compute );
}
///Get the different TCP ports from the results
fn get_ports(&self) -> Vec<u32> {
let mut ports = vec![];
for r in &self.results {
match r.rtype {
ResType::Tcp(p) => {
if !ports.contains(&p) {
ports.push(p);
}
},
ResType::Http => (),
}
}
ports
}
///Show info, by port if we are in TCP mode
pub fn show_info(&self) {
println!("\n===== RESULTS =====");
match &self.restype {
ResType::Tcp(_) => {
let ports = self.get_ports();
for port in ports {
let mut results = Vec::new();
for res in &self.results {
match res.rtype {
ResType::Tcp(v) => {
if v == port { *&mut results.push(res.clone()); }
},
_ => (),
}
}
let list = ListOfResults { results: results, restype: ResType::Tcp(1) };
println!("=====> PORT {}", port);
list.show_mean_time();
list.compute_ratio();
}
},
ResType::Http => {
self.show_mean_time();
self.compute_ratio();
},
}
}
fn show_mean_time(&self) {
let mut total: u128 = 0;
let mut acc: u128 = 0;
for i in &self.results {
if i.ok {
*&mut total += 1;
*&mut acc += i.time.as_millis();
}
}
if total == 0 { total += 1 };
let restime = acc / total;
println!("Average response time : {:?}", Duration::from_millis(restime.try_into().unwrap()));
}
}

126
src/tcp.rs Normal file
View File

@ -0,0 +1,126 @@
use std::io::prelude::*;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::time::{Duration, Instant};
use std::thread;
use std::io::BufReader;
use std::sync::mpsc;
use crate::results::*;
///Scan the ports on address by attempting a tcp connection.
pub fn tcp_scan(address: String, timeout: Duration, sleep: Duration, ports: Vec<u32>) -> std::io::Result<()> {
println!("Scanning {}", address);
for i in ports {
let socket = resolve_add(&address.as_str(), &i);
match TcpStream::connect_timeout(&socket, timeout) {
Ok(_) => {
println!("TCP/{} => ACCEPT", i);
//s.write(b"Some padding")?;
}
Err(_) => {
println!("TCP/{} => REJECT", i);
}
}
thread::sleep(sleep.clone());
//stream.write(b"Some great padding")?;
//stream.read(&mut [0; 128])?;
}
Ok(())
}
///Takes either an hostname or an IP address and port, and resolve to a socket address.
///DNS recordings can lead to multiple entries : we take the first one.
fn resolve_add(host: &str, port: &u32) -> SocketAddr {
let details = format!("{}:{}", host, port);
let server: Vec<_> = details
.to_socket_addrs()
.expect("Can't resolve your address")
.collect();
return server[0];
}
///Try to stress the remote machine by attempting to every given port at once and sending payload
pub fn tcp_stress(payload: String, address: String, timeout: Duration, interval: Duration, ports: Vec<u32>, threads: u32) -> std::io::Result<()> {
let mut handles = vec![];
let (tx, rx) = mpsc::channel();
for port in ports {
let mut threads_left = threads;
let tx2 = tx.clone();
loop {
let add = address.clone();
let pay = payload.clone();
let int = interval;
let end_time = Instant::now() + int;
let tx3 = tx2.clone();
//pay.push_str("\r\n");
handles.push(thread::spawn( move || {
let socket = resolve_add(&add.as_str(), &port);
loop {
//Check if it is time to stop
if Instant::now() >= end_time { break; }
let b4 = Instant::now();
match TcpStream::connect_timeout(&socket, timeout) {
Ok(mut s) => {
//Remote port answers
//Writing
s.write_all(pay.as_bytes()).unwrap();
s.flush().unwrap();
//Reading
s.set_read_timeout(Some(Duration::from_millis(500))).unwrap();
let mut reader = BufReader::new(s.try_clone().unwrap());
let mut answer = String::new();
let count = reader.read_line(&mut answer).unwrap_or(0);
if count > 0 {
println!("Read {} bytes for port {} -> {}", count, &port, answer);
}
let time = Instant::now() - b4;
let myres = StressResult { time: time, ok: true, rtype: ResType::Tcp(port.clone()) };
let _ = tx3.send(myres);
//Sleeping
thread::sleep(Duration::from_millis(10));
},
Err(_) => {
let time = Instant::now() - b4;
let myres = StressResult { time: time, ok: false, rtype: ResType::Tcp(port.clone()) };
let _ = tx3.send(myres);
}
}
}
}));
*&mut threads_left -=1;
if threads_left == 0 { break; }
}
}
drop(tx);
println!("Stressing {} using {} concurrent threads per port for {:?} \n", address, threads, interval);
for handle in handles {
let _ = handle.join();
}
let mut res: Vec<StressResult> = vec![];
for r in rx.try_iter() {
res.push(r);
}
let listofres = ListOfResults { results: res, restype: ResType::Tcp(1) };
listofres.show_info();
Ok(())
}