Let's write a TCP Port Scanner In Rust
Hi, In this post I'm going to write a TCP Port Scanner In the Rust Programming Language. This Cli Program will have Three modes:
- Single: check a single port.
- Range: check a range of ports.
- List: check the list of ports.
Ok, Let's create a project:
Add the Clap
crate with derive
feature:
Now, declare the Command Line Interface(CLI) for our program with four arguments. Keep in mind that addr
is required and single
, range
, and list
is optional. of course each time the user gonna use just one of them
These are the CLI arguments we need:
Well done. The next thing to do is parse
the arguments, and check optional arguments based on Option
Enum which tells us if there is a Some
value or None
. This is our main
function:
fn main() {
let args = Cli::parse();
if let Some(single) = args.single {
scan_ports(&args.addr, vec![single]);
}
if let Some(range) = args.range {
let mut split = range.split("-");
let start: u16 = match split.next() {
Some(v) => v.parse().unwrap(),
None => panic!("range value is not valid, see pscan --help for more info")
};
let end: u16 = match split.next() {
Some(v) => v.parse().unwrap(),
None => panic!("range value is not valid, see pscan --help for more info")
};
let mut list = vec![];
(start..=end).into_iter().for_each(|x| list.push(x));
scan_ports(&args.addr, list);
}
if let Some(ports) = args.list {
let mut list = vec![];
let mut split = ports.split(",");
loop {
match split.next() {
Some(v) => {
list.push(v.parse().unwrap());
}
None => break
}
}
scan_ports(&args.addr, list);
}
}
So we parse the string
values to the u16
values which minimum value fit in this type is 0
and maximum is 65,535
which is the maximum valid port number.
Ok, What's next? If you look at the code above, We have a scan_ports
function which accepts reference of String &String
and a list of ports Vec<u16>
.
The mechanism of the program is simple:
- Connect to IP:Port with
TcpStream
. - If the connection succeeds, Then the Port is open.
- If not, the Port is closed.
But what is the handles
vector? we spawn threads for each port we have to check. If we just spawn and don't wait until they have done, the program gonna close and we will see nothing! So we have to join
on each thread to be able to see the result from each of them.
Usage
pscan 127.0.0.1 -s 443 // check the port 443
pscan 127.0.0.1 -r 75-82 // check the range between two number
pscan 127.0.0.1 -l 80,443,1080 // check three provided ports
This is great! we wrote our program 😃. Good Luck.
By the way, you can watch the youtube video of this Article: