class Portfinder::Scanner
Portfinder
Scanner
base class
Attributes
monitor[R]
Scan monitor accessor for in-scan monitoring and logging (readonly)
randomize[R]
Readonly port randomization flag
result[R]
Provides access to raw scan result
Public Class Methods
new(target, port, config = { randomize: true, threaded: true, threads: 10, thread_for: :port)
click to toggle source
Scanner
initializer
# File lib/portfinder/scanner.rb 12 def initialize target, port, config = { 13 randomize: true, threaded: true, threads: 10, thread_for: :port 14 } 15 @hosts = host_range target 16 @randomize = config[:randomize] 17 @ports = port_range port 18 @threaded = config[:threaded] 19 @thread_for = config[:thread_for] 20 @result = {} 21 @monitor = Monitor.new 22 @pool = 23 Pool.new( 24 threads_to_open( 25 @thread_for, config[:threads], @hosts, @ports 26 ) 27 ) 28 end
Public Instance Methods
generate_result(pretty = false)
click to toggle source
Generates scan result in the specified format
# File lib/portfinder/scanner.rb 61 def generate_result pretty = false 62 @result = @pool.complete_result if @threaded 63 pretty ? pretty_print(@result) : @result 64 end
json_report()
click to toggle source
Generates a JSON report
# File lib/portfinder/scanner.rb 79 def json_report 80 report_as :json 81 end
log(&logger)
click to toggle source
Defines a logger (accepts logger as a block)
# File lib/portfinder/scanner.rb 56 def log &logger 57 Thread.new { logger.call @monitor } 58 end
report_as(format)
click to toggle source
Generates a report in the specified format from the scan result
# File lib/portfinder/scanner.rb 67 def report_as format 68 case format 69 when :json 70 JSON.pretty_generate @result 71 when :yml 72 YAML.dump @result 73 else 74 raise ArgumentError, "Unknown format: #{format}" 75 end 76 end
scan(synchronus = true, &callback)
click to toggle source
Scans host(s) according to provided specification
# File lib/portfinder/scanner.rb 31 def scan synchronus = true, &callback 32 @monitor.start 33 if @threaded 34 case @thread_for 35 when :ip 36 scan_threaded_ip 37 when :port 38 scan_threaded_port 39 end 40 41 if synchronus 42 @pool.shutdown 43 @monitor.stop 44 elsif callback 45 @pool.shutdown(false) do 46 callback.call 47 @monitor 48 end 49 end 50 else 51 synchronus_scan 52 end 53 end
yml_report()
click to toggle source
Generates a YAML report
# File lib/portfinder/scanner.rb 84 def yml_report 85 report_as :yml 86 end
Private Instance Methods
host_range(target)
click to toggle source
# File lib/portfinder/scanner.rb 121 def host_range target 122 type = target.class 123 if [Array, Enumerator].include? type 124 target 125 elsif type == String 126 [target] 127 else 128 [] 129 end 130 end
port_open?(host, port)
click to toggle source
# File lib/portfinder/scanner.rb 199 def port_open? host, port 200 socket = Socket.new :INET, :STREAM, 0 201 address = Socket.pack_sockaddr_in(port, host) 202 203 begin 204 socket.connect address 205 socket.close 206 port 207 rescue StandardError 208 nil 209 end 210 end
port_range(port)
click to toggle source
:reek: FeatureEnvy
# File lib/portfinder/scanner.rb 133 def port_range port 134 port = port.dup 135 port = [port] if port.class == Integer 136 @randomize ? port.to_a.shuffle : port 137 end
pretty_print(result)
click to toggle source
# File lib/portfinder/scanner.rb 90 def pretty_print result 91 formatted = "Scan complete!\n\n" 92 result.keys.each do |ip| 93 ports = result[ip].to_s.gsub(/[\[\]]/, "") 94 formatted << "IP: #{ip}\n\tOpen ports: #{ports}\n\n" 95 end 96 97 formatted 98 end
scan_synchronized_port()
click to toggle source
# File lib/portfinder/scanner.rb 182 def scan_synchronized_port 183 scannable_pairs(@hosts, @ports).each do |pair| 184 host, port = pair 185 @monitor.update(*pair) 186 187 if port_open?(*pair) 188 ports = @result[host] 189 @result[host] = ports ? ports.push(port).sort : [port] 190 end 191 end 192 end
scan_threaded_ip()
click to toggle source
# File lib/portfinder/scanner.rb 139 def scan_threaded_ip 140 @monitor.threads = @pool.size 141 @pool.result_format do |result, args, value| 142 result = result.dup 143 if value.any? 144 host = args[0] 145 result[host] = value 146 end 147 result 148 end 149 150 @hosts.each do |host| 151 @pool.schedule host do 152 open_ports = [] 153 @ports.each do |port| 154 @monitor.update host, port 155 open_ports << port if port_open? host, port 156 end 157 open_ports.sort 158 end 159 end 160 end
scan_threaded_port()
click to toggle source
# File lib/portfinder/scanner.rb 162 def scan_threaded_port 163 @monitor.threads = @pool.size 164 @pool.result_format do |result, args, value| 165 result = result.dup 166 if value 167 host = args[0][0] 168 ports = result[host] 169 result[host] = ports ? ports.push(value).sort : [value] 170 end 171 result 172 end 173 174 scannable_pairs(@hosts, @ports).each do |pair| 175 @pool.schedule(pair) do 176 @monitor.update(*pair) 177 port_open?(*pair) 178 end 179 end 180 end
scannable_pairs(hosts, ports)
click to toggle source
# File lib/portfinder/scanner.rb 100 def scannable_pairs hosts, ports 101 Enumerator.new(hosts.size * ports.size) do |pair| 102 hosts.each do |host| 103 ports.each do |port| 104 pair << [host, port] 105 end 106 end 107 end 108 end
synchronus_scan()
click to toggle source
# File lib/portfinder/scanner.rb 194 def synchronus_scan 195 scan_synchronized_port 196 @monitor.stop 197 end
threads_to_open(thread_for, max, hosts, ports)
click to toggle source
# File lib/portfinder/scanner.rb 110 def threads_to_open thread_for, max, hosts, ports 111 case thread_for 112 when :ip 113 host_count = hosts.size 114 host_count > max ? max : host_count 115 when :port 116 tasks = scannable_pairs(hosts, ports).size 117 tasks > max ? max : tasks 118 end 119 end