Skip to content

Commit e368a2b

Browse files
committed
Add tries to scan_socket.
By default the number of try is 1, it can be set on the command line by using --tries option. This should close #38.
1 parent 5b35a09 commit e368a2b

File tree

4 files changed

+111
-40
lines changed

4 files changed

+111
-40
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ OPTIONS:
242242
ascending order while the "random" option will scan ports randomly [default:
243243
serial] [possible values: Serial, Random]
244244
-t, --timeout <timeout> The timeout in milliseconds before a port is assumed to be closed [default: 1500]
245+
--tries <tries> The number of tries before a port is assumed to be closed. If set to 0, rustscan
246+
will correct it to 1 [default: 1]
245247
-u, --ulimit <ulimit> Automatically ups the ULIMIT with the value you provided
246248

247249
ARGS:
@@ -260,7 +262,7 @@ Your operating system may not support this, but it is worth it to play around an
260262

261263
## Configuration file
262264

263-
This binary accepts a configuration file that is read from the home directory of the user. It follows the TOML format
265+
This binary accepts a configuration file, named `.rustscan.toml`, that is read from the home directory of the user. It follows the TOML format
264266
and accepts the following fields:
265267

266268
- `addresses`
@@ -272,6 +274,7 @@ and accepts the following fields:
272274
- `greppable`
273275
- `batch-size`
274276
- `timeout`
277+
- `tries`
275278
- `ulimit`
276279

