Connessione FTP sicura con server Aruba

Il protocollo FTP (File Transfer Protocol) è un protocollo molto utilizzato per lo scambio dati tra host, tipicamente con host remoti. Il problema principale di tale protocollo riguarda la sicurezza in quanto sia i dati che le credenziali d’accesso viaggiano in chiaro, non sono cifrati. Per ovviare a questa problematica si possono utilizzare protocolli diversi o varianti dello stesso protocollo FTP, in particolare: SFTP (SSH File Transfer Protocol), FTPS (FTP su SSL) e SCP (Secure Copy).

I server Aruba permettono di utilizzare connessioni sicure per lo scambio dati attraverso il protocollo FTPS che è una variante dell’FTP e utilizza le stesse porte per lo scambio dati. FTPS, al contrario di FTP, effettua una cifratura per l’invio delle credenziali d’accesso e/o dei dati tramite SSL/TLS (Secure Sockets Layer/Transport Layer Security).
L’iter della transazione è il seguente: il client si connette alla porte 21 del server FTP, deve accettare il certificato del server e a quel punto avviene la sincronizzazione con SSL/TLS.

Per utilizzare il il protocollo FTPS per lo scambio dati con i server Aruba basta modificare il nome host del server con ftps://ftp.nomedominio.xx al posto di ftp.nomedominio.xx e, successivamente, accettarne il certificato. Ove richiesto dal client FTP, è possibile utilizzare FTP su SSL/TLS sia implicito che esplicito.

SSH .File Transfer Protocol

Classe per l’invio di file tramite il protocollo FTP in PHP

In questo articolo vedremo una classe creata per l’utilizzo delle funzioni php per il trasferimento di file attraverso il protocollo FTP (File Transfer Protocol). Ho cercato di semplificare la classe per far eseguire le funzioni elementari utili per lo scambio di file con un server FTP remoto, utilizzando anche meccanismi per la verifica dei file che controllino che il file sia già presente sul server o meno.

Come al solito posto tutto il codice e, successivamente, verrà commentato. Ho chiamato la classe simpleFtp.

<?php

class simpleFtp {

 //dati per l'accesso
 var $ftp_host = ''; //indirizzo server ftp
 var $username = ''; //nome utente per l'accesso ftp
 var $pwd = '';      //password per l'accesso ftp
 var $connect;
 var $login;
 var $source_file;
 var $destination_file;

 //nel costruttore effettuo connessione e login
 function simpleFtp(){
 //effettuo la connessione
 $this->connect = ftp_connect($this->ftp_host) or die("Si è verificato un errore durante la connessione al server ftp");

 //effettuo il login
 $this->login = ftp_login($this->connect, $this->username, $this->pwd) or die("Si è verificao un errore durante l'accesso al server ftp");

 }

 //funzione per il trasferimento dei file
 function trasferisci($sorgente, $destinazione){
 //file da trasferire
 $this->source_file = $sorgente;
 //va indicato il percorso e il nome del file
 $this->destination_file = $destinazione;
 //verifico che il file non esista già altrimenti modifico il nome
 $this->destination_file = $this->verificaFile($this->destination_file, 'put'); 

 ftp_put($this->connect, $this->destination_file, $this->source_file, FTP_BINARY) or die("Errore durante l'upload del file $source_file nel server ftp");

 }

 function preleva($destinazione, $sorgente){
 if($this->verificaEsistenza($sorgente)){
 //file da trasferire dal server remoto
 $this->source_file = $sorgente;
 //percorso e nome locale da dare al file
 $this->destination_file = $destinazione;
 //verifico che il file non esista già altrimenti modifico il nome
 $this->destination_file = $this->verificaFile($this->destination_file, 'get');        

 ftp_get($this->connect, $this->destination_file, $this->source_file, FTP_BINARY) or die("Errore durante il download del file $source_file nel server ftp");

 }else
 echo "File non trovato.";
 }

 //cancella un file sul server remoto
 function cancella($file){
 if($this->verificaEsistenza($file))
 ftp_delete($this->connect, $file) or die("Errore durante la cancellazione del file dal server ftp");
 else
 echo "File non trovato";
 }

 //cambia la directory sul server remoto
 function cambiaDirectory($dir){
 ftp_chdir($this->connect,$dir) or die('Errore durante il cambio di directory');
 }

 //restituisce la directory corrente
 function directoryCorrente(){
 return ftp_pwd($this->connect);
 }

 //cambia i permessi su un file, i permessi devono essere a 4 cifre. Es.: 0755
 function cambiaPermessiFile($permessi, $file){
 if($this->verificaEsistenza($file) && is_numeric($permessi))
 ftp_chmod($this->connect, $permessi, $file);
 else
 echo "File non trovato";
 }

 //rinomina un file sul server remoto
 function rinomina($old, $new){
 if($this->verificaEsistenza($old)){
 $new = $this->verificaFile($new, 'put');
 ftp_rename($this->connect, $old, $new);
 }
 else
 echo "File non trovato";
 }

