Updated 2012-07-30 02:20:53 by RLE
 #!/bin/sh
 # the next line restarts using -*-Tcl-*-sh \
 exec tclsh "$0" ${1+"$@"}

 # records all attempts to connect to the ports listed
 # in the portlist.
 # log lines consist of a timestamp, the port number
 # that was connected to, and client peer info.
 # original version by: phil@slug.org 

 set portlist [ list 6667 8080 31337 ]

 proc cfg { cid addr port } {
     fileevent $cid writable "handle $cid"
     fconfigure $cid -blocking  off
 }

 proc handle { cid } {
     set peerinfo [ fconfigure $cid -peername ]
     set port     [ fconfigure $cid -sockname ]
     close $cid
     set port [ lindex $port 2 ]
     set time [ clock seconds ]
     set time [ clock format $time -format "%m/%d/%y-%r %Z" ]
     puts stdout "$time $port $peerinfo"
 }

 foreach port $portlist {
    socket -server cfg $port
 }   
 vwait enter-mainloop

See also: fileevent

See also: Port scanning in tcl

TP 14Sep2005 If your purpose is to detect malicious scanners, perhaps make it somewhat painful for them, by leaving the socket open for a bit? Replace
     close $cid

with:
     set some_pain [expr {60 * 1000}]
     after $some_pain [list close $cid]
     fileevent $cid writable {}

Optimally, you wouldn't leave sockets open, chewing up resources. I once attended a talk by Marcus Ranum [1] where he described changing kernel TCP code to send back the TCP handshake, but otherwise ignore the connection. No need to play fair with scanners.

(SS I don't know what is the date of the Ranum's talk, btw I think I was one of the first to propose this a lot of time ago, see http://seclists.org/lists/bugtraq/1999/Jul/0150.html)

SS Another interesting approach can be to open tcpdump from Tcl and analyze the traffic. Btw port scanning detection is nearly useless, if the server is secured against known attacks to know that somebody is scanning you is not needed, if the server is insecure what to do if somebody is scanning you? To close all the services causing an auto-denial-of-service? ;)

rdt Well, no what you do is to drop all traffic from that IP. See AutoDrop.