277280
### Format example
@@ -286,6 +289,7 @@ accessible = true
286289
scan_order = "Serial"
287290
batch_size = 1000
288291
timeout = 1000
292+
tries = 3
289293
ulimit = 1000
290294
```
291295

src/input.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ pub struct Opts {
9595
#[structopt(short, long, default_value = "1500")]
9696
pub timeout: u32,
9797

98+
/// The number of tries before a port is assumed to be closed.
99+
/// If set to 0, rustscan will correct it to 1.
100+
#[structopt(long, default_value = "1")]
101+
pub tries: u8,
102+
98103
/// Automatically ups the ULIMIT with the value you provided.
99104
#[structopt(short, long)]
100105
pub ulimit: Option<rlimit::rlim>,
@@ -153,7 +158,9 @@ impl Opts {
153158
}
154159
}
155160

156-
merge_required!(addresses, greppable, accessible, batch_size, timeout, scan_order, command);
161+
merge_required!(
162+
addresses, greppable, accessible, batch_size, timeout, tries, scan_order, command
163+
);
157164
}
158165

159166
fn merge_optional(&mut self, config: &Config) {
@@ -195,6 +202,7 @@ pub struct Config {
195202
accessible: Option<bool>,
196203
batch_size: Option<u16>,
197204
timeout: Option<u32>,
205+
tries: Option<u8>,
198206
no_nmap: Option<bool>,
199207
ulimit: Option<rlimit::rlim>,
200208
scan_order: Option<ScanOrder>,
@@ -252,6 +260,7 @@ mod tests {
252260
greppable: Some(true),
253261
batch_size: Some(25_000),
254262
timeout: Some(1_000),
263+
tries: Some(1),
255264
ulimit: None,
256265
no_nmap: Some(false),
257266
command: Some(vec!["-A".to_owned()]),
@@ -270,6 +279,7 @@ mod tests {
270279
greppable: true,
271280
batch_size: 0,
272281
timeout: 0,
282+
tries: 0,
273283
ulimit: None,
274284
command: vec![],
275285
accessible: false,

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ fn main() {
7777
&ips,
7878
batch_size,
7979
Duration::from_millis(opts.timeout.into()),
80+
opts.tries,
8081
opts.greppable,
8182
PortStrategy::pick(opts.range, opts.ports, opts.scan_order),
8283
opts.accessible,

src/scanner/mod.rs

Lines changed: 94 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use futures::stream::FuturesUnordered;
1111
use std::{
1212
io::ErrorKind,
1313
net::{IpAddr, Shutdown, SocketAddr},
14+
num::NonZeroU8,
1415
time::Duration,
1516
};
1617

@@ -26,6 +27,7 @@ pub struct Scanner {
2627
ips: Vec<IpAddr>,
2728
batch_size: u16,
2829
timeout: Duration,
30+
tries: NonZeroU8,
2931
greppable: bool,
3032
port_strategy: PortStrategy,
3133
accessible: bool,
@@ -36,13 +38,15 @@ impl Scanner {
3638
ips: &[IpAddr],
3739
batch_size: u16,
3840
timeout: Duration,
41+
tries: u8,
3942
greppable: bool,
4043
port_strategy: PortStrategy,
4144
accessible: bool,
4245
) -> Self {
4346
Self {
4447
batch_size,
4548
timeout,
49+
tries: NonZeroU8::new(std::cmp::max(tries, 1)).unwrap(),
4650
greppable,
4751
port_strategy,
4852
ips: ips.iter().map(|ip| ip.to_owned()).collect(),
@@ -87,54 +91,66 @@ impl Scanner {
8791
open_sockets
8892
}
8993

90-
/// Given a port, scan it.
94+
/// Given a socket, scan it self.tries times.
9195
/// Turns the address into a SocketAddr
9296
/// Deals with the <result> type
9397
/// If it experiences error ErrorKind::Other then too many files are open and it Panics!
94-
/// ese any other error, it returns the error in Result as a string
95-
/// If no errors occur, it returns the port number in Result to signify the port is open.
98+
/// Else any other error, it returns the error in Result as a string
99+
/// If no errors occur, it returns the port number in Result to signify the port is open.
96100
/// This function mainly deals with the logic of Results handling.
97101
/// # Example
98102
///
99-
/// self.scan_port(10:u16)
103+
/// self.scan_socket(socket)
100104
///
101105
/// Note: `self` must contain `self.ip`.
102106
async fn scan_socket(&self, socket: SocketAddr) -> io::Result<SocketAddr> {
103-
match self.connect(socket).await {
104-
Ok(x) => {
105-
debug!(
106-
"Connection was successful, shutting down stream {}",
107-
&socket
108-
);
109-
match x.shutdown(Shutdown::Both) {
110-
Err(e) => debug!("Shutdown stream error {}", &e),
111-
_ => {}
112-
}
113-
if !self.greppable {
114-
if self.accessible {
115-
println!("Open {}", socket.to_string());
116-
} else {
117-
println!("Open {}", socket.to_string().purple());
107+
let tries = self.tries.get();
108+
109+
debug!("self.tries: {}", tries);
110+
111+
for nr_try in 1..=tries {
112+
debug!("Try number: {}", nr_try);
113+
114+
match self.connect(socket).await {
115+
Ok(x) => {
116+
debug!(
117+
"Connection was successful, shutting down stream {}",
118+
&socket
119+
);
120+
if let Err(e) = x.shutdown(Shutdown::Both) {
121+
debug!("Shutdown stream error {}", &e);
122+
}
123+
if !self.greppable {
124+
if self.accessible {
125+
println!("Open {}", socket.to_string());
126+
} else {
127+
println!("Open {}", socket.to_string().purple());
128+
}
118129
}
130+
131+
debug!("Return Ok after {} tries", nr_try);
132+
return Ok(socket);
119133
}
134+
Err(e) => {
135+
let error_string = e.to_string();
120136

121-
Ok(socket)
122-
}
123-
Err(e) => match e.kind() {
124-
ErrorKind::Other => {
125-
if e.to_string().contains("No route to host")
126-
|| e.to_string().contains("Network is unreachable")
127-
{
128-
debug!("Socket connect error: {} {}", &e.to_string(), &socket);
129-
Err(io::Error::new(io::ErrorKind::Other, e.to_string()))
130-
} else {
131-
debug!("Socket connect error: {} {}", &e.to_string(), &socket);
132-
panic!("Too many open files. Please reduce batch size. The default is 5000. Try -b 2500.");
137+
if e.kind() == ErrorKind::Other {
138+
debug!("Socket connect error: {} {}", &error_string, &socket);
139+
140+
if !error_string.contains("No route to host")
141+
&& !error_string.contains("Network is unreachable")
142+
{
143+
panic!("Too many open files. Please reduce batch size. The default is 5000. Try -b 2500.");
144+
}
145+
}
146+
147+
if nr_try == tries {
148+
return Err(io::Error::new(io::ErrorKind::Other, error_string));
133149
}
134150
}
135-
_ => Err(io::Error::new(io::ErrorKind::Other, e.to_string())),
136-
},
151+
};
137152
}
153+
unreachable!();
138154
}
139155

140156
/// Performs the connection to the socket with timeout
@@ -174,7 +190,15 @@ mod tests {
174190
end: 1_000,
175191
};
176192
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
177-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
193+
let scanner = Scanner::new(
194+
&addrs,
195+
10,
196+
Duration::from_millis(100),
197+
1,
198+
true,
199+
strategy,
200+
true,
201+
);
178202
block_on(scanner.run());
179203
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
180204
assert_eq!(1, 1);
@@ -188,7 +212,15 @@ mod tests {
188212
end: 1_000,
189213
};
190214
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
191-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
215+
let scanner = Scanner::new(
216+
&addrs,
217+
10,
218+
Duration::from_millis(100),
219+
1,
220+
true,
221+
strategy,
222+
true,
223+
);
192224
block_on(scanner.run());
193225
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
194226
assert_eq!(1, 1);
@@ -201,7 +233,15 @@ mod tests {
201233
end: 1_000,
202234
};
203235
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
204-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
236+
let scanner = Scanner::new(
237+
&addrs,
238+
10,
239+
Duration::from_millis(100),
240+
1,
241+
true,
242+
strategy,
243+
true,
244+
);
205245
block_on(scanner.run());
206246
assert_eq!(1, 1);
207247
}
@@ -213,7 +253,15 @@ mod tests {
213253
end: 445,
214254
};
215255
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
216-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
256+
let scanner = Scanner::new(
257+
&addrs,
258+
10,
259+
Duration::from_millis(100),
260+
1,
261+
true,
262+
strategy,
263+
true,
264+
);
217265
block_on(scanner.run());
218266
assert_eq!(1, 1);
219267
}
@@ -228,7 +276,15 @@ mod tests {
228276
end: 600,
229277
};
230278
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
231-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
279+
let scanner = Scanner::new(
280+
&addrs,
281+
10,
282+
Duration::from_millis(100),
283+
1,
284+
true,
285+
strategy,
286+
true,
287+
);
232288
block_on(scanner.run());
233289
assert_eq!(1, 1);
234290
}

0 commit comments

Comments
 (0)