 //restituisce un array con i nomi dei file nella directory passata
 function visualizzaFile($dir){
 $result = ftp_nlist($this->connect, $dir);
 return $result;
 }

 //crea una directory sul server remoto a partire dalla directory corrente
 function creaDirectory($dir){
 @ftp_mkdir($this->connect, $dir) or die('La directory esiste già o non hai i permessi per crearne una.');

 }

 //elimina una directory dal server remoto a partire dalla directory corrente
 function eliminaDirectory($dir){
 @ftp_rmdir($this->connect, $dir) or die('La directory non esiste o non hai i permessi per eliminarla.');

 }

 //chiudo la connessione
 function close(){
 ftp_quit($this->connect) or die("Si è verificato un errore durante la chiusura della connessione al server ftp");
 }

 //Verifico il tipo di file in base all'estensione
 function verificaFile($nomeFile, $tipo){
 $ext = explode('.', trim($nomeFile));
 $num = count($ext);
 if($ext[$num-1]=='jpg' || $ext[$num-1]=='pdf')
 if($tipo=='put')
 return $this->verifica($nomeFile, $ext[$num-1]);
 elseif($tipo=='get')
 return $this->verificaLocale($nomeFile, $ext[$num-1]);
 }

 //funzione che modifica i caratteri speciali e cambia il nome del file se dovesse già esistere sul server
 function verifica($nomeFile, $ext){
 $nomeFile=stripcslashes($nomeFile);
 $nomeFile=str_replace("'"," ",$nomeFile);
 $nomeFile=str_replace("`"," ",$nomeFile);
 $nomeFile=str_replace("\\"," ",$nomeFile);
 $nomeFile=str_replace("&"," ",$nomeFile);
 $nomeFile=str_replace("%"," ",$nomeFile);
 $nomeFile=str_replace("\""," ",$nomeFile);
 $nomeFile=str_replace("à","a",$nomeFile);
 $nomeFile=str_replace("è","e",$nomeFile);
 $nomeFile=str_replace("é","e",$nomeFile);
 $nomeFile=str_replace("ì","i",$nomeFile);
 $nomeFile=str_replace("ò","o",$nomeFile);
 $nomeFile=str_replace("ù","u",$nomeFile);

 if($this->verificaEsistenza($nomeFile)){
 $temp=substr($nomeFile, 0, -4);
 if($ext=='jpg'){
 $nomeFile=$temp.'_.jpg';
 }
 elseif($ext=='pdf'){
 $nomeFile=$temp.'_.pdf';
 }
 $nomeFile=$this->verifica($nomeFile, $ext);
 }
 return $nomeFile;

 }

 /*
 Verifico che un file esista già sul server a cui mi collego, la funzione ftp_size restituisce la dimensione del file se trova un file con quel nome nella directory indicata, altrimenti restituisce -1
 */
 function verificaEsistenza($file){
 $verifica = ftp_size($this->connect, $file);
 if($verifica==-1)
 return false;
 else
 return true;
 }

 //funzione che modifica i caratteri speciali e cambia il nome del file se dovesse già esistere in locale
 function verificaLocale($nomeFile, $ext){

 if(file_exists($nomeFile)){
 $temp=substr($nomeFile, 0, -4);
 if($ext=='jpg'){
 $nomeFile=$temp.'_.jpg';
 }
 elseif($ext=='pdf'){
 $nomeFile=$temp.'_.pdf';
 }
 $nomeFile=$this->verificaLocale($nomeFile, $ext);
 }
 return $nomeFile;

 }

}
?>

La classe utilizza le funzioni messe a disposizione da PHP per il trasferimento file utilizzando il protocollo FTP; in aggiunta, ho inserito delle funzioni per la verifica che un file si trovi già sul server (verificaEsistenza()) o, se stiamo prelevando dal server, se il file esiste in locale (verificaLocale()). Non utilizzando tali funzioni i file, se già esistenti, vengono sovrascritti senza alcun output per l’utente.
Inoltre, sono state implementate le funzioni verifica() e verificaFile() che hanno il compito di modificare il nome del file evitando i caratteri speciali e le lettere accentate e, se il file si trova già sul server, modificandone il nome inserendo degli underscore dopo il nome e prima dell’estensione. Naturalmente il bisogna conoscere il tipo di file, infatti la classe è impostata per il trasferimento di file immagini (jpg) e pdf. La classe gestisce questi 2 tipi di file ma è possibile adattarla facilmente per tipi di file qualsiasi in base alle necessità.

Gli unici parametri che vanno inseriti all’interno della classe sono i dati per l’accesso FTP al server remoto, tutto il resto verrà effettuato tramite funzioni d’accesso. Il costruttore simpleFtp() ha il compito di effettuare la connessione al server FTP e la relativa login. Seguono le funzioni principali per l’utilizzo della classe, ovvero trasferisci(), preleva() e cancella(). Tutte queste funzioni leggono il percorso del file sul server FTP a partire dalla root, quindi è necessario inserire il percorso completo al file oppure spostarsi, prima di tali operazioni, sulla directory di lavoro con la funzione cambiaDirectory().

