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 portfinderUsage
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 80It is possible to scan multiple ports of a host. In this case, ports can be a range,
portfinder 192.168.1.1 -p 1-1024Or, a list of selections:
portfinder 192.168.1.1 -p 22,80,8080,443Similarly, 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-65535or, a range of hosts,
portfinder 192.168.1.1-10 -p 1-65535or, on an entire network block, if you like.
portfinder 192.168.1.0/24 -p 1-65535If 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 20By 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 -rAs 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_reportIt 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.closeMode 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 10Please 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.