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?

Posted in ,
Tags ,
3 comments
no trackbacks
Reddit Delicious

Comments

  1. Kay said 690 days later:

    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.

  2. nothingmuch said 824 days later:

    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 ;-)

  3. tasos said 1066 days later:

    oh my god

Trackbacks

Use the following link to trackback from your own site:
http://blog.moertel.com/articles/trackback/38

(leave url/email »)

   Comment Markup Help Preview comment