TCP/IP Ports scannen mit PHP

PHP bietet mit der Funktion fsockopen die Möglichkeit eine Verbindung zu einem Kommunikationspartner über einen dedizierten TCP/IP Port aufzubauen. Damit ein Verbindungsaufbau erfolgreich ist, muss der entsprechende Port des Kommunikationsteilnehmers offen sein. D.h. der Port darf nicht durch eine Firewall Regel blockiert werden.

Im folgenden Skript werden einfach alle bekannten TCP/IP Ports eines Kommunikationsteilnehmers überprüft, ob es generell Möglich ist, über den Port eine Kommunikation zu initiieren. Da es eine sehr große menge an verfügbaren Porst geben kann, ist diese Beispiel Skript zweigeteilt. Es wird ein Frontend über die index.php generiert und über AJAX ein Backend Skript genutzt, um den Test auf den Port auszuführen.

Werfen wir einen Blick auf das Frontend:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <script type='text/javascript' src='http://code.jquery.com/jquery-latest.min.js'</script>
        <script type="text/javascript">
            function post_ajx(port, max) {
                if(port!=max){
                    document.getElementById('current_port').innerHTML = 'testing port: ' + port;
                    document.getElementById('start_button').style.display = 'none';
                    document.title = Math.round(calc_process(max, port)) + '% accomplished' ;
 
                    $.ajax({
                        type: "POST",
                        url: "ajx.php",
                        data: "port=" + port,
                        success: function(phpData){
                            document.getElementById('content').innerHTML = document.getElementById('content').innerHTML + phpData;
                            post_ajx(port + 1, max);
                        }
                    })
                }else{
                    document.getElementById('start_button').style.display = 'block';
                }
            }
            function calc_process(g, w){
                var p = w/g * 100;
                return p;
            }
        </script>
        <style type="text/css">
        #menue_main{float:left, clear:both; width:100%}
        #container{float:left, clear:both;}
        #content{float:left, clear:both;}
        #start_button{cursor:pointer;}
        </style>
        <title>portscan of <?php echo $_SERVER['REMOTE_ADDR'] ?></title>
    </head>
    <body>
        <div id="menue_main">
        <div id="current_port"></div>
        <div id="start_button" onclick="post_ajx(0,64739)">Test starten</div>
        </div>
        <div id="container">
            <div id="content"></div>
        </div>
    </body>
</html>

Und nun das dazugehörige Backendskript ajax.php

<?php
if(preg_match("|\Ahttp://(www\.)?".$_SERVER['HTTP_HOST']."|", $_SERVER['HTTP_REFERER'])){
 
    /*    setting the post data in to a local var*/
    $ajxData = $_POST;
 
    /*    exceuting the main function */
    echo main($ajxData);
 
}
function main($ajxData) {
 
    /*    if the test runs against localhost, we have to set the correct ip */
    if ($_SERVER['REMOTE_ADDR'] == '::1'){
        $ip = '127.0.0.1';
    }else{
        /*    if its not the localhost, then set the requester ip */
        $ip = $_SERVER['REMOTE_ADDR'];
    }
 
    /*    going in to the tests of all known tcp ports (wikipedia listed) */
    $fp = @fsockopen($ip, $ajxData['port'], $errno, $errstr, 5);
 
    if(!$fp){
 
        $content = '';
 
    }else{
        $content = 'port:'.$ajxData['port'].' - is open&lt;br&gt;';        
        fclose($fp);
    }
 
    return $content;
 
}
?>

Das Backendskript führt die Port-Test immer gegen den anfragenden Client aus. Wenn man eine anderen IP oder DNS Adresse testen möchte, muss man das Skript entsprechend abändern.

Wenn das Skript gestartet wird, erscheinen die offenen Ports nach und nach im Frontend:

screenshot der frontend ausgabe

Zusätzlich wird der aktuell unter test stehende Port angezeigt und eine Prozentangabe im Bowsertitel informiert über den Stand der Tests. D.h. man kann erkennen, wieviel Tests bereits abgeschlossen sind und wieviele Tests noch durchgeführt werden.

Für die Freunde von Agile Coding habe ich das Skript online gestellt, damit kann jeder mal seinen heimischen Router auf offene Ports testen.

http://www.agile-coding.net/tcpip-ports-scannen-mit-php/