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.
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]]
name = "aho-corasick"
version = "1.0.2"
@ -71,18 +86,63 @@ dependencies = [
"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]]
name = "bitflags"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.3.11"
@ -130,6 +190,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "errno"
version = "0.3.1"
@ -151,12 +220,118 @@ dependencies = [
"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]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "heck"
version = "0.4.1"
@ -178,6 +353,104 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "ipnetwork"
version = "0.20.0"
@ -198,6 +471,21 @@ dependencies = [
"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]]
name = "libc"
version = "0.2.147"
@ -210,24 +498,93 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
[[package]]
name = "log"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "no-std-net"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "pnet"
version = "0.33.0"
@ -321,11 +678,12 @@ dependencies = [
[[package]]
name = "portnut"
version = "0.1.0"
version = "0.1.2"
dependencies = [
"atty",
"clap",
"pnet",
"reqwest",
]
[[package]]
@ -375,6 +733,66 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "rustix"
version = "0.38.4"
@ -388,12 +806,107 @@ dependencies = [
"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]]
name = "serde"
version = "1.0.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "strsim"
version = "0.10.0"
@ -422,18 +935,248 @@ dependencies = [
"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]]
name = "unicode-ident"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "winapi"
version = "0.3.9"
@ -521,3 +1264,12 @@ name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]
name = "portnut"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
# 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"
clap = { version = "4.3.11", features = ["derive"] }
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
[![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
* Read the answer and count the number of answers received.
* Make a distributed version that allows stressing from multiple computers at the same time
* Return more stats (low 1%, high 1%)
# Install
Go to the releases page and download the latest version.
Give it execution rights and simply launch it.
# Building
Prerequisite to building reqwest:
> apt install libssl-dev
# Usage
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 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
Scanning 127.0.0.1
TCP/8080 => REJECT
TCP/22 => REJECT
2347 justine > portnut tcpscan -a 127.0.0.1 -p 8080,8090
____ ____ ____ _______ ____ ________
/ __ \/ __ \/ __ \/_ __/ | / / / / /_ __/
/ /_/ / / / / /_/ / / / / |/ / / / / / /
/ ____/ /_/ / _, _/ / / / /| / /_/ / / /
/_/ \____/_/ |_| /_/ /_/ |_/\____/ /_/
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
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 :
```
justine@portnut > target/release/portnut -h
A simple TCP port scanner / stresser. If stressing, you can pass a payload via a pipe
A simple TCP/HTTP 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:
-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]
-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)
-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
-c, --cthreads <CTHREADS> How many threads per port when stressing (Concurrent Threads) [default: 5]
-h, --help Print help
-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 std::io::prelude::*;
use std::io::{self, Read};
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::time::{Duration, Instant};
use std::thread;
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<()> {
@ -13,9 +19,12 @@ fn main() -> std::io::Result<()> {
let address = args.address;
let timeout = Duration::from_secs(args.timeout);
let sleep = Duration::from_millis(args.wait);
let duration = Duration::from_secs(args.duration);
let ports = handle_ports(args.ports.clone(), &args.range);
let threads = args.cthreads;
print_banner();
//Reading the payload from stdin (if applicable)
let mut payload = String::new();
let aatty = atty::is(Stream::Stdin);
@ -26,13 +35,26 @@ fn main() -> std::io::Result<()> {
payload = "SAKAMOTO".to_string();
}
if args.stress {
tcp_stress(payload, address, timeout, sleep, ports, threads)?;
} else {
tcp_scan(address, timeout, sleep, ports)?;
match args.mode.as_str() {
"tcpstress" => {
println!("===== TCP STRESS TEST =====");
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.
@ -50,115 +72,47 @@ fn handle_ports(ports: Vec<u32>, range: &bool) -> Vec<u32> {
}
}
fn print_banner() {
let lines = [
" ____ ____ ____ _______ ____ ________",
" / __ \\/ __ \\/ __ \\/_ __/ | / / / / /_ __/",
" / /_/ / / / / /_/ / / / / |/ / / / / / / ",
" / ____/ /_/ / _, _/ / / / /| / /_/ / / / ",
"/_/ \\____/_/ |_| /_/ /_/ |_/\\____/ /_/ ",
];
///Scan the ports on address by attempting a tcp connection.
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);
for line in lines {
println!("{}", line);
}
println!("");
}
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
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
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.
///A simple TCP/HTTP port scanner / stresser.
///If stressing, you can pass a payload via a pipe.
#[derive(Debug, Parser)]
#[command(author, version, about, long_about = None)]
#[command(author = "Squip", version, long_about = None)]
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)]
address: String,
///Timeout for each connection in seconds
#[arg(short, long, default_value_t = 1)]
///Timeout for each connection in seconds, default 30
#[arg(short, long, default_value_t = 30)]
timeout: u64,
///Number of milliseconds to wait in between scans when scanning
///OR duration of stress when stress testing (in seconds)
///Number of milliseconds to wait in between scans or requests
#[arg(short, long, default_value_t = 30)]
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)
#[arg(short, long, value_parser, num_args=1.., value_delimiter=',')]
#[arg(short, long, value_parser, num_args=0.., value_delimiter=',')]
ports: Vec<u32>,
///Set this flag to treat the ports as a range rather than a list
#[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(())
}