Successivamente sono state implementate altre funzioni molto utili in alcuni ambiti, e sono la funzione cambiaPermessiFile() e rinomina(). La prima serve per modificare i permessi d’accesso al file, ad esempio si può impostare un file con i permessi 0777; la seconda serve per rinominare un fle remoto. Ovviamente, per entrambe le funzioni, si verifica prima se il file sul server esista.

La funzione directoryCorrente() restituisce il percorso della cartella del server su cui si sta lavorando mentre le funzioni creaDirectory() ed eliminaDirectory() sono utilizzate, rispettivamente, per creare ed eliminare cartelle sul server FTP; visualizzaFile(), invece, restituisce un array con la lista dei file presenti nella direcotory passata.
Infine, la funzione close() termina la connessione con il server FTP.

Per rendere maggiormente utilizzabile la classe è possibile modificarne il costruttore in modo da prendere dall’esterno i parametri per la connessione. In altri articoli, se ce ne sarà bisogno, integrerò la classe per l’utilizzo di connessioni cifrate per lo scambio di dati in FTP.

Come cambiare il MAC address delle schede di rete in linux

Il MAC (Media Access Control) address è un indirizzo che identifica univocamente ogni scheda di rete prodotta a livello globale. Viene anche detto indirizzo fisico ed è composto da 48 bit di cui i primi 24 identificano il produttore (OUI, Organizationally Unique Identifier) dell’hardware mentre i restanti bit identificano il componente. Esso è usato per l’instradamento in reti switched, quindi a livello 2 dello stack ISO-OSI.

Anche se il MAC address è unico al mondo, per una determinata scheda di rete, è possibile modificarlo via software per usi più o meno “consoni”. In windows non è possibile modificarlo se non utilizzando appositi tools, mentre in linux la procedura è molto semplice, bastano poche istruzioni eseguite da shell.
Per visualizzare il MAC address delle nostre schede di rete, basta digitare il comando ifconfig e verranno visualizzate le informazioni su tutte le schede di rete attive sul pc; tra le informazioni troveremo il MAC address sotto la voce HWaddr.

Per modificare il MAC address bastano 3 semplici comandi: supponiamo di voler modificare il MAC della scheda ethernet (eth0), dobbiamo prima disattivarla, poi modifichiamo l’indirizzo fisico e, infine, la riattiviamo. Es.:

ifconfig eth0 down
ifconfig eth0 hw ether 00:11:22:33:44:55
ifconfig eth0 up

Ovviamente è possibile inserire al posto di 00:11:22:33:44:55il MAC address voluto. Per effettuare tale operazione è necessario avere i privilegi di amministratore, quindi se siete con ubuntu, ad esempio, dovete anteporre ai comandi l’istruzione sudo.

Se non ricordate più il MAC address originale niente panico! Riavviando il PC verrà reimpostato il MAC address originale della scheda di rete poiché la modifica viene effettuata solo via software senza modificare in alcun modo il firmware della scheda di rete.

Tags: , , , ,

Script Php per ricerche fulltext con MySQL

Nel precedente articolo abbiamo visto la sintassi SQL per l’utilizzo degli indici fulltext nelle ricerche sul database. In questo articolo vedremo un semplice script per l’utilizzo pratico di tale ricerca utilizzando una classe appositamente scritta.

Supponiamo di avere un form con un campo di ricerca del tipo:

<form name="cerca" method="post" id="cerca" action="esito_ricerca.php">
<input type="text" name="campo" />
<input type="submit" name="invia" /></form>

Al submit si aprirà una nuova pagina php nella quale riprenderemo i valori passati ed eseguiremo le operazioni necessarie per la ricerca e la visualizzazione dei risultati. Per semplificare le cose utilizzeremo la seguente classe:

< ?php

class Ricerca
{
var $campi;
var $tabella;
var $key;
var $tuple;

function Ricerca($key, $tabella, $campi)
{
$this->key = $key;
if($tabella!="")
$this->tabella = $tabella;
if($campi!="")
$this->campi = $campi;
$this->pulisciStringa();
}

function Query()
{

$query = "SELECT *, MATCH($this->campi) AGAINST('$this->key' IN BOOLEAN MODE) AS attinenza FROM $this->tabella WHERE MATCH($this->campi) AGAINST('$this->key' IN BOOLEAN MODE) ORDER BY attinenza DESC";

$this->tuple = mysql_query($query);

}

function pulisciStringa()
{
$keyMod = strip_tags($this->key);
$keyMod = mysql_real_escape_string($keyMod);
$this->key = trim($keyMod);
}

function ricercaParole()
{
$word = explode(' ', trim($this->key));
$num = count($word);

$i=0;
while($i< $num){
$word[$i] = '+'.$word[$i];
$i++;
}
$this->key = implode(' ',$word);
}

function ricercaFrase()
{
$word = $this->key;
$word = '"'.$word.'"';
$this->key = $word;
}

}

?>

