Port Scanning

Due March 26, 2010

The first program is a port prober. When started with the command line
    java portscan ulam2.cs.luc.edu 2000 2100
then connection will be attempted to every port on ulam2.cs.luc.edu between 2000 and 2100. When a connection is accepted, the first 1K of data will be read from remotehost, if any. (Ideally, a read of up to 1K will be attempted; it may block after returning much less than that. You should, however, continue reading until a timeout occurs; the read() may simply have returned less than 1K because the smaller amount was immediately available.)

You will need to implement timeouts for reading, because the remote host may not in fact ever send anything. It is also possible to set a timeout for the action of connecting itself, but this is less important because under normal circumstances the remote machine will immediately return either SYN+ACK (connection accepted) or RST (connection refused). However, if the remote machine is unavailable or the port is blocked by an intervening router, the connection delay can be substantial (several minutes). Making connections with timeout is demonstrated in quickconnect.java.

Timeout values in the range of 1000 milliseconds can be used. 1000 milliseconds times 100 ports is, of course, close to two minutes, but most ports respond more promptly.

Print something for each port; nonactive port ranges can be summarized eg with
   ports 3489-3621: no connections

To do a read with timeout, you use a two-step process. First, you set the socket timeout with s.setSoTimeout(timeoutval) (timeoutval is again in milliseconds); you need to catch SocketException but you can treat that as a fatal error. You can do this at any point in the program; you probably should do it soon after creating the socket. 

To read data from a socket s, with or without timeout, you actually read from s.getInputStream(), of type InputStream. An example of this appears in tcp_stalks.java, where s.getInputStream() is then converted to an InputStreamReader and then to a BufferedReader.

If you've set s.setSoTimeout(), either before or after calling s.getInputStream(), then any input-related read operation on the inputstream (or its descendants) (eg readLine()) will, if nothing is received over the network during the timeout interval, throw the SocketTimeoutException exception. Note that this is a SocketTimeoutException even though the underlying socket is not evident and it looks like you're reading from a generic InputStream.

You can catch a SocketTimeoutException from any read-type call on an InputStream that derived from a Socket, but this exception will never be thrown unless you have executed s.setSoTimeout(val) at some point.

You do not need threads with this program; just check each port in turn. (If you were allowing very long timeouts, threads would allow ports to be queried in parallel, but that's not an issue here.) I would get started with the stalkc.java/stalks.java files. Also note that stalkc.java creates a new connection and then writes data; portscan.java will create a new connection and then read.

You do not need to do any fancy block-oriented reads; you can just use the InputStream.read() method.  You first get the associated stream:
      InputStream  is = sock.getInputStream();
At this point you can read and write, eg
    int readsize = is.read(buf);
A readsize of -1 or 0 means you're done. So does a timeout. Note that it is the socket and not the InputStream that has the timeout interval set:
    sock.setSoTimeout();
   
Note that the approach to portscanning here goes through a full three-way handshake on each port. That means that the scan attempt will be recognized by the server-side application. There is a whole series of techniques for "stealth" scans, involving sending something like a broken opening handshake or even just a FIN; the goal is to find something to send such that the server will respond differently if the port is open versus closed, and such that the server will be unlikely to log the probe. These techniques almost by definition do not create an open connection, and so do not permit reading of data.


Files:
    quickconnect.java
    tcp_stalks.java
    tcp_stalkc.java
    tcp_stalkc.py       if you would rather work in python3