Concurrent port scanner in Haskell
Posted by Tom Moertel Sat, 13 Mar 2004 17:00:00 GMT
In another draft of his article about Scheme programming, jacob shows how he approaches the problem of writing a TCP port scanner. That seemed like a fun problem, and so I whipped up this version in one of my favorite programming languages, Haskell:
module Main (main) where
import Control.Concurrent
import Control.Exception
import Data.Maybe
import Network
import Network.BSD
import System.Environment
import System.Exit
import System.IO
main :: IO ()
main = do
args <- getArgs
case args of
[host, from, to] -> withSocketsDo $
scanRange host [read from .. read to]
_ -> usage
usage = do
hPutStrLn stderr "Usage: Portscan host from_port to_port"
exitFailure
scanRange host ports =
mapM (threadWithChannel . scanPort host . fromIntegral) ports >>=
mapM_ hitCheck
where
hitCheck mvar = takeMVar mvar >>= maybe (return ()) printHit
printHit port = putStrLn =<< showService port
threadWithChannel action = do
mvar <- newEmptyMVar
forkIO (action >>= putMVar mvar)
return mvar
scanPort host port =
withDefault Nothing (tryPort >> return (Just port))
where
tryPort = connectTo host (PortNumber port) >>= hClose
showService port =
withDefault (show port) $ do
service <- getServiceByPort port "tcp"
return (show port ++ " " ++ serviceName service)
withDefault defaultVal action =
handle (const $ return defaultVal) action
-- Local Variables: ***
-- compile-command: "ghc -o Portscan --make Portscan.hs" ***
-- End: ***
Example usage:
$ ./Portscan internalhost.moertel.com 1 1000
21 ftp
22 ssh
80 http
111 sunrpc
139 netbios-ssn
443 https
445 microsoft-ds
631 ipp
709
720
Care to give it a try in your favorite programming language?
readers


Awesome. That’s some well-written Haskell code.
I’ve never seen the “case args of [a,b,c]” thing before. I’ve been doing it with ”!!”.
Also, you should post this on the haskell wiki.
FWIW, your version is connect based while the versions he seemed to like abstract over pcap or something like that.
I personally found the code pretty clear and interesting, and surprisingly concise for it’s async nature.
What I would do to improve it as someone who is not really used to haskell is to use less point-free notation where crucial decisions are being made. This way bits of data that have significance are bound to symbols at the point where they make a difference, helping to draw attension to more subtle details.
But maybe I’m just not used to reading haskell ;-)
oh my god