La classe è abbastanza semplice, la funzione Ricerca() ha il compito di inizializzare alcuni parametri necessari per l’esecuzione della ricerca, in particolare riceve in ingresso le chiavi di ricerca, la tabella su cui effettuare la query e i campi fulltext da analizzare.
La funzione Query() effettua la query vera e propria riportando i valori ordinati per attinenza. La funzione pulisciStringa() serve per ripulire il codice e aumentarne la sicurezza. In tale funzione si possono fare tutti i controlli e le sostituzioni di caratteri che si vogliono. Se all’interno del database i caratteri sono codificati nelle loro rispettive entità html (situazione che capita spesso se si usa un editor wysiwyg) allora è possibile utilizzare al posto di mysql_real_escape_string() la funzione htmlentities().
Ho inserito nella classe anche 2 funzioni che possono essere molto utili. La prima è ricercaParole() che ha il compito di inserire davanti a ogni parola il segno “+”. Utilizzare tale parametro equivale a effettuare una ricerca di “tutte le parole” passate, ovvero tra i risultati ci saranno soltanto tuple che contengono tutte le parole di ricerca passate. La seconda è, invece, ricercaFrase() che ha il compito di restituire tra i risultati solamente tuple che contengono la chiave di ricerca così com’è. E’ utile per ricercare una “frase esatta” all’interno dei campi e si attua inserendo la chiave di ricerca all’interno di doppi apici.

Vediamo come utilizzare la classe in una ricerca utilizzando il form precedente. Supponiamo che la connessione al database sia già stata effettuata, avremo:

$campo=$_POST['campo'];

$search = new Ricerca($campo, 'tabella', 'campo1, campo2');
$search->Query();
$cont = mysql_num_rows($search->tuple);

if($cont<1)
echo "Non vi sono risultati per la ricerca selezionata";
else{
while ($row = mysql_fetch_array($search->tuple))
{
echo $row['campo1'];
}
}

Si riprende il campo e si inizializza la classe attraverso il costruttore passandogli la chiave di ricerca, la tabella e i campi da analizzare. Successivamente effettuiamo la query e procediamo alla visualizzazione dei risultati.

Per avere tra i risultati della ricerca solo i risultati che contengono tutte le parole passate inseriamo prima della Query() la funzione ricercaParole():

$search = new Ricerca($campo, 'tabella', 'campo1, campo2');
$search->ricercaParole();
$search->Query();

mentre per ricercare una frase esatta:

$search = new Ricerca($campo, 'tabella', 'campo1, campo2');
$search->ricercaFrase();
$search->Query();

La classe vista finora è molto semplice e funzionale, può essere ampliata a piacimento per implementare funzioni che possono essere d’aiuto nel personalizzarla a seconda dei propri scopi.

Motore di ricerca per MySQL con indici fulltext

In questo articolo vedremo come creare un semplice motore di ricerca in php utilizzando gli indici fulltext di MySQL. Gli indici fulltext sono un meccanismo che consente di velocizzare le ricerche le quali risultano così molto più efficienti rispetto l’utilizzo del comando LIKE. Inoltre, con questo meccanismo, i risultati saranno visualizzati in ordine di attinenza con le chiavi di ricerca.
Affinché si possano utilizzare le ricerche fulltext bisogna prima preparare il database e, successivamente, il codice per effettuare le ricerche.

Preparazione del database
Condizione necessaria per l’utilizzo di questo tipo di ricerche è l’impostazione dei campi con indice fulltext. Tale impostazione può essere effettuata al momento della creazione della tabella o successivamente. Vediamo degli esempi.
Per impostare i campi fulltext alla creazione della tabella basta inserire nella query SQL la stringa FULLTEXT (campo1, campo2), dove i campi possono essere 1, 2 o più e sono separati da virgole. Es:

CREATE TABLE tabella(
id INT AUTOINCREMENT NOT NULL PRIMARY KEY
campo1 VARCHAR(255),
campo2 TEXT,
FULLTEXT (campo1, campo2)
);

Per inserire gli indici in una tabella già esistente basta invece utilizzare la sintassi:

ALTER TABLE tabella ADD FULLTEXT(campo1,campo2);

Se non avete voglia di scrivere la query a mano potete anche utilizzare l’interfaccia di phpmyadmin per impostare i campi: selezionate la tabella su cui aggiungere i campi, selezionate “struttura” e nella riga del campo da impostare troverete come ultima opzione una casellina che dice FULLTEXT (testo completo).

Nota: affinché si possano utilizzare gli indici fulltext è necessario che la tabella utilizzi l’engine MyISAM e che i campi siano campi di testo (VARCHAR, TEXT…..).

Sintassi per le ricerche
Il cuore delle ricerche fulltext è rappresentato dai comandi MATCH(….) e AGAINST(….) nei quali vanno inseriti rispettivamente il nome dei campi da analizzare e le chiavi di ricerca. Un esempio pratico è il seguente:

SELECT *
FROM tabella
WHERE MATCH(campo1, campo2) AGAINST(‘key’);

