Portfinder
Summary
Portfinder is a ruby based port scanner with features like network/CIDR scanning, port randomization, hostname discovery and banner grabbing.
Installation
Portfinder installation is as simple as a gem installation can get.
gem install portfinder
Usage
As a CLI tool
portfinder <host> [--port=PORT] [--thread=THREAD] [--randomize]
[--out=OUT_FILE] [--verbose]
portfinder
can also be invoked using it's aliased form pf
.
To it's simplest form, single port of a host can be scanned.
portfinder 192.168.1.1 -p 80
It is possible to scan multiple ports of a host. In this case, ports can be a range,
portfinder 192.168.1.1 -p 1-1024
Or, a list of selections:
portfinder 192.168.1.1 -p 22,80,8080,443
Similarly, a scan can be performed on a selection of hosts,
portfinder 192.168.1.1,192.168.1.100,192.168.1.101 -p 1-65535
or, a range of hosts,
portfinder 192.168.1.1-10 -p 1-65535
or, on an entire network block, if you like.
portfinder 192.168.1.0/24 -p 1-65535
If a large number of host needs to be scanned, you may choose to increase the
number of concurrent scanners using the available --thread
option.
portfinder 192.168.1.0/24 -p 1-65535 -t 20
By default, ten scanner threads are spawned at max.
When multiple ports are being scanned, they get scanned in the ascending order,
or in the provided port selection order. If a randomized scan order is expected,
--randomize
flag can be utilized.
portfinder 192.168.1.0/24 -r
As an API
A minimal usage example,
require "portfinder"
scanner = Portfinder::Scanner.new("192.168.1.1", [22, 80, 8080], threads = 5)
scanner.scan
puts "\nOpen ports detected: #{scanner.result[host]}"
puts "Raw scan result: #{scanner.result}"
yml_stream = scanner.report_as "yml"
json_stream = scanner.json_report
It is possible to use the API in different modes,
Mode 1: Blocking mode with monitoring
scanner =
Portfinder::Scanner.new(
hosts, ports,
randomize: false, threaded: true, threads: 10, thread_for: :port
)
scanner.log do |monitor|
puts "Active threads:\t#{monitor.threads}\nScanning now:\n"
while true
print "\tHost:\t#{monitor.host}\tPort:\t#{monitor.port}\tStatus: #{
monitor.state}\r"
sleep 0.1
end
end
scanner.scan
puts "\nScan complete!\n\nResult: #{scanner.generate_result}"
format = "json"
file = open("export.#{format}", "wb")
file.write scanner.report_as format.to_sym
file.close
Mode 2: Partial blocking (join during result invocation)
scanner = Portfinder::Scanner.new("192.168.0.101", 1..65535)
#logger can be placed here...
scanner.scan synchronus = false
# logger can be placed here...
puts "\nScan complete!\n\nResult: #{scanner.generate_result}"
Mode 3 (GUI): Non-blocking (callback invocation upon completion)
(NOTE: Parent thread must be alive to receive callback)
scanner = Portfinder::Scanner.new("192.168.0.101", 1..65535)
scanner.scan(false) do
puts "\nScan complete!\n\nResult: #{scanner.generate_result}"
end
# logger can be placed here...
sleep 10
Please note that the default scanner scans TCP ports using a full handshake (which is not, well..., stealthy. But, if you were expecting this feature, it's gonna be available on the TCP SYN scanner release).
It's also worth noting that, the current implementation doesn't check for host status (alive/dead). So, scan can be considerably slow for dead hosts.
Contributing
If you are interested in contributing, please submit a pull request.