Skip to content

Commit

Permalink
FEAT: simple TCP port scanner (module)
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Feb 16, 2021
1 parent 6bf2b8a commit c990e82
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
100 changes: 100 additions & 0 deletions src/modules/port-scanner.reb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
Rebol [
Title: "TCP Port scanner"
File: %port-scanner.reb
Type: module
Name: port-scanner
Version: 1.0.0
Date: 16-Feb-2021
Exports: [scan-ports]
Note: {
If you use anything other than `localhost` you had better have permission
for the host name you do use, or you will suddenly be an *internet bad guy*.
Don't.}
]

; result:
found: copy []

; options:
batch-size: 8000 ; higher batch size means higher CPU use!
timeout: 0:0:0.5 ; setting timeout too low may result in not resolved opened ports!

; actor:
on-awake: func [event /local port id] [
port: event/port
;print [as-green "==TCP-event:" as-red event/type "port:" as-red port/spec/port-id]
switch/default event/type [
lookup [open port]
connect [
id: port/spec/port-id
print ["Open port found:" as-red id]
append found id
false
]
][true]
]

scan-ports: function [
from [integer!] "lowest port numer"
to [integer!] "max port number"
/host name [tuple! string!]
][
clear found
checking: make block! batch-size
started: now/time/precise

if to < from [id: to to: from from: id]

id: low:
from: max 1 from
to: max 1 min to 65535

total: 1 + to - from

try/except [
ip: either tuple? name [ name ][
read join dns:// any [name 'localhost]
]
][
sys/log/error 'REBOL system/state/last-error
return none
]

print [
as-green "Using IP:" as-yellow ip
as-green "timeout:" as-yellow timeout
as-green "batch size:" as-yellow batch-size
newline
]

while [id <= to][
port: make port! compose [
scheme: 'tcp
host: (ip)
port-id: (id)
awake: :on-awake
]
open port
append checking port
if any [
id = to
batch-size = length? checking
][
print [as-green "Checking range:" as-yellow low "-" as-yellow id]
; wait some time...
wait timeout
; and check what was opened...
foreach port checking [ close port ]
clear checking
if id < to [ low: low + batch-size ]
]
++ id
]
checking: none
print ajoin [
as-green "^/Scan of " as-yellow total
as-green " ports finished in time: " as-yellow now/time/precise - started
as-green ".^/Found " as-red length? found as-green " listening TCP ports!^/"
]
found
]
21 changes: 21 additions & 0 deletions src/tests/test-port-scanner.r3
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Rebol [
Title: "Test async TCP port scanner"
File: %test-port-scanner.r3
Date: 16-Feb-2021
]

scanner: import 'port-scanner

;- higher batch size means higher CPU use!
;scanner/batch-size: 10000
;- low timeout may result in not founding all listening ports!
;- if the scenner is used on non local ip, the timeout should
;- count with netword latency!
;scanner/timeout: 0:0:0.25

scan-ports/host 1 65535 127.0.0.1

if system/options/script [
?? scanner/found
ask "^/DONE"
]

0 comments on commit c990e82

Please sign in to comment.