Vi saranno risultati solo se vi sarà un valore di attinenza con la chiave di ricerca. MATCH e AGAINST producono un valore di attinenza in virgola mobile, se tale valore è zero non vi saranno risultati. La query così formata però ha il difetto di non riportare i risultati ordinati per attinenza. Quella che segue è una query più completa e funzionale.

SELECT *, MATCH(campo1, campo2) AGAINST(‘key’, IN BOOLEAN MODE) AS attinenza
FROM tabella
WHERE MATCH(campo1, campo2) AGAINST(‘key’, IN BOOLEAN MODE)
ORDER BY attinenza DESC;

Tale query restituisce i risultati ordinati per attinenza per come viene calcolata dai comandi MATCH e AGAINST. Nella clausola AGAINST viene utilizzato altresì la dicitura IN BOOLEAN MODE, che permette di utilizzare operatori booleani per personalizzare e migliorare le ricerche.

Operatori di ricerca
Oltre ai normali operatori AND e OR logici, nelle ricerche fulltest possono essere inseriti altri tipi di operatori per meglio filtrare i risultati, tra cui:

  • Operatore +: indica che la parola a cui è anteposto deve essere presente in ogni record restituito;
  • Operatore -: indica che la parola a cui è anteposto non deve essere presente in alcun record restituito;
  • Operatori < e >: sono utilizzati per variare il contributo che la parola dona alla rilevanza (score) di un singolo record;
  • Operatori (): le parentesi sono utili al fine di raggruppare tra loro sotto-espressioni che avranno un più alto grado di precedenza;
  • Operatore ~: viene utilizzato per segnare una parola in modo che questa diminuisca l’attinenza di un record (viene utilizzato per marcare le cosidette bad words);
  • Operatore *:  è l’unico operatore che può essere posto alla fine della parola o di una parte di essa. Serve ad indicare che caratteri qualsiasi possono seguire la parola o precederla;
  • Operatore “: le parole o frasi racchiuse tra apici doppi obbligheranno MySQL ad effettuare ricerche sulla frase completa e non su ogni singola parola.

Nel prossimo articolo vedremo come usare praticamente le ricerche fulltext con php utilizzando una semplice classe.

Configurazione delle ACL: standard, extended e named. Posizionamento

Nel precedente articolo abbiamo iniziato a trattare l’argomento delle ACLs con una panoramica teorica e pratica sulle wildcard e sui tipi di ACLs. Abbiamo, inoltre, visto la configurazione di una semplice ACL standard. Prima di passare in questo articolo alle Extended ACLs, terminiamo dicendo che nelle Standard ACL (ma anche nelle altre) è possibile inserire un commento per meglio identificare l’ACL in maniera pratica e veloce tramite il comando remark (comando opzionale).
Per inserire il commento a una ACL esistente bisogna inserire il comando:

Router(config)#access-list numero remark commento

L’ultimo comando utilizzabile è il comando log (comando opzionale) alla fine della dichiarazione di una ACL: esso crea una serie di informazioni di logging sui pacchetti inviati o bloccati dalle ACLs. In tali informazioni si trovano il numero dell’ACL, il numero di pacchetti passati o scartati e  l’IP sorgente. In generale il comando per impostare una ACL standard è:

Router(config)#access-list access-list-number {permit deny} {test-conditions}

più le eventuali opzioni.

Passiamo adesso alle Extended ACLs che sono spesso preferite alle Standard ACLs in quanto sono configurabili con molti più parametri: esse possono fare un controllo sull’IP sorgente, su quello di destinazione, sul protocollo e sul numero di porta.
Le Extended ACLs sono caratterizzate da numeri identificativi che vanno da 100 a 199 e da 2000 a 2699; vanno applicate il più vicino possibile alla sorgente di traffico. Facciamo un esempio pratico per capire come settare questo tipo di ACL.

Supponiamo di voler bloccare il telnet dall’host 192.168.50.15, la regola sarà:

Router(config)#access-list 101 deny tcp host 192.168.50.15 eq telnet

oppure

Router(config)#access-list 101 deny tcp host 192.168.50.15 eq 23

Per prima cosa identifichiamo l’ACL con un identificativo nel range apposito, successivamente va indicato il protocollo (nel nostro caso il tcp) e l’indirizzo con la wildcard mask. Nel nostro esempio si è usato il comando host al posto della wildcard 0.0.0.0; infine va indicato il servizio o la porta da bloccare. Il resto dei comandi resta uguale alle standard ACLs:

Router(config)#interface {interfaccia}
Router(config-if)# ip access-group numero_acl {in|out}

Le ACLs viste finora sono dette numbered poiché la singola ACL è identificata da un identificativo numerico. Oltre ad esse vi sono le ACLs basate sul nome, dette named ACLs. Le ACLs named possono essere sia standard che estese e il tipo va specificato in sede di configurazione nel seguente modo:

Router(config)#ip access-list {standard|extended} ACL-name

Nelle named ACLs il comando access-list è preceduto dal comando ip. I vantaggi di tali ACL sono:

  • possibilità di utilizzare caratteri alfanumerici per identificare l’ACL (anche semanticamente più facili da ricordare);
  • non vi è alcun limite al numero di named ACLs;
  • possono essere modificate senza cancellare completamente l’ACL e riconfigurarla.

Dove vanno posizionate le ACLs?
La regola generale è quella di posizionare le extended ACLs il più vicino possibile alla sorgente di traffico da bloccare per bloccare i pacchetti il prima possibile. Le standard ACL non specificano l’indirizzo di destinazione, pertanto le standard ACLs vanno posizionate il più vicino possibile alla destinazione. Questo impedisce che venga bloccato anche traffico utile che invece non va controllato.

Terminiamo questo articolo dicendo che le ACLs possono essere utilizzate anche per limitare gli accessi sulle virtual ports, dette anche vty lines, attraverso il comando access-class al posto di access-group. Tale procedura serve ad aumentare la sicurezza della rete; ad esempio, serve a limitare l’accesso al router tramite telnet (connessione vty). Il procedimento per la creazione di una vty access list è la stessa di quella descritta per le interfacce a parte il comando access-class. Facciamo un esempio: supponiamo che gli utenti della rete 192.168.10.0/24 possano utilizzare le virtual ports mentre bisogna bloccare i rimanenti accessi utilizzando una standard ACL con identificativo 5; i comandi saranno:

Router(config)#access-list 5 permit 192.168.10.0 0.0.0.255
Router(config)#access-list 5 deny any

Applichiamo adesso l’ACL:

Router(config)#line vty 0 4
Router(config-line)#login
Router(config-line)#password secret
Router(config-line)#access-class 5 in

Nota: per la ACL su vty line possono essere applicate solo ACLs numbered e non named.

Prelevare codice video youtube da URL o da codice incorporato con object o iframe

Mi è capitato spesso, nell’ultimo periodo, di dover inserire dei video youtube in siti web che richiedevano però modifiche del player, in particolare della sua dimensione. Per semplificare le cose ho scelto di incorporare nelle pagine uno stesso codice già personalizzato e passare a tale codice l’id del video scelto dal cliente.
Visto che ogni cliente ha un pensiero a sé stante, ho dovuto personalizzare il tutto in base alla scelta dell’utente di inserire l’URL del video, il vecchio codice di incorporamento o il nuovo codice utilizzato da youtube con il tag <iframe>. Per chi non lo sapesse, youtube ha da poco modificato il tipo di codice da incorporare con un codice che utilizza <iframe>; tale soluzione permette all’utente finale di visualizzare il video con tecnologia flash oppure HTML5 ed è particolarmente indicato per la visualizzazione dei video su dispositivi mobile. Tuttavia, il vecchio codice (tag <object>) è ancora disponibile su richiesta spuntando la voce “Utilizza vecchio codice di incorporamento” posto poco sotto il codice da incorporare.

Ho implementato una piccola funzione per l’estrazione dell’id del video in tutti e tre i casi. La riporto di seguito.

<?php
function estraiCodice($codice){
$codMod = $codice;
$tipo='';
$idVideo='';

//Verifico il tipo di codice
if(strstr($codMod, 'iframe'))
$tipo='iframe';
elseif(strstr($codMod, 'object'))
$tipo='object';
elseif(strstr($codMod, 'watch?v='))
$tipo='link';

//Operazioni nel caso di codice tradizionale con object
if($tipo=='object'){
$part = explode('?', $codice);
$cod = explode('.com/v/',$part[0]);
$idVideo = $cod[1];
}
//Operazioni nel caso di nuovo codice con iframe
elseif($tipo=='iframe'){
$part = explode('embed/', $codice);
$cod = explode('"',$part[1]);
$idVideo = $cod[0];
}
//Operazioni nel caso di inserimento di URL
elseif($tipo=='link'){
$part = explode('?v=', $codice);
if(strstr($part[1], '&')){
$cod = explode('&',$part[1]);
$idVideo = $cod[0];
}else{
$idVideo=$part[1];
}
}

return $idVideo;
}
?>

Il codice è molto semplice. Per prima cosa verifico il tipo di incorporamento che è stato inserito e, successivamente, effettuo le operazioni necessarie per estrarre l’id, che è il risultato che voglio ottenere.

Introduzione alle Access Control Lists su router Cisco e alle wildcard mask

Le Access Control Lists (nel seguito ACLs) sono una lista di condizioni utilizzate per “controllare” il traffico e si applicano alle porte del router che decide se far passare un determinato pacchetto oppure bloccarlo. I criteri decisionali si basano sull’indirizzo IP sorgente, quello di destinazione, sulle porte e sui protocolli. Le ACLs possono essere usate con qualsiasi protocollo routed di livello rete come IP e IPX. Elenchiamo alcuni aspetti positivi apportati dalle ACLs:

  • limitano il traffico della rete aumentando così le performance;
  • effettuano un controllo di flusso sul traffico;
  • offrono un livello base di sicurezza per l’accesso alla rete;
  • decidono quale tipo di traffico inoltrare e quale bloccare.

Se non vi è alcuna ACLs configurata sul router tutti i pacchetti vengono inoltrati senza distinzione.

Vediamo ora il funzionamento di un’ACLs. L’ordine in cui vengono immesse le ACLs è fondamentale in quanto l’IOS effettua un controllo sulle condizioni dall’alto verso il basso, ovvero dalla prima condizione immessa fino all’ultima. Se ad esempio la prima condizione permette l’inoltro di tutto il traffico tutte le altre verranno ignorate! Bisogna fare quindi molta attenzione.
Quando una condizione è verificata il pacchetto viene inoltrato o bloccato in base alla regola impostata nella ACLs; se nessuna delle condizioni nell’ACLs combacia,  implicitamente vi è un deny any in fondo alla lista, di default e, quindi, il pacchetto verrà scartato.

Le ACLs utilizzano le wildcard mask per impostare le condizioni. Una wildcard mask è formata da 32 bit suddivisa in 4 ottetti (esattamente come gli indirizzi IP) dove lo zero indica il bit nell’indirizzo da esaminare mentre l’1 il bit corrispondente nell’indirizzo da ignorare.  Vi sono 2 wildcard particolari che sono la 0.0.0.0 e la 255.255.255.255: la prima è sostituita dalla parola chiave host (verifica tutto l’IP) mentre la seconda dalla parola chiave any. Più avanti faremo un esempio pratico, prima però passiamo alla definizione delle ACLs sui ruoter Cisco.

Ci sono diversi tipi di ACLs: standard, extended e named. Quando una ACLs viene configurata gli viene assegnato un identificativo univoco che identifica anche il tipo di ACLs in base a un range di identificativi. I range disponibili sono:

  • standard IP: 1-99, 1300-1999
  • extended IP: 100-199, 2000-2699
  • AppleTalk: 600-699
  • IPX: 800-899
  • extended IPX: 900-999
  • IPX Service Advertising Protocol: 1000-1099

Per inserire le regole in una ACLs si utilizza il comando access-list seguito dai vari parametri mentre per associarla a un’interfaccia si utilizza il comando access-group. La regola generale è:

Router(config)#access-list access-list-number {permit deny} {test-conditions}

mentre sull’interfaccia:

Router(config-if)#{protocol} access-group access-list-number

Vediamo un esempio pratico mostrando il funzionamento della wildcard. Supponiamo di voler bloccare in ingresso all’interfaccia ethernet1 il traffico proveniente dalla rete 172.16.0.0/16 con una stardard ACLs con identificativo 2 mentre bisogna lasciar passare tutto il resto del traffico dalla rete 172.0.0.0/8, i comandi saranno:

Router(config)#access-list 2 deny 172.16.0.0 0.0.255.255
Router(config)#access-list 2 permit 172.0.0.0 0.255.255.255
Router(config)#interface e0
Router(config-if)# ip access-group 2 in

La prima condizione forma un valore di confronto (applicando la wildcard) che, se rispecchiato dall’indirizzo del pacchetto in ingresso, tale pacchetto sarà scartato.

IP addess 172.16.0.0 10101100 00010000 00000000 00000000
wildcard mask 00000000 00000000 xxxxxxxx xxxxxxxx
Valore di confronto 10101100 00010000 xxxxxxxx xxxxxxxx

Se in arrivo ho un pacchetto da un host con IP 172.16.4.64 avrò una situazione di questo tipo:

IP addess 172.16.4.64 10101100 00010000 00000100 01000000
wildcard mask 00000000 00000000 xxxxxxxx xxxxxxxx
Valore di confronto 10101100 00010000 xxxxxxxx xxxxxxxx

il valore di confronto combacia e quindi, per la regola impostata, il pacchetto verrà scartato. Viceversa, la seconda regola mi forma un valore di confronto del tipo:

IP addess 172.0.0.0 10101100 00000000 00000000 00000000
wildcard mask 00000000 xxxxxxxx xxxxxxxx xxxxxxxx
Valore di confronto 10101100 xxxxxxxx xxxxxxxx xxxxxxxx

Se ho un pacchetto in ingresso all’interfaccia da un host con IP 172.8.10.1:

IP addess 172.8.10.1 10101100 00001000 00001010 00000001
wildcard mask 00000000 xxxxxxxx xxxxxxxx xxxxxxxx
Valore di confronto 10101100 xxxxxxxx xxxxxxxx xxxxxxxx

tale pacchetto verrà inoltrato in quanto il valore di confronto coincide con la regola impostata nell’ACLs.

La verifica della configurazione delle ACLs si effettua attraverso i comandi show. Il comando show ip interface mostra le informazioni sulle ACLs impostate sulle interfacce. Il comando show access-list mostra, invece, il contenuto di tutte la ACLs programmate sul router.

Nel prossimo articolo vedremo la configurazione dei vari tipi di ACLs.

IGRP: caratteristiche, metrica e configurazione

