Port Scanning
Due Tuesday, November 27, 2012
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-2000 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 in java, 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();
When you make a connection, either by new Socket(dest, destport) or by s.connect(sockaddr, timeout), you can check for a refused connection by catching the exception ConnectException.
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 to base your work on:
quickconnect.java
tcp_stalks.java
tcp_stalkc.java
tcp_stalkc.py if you would rather work in python3