Created
February 3, 2025 00:14
-
-
Save jmsdnns/bc5edf4c2ef319f35d511d58c4988325 to your computer and use it in GitHub Desktop.
A port scanner in Ocaml. Rudimentary form done to learn how Ocaml does networking.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Scanner = struct | |
(* attempt to open a port and return an option *) | |
let open_port host port timeout = fun () -> | |
let open Lwt.Infix in | |
let sockaddr = Unix.ADDR_INET (Unix.inet_addr_of_string host, port) in | |
let socket = Lwt_unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in | |
Lwt.catch | |
(* Port is open *) | |
(fun () -> | |
Lwt_unix.connect socket sockaddr >>= fun () -> | |
Lwt_unix.close socket >>= fun () -> | |
Lwt.return (Some port) | |
) | |
(* Port is closed *) | |
(fun _ -> | |
Lwt_unix.close socket >>= fun () -> | |
Lwt.return None | |
) | |
(* scans a port by trying to open it or timing out *) | |
let scan_port host port timeout = | |
let open Lwt.Infix in | |
let connect_task = open_port host port timeout in | |
let timeout_task = Lwt_unix.sleep timeout >>= fun () -> Lwt.fail Lwt_unix.Timeout in | |
Lwt.pick [connect_task (); timeout_task] >>= function | |
| Some port -> Lwt.return (Some port) | |
| None -> Lwt.return None | |
(* scans a range of port *) | |
let scan_ports host start_port end_port timeout = | |
let open Lwt.Infix in | |
let ports = List.init (end_port - start_port + 1) (fun i -> start_port + i) in | |
let scan_results = | |
List.map (fun port -> | |
scan_port host port timeout >>= function | |
| Some port -> Printf.printf "Port %d is open\n" port; Lwt.return () | |
| None -> Printf.printf "Port %d is closed\n" port; Lwt.return () | |
) ports | |
in | |
Lwt.join scan_results | |
end | |
let () = | |
let host = "127.0.0.1" in | |
let start_port = 8000 in | |
let end_port = 8090 in | |
let timeout = 2.0 in | |
let open Lwt.Infix in | |
Lwt_main.run ( | |
Scanner.scan_ports host start_port end_port timeout >>= fun () -> Lwt.return () | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment