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());