L’Interior Gateway Routing Protocol (IGRP) è un protocollo distance vector proprietario cisco. Essendo un protocollo distance vector l’IGRP invia aggiornamenti periodici di routing per mantenere la consistenza delle informazioni al variare della rete (per l’inserimento di nuove destinazioni o per identificare reti irraggiungibili).

Gli update di routing dell’IGRP vengono inviati ogni 90 secondi ai router appartenenti allo stesso AS (ricordiamo che l’IGRP è un protocollo IGP). Le caratteristiche principali di tale protocollo sono:

  • adattamento automatico alle variazioni anche in reti con topologia complessa;
  • flessibilità nella gestione di reti con diverse caratteristiche di banda e latenza;
  • scalabilità necessaria per reti molto estese.

Di base l’IGRP sceglie il percorso su cui instradare un pacchetto in base a una metrica basata sulla banda disponibile e sul ritardo. Tuttavia, l’IGRP può essere configurato per tenere conto, oltre che della banda e del ritardo, anche del carico in quel momento e dell’affidabilità della rete.  Tale metrica è, ovviamente, più accurata dell’hop count utilizzato dal RIP per scegliere il percorso di un pacchetto fino a destinazione. Vediamo meglio i parametri principali utilizzati nella metrica per la scelta del percorso:

  • banda: si tiene conto della banda delle reti che si attraversano fino a destinazione;
  • ritardo: ritardo cumulativo calcolato sulle interfacce oltrepassate lungo il percorso;
  • affidabilità: l’affidabilità del collegamento fino a destinazione determinato con lo scambio di informazioni riguardo la raggiungibilità delle reti nel tempo;
  • carico: il carico di un link verso la destinazione misurato in bit/secondo.

L’IGRP implementa le funzioni di holddowns, split horizons e poison reverse updates (già trattati in un precedente articolo). Tale protocollo non supporta le VLSM, supportate invece da un altro protocollo proprietario cisco che è l’EIGRP.

Passiamo adesso alla configurazione del protocollo. Il processo di routing si attiva con il comando router igrp in modalità configurazione (per disabilitarlo basta inserire il comando no router igrp). Perché il comando sia completo bisogna inserire anche un as-number, ovvero un identificativo per il processo IGRP; tutti i router che partecipano al processo di routing devono avere lo stesso as-number. Nel successivo menu bisogna inserire le reti direttamente connesse su cui inviare e ricevere gli update tramite il comando network (esattamente come accade per il RIP). Facciamo un esempio. Vogliamo inserire su un router 2 reti con identificativo di processo 101, i comandi saranno:

Router(config)# router igrp 101
Router(config-router)# network 192.168.10.0
Router(config-router)# network 192.168.11.0

RIP: load balancing e integrazione delle rotte statiche

Il load balancing (bilanciamento del carico) è il concetto che i router seguono per bilanciare il carico (traffico) in molteplici best path. Questi percorsi sono calcolati dinamicamente dal RIP e tale protocollo permette di indirizzare il traffico fino a un massimo di 6 best path utilizzati attraverso un meccanismo detto round robin. Tale meccanismo è ciclico, ovvero il router invierà il maniera ciclica il traffico sulle diverse interfacce su cui vi è un best path senza però tener conto della banda che vi si trova su ognuna di tali interfacce (il RIP non fa distinzioni sull’invio di pacchetti su un percorso PSTN a 56kbps o su una ATM a 155Mbps, calcola il best path tenendo in considerazione solamente il numero di hop da superare prima di arrivare a destinazione).
Le rotte con metrica uguale possono essere individuate usando il comando show ip route seguito dall’indirizzo della rete. Es.:

Router#show ip route 192.168.10.0

Per modificare il numero massimo di path bisogna digitare, in router configuration mode, il comando:

Router(config-router)#maximum-paths {number}

Parliamo adesso delle rotte statiche e al possibile utilizzo a fianco del RIP. La rotte statiche forzano l’instradamento dei pacchetti da una sorgente a una destinazione. Sono spesso utilizzate per definire una default route e, quindi, instradare un pacchetto anche quando la rete non è presente nella routing table.
Un router che usa RIP può ricevere una default route tramite update da un altro router che usa anch’esso RIP; un’altra opzione è che il router auto generi la sua default route.

Le rotte statiche hanno, ovviamente, prelazione su quelle dinamiche in virtù di una distanza amministrativa decisamente minore (per eliminare le default route basta digitare il comando no ip route in global configuration mode). Per ovviare a ciò basta impostare alla rotta statica una distanza amministrativa maggiore di quella del routing dinamico utilizzato. Così facendo si possono impostare rotte di backup nel caso in cui il processo di RIP non vada a buon fine.

Le rotte statiche saranno annunciate con gli update del RIP e propagate per tutta la rete: questo perché le rotte statiche sono contenute nella routing table ed il router non distingue tra rotte statiche e dinamiche. Quando un’interfaccia diviene indisponibile tutte le rotte statiche che la utilizzavano vengono rimosse dalla routing table. Quando il software non riesce più trovare un next-hop valido per l’indirizzo specificato nella static route, allora la rotte statica viene eliminata.