Go to the documentation of this file.00001 
00002 import java.io.FileOutputStream;
00003 import java.io.IOException;
00004 import java.io.PrintStream;
00005 import java.net.InetAddress;
00006 import java.net.InetSocketAddress;
00007 import java.net.UnknownHostException;
00008 import java.text.SimpleDateFormat;
00009 import java.util.Calendar;
00010 import java.util.concurrent.ExecutorService;
00011 import java.util.concurrent.Executors;
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 public class PortScanner extends Thread implements PortConnect.Context
00026 {
00027 
00028     
00029 
00030 
00031     private final static int connectionTimeout = 0;
00032     
00033 
00034 
00035     private final static int  maxThreadCount = 1000;
00036     
00037 
00038 
00039     private final static int maxEndpointsToScan = 1024 * 1024;
00040     
00041 
00042 
00043 
00044     private final static boolean reportFailedEndpoints = false;
00045 
00046 
00047     
00048 
00049 
00050     private ServiceNames verboseServices;
00051 
00052 
00053 
00054     private PrintStream out;
00055 
00056 
00057     
00058 
00059 
00060     
00061 
00062 
00063     private boolean endpointDepleted;
00064     
00065 
00066 
00067     private RawIpAddress currentAddr;
00068     
00069 
00070 
00071     private int currentPort; 
00072     
00073 
00074 
00075     private RawIpAddress firstAddr;
00076     
00077 
00078 
00079     private RawIpAddress lastAddr;
00080     
00081 
00082 
00083     private int firstPort;
00084     
00085 
00086 
00087     private int lastPort;
00088     
00089 
00090     
00091 
00092     
00093 
00094 
00095     private int workerThreadCount = 0; 
00096     
00097 
00098 
00099     private int scannedEndpointCount = 0; 
00100     
00101 
00102 
00103     private int okEndpointCount  = 0;
00104     
00105 
00106 
00107     private int failedEndpointCount = 0;
00108     
00109 
00110     
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120     public PortScanner( 
00121             RawIpAddress firstAddr, RawIpAddress lastAddr, 
00122             int firstPort, int lastPort,
00123             PrintStream out )
00124     {
00125         this.firstAddr = firstAddr;
00126         this.lastAddr  = lastAddr;
00127         this.firstPort = firstPort;
00128         this.lastPort  = lastPort;
00129         this.out       = out;
00130 
00131         this.endpointDepleted = false;
00132 
00133         
00134 
00135         this.currentAddr = new RawIpAddress( firstAddr );
00136 
00137         
00138 
00139         this.currentPort = firstPort;
00140     }
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160     @Override
00161     public synchronized InetSocketAddress getNextSocketAddress ()
00162     {
00163         InetSocketAddress endpoint = null;
00164 
00165         while( ! endpointDepleted && endpoint == null ) 
00166         {
00167             
00168 
00169             try {
00170                 InetAddress addr = currentAddr.getInetAddress ();
00171                 endpoint = new InetSocketAddress( addr, currentPort );
00172             } catch( Exception e ) {
00173                 
00174                 e.printStackTrace ();
00175             }
00176 
00177             
00178 
00179             currentAddr.increase ();
00180 
00181             if ( currentAddr.compare( lastAddr ) > 0 ) 
00182             {
00183                 currentAddr.set( firstAddr ); 
00184 
00185                 if ( ++currentPort > lastPort ) {
00186                     currentPort = firstPort; 
00187                     endpointDepleted = true; 
00188                 }
00189             }
00190         }
00191 
00192         return endpoint;
00193     }
00194 
00195 
00196 
00197 
00198 
00199     @Override
00200     public synchronized void onPortConnected( long threadId, InetSocketAddress addr,
00201             boolean ok, String error, int timeMillis )
00202     {
00203         ++scannedEndpointCount;
00204         
00205         if ( ok ) {
00206             ++okEndpointCount;
00207         } else {
00208             ++failedEndpointCount;
00209         }
00210 
00211         if ( ok || ( ! ok && reportFailedEndpoints ) ) 
00212         {
00213             String serviceName = verboseServices.lookup( "tcp", addr.getPort () );
00214     
00215             if ( serviceName != null ) {
00216                 out.println( now () 
00217                         + error + ": " + addr.getAddress() + ":" + addr.getPort ()
00218                         + " (" + serviceName + ")"
00219                         + ", Thread " + threadId + ", Elapsed " + timeMillis + " ms" );
00220             } else {
00221                 out.println( now () 
00222                         + error + ": " + addr.getAddress() + ":" + addr.getPort ()
00223                         + ", Thread " + threadId + ", Elapsed " + timeMillis + " ms" );
00224             }
00225 
00226             out.flush ();
00227         }
00228     }
00229 
00230 
00231 
00232 
00233     @Override
00234     public synchronized void workerThreadSignIn( long threadId )
00235     {
00236         ++workerThreadCount;
00237     }
00238     
00239 
00240 
00241 
00242     public synchronized void workerThreadSignOut( long threadId )
00243     {
00244         --workerThreadCount;
00245     }
00246     
00247 
00248 
00249 
00250 
00251 
00252     private static String now ()
00253     {
00254         Calendar cal = Calendar.getInstance ();
00255         SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS " );
00256         return sdf.format( cal.getTime() );
00257     }
00258     
00259 
00260 
00261 
00262     @Override
00263     public void run()
00264     {
00265         long startTime = System.nanoTime ();
00266 
00267         out.println( now () + "Started...\n" );
00268 
00269         
00270 
00271         verboseServices = new ServiceNames( "services.txt" );
00272 
00273         
00274 
00275 
00276         int addrSpanSize = (int)( lastAddr.subtract( firstAddr ) + 1 );
00277         int portSpanSize = lastPort - firstPort + 1;
00278         int endpointCount = addrSpanSize * portSpanSize;
00279 
00280         System.out.println( "\nScanning " 
00281                 + addrSpanSize + " hosts * " 
00282                 + portSpanSize + " ports/host = total "
00283                 + endpointCount + " end-points..."
00284                 );
00285         
00286         
00287 
00288         if ( endpointCount >= maxEndpointsToScan ) {
00289             String error = "Error: Cowardly refusing to scan more than " 
00290                 + maxEndpointsToScan + " end-points!\n\n"
00291                 + "If you really wanted to scan " + endpointCount + " end-points, "
00292                 + "please start multiple instances of the port scanner "
00293                 + "(either sequantially or in parallel).\n";
00294             
00295             out.println( now () + error ); 
00296             out.println( now () + "Completed." );
00297             
00298             System.err.println( "\n" + error ); 
00299             System.out.println( "Completed." );
00300             
00301             out.flush ();
00302             out.close ();
00303             
00304             return;
00305         }
00306         
00307         
00308 
00309 
00310         ExecutorService threadPool = Executors.newFixedThreadPool( maxThreadCount );
00311         for ( int i = 0; i < maxThreadCount; ++ i )
00312         {
00313             threadPool.execute( new PortConnect( this, connectionTimeout ) );
00314         }
00315         
00316         
00317 
00318         while( true )
00319         {
00320             try {
00321                 Thread.sleep( 1000 );
00322             } catch( InterruptedException e ) {
00323                 break;
00324             }
00325 
00326             synchronized( this )
00327             {
00328                 
00329 
00330                 int elapsed = (int) ( ( System.nanoTime () - startTime ) / 1000000000l );
00331                 
00332                 System.out.print(
00333                         "\rElapsed " + elapsed + " sec; "
00334                         + "Scanned " + scannedEndpointCount
00335                         + " of " + endpointCount
00336                         + " end-points (" + okEndpointCount
00337                         + " alive + " + failedEndpointCount
00338                         + " dead); " + workerThreadCount 
00339                         + " threads active                 "
00340                         );
00341                 System.out.flush ();
00342                 
00343                 
00344 
00345                 if ( workerThreadCount <= 0) {
00346                     break;
00347                 }
00348             }
00349         }
00350 
00351         
00352 
00353         out.println( "\n" + now() + "Completed." );
00354 
00355         out.flush ();
00356         out.close ();
00357         
00358         threadPool.shutdownNow ();
00359         
00360         System.out.println( "\nCompleted." );
00361     }
00362 
00363 
00364 
00365 
00366 
00367 
00368     public static void main( String[] args )
00369     {
00370         if ( args.length < 5 ) {
00371             System.err.println( 
00372                     "\nUsage: java -jar portScan.jar "
00373                     + "startAddr stopAddr startPort stopPort resultFile\n"
00374                     );
00375             System.exit( 0 );
00376         }
00377 
00378         String firstHostname = args[0];
00379         String lastHostname  = args[1];
00380         
00381 
00382         
00383         
00384 
00385         RawIpAddress firstAddr = null;
00386         try {
00387             firstAddr = new RawIpAddress( firstHostname );
00388         }  catch( UnknownHostException e ) {
00389             System.err.println( 
00390                     "\nError: Failed to parse startAddr " + firstHostname + "\n"
00391                     + e.toString () );
00392             System.exit( 0 );
00393         }
00394 
00395 
00396         
00397         
00398 
00399         RawIpAddress lastAddr = null;
00400         try {
00401             lastAddr = new RawIpAddress( lastHostname );
00402         } catch( UnknownHostException e ) {
00403             System.err.println( 
00404                     "\nError: Failed to parse stopAddr " + lastHostname + "\n"
00405                     + e.toString () );
00406             System.exit( 0 );
00407         }
00408 
00409 
00410         
00411         
00412 
00413         if ( ! firstAddr.isSameVersion( lastAddr ) ) {
00414             System.err.println( 
00415                     "\nError: The first and last IP addresses must be of the same IP version\n"
00416                     );
00417             System.exit( 0 );
00418         }
00419 
00420 
00421         
00422         
00423 
00424         long spanSize = lastAddr.subtract( firstAddr ) + 1; 
00425         if ( spanSize <= 0 ) {
00426             System.out.println( 
00427                     "\nWarning: The first IP address is greater than the last "
00428                     + "IP address.\nSwapping IP addresses...\n"
00429                     );
00430             RawIpAddress temp = firstAddr; firstAddr = lastAddr; lastAddr = temp;
00431         }
00432 
00433 
00434         
00435         
00436 
00437         int firstPort = -1;
00438         try {
00439             firstPort = Integer.parseInt( args[2] );
00440         } catch( NumberFormatException e ) {
00441             
00442         }
00443         if ( firstPort < 0 ) {
00444             System.err.println( 
00445                     "\nError: The startPort must be integer between 0 and 65535\n"
00446                     );
00447             System.exit( 0 );
00448         }
00449         
00450 
00451         
00452         
00453 
00454         int lastPort  = 80;
00455         try {
00456             lastPort = Integer.parseInt( args[3] );
00457         } catch( NumberFormatException e ) {
00458             
00459         }
00460         if ( lastPort < 0 ) {
00461             System.err.println( 
00462                     "\nError: The stopPort must be integer between 0 and 65535\n"
00463                     );
00464             System.exit( 0 );
00465         }
00466 
00467 
00468         
00469         
00470 
00471         if ( firstPort > lastPort ) {
00472             System.out.println( 
00473                     "\nWarning: The first TCP port is greater than the last "
00474                     + "TCP port.\nSwapping TCP ports...\n"
00475                     );
00476             
00477             int temp = firstPort; firstPort = lastPort; lastPort = temp;
00478         }
00479         
00480 
00481         
00482         
00483 
00484         String result = args[4];
00485 
00486         PrintStream out = null;
00487         try {
00488             FileOutputStream file = new FileOutputStream( result );
00489             out = new PrintStream( file );
00490         } catch( IOException e ) {
00491             System.err.println( 
00492                     "\nError: Failed to open file '" + result + "' for writing\n"
00493                     + e.toString () );
00494             System.exit( 0 );
00495         }
00496 
00497 
00498         
00499         
00500 
00501 
00502         PortScanner ps = new PortScanner( firstAddr, lastAddr, firstPort, lastPort, out );
00503         ps.start ();
00504     }
00505 }
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633