Note introduttive
Nota bene prima di leggere oltre: Questo testo tratta della configurazione base di un Router Cisco 827 con diversi spunti relativi a quello che si può fare oltre.
Noterete anche che non c’è da nessuna parte un file di configurazione finito e pronto per essere usato, la ragione è duplice: da un verso molta gente, valutando la difficoltà del testo dalla sua lunghezza in righe si limita a saltare alla configurazione (salvo poi accorgersi che l’esempio non calza con la sua configurazione), dall’altro questa è una guida, non un howto, il focus è nello spiegare perchè si fanno certe cose (ovviamente con dei limiti, IOS è immenso) e non fornire esempi “pronti all’uso” che lasciano i lettori all’oscuro del perchè delle cose.
Introduzione
La famiglia Cisco è estremamente grossa e variegata ma ha il grandissimo vantaggio di essere uniforme a livello di comandi grazie ad IOS, quanto fatto da noi qui, usando come default il Cisco 827 può essere adattato con poche o nessuna modifica ad altri modelli, ben più grossi/recenti/blasonati della famiglia Cisco.
In questo articolo non si parla di come impostare data e ora del nostro router; non è una dimenticanza, è che l’827 non ha una batteria tampone e non supporta i comandi per il sync dell’ora via NTP, quindi al primo blackout o abbassamento di tensione l’orologio viene comunque riazzerato. La cosa non pregiudica il corretto funzionamento del router e quindi abbiamo ritenuto più giusto non fornire informazioni in merito ad un qualcosa che si tradurrebbe, per l’utente medio, nell’obbligo di dover accedere all’interfaccia del router ad ogni riavvio e reimpostare manualmente l’orario con pochissimi (nessuno?) vantaggi.
Aggiornamento Sul Cisco 827 e per tutti i modelli 82x esiste la versione “piccola” del NTP: SNTP, che funziona correttamente e che verrà descritta nell’apposito paragrafo. Il Cisco 828 è invece provvisto di un servizio NTP integrato.
Si ringrazia Alessandro Torchia per aver trovato e segnalato tempestivamente la svista.
Primo setup
Innanzitutto prendiamo il cavo azzurro, colleghiamo la parte femmina a nove poli al PC e la parte RJ-45 all’interfaccia “console” sul retro del router, quindi lanciamo un programma come hyperterminal o terraterm.
Accendiamo il router e aspettiamo che lo stesso prepari l’IOS e presenti il proprio prompt di comandi, vedremo la diagnostica e l’avvio di IOS. Il router impiega circa 90 secondi (il tempo è variabile e dipende da quant’è grossa la versione di IOS che state eseguendo) per il caricamento del sistema e altri 15-30 per ottenere la sincronizzazione del livello fisico dell’ADSL.
Una volta finito tutto lo sbrodolamento di messaggi ed informazioni premiamo invio e, se tutto è sistemato a dovere, dovremmo essere nella modalità “base” del router (altrimenti qualcosa è andato male e siamo in ROMMON, che non tratteremo qui). In questa modalità, in cui il prompt è il simbolo ‘>’ si ha un accesso molto limitato al router in cui è possibile solo avere informazioni relative al corretto funzionamento ed allo stato delle interfacce. Per poter configurare ed accedere alle funzionalità più “avanzate” del router stesso è necessario passare da questa modalità a quella privilegiata; per far ciò si usa il comando ‘enable’:
Router>enable
Su un router nuovo o non configurato non c’è nessuna password, qualora ve ne sia una per andare in modalità privilegiata vi verrà chiesta. A questo punto il prompt si presenterà in modalità privilegiata cambiando da ‘>’ a ‘#:
Router#
Ora, per configurare il router dobbiamo entrare in una terza modalità, la modalità di configurazione (accessibile, appunto, solo dalla modalità privilegiata), per entrarvi si usa “configure” e, essendo noi collegati al terminale, il comando completo è “configure terminal” o, per brevità:
Router#conf t
A questo punto il prompt cambierà nuovamente, la “parte” fra parentesi ci indicherà in che “parte” della configurazione ci troviamo (la cosa tornerà più chiara in seguito).
Router(config)#
La prima cosa che andremo a configurare è sicuramente l’interfaccia ethernet (che il cisco chiama ethernet 0); per “spostarci” sulla configurazione dell’interfaccia digitiamo:
Router(config)#interface ethernet 0
Il prompt cambierà facendoci vedere “dove ci troviamo”:
Router(config-if)#
La prima cosa da fare è dare un IP all’interfaccia, in modo da essere raggiungibili (ping, telnet e così via). Per i setup domestici (specie in PPPoA e PPPoE) si usano IP privati (quelli, cioè, che sono riservati alle reti interne e non utilizzati su internet, cioè nelle classi 10.0.0.0/8, 172.16.0.0/12 o 192.168.0.0/16).
Mettiamo di voler usare solo 256 IP della classe più piccola, in particolare di voler dare al router 192.168.0.1 e di “riconoscere” come locali tutti gli IP che “cominciano” con 192.168.0 ; il comando sarà:
Router(config -if)#ip address 192.168.0.1 255.255.255.0
In un mondo (non)perfetto a questo punto l’interfaccia sarebbe tranquillamente aperta ed accessibile ma, visto che Cisco è una società seria e fa le cose per bene a questo punto l’interfaccia è ancora saldamente “staccata” per ragioni di sicurezza, che non discuteremo qui. Quello che c’interessa a questo punto è abilitare l’interfaccia, cosa discretamente semplice che si fa con il comando:
Router(config-if)#no shutdown
Finito questo setup dell’interfaccia possiamo lasciare la configurazione dell’interfaccia di rete e tornare nella “root” di configurazione, con un comando molto difficile da ricordare a memoria:
Router(config-if)#exit
Ovviamente il prompt ci gratificherà mostrandoci dove siamo e, si spera, impedendoci di fare errori madornali come configurare i parametri di un interfaccia in un altra (visto che ora il discorso delle “parti” della configurazione torna?):
Router(config)#
Configurazione dell’interfaccia esterna e NAT (parte prima)
Innanzitutto entriamo nella configurazione dell’interfaccia virtuale Dialer 0 in modo molto simile a come abbiamo fatto per l’ethernet:
Router(config)#interface dialer 0
Se vogliamo fare una cosa “pulita” possiamo mettere una piccola descrizione (del tutto ininfluente per il router ma molto pratica quando si va a controllare la configurazione) da associare all’interfaccia:
Router(config)#description Connessione ad INTERNET (PPPoA Aruba)
Se da contratto non abbiamo un IP fisso ma ci viene assegnato di volta in volta dal nostro provider usiamo il comando:
Router(config-if)#ip address negotiated
che dirà che per quest’interfaccia l’IP viene fornito “dall’altra parte” mentre, se conosciamo l’IP (o gli IP) che ci è stato assegnato possiamo usare:
Router(config-if)#ip address ip_address subnet_mask
Dove i campi ip_address e subnet_mask sono abbastanza auto esplicativi (e, come il resto del comando, del tutto identici come funzionalità a quelli usati per l’interfaccia Ethernet).
Settiamo, quindi, l’incapsulamento PPP (cioè diciamo che l’interfaccia “incapsula” i pacchetti dentro a frame PPP), digitando:
Router(config-if)#encapsulation ppp
A questo punto se nella rete domestica abbiamo usato degli IP privati e vogliamo che le macchine possano comunicare con l’esterno avremo bisogno di effettuare il NAT.
Ecco quindi che specifichiamo che vogliamo il NAT sui pacchetti che escono da Dialer0:
Router(config-if)#ip nat outside
A questo punto ci toccherà indicare uno o più dialer pool; un dialer pool è nient’altro che una lista (pool) di dati di accounting da usare come credenziali (in pratica login e password) per autenticarsi, in questo caso definiamo un solo dialer pool:
Router(config-if)#dialer pool 1
A questo punto dobbiamo definire i nostri cari, vecchi login e password; in generale l’autenticazione avviene mediante PAP o CHAP. Ecco come si specificano i valori per ambedue i metodi d’autenticazione;
Per il CHAP:
Router(config-if)#ppp chap hostname xxxxxxx Router(config-if)#ppp chap password yyyyyyy
e per il PAP :
Router(config-if)#ppp pap sent-username xxxxxx password yyyyyy
Ora possiamo uscire dalla configurazione dell’interfaccia del Cisco, con lo stesso comando che abbiamo visto prima:
Router(config-if)#exit
A questo punto dobbiamo configurare il livello sottostante, ovvero quello dell’interfaccia (non più virtuale ma fisica) su cui si appoggia Dialer0. L’interfaccia fisica è quella dell’ADSL e viene chiamata da Cisco (in forza al tipo di protocollo usato su di essa) ATM 0, quindi per entrarvi useremo:
Router(config)#interface ATM 0
Ed il prompt si modificherà nuovamente:
Router(config-if)#
Non vogliamo dare all’interfaccia ATM un suo IP (sarà Dialer, l’interfaccia virtuale che si “appoggia” ad ATM0 ad averla), per cui usiamo:
Router(config-if)#no ip address
Possiamo definire la dimensione di un buffer che contenga le ultime celle ATM arrivate (nel nostro caso 224 celle) tramite il comando:
Router(config-if)#hold-queue 224 in
Possiamo anche definire il modo in cui vogliamo che venga stabilito il link ADSL, in generale il parametro “safe” nonché lo standard è auto ma si possono anche indicare (a seconda delle necessità) ansi-dmt (che è quella che viene di solito selezionata da auto), itu-dmt (diversa partitura per le portanti, ma funziona altrettanto bene con le apparecchiature impiegate in italia) o splitterless (G.Lite, senza filtri per connessioni a bassa velocità, non usata in Italia):
Router(config-if)#dsl operating-mode auto
Ecco, a questo punto dobbiamo configurare il circuito PVC, cioè il canale “permanente” per lo scambio di dati, questo si ottiene indicando una coppia di valori: VPI/VCI, tipici per ogni paese (nel senso che per le ADSL sono dipendenti dallo stato in cui si abilita la linea e pressoché fissi per tutto il territorio nazionale)… in particolare per l’Italia trattasi di VPI=8 e VCI=35; il comando, in tutta la sua maestosità è quindi:
Router(config-if)#pvc 8/35
In questo caso il prompt cambierà automaticamente in modalità ATM virtual connection:
Router (config-atm-vc)#
Ed eccoci al terzo livello d’impacchettamento (speaking of scatology), i pacchetti IP vengono incapsulati in frame PPP che a loro volta “viaggiano” dentro celle ATM, per cui abbiamo un PPP over ATM, più nota come PPPoA.
A questo punto dobbiamo solo spiegare al router che vogliamo questo tipo d’incapsulamento, per farlo useremo VC-Mux (chi fosse interessato a successivi approfondimenti può divertirsi a leggere RFC 2364 - ATM Adaptation Layer 5 (aal5)) ed il tutto è fatto dal comando:
Router(config-atm-vc)#encapsulation aal5mux ppp dialer
Cioè incapsulamento dialer -> ppp -> aal5mux, in alternativa possiamo usare come incapsulamento LLC-mux:
Router(config-atm-vc)#encapsulation aal5snap
Che è considerato leggermente meno “prestante” (ed è il default per il nostro router se non viene specificato nulla).
Ora dobbiamo associare un pool all’interfaccia per poter effettuare l’autenticazione, ecco che quindi ci lanciamo in un:
Router(config-atm-vc)#dialer pool-member 1
Se invece la nostra connessione è di tipo PPPoE (in genere quella utilizzata da chi ha Linux o MacOS-X in quanto non richiede driver per il modem) appena entrati in config-atm-vc possiamo limitarci a scrivere qualcosa come:
Router (config-atm-vc)#pppoe-client dial-pool-number 1
E, anche qui come per l’ethernet, attiviamo l’interfaccia fisica mediante l’apposito comando:
Router(config-atm-vc)#no shutdown
Usciamo quindi dalla configurazione di quest’interfaccia:
Router(config-atm-vc)#exit
Configurazione di routing e NAT (parte seconda)
A questo punto, nella configurazione generale dobbiamo dire al router di effettuare il NAT sulla rete LAN per tutti i pacchetti che vanno verso dialer 0, per far questo usiamo il seguente comando:
Router(config)#ip nat inside source list 1 interface dialer 0 overload
La parte “source list 1” è relativa alle ACL, che vedremo più avanti, per ora ci si limiti ad osservare il resto della configurazione.
Fatto questo dobbiamo dire al router di instradare i pacchetti verso l’esterno, in una configurazione domestica tipica dove il router è l’unico punto per raggiungere internet la regola generale è questa:
Router(config)#ip route 0.0.0.0 0.0.0.0 dialer 0
Cioè instrada tutto (0.0.0.0 con subnet mask 0.0.0.0) verso l’interfaccia dialer 0.
Passiamo quindi a fare l’access list che abbiamo specificato poche righe sopra; in pratica dobbiamo definire una regola che ci permetta di definire i pacchetti che vogliamo che vengano nattati; nel nostro esempio la regola sarà:
Router(config)#access-list 1 permit 192.168.0.0 0.0.0.255
cioè una regola che “accetta” (permit) tutti i pacchetti con IP da 192.168.0.0 a 192.168.0.255 (si noti che la subnet mask è “invertita” rispetto alla scrittura “classica”): se andiamo a rileggere ora il comando sopra “ip nat inside source list 1 interface dialer 0 overload” possiamo ora capire che dice”effettua il nat ip per tutti i pacchetti che hanno un origine accettata dall’ACL 1 e diretti verso dialer 0”.
Su come si fanno le ACL si tornerà più avanti in un capitolo a parte, per adesso andiamo avanti.
A questo punto torniamo sull’interfaccia ethernet 0:
Router (config)#interface ethernet 0
ed abilitiamo il NAT su quello che “arriva” all’interfaccia:
Router (config-if)#ip nat inside
Si noti che sull’interfaccia connessa agli IP nattati definiamo “ip nat inside” mentre sull’interfaccia pubblica definiamo “ip nat outside”.
Infine, per uscire dalla configurazione, digitate:
Router (config-if)#exit
Setup avanzato e tunning dei parametri di funzionamento del NAT
Ritornando nella “principale” di configurazione possiamo divertirci a modificare i parametri di funzionamento relativi al NAT; visto che in NAT il router deve “tenere traccia” dei binding ovviamente ci sarà una tabella che manterrà questi valori, la dimensione di questa tabella è specificabile attraverso il comando:
Router(config)#ip nat translation max-entries 5000
che, in questo caso, pone a 5000 il numero di elementi di tabella (quindi fino a 5000 “connessioni” contemporanee).
I singoli binding in tabella verranno gestiti in modo dinamico ed “eliminati” se non vi è traffico per più di un certo periodo di tempo (relativo al tipo di connessione ed allo stato), vediamo insieme come indicare separatamente i vari valori di timeout:
Router(config)#ip nat translation timeout 420
Ci dice che “genericamente” ogni binding “cade” dopo sette minuti (il tempo è in secondi, 7 x 60 = 420) che non vi è traffico.
Router(config)#ip nat translation tcp-timeout 120
Due minuti per le connessioni TCP
Router(config)#ip nat translation pptp-timeout 420
Sette minuti per le connessioni pptp (tunnel)
Router(config)#ip nat translation finrst-timeout 300
Cinque minuti per le connessioni in fase di chiusura
Router(config)#ip nat translation syn-timeout 120
E due minuti per le connessioni che si stanno stabilendo.
Affianco a queste è possibile stabilire delle regole praticamente identiche per i flussi UDP che, pur non avendo una “connessione”, in NAT hanno bisogno di un binding per dei possibili flussi di ritorno (ad esempio quelli impiegati dai DNS), per questi c’è una serie apposita di parametri:
Router(config)#ip nat translation udp-timeout 120
Un binding UDP avrà un timeout di due minuti
Router(config)#ip nat translation dns-timeout 300
Le query DNS avranno un tempo di vita di cinque minuti
E poi ci sono i timeout per ICMP, qui ci limitiamo a dargli due minuti di vita.
Router(config)#ip nat translation icmp-timeout 120
In caso nella vostra rete qualcuno utilizzi VoIP trammite il protocollo SIP potete utilizzare il seguente comando, specificando opportunamente la porta che utilizza il servizio che utilizzate (5061 nel caso di Messagenet).
Router(config)#ip nat service sip udp port 5061
Fino a qui è stato “semplice”, abbiamo attivato il NAT dall’interno all’esterno, ma cosa succede se arriva una connessione da fuori? I server hanno bisogno di poter ricevere connessioni dall’esterno ed i programmi di P2P funzionano molto male se non riescono a ricevere connessioni dall’esterno (visto che i programmi di P2P fanno sia da client che da server).
Tuttavia il nostro router ha solo uno (o comunque pochi) indirizzi IP pubblici e diversi IP privati; non può sapere a priori a chi “forwardare” le connessioni entranti; siamo noi a dover specificare (nella configurazione) questo genere di cose: La prima regola che vedremo è quella di forwarding “indiscriminato”, in pratica con questa tutte le connessioni entranti verranno inviate ad un IP fisso che specificheremo nel comando stesso (in questo caso 192.168.0.2):
Router(config)#ip nat inside source static 192.168.0.2 interface Dialer0
Ma, ammettiamo di voler “differenziare” l’invio a seconda della porta o del protocollo per definire dei forward “diversi” a seconda del tipo di servizio (ad esempio per inviare verso il server web le connessioni che arrivano sulla porta 80), in questo caso si usa una versione estesa del comando di cui sopra:
Router(config)#ip nat inside source static tcp 192.168.0.3 80 interface Dialer0 80
E possiamo anche specificare una porta “diversa” da quella in cui arriva “nativamente” il pacchetto, per esempio:
Router(config)#ip nat inside source static tcp 192.168.0.3 22 interface Dialer0 21
Così come possiamo stabilire un binding statico per i datagrammi UDP (cosa pratica per vari client P2P):
Router(config)#ip nat inside source static udp 192.168.0.3 56005 interface Dialer0 56005
Oppure aprire un binding statico tanto per le connessioni TCP che per quelle UDP, fattibile tramite la forma abbreviata:
Router(config)#ip nat inside source static 192.168.0.3 56006 interface Dialer0 56006
Log e grafici
Una delle cose meravigliose dei router Cisco è la possibilità di amministrarli e monitorarli da remoto tramite SNMP.
Qui ci limiteremo a indicare com’è possibile configurare in modo veloce il router per permettere ad un applicazione su una macchina remota (nel mio caso ho usato cacti) di generare grafici di traffico e stress del processore.
Per prima cosa bisogna impostare una community read only, grossomodo una community è l’equivalente di una password e l’impostazione read only implica che tramite tale password sarà possibile solo leggere i valori di funzionamento e non modificare i parametri del router stesso:
Router(config)#snmp-server community catchme RO
In questo caso la community si chiama catchme e RO stà appunto per read only, la seconda cosa è impostare l’interfaccia da cui si può accedere ai servizi SNMP (giusto per evitare che qualcuno provi a pacchettarvi il router o che tenti di sapere i cavoli vostri), in pratica:
Router(config)#snmp-server trap-source Ethernet0
Infine bisogna indicare la macchina da cui accettare l’accesso alla community:
Router(config)#snmp-server host 192.168.1.253 catchme
Se poi vogliamo loggare tutti i messaggi generati dal router via syslog possiamo farlo con due semplicissimi comandi:
Router(config)#logging facility local3
che indica quale facility utilizzare per inviare i messaggi generati e:
Router(config)#logging 192.168.0.4
che indica verso quale macchina inviare i pacchetti UDP relativi ai log.
Configurazione dell’accesso al router
Mettiamo ora di voler configurare l’accesso al router, innanzitutto impostiamo i valori relativi alla console seriale:
Router(config)#line con 0
Indichiamo il numero di bit di stop (1)
Router(config-if)#stopbits 1
e la velocità dell’interfaccia seriale (115200, la massima, giusto per non invecchiare mentre scorre il nostro “sh conf”):
Router(config-if)#speed 115200
Usciamo dalla configurazione della seriale:
Router(config-if)#exit
e passiamo alla configurazione delle vty (i virtual terminal, telnet & compagnia bella), diciamo che vogliamo cinque vty, numerate da 0 a 4:
Router(config)#line vty 0 4
Impostiamo la password per l’accesso via rete:
password qui-la-tua-password
ed infine indichiamo che vogliamo il login per accedere via telnet.
login
Add ons alla configurazione di base
Altre cose comode da aggiungere nella configurazione generale sono:
Sull’ethernet, impostare un sistema di rimodulazione del MSS (spazio destinato ai dati dentro un pacchetto TCP) (x è il valore in bytes, ad esempio 1452):
Router(config-if)#ip tcp adjust-mss x
Abilitare il servizio di criptazione delle password (per evitare che vengano conservate “in chiaro” nel file di configurazione):
Router(config)#service password-encryption
Indicare il nome del router stesso:
Router(config)#hostname Cisco827
Impostare una password di “enable” cosicchè per poter accedere alla modalità privilegiata è necessario fornire questa seconda password.
Router(config)#enable password qui-la-tua-enable-password
Impostare la massima dimensione di un pacchetto TCP (senza headers):
Router(config)# ip tcp mss 1452
Indicare i DNS che il router usa internamente (quando si effettuano i ping ad esempio):
Router(config)#ip name-server 195.210.91.100 Router(config)#ip name-server 193.70.192.100
A questo punto possiamo uscire dalla configurazione tramite exit (tornando alla modalità privilegiata).
Salvare la configurazione del router e verificare che tutto funzioni
Per salvare la configurazione sulla NVRAM (in modo il router la ricarichi al riavvio), cosa che viene fatta tramite il comando ‘copy’ o, più specificatamente da:
Router#Copy running-config startup-config
che, in versione bonsai è:
Router#wr mem
A questo punto potremo controllare lo stato della connessione (link fisico) dell’ADSL mediante il comando:
Router# show int atm 0
che dovrebbe produrre qualcosa di simile a:
ATM0 is up, line protocol is up Hardware is PQUICC_SAR (with Alcatel ADSL Module) MTU 1500 bytes, sub MTU 1500, BW 320 Kbit, DLY 80 usec, reliability 255/255, txload 172/255, rxload 235/255 Encapsulation ATM, loopback not set Encapsulation(s): AAL5 AAL2, PVC mode 10 maximum active VCs, 1024 VCs per VP, 2 current VCCs VC Auto Creation Disabled. VC idle disconnect time: 300 seconds Last input never, output 00:00:00, output hang never Last clearing of "show interface" counters never Input queue: 0/224/0/0 (size/max/drops/flushes); Total output drops: 2831 Queueing strategy: Per VC Queueing 5 minute input rate 532000 bits/sec, 93 packets/sec 5 minute output rate 216000 bits/sec, 91 packets/sec 23382790 packets input, 1778160515 bytes, 0 no buffer Received 0 broadcasts, 0 runts, 0 giants, 0 throttles 0 input errors, 1 CRC, 0 frame, 0 overrun, 0 ignored, 1 abort 19123900 packets output, 4290284361 bytes, 0 underruns 0 output errors, 0 collisions, 2 interface resets 0 output buffer failures, 0 output buffers swapped out
Mentre per avere i dettagli relativi alla connessione al provider basta usare
Router# show int dialer 0
Si avrà qualcosa di simile a:
Dialer1 is up, line protocol is up (spoofing) Hardware is Unknown Internet address is 151.49.228.159/32 MTU 1492 bytes, BW 56 Kbit, DLY 20000 usec, reliability 255/255, txload 28/255, rxload 159/255 Encapsulation PPP, loopback not set Keepalive set (10 sec) DTR is pulsed for 1 seconds on reset Interface is bound to Vi2 Last input never, output never, output hang never Last clearing of "show interface" counters 3d02h Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0 Queueing strategy: fifo Output queue: 0/40 (size/max) 5 minute input rate 541000 bits/sec, 66 packets/sec 5 minute output rate 175000 bits/sec, 51 packets/sec 23471757 packets input, 1845575375 bytes 18944802 packets output, 6021208 bytes Bound to: Virtual-Access2 is up, line protocol is up Hardware is Virtual Access interface MTU 1492 bytes, BW 0 Kbit, DLY 20000 usec, reliability 255/255, txload 252/255, rxload 255/255 Encapsulation PPP, LCP Open Open: IPCP PPPoATM vaccess, cloned from Dialer1 Vaccess status 0x44 Bound to ATM0 VCD: 2, VPI: 8, VCI: 35, loopback not set Keepalive set (10 sec) DTR is pulsed for 5 seconds on reset Interface is bound to Di1 (Encapsulation PPP) Last input 00:00:00, output never, output hang never Last clearing of "show interface" counters 3d02h Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0 Queueing strategy: fifo Output queue: 0/40 (size/max) 5 minute input rate 595000 bits/sec, 94 packets/sec 5 minute output rate 215000 bits/sec, 89 packets/sec 23472447 packets input, 1846195759 bytes, 0 no buffer Received 0 broadcasts, 0 runts, 0 giants, 0 throttles 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort 18945160 packets output, 6131384 bytes, 0 underruns 0 output errors, 0 collisions, 0 interface resets 0 output buffer failures, 0 output buffers swapped out 0 carrier transitions
Le ACL
Le Access Control List (o, per brevità, ACL) sono liste di istruzioni che controllano ogni singolo pacchetto di ogni flusso di dati per diverse ragioni, molto importante ne è quindi l’ordine in cui sono inserite.
Quando un pacchetto passa per una ACL, la lista viene scorsa istruzione per istruzione (riga per riga), dall’alto al basso, in cerca di una regola che combaci con il pacchetto interessato.
Quando il match è positivo, viene effettuata l’azione relativa alla regola e lo scorrimento della lista termina.
Le ACL possono assumere due ruoli all’interno di una configurazione:
- 1. Identificare una categoria di dati secondo parametri precisi, all’interno di un istruzione.
- 2. Identificare e filtrare il traffico indesiderato, quando applicate ad un’interfaccia.
Ogni ACL è marcata da un numero che è comune a tutta la lista di istruzioni. Il numero è arbitrario ma deve sottostare ad una regola: range diversi implicano sintassi diverse.
Le ACL standard vengono identificate da un numero tra 1 e 99. Comprendono una parte descrittiva e una decisionale. Vengono normalmente impiegate per un filtering Basilare.
La sintassi è: access-list [1-99] [decisione] [ip sorgente]
Le ACL estese sono la seconda generazione e sono identificate dai numeri da 100 a 199. I blocchi della sintassi sono i medesimi, ma le possibilità sono molto più potenti. E’ possibile descrivere regole modo molto più dettagliate.
La sintassi è: access-list [100-199] [decisione] [protocollo] [indirizzo sorgente] [porta sorgente] [indirizzo destinazione] [porta destinazione] [tipo messaggio]
In ambedue i casi le decisioni ammesse sono permit o deny.
Esistono altri range per altri tipi di ACL che però non tratteremo qui, chi è interessato può cercare sulla documentazione Cisco.
Ora che conosciamo un po’ di teoria andiamo a scrivere una semplice ACL estesa per proteggere il nostro router da ip spoofing, vedremo, inoltre come ad esempio bloccare l’accesso a internet ad un pc della nostra rete.
Esempio 1: ACL applicata sull’interfaccia che blocca attacchi di tipo spoofing e tutto ciò che proviene dall’ip 100.90.80.10:
Router(config)#no access-list 103 Router(config)#access-list 103 deny ip host 0.0.0.0 any log Router(config)#access-list 103 deny ip 127.0.0.0 0.255.255.255 any log Router(config)#access-list 103 deny ip 10.0.0.0 0.255.255.255 any log Router(config)#access-list 103 deny ip 172.16.0.0 0.15.255.255 any log Router(config)#access-list 103 deny ip 192.168.0.0 0.0.255.255 any log Router(config)#access-list 103 deny ip any any Router(config)#access-list 103 deny ip host 100.90.80.10 any log Router(config)#access-list 103 permit tcp any any established Router(config)#access-list 103 permit ip any any end
Non commenteremo le singole linee (sono abbastanza autoesplicative), ci teniamo a far notare però che tutte le regole iniziano con un “no access-list” che cancella completamente la regola; visto che le righe della regola vengono valutate nell’ordine in cui esse sono immesse in caso di errore bisognerà cancellare l’intera regola e riscriverla ex-novo.
Per applicare la regola si usa, dalla configurazione dell’interfaccia su cui vogliamo applicarla:
Router(config-if)#ip access-group 103 in
Esempio 2: ACL che blocca l’accesso a internet a 1 pc della rete locale
Router(config)#access-list 2 deny 10.1.1.89 Router(config)#access-list 2 permit 10.1.1.0 0.0.0.255 Router(config)#access-list 2 deny any
Anche in questo caso per applicare la regola si usa:
Router(config-if)#ip access-group 2 in
Ricordate, se avete bisogno di un suggerimento sul comando da dare vi basterà digitare nella console un ? e vi verrà visualizzato l’elenco delle possibili opzioni. (vale per tutti i comandi non solo per le ACL).
Il mondo finisce oltre questo limite
Quel che segue questo punto rappresenta una serie di nozioni ed informazioni recuperate ed usate solo marginalmente su cui si sono fatti solo alcuni esperimenti (o, a volte, nessuno) e sono riportati per completezza e senza assicurazioni sul funzionamento.
Si è preferito, per completezza, riportare qui quanto si è trovato, visto ed appreso a solo titolo informativo; non c’è una precisa indicazione di cosa funzioni e cosa non funzioni ma, orientativamente, quanto messo a seguire è una buona base d’inizio per chi volesse implementare le soluzioni ivi presenti e noi stessi ci candidiamo ad estendere, migliorare e (si spera) completare un giorno le seguenti sezioni.
Il Cisco 827 come server DHCP
Per impostare un server DHCP sulla rete cisco (12.2+) innanzitutto abilitiamo il servizio DHCP nella configurazione del router:
Router(config)#service dhcp
Disabilitare il servizio di riconoscimento dei conflitti fra server DHCP multipli (nella maggior parte delle configurazioni non avremo più di un server DHCP):
Router(config)#no ip dhcp conflict logging
Per evitare che venga assegnato erroneamente un IP (in questo esempio 192.168.1.55) già staticamente definito:
Router(config)#ip dhcp excluded-address 192.168.1.55
Definire un pool (un blocco di IP da assegnare dinamicamente ed i loro default value):
Router(config)#ip dhcp pool nomepool
Entreremo in un “sotto-prompt” in cui potremo stabilire i dati relativi al pool. Indicare subnet e subnet mask del pool (x.x.x.x è la subnet, y è la subnet mask):
Router(dhcp-config)#network x.x.x.x y.y.y.y
Definire il nome del dominio del pool:
Router(dhcp-config)#domain-name dominio
Indicare il router di default:
Router(dhcp-config)#default-router 192.168.1.1
Indicare i DNS server di tale dominio (fino ad otto):
Router(dhcp-config)#dns-server address1 ... address8
Indicare i server WINS (fino ad otto, usato su reti microsoft):
Router(dhcp-config)#netbios-name-server address1 ... address8
Indicare il nome di tipo netbios usato (su una rete senza windows server e domini è in genere broadcast), questo passo è facoltativo e può essere tranquillamente saltato:
Router(dhcp-config)#netbios-node-type b
Impostare la durata dei lease (cioè ogni quanto tempo l’IP va rinegoziato, dd=giorni, hh=ore, mm=minuti):
Router(dhcp-config)#lease dd hh mm
oppure
Router(dhcp-config)#lease infinite
Uscire dalla definizione del pool.
Router(dhcp-config)#exit
Se si vuole fare un binding statico (cioè indicare un IP da dare in modo fisso all’host con un MAC address predefinito) occorre un pool individuale per ogni binding statico
Router(cnfig)#ip dhcp pool nomepool
Indicare la subnet e la subnet mask (come sopra):
Router(dhcp-config)#network x.x.x.x y.y.y.y
(opzionale) Indicare il tipo di piattaforma, i possibili valori sonoieee802 o ethernet, ma per noi è sempre il default (ethernet);questa parte può essere quindi saltata
Router(dhcp-config)#hardware-address ethernet
Indicare il MAC address (xx.xxxx.xxxx.xx) del client, yy è 01 per Ethernet e 06 per ieee802:
Router(dhcp-config)#client-identifier yyxx.xxxx.xxxx.xx
(opzionale) Indicare il nome del client:
Router(dhcp-config)#client-name nome
Uscire dalla definizione del pool:
Router(dhcp-config)#exit
Nel caso di DHCP multipli e reti congestionate o molto lente per evitare conflitti è utile alzare il numero (x) di ping da fare per verificare che l’IP non sia già utilizzato, impostando il ping a zero invece non viene effettuato nessun controllo preventivo sull’assegnamento. In generale per gli usi “domestici” evitare il controllo è abbastanza “sicuro”, a patto di non dover fare i conti con gente che assegna staticamente (ed indiscriminatamente) gli IP alle macchine.
Router(config)#ip dhcp ping packets x
Anche il tempo di timeout (mm) può essere cambiato in base alle necessità (è in millisecondi):
Router(config)#ip dhcp timeout mm
Per ulteriori informazioni su come impostare il DHCP sui router Cisco in genere potete consultare
Trasparent proxy, il redirect sui Cisco
Quanto segue è tratto da un documento relativo a come configurare i router Cisco con squid per abilitare il trasparent proxy (cioè per redirigere le connessioni HTTP verso un proxy che “impersonerà” il server HTTP vero).
Per redirigere una parte del traffico (in questo caso il traffico HTTP verso un proxy) prima di tutto definiamo una mappa di routing.
Router(config#)route-map proxy-redirect permit 10
Quindi indichiamo che questa route-map (che abbiamo chiamato proxy-redirect) coinvolge quanto definito dall’ACL x:
Router(config-route-map)#match ip address x
Infine indichiamo cosa fa effettivamente la routing map, cioè instradare i pacchetti verso y.y.y.y:
Router(config-route-map)#set ip next-hop y.y.y.y
A questo punto definiamo l’ACL x relativa, la prima regola scarta i pacchetti “non web”:
Router(config)#access-list x deny tcp any any neq www
La seconda scarta il traffico generato dal server proxy (qui indicato come y.y.y.y) visto che il traffico originato dal proxy non deve essere reindirizzato al proxy:
Router(config)#access-list x deny tcp host y.y.y.y any
Infine mettiamo la regola “catch all” che in pratica “acchiappa” tutti i pacchetti che non sono stati scartati precedentemente (cioè tutti i pacchetti www non originati da y.y.y.y):
Router(config)#access-list x permit tcp any any
A questo punto per applicare il routing ad un interfaccia lanciamo il seguente comando dalla configurazione dell’interfaccia stessa:
Router(config-if)#ip policy route-map proxy-redirect
Una nota su Internet fa presente che è preferibile un altra ACL che non da problemi con pacchetti TCP “larghi” (>1472 bytes) ma che sforza di più la CPU:
Router(config)#access-list x deny tcp host y.y.y.y any Router(config)#access-list x permit tcp any any eq www Router(config)#access-list x deny tcp any any
Questa seconda forma è concettualmente identica alla prima con la differenza evidente che un pacchetto tcp non http deve scorrere tutte e tre le regole anzichè una; il vantaggio è che la frammentazione dei pacchetti TCP non provoca problemi, lo svantaggio è che il router ha molto più lavoro da svolgere.
CBAC, il minimo
Altre aggiunte “comode” (disponibili solo su alcune versioni di IOS) particolarmente utili contro i DoS ed i DDoS sono quelle relative al firewall di Cisco vero e proprio, di cui qui ci si occuperà solo marginalmente e relativamente alle operazioni di tuning; senza entrare nel dettaglio di come configurare “in pieno” questo formidabile sistema. In particolare le opzioni che vedremo sono:
Comincia a cancellare le connessioni “half-open” quando queste superano un valore di soglia x:
Router(config)#ip inspect max-incomplete high x
Smette di chiudere le connessioni “half-open” quando scendono sotto il valore di soglia x:
Router(config)#ip inspect max-incomplete low x
Comincia a chiudere le connessioni “half-open” quando vengono aperte più di un certo valore di soglia x di connessioni al minuto:
Router(config)#ip inspect one-minute high x
Smette di chiudere le connessioni “half-open” quando ne rimangono solo un certo valore di soglia x fra quelle aperte nell’ultimo minuto:
Router(config)#ip inspect one-minute low x
Imposta il tempo (x, in secondi) da attendere prima di chiudere le connessioni “half-open” (esiste già qualcosa di simile per il NAT ma agisce sui binding, questo invece lavora a livello di IP):
Router(config)#ip inspect tcp synwait-time x
Il supporto completo CBAC per ovvie ragioni esula dalla trattazione, ma scriveremo qualche regola “comoda”; mettiamo ad esempio di voler stabilire staticamente dei timeout “a parte” per alcune interfacce e per alcuni comandi, si comincia definendo una classe fw.
Impostiamo un timeout di 3600 secondi (un ora) sulle connessioni FTP:
Router(config)#ip inspect name fw ftp timeout 3600
Un timeout di 3600 secondi per un le connessioni SMTP (posta):
Router(config)#ip inspect name fw smtp timeout 3600
Uno di appena 30 secondi per TFTP:
Router(config)#ip inspect name fw tftp timeout 30
Un timeout di appena 15 secondi per gli UDP “generici”:
Router(config)#ip inspect name fw udp timeout 15
Un timeout di un’ora sulle connessioni TCP:
Router(config)#ip inspect name fw tcp timeout 3600
Ma queste sono davvero quattro stupidaggini messe per esempio, la trattazione di quello che si può controllare e di come lo si può controllare è decisamente vasta e complicata, per questo evitiamo di farla qui (dove siamo già abbastanza off-topic), ci limitiamo a dire che c’è molto altro da dire e vi rimandiamo a futuri approfondimenti (nostri) o alla sempre esaudiente documentazione di Cisco stessa.
A titolo di esempio gli altri tipi di protocolli supportati dalla mia versione di IOS sono: cuseeme, fragment (i frammenti di pacchetti successivi al primo), h323 (NetMeeting, Intel Video Phone), http, icmp, netshow, rcmd (i protocolli ‘remote commands’ di UNIX come r-exec, r-login, r-sh), realaudio, rpc, rtsp, sip, skinny, sqlnet, streamworks, vdolive, ognuno avente diverse regole e parametri da controllare (inspect).
A questo punto basterà entrare nell’interfaccia voluta:
Router(config)#interface Ethernet0
ed applicare la classe all’interfaccia (in questo caso sulle connessioni “entranti”):
Router(config-if)#ip inspect fw in
oppure
Router(config-if)#ip inspect fw out
a seconda dei casi, stessa cosa dicasi per IPv6:
Router(config-if)#ipv6 inspect fw in
oppure
Router(config-if)#ipv6 inspect fw out
Il supporto IPv6
NOTA : Il supporto IPv6 qui descritto è molto limitato, spesso presentato semplicemente per esempi e meno commentato rispetto al resto dell’articolo, la ragione è molto semplice, con IPv6 abbiamo lavorato decisamente di meno e le informazioni che abbiamo sono ottenute spesso in modo molto empirico o consultando la documentazione online con pochissimo supporto; vista comunque la diffusione in ambito domestico non credo che la cosa sia particolarmente limitante per il setup di un router come l’827 che, pur essendo un ottimo router con notevoli capacità, è spesso impiegato in ambiti SOHO in cui non è richiesto un particolare setup.
Per configurare IPv6 è necessario invece creare un tunnel IPv4 in cui che trasporti all’interno i frame IPv6, ecco come fare:
Intanto configuriamo l’interfaccia di rete locale per avere un IPv6 fisso:
Router(config)#Interface Ethernet0
Indichiamo qui l’IPv6 del router, la subnet mask (bit che valgono, y) e la codifica, eui-64 (non è strettamente necessario indicarla esplicitamente):
Router(config)#ipv6 address x/y eui-64
Abilitiamo IPv6 sull’interfaccia:
Router(config)#ipv6 enable
Usciamo dalla gestione dell’interfaccia:
Router(config)#exit
Attiviamo il routing di pacchetti IPv6:
Router(config)#ipv6 unicast-routing
A questo punto dobbiamo fare in modo che la nostra rete IPv6 comunichi col resto del mondo: innanzitutto creiamo l’interfaccia di tunnel (in questo caso Tunnel0):
Router(config)#interface Tunnel0
Diamole una descrizione (giusto per capirci qualcosa quando facciamo sh conf):
Router(config-if)#description descrizione
L’interfaccia tunnel non avrà un IP (IPv4) proprio:
Router(config-if)#no ip address
Impostiamo l’IP IPv6 dell’interfaccia (x) e la subnet (y, il numero di bit da considerare):
Router(config-if)#ipv6 address x/y
Impostiamo l’endpoint locale (IPv4) del tunnel (x.x.x.x è l’IPv4 del local endpoint, y è l’interfaccia “d’ascolto”, tipo Dialer 0 o Ethernet 0):
Router(config-if)#tunnel source x.x.x.x
oppure
Router(config-if)#tunnel source y
Impostiamo l’endpoint remoto (IPv4) del tunnel (y.y.y.y):
Router(config-if)#tunnel destination y.y.y.y
Ed indichiamo di che tipo di tunnel si tratta, cioè IPv6 over IP:
Router(config-if)#tunnel mode ipv6ip
Ed attivare il tunnel:
Router(config-if)#no shutdown
A questo punto possiamo uscire dalla definizione del tunnel:
Router(config-if)#exit
Impostiamo una route che permetta di instradare tutto il traffico (::/0) IPv6 attraverso Tunnel0, NOTA: questo non è un settaggio obbligato, ma è quello che si vuole nel 99.9% dei casi in una rete domestica:
Router(config)#route ::/0 Tunnel0
E’ possibile impostare diversi tunnel contemporaneamente, ed abilitare il RIP per migliorare il routing. Basta aggiungere in ogni tunnel (ripname è il nome del gruppo su cui effettuare il RIP):
Router(config-if)#ipv6 rip rinpame enable
Le ACL in IPv6
Ovviamente come per IPv4 è possibile imporre delle ACL di controllo anche per IPv6, per creare un ACL IPv6 utilizziamo:
Router(config)#ipv6 access-list inbound
dove inbound è appunto il nome dell’access list, il prompt cambierà in qualcosa di simile a:
Router(config-ipv6-acl)#
La sintassi (completa!) per le ACL IPv6 è la seguente:
[no] permit | deny ipv6 | <protocol> any | host <src> | src/len [sport] any | host <dest> | dest/len [dport] [reflect <name> [timeout<secs>]] [fragments] [routing] [dscp <val>] [flow-label <val>] [time-range <name>] [log | log-input] [sequence <num>]
E noi potremo definire le varie regole, una per riga con le stesse modalità di quelle IPv4:
Router(config-ipv6-acl)#permit icmp host 2001:888:10:FA::1 host 2001:888:10:FA::2 Router(config-ipv6-acl)#permit tcp any host 2001:888:10FA::1 eq 22 log Router(config-ipv6-acl)#permit tcp any host 2001:888:10FA::1 eq smtp log Router(config-ipv6-acl)#permit udp any host 2001:888:10FA::1 eq domain log Router(config-ipv6-acl)#permit tcp any host 2001:888:10FA::1 eq domain log Router(config-ipv6-acl)#permit tcp any host 2001:888:10FA::1 eq www log Router(config-ipv6-acl)#permit tcp any host 2001:888:10FA::1 eq 443 log Router(config-ipv6-acl)#permit icmp any 2001:888:10FA::/48 echo-reply log Router(config-ipv6-acl)#permit icmp any 2001:888:10FA::/48 unreachable log Router(config-ipv6-acl)#permit icmp any 2001:888:10FA::/48 time-exceeded log Router(config-ipv6-acl)#deny ipv6 any any log
E quindi usciamo, nel solito modo…
Router(config-ipv6-acl)#exit
A questo punto andiamo nell’interfaccia ed applichiamo l’ACL all’interfaccia voluta:
Router(config-if)#ipv6 traffic-filter inbound in
e, per il traffico uscente:
Router(config-if)#ipv6 traffic-filter outbound out
Fatto salvo che dobbiamo, in questo caso, creare un ACL chiamata outbound.
Detto questo valgono le stesse considerazioni relative alle ACL IPv4.
Per ulteriori informazioni rimandiamo allo slide di Cisco in merito reperibile presso: http://www.cisco.com/warp/public/732/Tech/ipv6/docs/ipv6_acls0403.ppt
Appendice 1. Il NAT, grossomodo
Il NAT, o Network Address Translation, è una brutta bestia :-).
Spesso ci troviamo ad avere assegnati uno o comunque pochi IP a disposizione; visto che però ci troviamo costretti ad offrire connettività a più macchine di quanti non siano gli IP a nostra disposizione si utilizza questa cosa “brutta” che è il NAT e che influenzerà pesantemente la configurazione del nostro (amato?) router.
In pratica noi usiamo degli IP non presenti su internet come IP della nostra rete; il router ha un suo IP “pubblico” (a volte anche più d’uno, nel qual caso la documentazione Cisco correttamente distingue fra NAT propriamente detto e PAT) e si limita a fingere che tutto il traffico generato dalle macchine “nattate” sia generato da lui.
Il procedimento è molto semplice, quando il router riceve un pacchetto originato nella LAN (rete privata) e diretto verso la WAN (rete pubblica/internet) si limita a sovrascrivere il campo “origine” del pacchetto IP con il suo proprio IP “pubblico”, ricalcolare il CRC del pacchetto e (se non l’ha già fatto) “segnarsi” chi ha originato il pacchetto nella LAN.
Quando riceverà i pacchetti di ritorno, cioè i pacchetti che vengono dalla WAN e che hanno come destinazione il suo IP pubblico si limita a vedere se ha, nella sua lista, un “binding” relativo al pacchetto (cioè se si è segnato qualcosa a riguardo), se così è si limita a sovrascrivere il campo destinazione del pacchetto con l’IP che si è segnato precedentemente, ricalcolare il CRC e poi inviare il pacchetto sulla LAN.
Nota Finale
L’esperienza insegna che senza ACL strane e con qualche regola CBAC quando il mio provider mi ha attivato la 2mbit l’uso della CPU è schizzato al 65%, con una 4mbit avrei saturato tutto (e non uso IPv6), per cui andateci piano, non avete sotto mano un router enterprise ed il NAT stressa molto la CPU. Ricordate inoltre che la RAM non è infinita, il modello 827 ne ha a disposizione 32mb (se avete fatto l’upgrade) e spesso con le versioni di IOS plus più nuove si tende a saturarla. I primi sintomi di questo problema possono essere ad esempio il mancato funzionamento del comando “sh run” e nei casi più gravi la disabilitazione del login via telnet.
Finito di scrivere il 2006/02/22