Skip to content

Commit dbc4a1a

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 dbc4a1a

File tree

4 files changed

+120
-39
lines changed

4 files changed

+120
-39
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ 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 [default: 1]
245246
-u, --ulimit <ulimit> Automatically ups the ULIMIT with the value you provided
246247

247248
ARGS:
@@ -260,7 +261,7 @@ Your operating system may not support this, but it is worth it to play around an
260261

261262
## Configuration file
262263

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

266267
- `addresses`
@@ -272,6 +273,7 @@ and accepts the following fields:
272273
- `greppable`
273274
- `batch-size`
274275
- `timeout`
276+
- `tries`
275277
- `ulimit`
276278

277279
### Format example
@@ -286,6 +288,7 @@ accessible = true
286288
scan_order = "Serial"
287289
batch_size = 1000
288290
timeout = 1000
291+
tries = 3
289292
ulimit = 1000
290293
```
291294

src/input.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ 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+
#[structopt(long, default_value = "1")]
100+
pub tries: u8,
101+
98102
/// Automatically ups the ULIMIT with the value you provided.
99103
#[structopt(short, long)]
100104
pub ulimit: Option<rlimit::rlim>,
@@ -153,7 +157,9 @@ impl Opts {
153157
}
154158
}
155159

156-
merge_required!(addresses, greppable, accessible, batch_size, timeout, scan_order, command);
160+
merge_required!(
161+
addresses, greppable, accessible, batch_size, timeout, tries, scan_order, command
162+
);
157163
}
158164

159165
fn merge_optional(&mut self, config: &Config) {
@@ -195,6 +201,7 @@ pub struct Config {
195201
accessible: Option<bool>,
196202
batch_size: Option<u16>,
197203
timeout: Option<u32>,
204+
tries: Option<u8>,
198205
no_nmap: Option<bool>,
199206
ulimit: Option<rlimit::rlim>,
200207
scan_order: Option<ScanOrder>,
@@ -252,6 +259,7 @@ mod tests {
252259
greppable: Some(true),
253260
batch_size: Some(25_000),
254261
timeout: Some(1_000),
262+
tries: Some(1),
255263
ulimit: None,
256264
no_nmap: Some(false),
257265
command: Some(vec!["-A".to_owned()]),
@@ -270,6 +278,7 @@ mod tests {
270278
greppable: true,
271279
batch_size: 0,
272280
timeout: 0,
281+
tries: 0,
273282
ulimit: None,
274283
command: vec![],
275284
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: 105 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use std::{
1414
time::Duration,
1515
};
1616

17+
use super::warning;
18+
1719
/// The class for the scanner
1820
/// IP is data type IpAddr and is the IP address
1921
/// start & end is where the port scan starts and ends
@@ -26,6 +28,7 @@ pub struct Scanner {
2628
ips: Vec<IpAddr>,
2729
batch_size: u16,
2830
timeout: Duration,
31+
tries: u8,
2932
greppable: bool,
3033
port_strategy: PortStrategy,
3134
accessible: bool,
@@ -36,13 +39,20 @@ impl Scanner {
3639
ips: &[IpAddr],
3740
batch_size: u16,
3841
timeout: Duration,
42+
tries: u8,
3943
greppable: bool,
4044
port_strategy: PortStrategy,
4145
accessible: bool,
4246
) -> Self {
4347
Self {
4448
batch_size,
4549
timeout,
50+
tries: if tries == 0 {
51+
warning!("tries is 0, corrected to 1!");
52+
1
53+
} else {
54+
tries
55+
},
4656
greppable,
4757
port_strategy,
4858
ips: ips.iter().map(|ip| ip.to_owned()).collect(),
@@ -87,54 +97,72 @@ impl Scanner {
8797
open_sockets
8898
}
8999

90-
/// Given a port, scan it.
100+
/// Given a port, scan it self.tries times.
91101
/// Turns the address into a SocketAddr
92102
/// Deals with the <result> type
93103
/// 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.
104+
/// Else any other error, it returns the error in Result as a string
105+
/// If no errors occur, it returns the port number in Result to signify the port is open.
96106
/// This function mainly deals with the logic of Results handling.
97107
/// # Example
98108
///
99109
/// self.scan_port(10:u16)
100110
///
101111
/// Note: `self` must contain `self.ip`.
102112
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());
113+
debug!("self.tries: {}", self.tries);
114+
for nr_try in 1..=self.tries {
115+
debug!("Try number: {}", nr_try);
116+
117+
match self.connect(socket).await {
118+
Ok(x) => {
119+
debug!(
120+
"Connection was successful, shutting down stream {}",
121+
&socket
122+
);
123+
match x.shutdown(Shutdown::Both) {
124+
Err(e) => debug!("Shutdown stream error {}", &e),
125+
_ => {}
118126
}
127+
if !self.greppable {
128+
if self.accessible {
129+
println!("Open {}", socket.to_string());
130+
} else {
131+
println!("Open {}", socket.to_string().purple());
132+
}
133+
}
134+
135+
debug!("Return Ok after {} tries", nr_try);
136+
return Ok(socket);
119137
}
138+
Err(e) => {
139+
let error = match e.kind() {
140+
ErrorKind::Other => {
141+
let error_string = e.to_string();
142+
if error_string.contains("No route to host")
143+
|| error_string.contains("Network is unreachable")
144+
{
145+
debug!("Socket connect error: {} {}", &e.to_string(), &socket);
146+
Err(io::Error::new(io::ErrorKind::Other, e.to_string()))
147+
} else {
148+
debug!("Socket connect error: {} {}", &e.to_string(), &socket);
149+
panic!("Too many open files. Please reduce batch size. The default is 5000. Try -b 2500.");
150+
}
151+
}
152+
_ => Err(io::Error::new(io::ErrorKind::Other, e.to_string())),
153+
};
120154

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.");
155+
if nr_try == self.tries {
156+
debug!("Return Err after {} tries", self.tries);
157+
return error;
133158
}
134159
}
135-
_ => Err(io::Error::new(io::ErrorKind::Other, e.to_string())),
136-
},
160+
};
137161
}
162+
return Err(io::Error::new(
163+
io::ErrorKind::Other,
164+
format!("self.tries is {} so port scanning is not done!", self.tries),
165+
));
138166
}
139167

140168
/// Performs the connection to the socket with timeout
@@ -174,7 +202,15 @@ mod tests {
174202
end: 1_000,
175203
};
176204
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
177-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
205+
let scanner = Scanner::new(
206+
&addrs,
207+
10,
208+
Duration::from_millis(100),
209+
1,
210+
true,
211+
strategy,
212+
true,
213+
);
178214
block_on(scanner.run());
179215
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
180216
assert_eq!(1, 1);
@@ -188,7 +224,15 @@ mod tests {
188224
end: 1_000,
189225
};
190226
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
191-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
227+
let scanner = Scanner::new(
228+
&addrs,
229+
10,
230+
Duration::from_millis(100),
231+
1,
232+
true,
233+
strategy,
234+
true,
235+
);
192236
block_on(scanner.run());
193237
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
194238
assert_eq!(1, 1);
@@ -201,7 +245,15 @@ mod tests {
201245
end: 1_000,
202246
};
203247
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
204-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
248+
let scanner = Scanner::new(
249+
&addrs,
250+
10,
251+
Duration::from_millis(100),
252+
1,
253+
true,
254+
strategy,
255+
true,
256+
);
205257
block_on(scanner.run());
206258
assert_eq!(1, 1);
207259
}
@@ -213,7 +265,15 @@ mod tests {
213265
end: 445,
214266
};
215267
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
216-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
268+
let scanner = Scanner::new(
269+
&addrs,
270+
10,
271+
Duration::from_millis(100),
272+
1,
273+
true,
274+
strategy,
275+
true,
276+
);
217277
block_on(scanner.run());
218278
assert_eq!(1, 1);
219279
}
@@ -228,7 +288,15 @@ mod tests {
228288
end: 600,
229289
};
230290
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
231-
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
291+
let scanner = Scanner::new(
292+
&addrs,
293+
10,
294+
Duration::from_millis(100),
295+
1,
296+
true,
297+
strategy,
298+
true,
299+
);
232300
block_on(scanner.run());
233301
assert_eq!(1, 1);
234302
}

0 commit comments

Comments
 (0)