PHP: effettuare la scansione delle porte di un host

PHP: effettuare la scansione delle porte di un host

In questo tutorial vedremo come effettuare la scansione delle porte di un host con PHP.

Si tratta di creare un range di numeri di porte validi (non inferiori a 1 e non superiori a 65535) e di usare la funzione core fsockcopen() cercando di stabilire una connessione con l'host remoto.

Se la funzione restituisce false, vuol dire che non è stato possibile stabilire una connessione. Viceversa, chiudiamo la connessione appena stabilita e aggiungiamo la porta all'array delle porte aperte.

I valori da validare sono il nome dell'host, che può essere un nome a dominio o un indirizzo IP e la porta di partenza e di destinazione.

Possiamo racchiudere questa logica in una classe.

class Scanner {

    const MAX_PORTS = 65535;

    private $host;
    private $start;
    private $end;
    private $results;

    public function __construct($host, $start, $end)
    {
        $this->host = $host;
        $this->start = $start;
        $this->end = $end;

        $this->results = [
            'open' => [],
            'closed' => []
        ];
    }

    public function getResults()
    {
        return $this->results;
    }

    public function scan()
    {
        if(!$this->validate()) {
            return false;
        }
        $ports = range($this->start, $this->end);
        for($i = 0; $i < count($ports); $i++) {
            $port = $ports[$i];
            $ping = $this->ping($port);
            if($ping) {
                $this->results['open'][] = $port;
            } else {
                $this->results['closed'][] = $port;
            }
        }
    }

    private function ping($port)
    {
        $socket = fsockopen($this->host, $port, $errno, $errstr, 1);
        if(!$socket) {
            return false;
        } else {
            fclose($socket);
            return true;
        }
    }

    private function validate()
    {
        $valid = true;
        if(!filter_var($this->host, FILTER_VALIDATE_DOMAIN) && !filter_var($this->host, FILTER_VALIDATE_IP)) {
            $valid = false;
        }
        if(!is_int($this->start) || !is_int($this->end)) {
            $valid = false;
        }

        $startPort = (int) $this->start;
        $endPort = (int) $this->end;

        if($startPort < 1 || $startPort >= self::MAX_PORTS || $startPort > $endPort) {
            $valid = false;
        }
        if($endPort < $startPort || $endPort > self::MAX_PORTS) {
            $valid = false;
        }

        return $valid;
    }
}

Esempio d'uso:

$scanner = new Scanner('phptutorial.it', 80, 443);
$scanner->scan();
print_r($scanner->getResults());
Torna su