lunedì 28 giugno 2010

GIMP Scripting - Fade and Shadow

Siccome qualcuno potrebbe pensare che questo blog sia stato abbandonato, provvedo a pubblicare qualcosa di nuovo che non è molto impegnativo, ma può fare molto comodo ed essere interessante.
Non pensate che siano stati abbandonati gli argomenti da sistemista, ma ho accumulato solamente un deciso ritardo perchè le tante bozze presenti sono da revisionare e correggere, alcune anche da terminare.
Visto che non mi piace farmi mancare "oggetti" scaturiti dalla mia mente e non perdo mai l'abitudine a cercare di arrivare dove altri si sentono a casa loro, mi sono dedicato ad un po' di sano scripting per GIMP, ovvero gli script-foo; questa tipologia di script serve per automatizzare operazioni ricorsive sulle immagini semplificando di molto la vita, ed aumentando moltissimo la velocità, se si devono applicare sempre gli stessi effetti.
Il primo e più semplice script che ho creato serve per effettuare un effetto fading e shadowing ad un'immagine, ovvero sfumare l'immagine ai bordi, come se fosse un rettangolo arrotondato, ed applicargli l'effetto ombra.

Ecco il codice:
; Script to make fading and shadowing of an image
;
; The script is located in "<Image> / Script-Fu / SebaX75 / Fade & Shadow..."
;
; Last changed: 25 Aprile 2010
;
; Copyright (C) 2010 SebaX75 <sebax75 AT yahoo DOT it>
;
; --------------------------------------------------------------------
; 
; Changelog:
;  Version 0.1
;    - First release
;
; --------------------------------------------------------------------
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.  
; 
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
; 
; You should have received a copy of the GNU General Public License
; along with this program; if not, you can view the GNU General Public
; License version 3 at the web site http://www.gnu.org/licenses/gpl-3.0.html
; Alternatively you can write to the Free Software Foundation, Inc., 675 Mass
; Ave, Cambridge, MA 02139, USA.
;

(define (script-fu-SebaX75-fade-shadow      myImage
     layer0
     offset_x
     offset_y
     arrotondamento
     riduzione
     sfumatura
     coloreOmbra
 )
;       Start an undo group so the process can be undone with one undo
 (gimp-image-undo-group-start myImage)

 ; Esegue la normalizzazione del layer principale
 (plug-in-normalize 1 myImage layer0)

 ; Rimuove qualunque selezione
 (gimp-selection-none myImage)

 ; Inizializzo le variabili da utilizzare
 (let* (
  (image-width (gimp-drawable-width layer0))
  (image-height (gimp-drawable-width layer0))
  (layer1())
  )

  ;Impostare il colore del primo piano a #444444
  (gimp-context-set-foreground coloreOmbra)
  ;Livello -> Trasparenza -> Aggiungi canale alfa
  (gimp-layer-add-alpha layer0)
  ; Seleziona -> Rettangolo arrotondato (20)
  (gimp-selection-all myImage)
  (script-fu-selection-rounded-rectangle myImage layer0 arrotondamento FALSE)
  ; Seleziona -> Riduci (10)
  (gimp-selection-shrink myImage riduzione)
  ; Seleziona -> Inverti
  (gimp-selection-invert myImage)
  ; Seleziona -> Sfumata (20)
  (gimp-selection-feather myImage sfumatura)
  ;Pressione Canc
  (gimp-edit-clear layer0)
;# Seleziona -> Niente
  ;Livello -> Nuovo livello con colore del primo piano ed in secondo piano
  (set! layer1 (car (gimp-layer-new-from-drawable layer0 myImage)))
  (gimp-image-add-layer myImage layer1 1)
  (gimp-drawable-fill layer1 FOREGROUND-FILL)
  ;Seleziona -> Rettangolo arrotondato (20)
  (gimp-selection-all myImage)
  (script-fu-selection-rounded-rectangle myImage layer1 arrotondamento FALSE)
  ;Seleziona -> Riduci (15)
  (gimp-selection-shrink myImage (+ riduzione 5))
  ;Seleziona -> Inverti
  (gimp-selection-invert myImage)
  ;#Seleziona -> Sfumata (20)
  (gimp-selection-feather myImage sfumatura)
  ;Pressione Canc
  (gimp-edit-clear layer1)
  ;Spostare di posizione il nuovo layer (10,10 pixel)
  (gimp-layer-set-offsets layer1 offset_x offset_y)
  ; Rimuove qualunque selezione
  (gimp-selection-none myImage)
  ; Unisco tutti i layer in uno unico
  (set! layer0 (car (gimp-image-flatten myImage)))
  (gimp-drawable-set-name layer0 "Ombra+Fade")
 )

 ;Finish the undo group for the process
 (gimp-image-undo-group-end myImage)

 ; Assicuro l'aggiornamento e la nuova visualizzazione
 (gimp-displays-flush)
)

; Registrazione dello script
(script-fu-register "script-fu-SebaX75-fade-shadow"
 _"<Image>/Script-Fu/SebaX75/Fade & Shadow..."
 "Applica gli effetti per ottenere l'ombra ed il fading dell'immagine"
 "SebaX75"
 "SebaX75"
 "April 21 2010"
 "*"
 SF-IMAGE "Image"     0
 SF-DRAWABLE     "Drawable"  0
 SF-ADJUSTMENT   _"Spostamento X" '(10 -4096 4096 1 10 0 1)
 SF-ADJUSTMENT   _"Spostamento Y" '(10 -4096 4096 1 10 0 1)
 SF-ADJUSTMENT   _"Arrotondamento %"     '(20 -4096 4096 1 10 0 1)
 SF-ADJUSTMENT   _"Riduzione"    '(10 0 1024 1 10 0 1)
 SF-ADJUSTMENT   _"Sfumatura"    '(20 0 1024 1 10 0 1)
 SF-COLOR _"Colore ombra" "#444444"
)

Per oggi direi che è tutto... buon divertimento con GIMP.

giovedì 8 aprile 2010

Utilizzare sudo per le operazioni di amministrazione

Molte distribuzioni user friendly, per abituare l'utente a non utilizzare l'account root, che comporta problemi di sicurezza e permetterebbe al neofita di creare grossi danni, si limitano alla creazione dell'utente "normale" e configurano sudo in maniera che questo possa eseguire tutte le operazioni di amministrazione. In molti casi non è neanche possibile utilizzare il comando "su -" per acquisire i permessi di root perchè l'account amministrativo non ha una password impostata, o comunque non la si conosce (può essere anche impostata ad un valore non riproducibile ad un logon), o magari è in lock.
L'eliminazione di questa possibilità aiuta anche a difendersi da possibili attacchi di tipo brute force costringendo l'attaccante a conoscere un account utente diverso da quello di root, oltre a dover indovinare la password, che sicuramente sarebbe presente ed in caso di esposizione del servizio ssh limita molto le possibilità di riuscire a penetrare il sistema (ssh, per fortuna, è quasi sempre configurato in modo da non permettere l'accesso ad utenti con password nulla od account in lock).
Nel caso il nostro sistema fosse configurato in maniera standard e volessimo invece riportarci nella condizione di utilizzare sudo per le operazioni di amministrazione, basta seguire le seguenti informazioni.
Attenzione, le operazioni che andremo ad eseguire comportano sostanziali modifiche delle credenziali e dei sistemi di autenticazione con la possibilità di perdita dell'accesso amministrativo al sistema; quindi dovete prestare un'elevata attenzione verificando di avere sempre la possibilità (o scappatoia) per eseguire operazioni amministrative. Inoltre, se ci sono dei software che vengono eseguiti con le credenziali di root, non so come possano comportarsi in assenza della password all'account amministrativo... io per adesso non ho mai incontrato problemi, ma sicuramente non ho provato tutte le casistiche, quindi prestate molta attenzione a tutto quello che fate.
I passi da fare per replicare la soluzione senza utente root saranno principalmente 2, da eseguire con una logica ben determinata per evitare di ritrovarci senza possibilità di eseguire comandi aministrativi (ed in caso di imprevisti o mal configurazione è ALTAMENTE probabile): configurazione di sudo per l'utente "abituale", con verifica del funzionamento, e rimozione della password dell'utente root.
Il comando sudo si basa sull'escalation dei privilegi, e quindi viene concessa la possibilità di eseguire comandi amministrativi, da parte degli utenti, in quanto i permessi vengono decisi in base a determinati filtri. Il file di configurazione è /etc/sudoers, ma non è possibile editarlo direttamente con vi, anche se è un file di testo, ma si deve utilizzare il comando visudo che autorizza l'apertura e le modifiche al file.
I parametri personalizzabili all'interno di questo file sono molti, dalla creazione di gruppi di comandi ammessi, all'autorizzazione dell'esecuzione di questi da parte di singoli utenti o di gruppi di utenti specifici, ma noi ci occuperemo solamente del caso più semplice... un singolo utente che deve eseguire i comandi amministrativi.
Sfogliando il file, molto spesso si può notare una riga del tipo "%sudo ALL=NOPASSWD: ALL"; questa opzione è molto allettante in quanto permetterebbe di rimuove la richiesta di digitazione della password dell'utente quando utilizza sudo (da molti ritenuta una scocciatura), ma comporta un grande problema di sicurezza in quanto chiunque si colleghi con quell'utente, o trovi una shell attiva, può eseguire comandi con privilegi amministrativi.
La configurazione che interessa nello specifico a noi è relativa all'autorizzazione dell'utente per l'esecuzione dei comandi amministrativi, inserendo la password del proprio account; osservando sempre all'interno del file possiamo notare una linea con "root ALL=(ALL) ALL", in pratica è quello che interessa a noi, ma dobbiamo farlo per un singolo utente, quindi la linea da aggiungere sarà "utente ALL=(ALL) ALL"... a questo punto il nostro "utente" potra eseguire operazioni amministrative digitando la sua password.
Dopo aver modificato la configurazione di sudo proviamo ad eseguire un comando che richieda privilegi amministrativi, ad esempio "cat /etc/sudoers"... dovremmo ricevere un "permission denied"; ora proviamo "sudo cat /etc/sudoers"... se tutto è stato configurato correttamente ci viene mostrato il contenuto del file ed a questo punto possiamo continuare.
Ora veniamo alla parte più semplice: la rimozione della password di root ed il lock dell'accout in modo che non sia possibile utilizzare la password per accedere come root; queste due operazioni sono ottenibili in maniera semplice ed immediata tramite i seguenti comandi:
  • passwd -d root;
  • passwd -l root;
Ora il vostro sistema è configurato per utilizzare solamente sudo ed avere un account di root senza password... buona sicurezza a tutti.

venerdì 26 febbraio 2010

VirtualBox su Debian

Benissimo, dopo aver trattato il repository Debian backports ed aver parlato dei sistemi di virtualizzazione siamo ora pronti a procedere all'installazione del software necessario per poter creare una virtual farm.
In base alle precedenti informazioni, utilizzeremo la distribuzione Debian, con repository backports, da cui andremo a prendere Virtual Box OSE (è la versione realmente libera di VirtualBox, senza supporto all'USB e senza la gestione nativa tramite il protocollo remote desktop, entrambe tecnologie con problemi di brevetti); questo perchè la versione più recente di VirtualBox nei repository stable è la 1.6.6, troppo vecchia in assoluto... sicuramente meglio optare per la 3.x disponibile nei backports.
Prima di tutto partiamo configurando i repository:
  • vi /etc/apt/sources.list
ed andiamo ad aggiungere le seguenti linee:
  • # Backported packages for Debian Lenny
  • deb http://www.backports.org/debian lenny-backports main
Siccome backports di default è disabilitato, ed inizialmente senza chiavi, dobbiamo specificare le chiavi da installare specificando il repository nel seguente modo:

  • aptitude update aptitude -t lenny-backports install debian-backports-keyring
A questo punto, se non utilizziamo il kernel presente in backports (cosa molto probabile se l'abbiamo configurato solamente per VirtualBox), dobbiamo scaricare i kernel header di quello attualmente in funzione al fine di poter compilare i moduli di VirtualBox... la procedura quindi è la seguente:
  • aptitude update
  • aptitude install linux-headers-$(uname -r)
A questo punto siamo pronti ad installare VirtualBox:
  • aptitude -t lenny-backports install virtualbox-ose
Al termine dell'installazione, DKMS si occuperà della creazione dei moduli per il sistema e questi verranno caricati automaticamente ad ogni avvio del sistema se non diversamente specificato in /etc/default/virtualbox-ose (LOAD_VBOXDRV_MODULE impostato a 0).
Ora non rimane che aggiungere gli utenti che devono poter gestire le macchine virtuali al gruppo vboxusers con il seguente comando:
  • adduser yourusername vboxusers
Attenzione: l'utente che crea una macchina virtuale ne salva le informazioni all'interno della sua home, quindi a meno di modifiche sostanziali di configurazione, una singola macchina non è gestibile da qualunque utente del gruppo vboxuser.
A questo punto il vostro VirtualBox è pronto e potete cominciare ad allestire la virtual farm.


Un ultimo punto riguarda un errore con cui mi sono ritrovato a confrontarmi... l'errore era relativo a "/dev/vboxdrv" ed ai permessi assegnati; questo file deve avere i permessi impostati nella seguente maniera (ls -l /dev/vboxdrv):

  • crw-rw---- 1 root root 10, 58 2009-06-22 16:33 /dev/vboxdrv
I permessi di questo file vengono impostati dal file /etc/udev/rules.d/z60_virtualbox-ose.rules, quindi la mask specificata all'interno di questo deve essere 660.
Per verificare se il problema è stato risolto si deve riavviare udev e rimuovere/ricaricare il driver nel seguente modo (operazioni da eseguire da root):
  • invoke-rc.d udev reload
  • modprobe -r vboxdrv
  • modprobe vboxdrv
Nel mio caso tutto era corretto, ma le cose continuavano a non funzionare... il motivo era legato ad un altro file, /etc/udev/rules.d/z60_virtualbox-ose-sources.rules, che definiva altri permessi e mi riscriveva quelli corretti; il problema si risolve modificando anche quel file o rimuovendolo dato che esegue operazioni doppie.

N.B.: per Debian è disponibile il pacchetto "ufficiale" di Sun, senza le limitazioni delle USB e del remote desktop... per chi lo desiderasse può modificare i propri repository includendo quello della Sun ed aggiungendo le seguenti linee in /etc/apt/sources.list:
  • # VirtualBox official repository
  • deb http://download.virtualbox.org/virtualbox/debian lenny non-free
Il procedimento che dovrebbe seguire penso sia molto simile a quello già illustrato per la versione OSE, ma non avendo provato non voglio scrivere informazioni non corrette.

Per oggi è tutto, buon divertimento con le macchine virtuali che andrete a creare e nelle prossime puntate ce ne sarà una in cui tratterò l'avvio e la gestione delle macchine virtuali da linea di comando.
Ciao ed a presto.

sabato 13 febbraio 2010

La virtualizzazione dei sistemi

La nuova puntata del blog la dedichiamo alla virtualizzazione dei sistemi, ovvero l'installazione software di un PC emulato all'interno di uno reale... i motivi per ottenere funzionalità di questo tipo sono svariate, ma le principali sono legate al testing dei sistemi operativi, al test del software od alla voglia di avere sempre con sè il proprio sistema operativo configurato in maniera personalizzata.
Per poter ottenere una configurazione di questo tipo, vi sono diverse possibilità, ma siccome la portabilità delle macchine virtuali la ritengo una cosa essenziale e molto comoda (potremo gestirne l'esecuzione indistintamente su piattaforme Windows e Linux), la disponibilità del codice sorgente e la gratuitità di utilizzo fanno il resto, i software da prendere in esame e di larga diffusione sono solamente due:
  • VMWare server
  • VirtualBox
VMWare server è stato il primo software di virtualizzazione di largo utilizzo, attualmente la versione disponibile è la 2 ed è probabilmente la più adatta in un ambiente server vero e proprio, cioè quando la macchina fisica deve rimanere costantemente accesa e deve eseguire in maniera automatica varie macchine virtuali; non lo consiglio in un ambiente PC per utilizzo desktop in quanto l'installazione è molto pesante (più di 500MB di download) e l'accessso è solamente garantito a livello di browser web o delle funzioni fornite dal sistema operativo virtuale una volta avviato.
VirtualBox è il prodotto di virtualizzazione offerto da Sun, che attualmente è stata acquistata da Oracle; ultimo arrivato sul mercato e già largamente diffuso ed offre ottime funzionalità per una complessità del software relativamente modesta. L'aspetto "server" non è così sviluppato, infatti l'avvio delle macchine virtuali, fino alla versione attuale (3.1.x), non è automatico all'avvio della macchina fisica, ma richiede l'intervento manuale di un operatore o delle modifiche manuali al software.
Per adesso è tutto... verrà trattata tra breve l'installazione di VirtualBox su di un server Debian... alla prossima.

mercoledì 10 febbraio 2010

Repository Debian: backports

Come tutti ormai dovreste sapere, le distribuzioni linux si basano sui pacchetti software che contengono i vari applicativi; questi pacchetti vengono organizzati e resi disponibili attraverso repository.
Se mi avete seguito fin dall'inizio, la vostra distribuzione è configurata per utilizzare i pacchetti scaricati dai repository chiamati stable (lenny al momento attuale) o testing (squeeze).
Uno dei difetti per chi ha bisogno di utilizzare software recente su di una distribuzione stable è che spesso questo non è disponibile od è disponibile in versioni obsolete (e quindi considerate sicure e per ambienti di produzione in quanto testate a lungo ed approfonditamente).
Per ovviare a questo problema ed usare software più recente qualcuno potrebbe pensare che basta utilizzare il repository testing che contiene versioni di software più aggiornate, ma a questo punto nascono i problemi delle dipendenze dei pacchetti... provare dei pacchetti della versione testing richiede che anche i pacchetti da cui dipendono siano di tipo testing e questo porterebbe ad un aggiornamento dell'intero sistema, ma questa è una soluzione che pochi sono disposti ad accettare in un ambiente di produzione.
Quindi, per adesso, non c'è la soluzione utilizzando i repository ufficiali, ed a questo scopo è nato un repository apposta, che si chiama backports (http://www.backports.org); questo archivio è nato dall'esigenza di poter utilizzare del software abbastanza aggiornato utilizzando grazie al fatto che è stato compilato su macchine di tipo stable e quindi le dipendenze sono relative a pacchetti riservati ad un ambiente di produzione... ora passiamo alla parte pratica di configurazione.
Andiamo ad aggiungere ai nostri soliti repository quello nuovo, aggiungiamo la chiave GPG ed aggiorniamo la lista dei pacchetti software disponibili:
  • echo "deb http://www.backports.org/debian lenny-backports main contrib non-free" > /etc/apt/sources.list
  • wget -O - http://backports.org/debian/archive.key | apt-key add -
  • apt-get update
A questo punto i pacchetti del repository sono stati indicizzati nel database locale e quindi quando eseguiremo ricerche o comandi di installazione potremo utilizzare anche questi; siccome di default il repository è disattivato di default, dobbiamo specificarne l'utilizzo dalla linea di comando per poterlo utilizzare e la sintasis del comando di installazione è la seguente:
  • apt-get -t lenny-backports install “package”
  • aptitude -t lenny-backports install “package”
Se volessimo utilizzare sempre i pacchetti di backports e quindi abilitarlo di default (attenzione che tutto verrebbe aggiornato rispetto ad una versione stable dato che il software è più recente), possiamo andare a modificare il file /etc/apt/preferences in maniera che siano presenti le seguenti linee:
  • Package: *
  • Pin: release a=lenny-backports
  • Pin-Priority: 200
Direi che per oggi è tutto... buon divertimento con il software aggiornato.

mercoledì 27 gennaio 2010

Creare file utilizzando solo copia/incolla con la bash

Benissimo, siamo ad una nuova puntata dopo molti giorni di assenza; questo articolo è solamente per richiamare alcune funzionalità della bash che la rendono molto comoda per la creazione di file o script utilizzando il semplice copia/incolla; di questa funzionalità ne ho già fatto uso in altri miei articoli, ma non era mai stata spiegata ed ora è giunto il momento.
Ora passiamo alla parte pratica, se avete letto i miei precedenti articoli avrete notato che in alcuni casi utilizzo una sintassi del tipo:
cat > file.out <<> file.out <<> file.out << 'EOF' Adesso la variabile $PWD non viene interpretata EOF A questo punto abbiamo trovato la strada per creare degli script con inclusi i nomi di variabile senza doverli escapare singolarmente in maniera molto semplice e veloce, ma ci manca ancora un'ultima considerazione... se stiamo creando uno script abbiamo bisogno anche di poter indentare il codice, ovvero poter aggiungere dei tab (non sto parlando di caratteri di spazio) ad inizio linea per migliorarne la comprensione, ma utilizziando la precedente sintassi possiamo accorgerci velocemente che le cose vanno diversamente da come sperato. Volendo inserire i tab all'inizio di ogni linea possiamo osservare che questi non vengono riprodotti durante la fase di output, e questo costituisce un grosso problema per la leggibilità del codice che stiamo creando... ma anche a questo c'è rimedio per fortuna, e quindi per poter produrre un output pari all'input dobbiamo far seguire i simboli di redirezione << dal carattere '-', quindi la nuova sintassi, per un testo indentato, sarà la seguente: cat > file.out <<- 'EOF'
Adesso la
variabile $PWD
non viene
interpretata
EOF
Con questo direi che per oggi è tutto; ora siete in grado di creare automaticamente dei file senza bisogno di utilizzare nessun editor di testo, ma semplicemente facendo dei semplici copia/incolla del testo all'interno di una shell.

lunedì 28 dicembre 2009

Frame buffer con Grub e Grub 2

Oggi trattiamo un aspetto puramente estetico, ovvero la risoluzione della console all'avvio della macchina.
Normalmente un sistema Debian, di default, viene installato e configurato per essere il più possibile compatibile con tutto l'hardware presente sul mercato, quindi la risoluzione della console viene impostata a valori molto bassi (640x480) per poter funzionare su qualunque monitor, ma questo fa sì che anche l'interfaccia testuale abbia un numero limitato di righe e colonne (80x24 se ricordo giusto).
A me questa risoluzione risulta troppo scarsa per poter lavorare adeguatamente, quindi voglio sempre aumentare la risoluzione aumentando di conseguenza il numero di righe e colonne di testo visualizzabili. Per far questo si deve modificare il file di configurazione di grub; questo file è diverso a seconda della versione di grub:
  • /boot/grub/menu.lst per grub 1 aggiungendo il parametro vga nelle opzioni di avvio del kernel (ricordatevi di modificare la linea corretta, ovvero non quella che riguarda il single-user mode);
  • /boot/grub/grub.cfg per grub 2 modificando il parametro gfxmode e gfxpayload.
In grub 1 le varie modalità video sono identificate da valori esadecimali (0x) in base alla propria scheda video; per conoscere le modalità disponibili ed i valori associati si utilizza il comando vbeprobe dalla modalità a linea di comando di grub (vi si entra premendo 'c' durante la visualizzazione del menù) e, una volta identificata la modalità desiderata, la si testa con vbetest. Se tutto viene visualizzato correttamente si può procedere con i calcoli necessari a ricavare il valore da associare al parametro vga.
Il valore da impostare al parametro vga da inserire come opzione alla stringa di avvio del kernel si ottiene partendo dal valore esadecimale di proprio interesse (ad esempio 0x144), a questo si aggiunge 0x200 (ottenendo 0x344, in decimale 836), il nuovo valore così ottenuto in genere è del tipo 0x3..; questo è il valore da assegnare al parametro vga specificandolo come vga=0x3.. oppure vga=8.. (valore decimale).
La nuova linea di avvio all'interno di grub sarà del tipo:
  • kernel /boot/vmlinuz-x.y.z root=/dev/hda1 ro quiet vga=0x344
Fate attenzione a modificare la linea corretta, ovvero non quella di failsafe o single user mode.
In grub 2 le impostazioni sono molto più semplici ed
i parametri sono in formato "uman readable", ovvero la stringa del valore e del tipo RisoluzioneOrizzontalexRisoluzioneVerticalexBitDiColore; i parametri coinvolti in questo caso sono due: gfxmode, che stabilisce la risoluzione durante la visualizzazione del menù di avivo, e gfxpayload, che tsabilisce la risoluzione da visualizzare in modalità testuale. Ad esempio, per avere tutte le risoluzioni a 1024x768 con una profondità di colore a 32 bit si dovranno aggiungere le seguenti linee:
  • set gfxmode=1024x768x32
  • set gfxpayload=1024x768x32
Direi che per oggi è tutto, buon divertimento con le nuove risoluzioni.

giovedì 10 dicembre 2009

Collegarsi da fuori alla rete di casa? openVPN!

Ora che abbiamo parlato dei certificati possiamo cominciare ad utilizzarli; probabilmente questo utilizzo non è quello più semplice che una persona possa immaginare, ma sicuramente è uno di quelli che permette di capire le potenzialità offerte dalla struttura di certificati di tipo X.509.
Tralasciando la parte relativa alla creazione dei certificati che ormai è stata ampiamente trattata, vi annuncio solamente che l'autenticazione avviene attraverso i certificati X.509, quindi per il server e per ogni client sarà necessario avere a disposizione un certificato, garantito dalla propria CA, con la relativa chiave privata. Due comandi che potrebbero farvi comodo per abbreviare i processi di creazione dei certificati, in caso di creazioni massive, sono i seguenti (dovete posizionarvi all'interno della directory della CA):
  • openssl req -new -keyout private/host-utente.unsec.key -out newcerts/host-utente.pem.csr -nodes -text -config ../openssl.conf -subj /"C=IT"/"ST=Provincia"/"L=Città"/"O=Organizzazione"/"OU=openVPN organizzazione"/"CN=utente"/"emailAddress=indirizzo di posta"/
  • openssl ca -policy policy_anything -in newcerts/host-utente.pem.csr -out certs/host-utente.pem.crt -config ../openssl.conf -batch -days 1465
Ora veniamo alla parte più complessa, le configurazioni del server e dei client, ma prima di procedere vi devo descrivere la struttura di funzionamento su cui si basa openVPN (considerate che alcune assunzioni sono relative solamente alla mia metodologia di configurazione e vi sono altre possibilità):
  • l'autenticazione avviene SOLAMENTE attraverso i certificati firmati dalla stessa CA;
  • l'assegnazione degli indirizzi viene fatta in base al certificato presentato dal client, quindi se il file di configurazione per il client non è stato creato non è possibile collegarsi alla VPN perchè non viene assegnato l'indirizzo;
  • la default route rimane quella presente anche prima dell'attivazione della VPN;
  • solamente le macchine per cui viene specificato il routing sono raggiungibili (questo per limitare le possibilità di conflitto degli indirizzi).
A questo punto creiamo il file di configurazione del server che sarà /etc/openvpn/host-server.conf:
daemon
mode server
tls-server
dev-node /dev/net/tun
dev tun1194
proto udp
port 1194
tun-mtu 1250
ifconfig 10.0.0.1 10.0.0.2
client-config-dir /etc/openvpn/CN2ip
route 10.0.0.0 255.255.255.0
push "route 10.0.0.1 255.255.255.255"
client-to-client
dh /etc/openvpn/certs/dh1024.pem
ca /etc/ssl/YOUR_CA/CA.pem
cert certs/host-server.pem.crt
key certs/host-server.unsec.key
user nobody
group nogroup
persist-key
persist-tun
comp-lzo
keepalive 20 90
verb 1
log-append /var/log/openvpn/server.log
mssfix
Ora spiego i paratetri principali... il parametro daemon, mode server, tls-server e quelli realtivi al tun significano di eseguire openVPN come servizio, di abilitare le modalità server, di creare ed utilizzare utilizzare l'interfaccia tun1194 ed associargli l'mtu dichiarato.
I parametri proto, port, persist-key, persist-tun, comp-lzo e keepalive specificano il protocollo, la porta di servizio, la persistenza della chiave privata e dell'interfaccia tunnel (in caso di restart non vengono reiniziallate), la compressione ed il keepalive, ovvero ogni quanti secondi, dopo che non vi è traffico, inviare dei dati e quanto aspettare prima di riavviare il tunnel se non vi è risposta... parlando di standard imposti dallo IANA, openVPN è stato attestato sulla porta 1194 e con protocolli TCP/UDP. La scelta del protocollo può essere influenzata principalemente da due fattori, la facilità di attraversamento dei firewall per il protocollo UDP o la possibilità di utilizzare il protocollo TCP (modalità tcp-server/tcp-client) per tunnellizzare le connessioni (ad esempio tramite ssh).
I parametri ifconfig e route assegnano l'indirizzo ip e le informazioni di routing all'interfaccia rete creata, mentre client-to-client permette a client di vedersi a vicenda.
Le impostazioni scritte in formato push sono invece relative ai comandi da inviare indistintamente ad ogni client che si collega; siccome può capitare, e nel caso di indirizzo ip statico capita sicuramente, di dover inviare informazioni specifiche a client identificati, l'opzione che ci fa comodo è client-config-dir, e rappresenta il percorso in cui devono essere presenti i file con le configurazioni personalizzate. All'interno di questa directory, i file vengono collegati al loro destinatario attraverso il nome, questo deve essere lo stesso presente all'interno del CN ed in caso di spazi il carattere viene sostituito con l'underscore (_).
Ad esempio, se noi vogliamo che chi si presenta con un certificato valido con CN "Mario Bianchi" abbia un determinato indirizzo IP assegnato, dovremo creare il file /etc/openvpn/CN2ip/Mario_Bianchi con al suo interno i seguenti comandi:
ifconfig-push 10.0.0.14 10.0.0.13
# push "route 192.168.0.127 255.255.255.255" # Indirizzo da raggiungere attraverso la VPN
Ricordate che ogni client in connessione occupa una classe di tipo /30, ovvero ip di network, ip del client, ip del peer, ip di broadcast, quindi equivale dire 4 indirizzi ip... affinchè non vi siano errori di rete dovuti a sovrapposizioni, i client potranno solamente avere indirizzi ip 10.0.0.6, 10.0.0.10, 10.0.0.14...
Le opzioni ca, cert e key non dovrebbero aver bisogno di spiegazioni, sono i parametri relativi alla CA ed al certificato presentato dal server; l'unico parametro non noto e relativo alla crittografia è dh, che deve essere un file di tipo Diffie Hellman; per generarlo potete utilizzare il seguente comando:
  • openssl dhparam 1024 > /etc/openvpn/certs/dh1024.pem
I parametri user, group, verb e log-append specificano le modalità con cui il tunnel deve funzionare, ovvero i permessi con cui girare e quante informazioni di debug devono essere presenti all'interno del file di log.
Ora, se avete terminato la configurazione e l'avete terminata in maniera corretta potete provare a vedere cosa succede avviando la openVPN con:
  • /etc/init.d/openvpn restart
Se tutto ha funzionato ora avete un processo openVPN che è in esecuzione... adesso non rimane che configurare i client.
Il file di configurazione di un client è molto simile a quello per il server, ma mancano le informazioni per l'assegnazione dei parametri di rete che devono essere prelevate dal server, inoltre in genere la maggior parte dei client normalmente sono machcine windows, quindi file di configurazione con estensione ovpn, certificato e chiave saranno in un'unica cartella; un file di esempio è il seguente:
pull
tls-client
dev tun
proto udp
remote server-host port
remote server-ip port
tun-mtu 1250
resolv-retry infinite
nobind
ca ./hostCA.crt
cert ./host-nome.pem.crt
key ./host-nome.unsec.key
persist-key
persist-tun
ping 30
ping-restart 90
comp-lzo
mssfix
verb 1
Adesso vi spiego i nuovi parametri apparsi... pull e tls-client significano di richiedere le informazioni di configurazione al server ed il tipo di autenticazione utilizzata, remote è una lista di host/ip seguiti dalla porta che dovrebbe essere in ascolto a cui il client continuerà a provare a collegarsi all'infinito.
Siccome la maggior parte dei client saranno macchine windows (od almeno questa è la mia esperienza), affinchè il file di configuraizone venga riconosciuto come tale, deve avere estensione ovpn; inoltre, sotto windows, è molto più semplice mettere tutti i file relativi ad una VPN in una singola cartella (file.ovpn, file.unsec.key, file.crt e fileCA.crt) per non dover specificare percorsi assoluti che potrebbero cambiare con lo spostamento della directory.
Il parametro nobind impedisce ad openVPN di posizionarsi in ascolto, ma fa sì che la connessione alla VPN venga solamente tentata e non attesa, mentre ping e ping-restart fanno sì che avvenga un ping ogni tot secondi e se non si riceve risposta il tunnel viene reinizializzato.
Ultima cosa da notare... non c'è l'informazione relativa al file di log, sappiate che se abilitate il log su file non sarete più in grado di vederlo a video se siete su di una macchina windows.
Direi che a questo punto potete provare la connessione da un client, ricordatevi che il certificato della CA deve essere presente assieme ai file relativi al client, questo perchè openVPN controlla che il server sia effettivamente colui che ci si aspetta e quindi il suo certificato deve essere firmato dalla stessa CA.
Con questo penso di aver trattato tutto il minimo necessario per fare una VPN con determinate caratteristiche; la configurazione di esempio che ho utilizzato è quella che utilizzo più spesso dato che consente di vincolare univocamente un indirizzo IP ad un determinato certificato, sappiate che comunque è possibile creare una VPN in maniera che chiunque si presenta con un certificato valido riceva un indirizzo come se fosse presente un DHCP. Di sicuro cercando su internet troverete molte informazioni più dettagliate ed altre modalità di funzionamento, ma il mio voleva essere solamente un vademecum di come mettere su una VPN, in maniera veloce ed indolore, con autenticazione tramite certificati ed indirizzi ip statici.

venerdì 4 dicembre 2009

Creare i certificati X.509

Bene, ora è giunto il momento di creare la nostra gerarchia di certificati, ma prima di fare questo guardiamoci un attimo attorno per capire come funzionano le cose fatte dai grandi gestori... se prendessimo come esempio le CA riconosciute ufficialmente, osserveremmo che loro richiedono solamente la richiesta di certificato, a cui applicano la firma, per poter poi restituire il certificato; questo viene fatto ai fini di sicurezza dato che voi, i proprietari della chiave privata, volete che NESSUNO sia in grado di venire a conoscenza dei dati che transitano; logicamente se generassero loro la vostra richiesta di certificato, avrebbero generato anche la chiave privata, e quindi la conoscerebbero; inoltre ve la dovrebbero trasmettere, esponendo la chiave privata a possibili sguardi inopportuni e riducendo largamente la sicurezza del sistema creato.
Nel nostro caso le cose si semplificano di molto dato che do per assunto una situazione prestabilita (che riduce altamente la sicurezza in caso di compromissione del server, ma non facendo transazioni bancarie lo ritengo un rischio accettabile): la chiave privata verrà utilizzata da servizi presenti sulla stessa macchina che gestisce la CA, quindi entrambe le chiavi possono risiedere a bordo di questa e gli unici occhi che le possono leggere sono i nostri (sempre che abbiate protetto bene il server).
Per generare la coppia di chiavi, ovvero la chiave privata e la richiesta di certificato (che contiene quella pubblica), eseguire la firma con la CA ed ottenere quindi il certificato, si può utilizzare il seguente script in /etc/*/makeCert.sh:

#!/bin/bash

# Script per la creazione della coppia chiavi pubblica/privata, per la generazione della richiesta di certificato, per la firma della richista trmaite la CA e per la generazione del certificato.
function newCert {
echo -n "Vuoi generare una chiave privata senza password? (s/N) ";
read ANS;
case ${ANS} in
"S"|"s"|"Y"|"y") echo "Attenzione, la chiave privata sara' leggibile da chiunque!";
openssl req -config ${opensslConf} -new -text -nodes -keyout ${CApath}/private/${NOME}.key -out ${CApath}/certs/${NOME}.pem.req;
;;
"N"|"n"|"") echo "Attenzione, ad ogni accesso alla chiave privata si dovra' fornire la password!";
openssl req -config ${opensslConf} -new -text -keyout ${CApath}/private/${NOME}.key -out ${CApath}/certs/${NOME}.pem.req;
echo "Per la rimozione della password usare il seguente comando: openssl rsa -in ${CApath}/private/${NOME}.key -out ${CApath}/private/${NOME}.unsecure.key";
;;
esac;
}
opensslConf=$(find /etc -iname openssl.cnf|sort|head -1);
CApath=$(grep "^[[:space:]]*dir[[:space:]]*=" ${opensslConf} | sed "s/.*=\s\+//" | awk '{print $1}');
if [ "$1" == "" ]; then
echo "La sintassi del comando e' $0 <nome_cert>";
exit -1;
fi;
NOME=$1;
if [ -s "${CApath}/newcerts/${NOME}.pem.crt" ]; then
echo "E' gia' presente il certificato ${CApath}/certs/${NOME}.pem.crt, vuoi rinnovarlo revocandolo ed emettendone uno nuovo [s/N]? ";
read ANS;
case ${ANS} in
"S"|"s"|"Y"|"y") echo "Verra' ora revocato il certificato";
openssl ca -config ${opensslConf} -revoke ${CApath}/newcerts/${NOME}.pem.crt
;;
"N"|"n"|"") echo "Si e' deciso di non revocare il certificato precedente, si potra' proseguire solamente sovrascrivendo i vecchi dati, ricordati che non puoi avere certificati con CN uguali.";
;;
esac;
unset ANS;
fi;
if [ -s "${CApath}/certs/${NOME}.pem.req" -o -s "${CApath}/private/${NOME}.key" ]; then
echo "E' gia' presente la richiesta di certificato ${CApath}/certs/${NOME}.pem.crt, vuoi sovrascriverla [s/N]? ";
read ANS;
case ${ANS} in
"S"|"s"|"Y"|"y") echo "La richiesta di certificato e le relative chiavi verranno sovrascritte.";
newCert;
;;
"N"|"n"|"") echo "Si e' deciso di non sovrascrivere la vecchia richiesta, impossibile proseguire.";
exit -1;
;;
esac;
unset ANS;
else
newCert;
fi;
OLD_UMASK=`umask`;
umask 77;
openssl ca -config ${opensslConf} -policy policy_anything -days 730 -out ${CApath}/newcerts/${NOME}.pem.crt -infiles ${CApath}/certs/${NOME}.pem.req;
chmod a+r ${CApath}/newcerts/*;
umask ${OLD_UMASK};

Dopo tutta questa sbrodolata di codice io sono esaurito, anche perchè lo scrivevo assieme al post e mentre facevo le prove; inoltre penso che se è la prima volta che vi avvicinate ad openssl abbiate le idee molto confuse... tranquilli, è normale. Negli script riportati in precedenza ci sono molti concetti sul funzionamento di openssl, su di alcuni schemi condizionali e sulle nomenclature (scelte da me con una certa logica); uno dei concetti più importanti che ci sono, riguarda il campo CN (Common Name) di un certificato: questo deve essere univoco all'interno di una CA, quindi se avete già emesso un certificato con quel CN è obbligatorio lo revochiate per poterne emettere un altro, anche se questo è già scaduto.
Con questo direi che la trattazione sembra abbastanza esaustiva o comunque sufficiente per rendervi operativi... ricordate che il CN è il campo fondamentale del vostro certificato, e deve contenere l'host, l'ip o l'indirizzo email, relativi al tipo di dati che si vuole proteggere.

giovedì 3 dicembre 2009

Certification authority? Certo, sulla Linux Box

Benissimo, se siete qui a leggere vuole dire che vi servivano informazioni su questo argomento, oppure vi sono piaciuti i post precedenti... io spero la seconda, logicamente per soddisfare un po' il mio ego.
Ora veniamo a noi ed alla breve spiegazione teorica... quando si parla di garantire trasmissioni sicure, si vuole ottenere un sistema che sia in grado di realizzare uno o più dei seguenti requisiti:
  • riservatezza/confidenzialità;
  • integrità;
  • autenticità;
  • non ripudio.
Lo scopo viene ottenuto grazie all'utilizzo della crittografia con il sistema delle chiavi pubblica/privata. Questo sistema viene realizzato attraverso i certificati X.509, che realizzano una struttura gerarchica, con sviluppo ad albero, i cui elementi sono legati tramite un rapporto di fiducia, ovvero il "padre" garantisce che i suoi "figli" sono coloro che dicono di essere (autenticità), mentre le parti di integrità, riservatezza e non ripudio sono garantite dalla crittografia legata all'utilizzo delle due chiavi. Logicamente, come dicono i nomi, la chiave pubblica può e deve essere distribuita per poter stabilire se un determinato messaggio è firmato dalla relativa chiave privata o, nel caso di utilizzo della crittografia, per poter crittografare il messaggio che verrà poi decifrato attraverso l'uso della chiave privata. Dietro a tutto questo ci sono molti concetti matematici, che se volete potete cercare e studiare, ma questo esula sicuramente da quello che voglio dirvi.
La parte pratica viene gestita nella seguente maniera:
  1. Il figlio genera la richiesta di certificato.
  2. Il padre firma la richiesta di certificato del figlio, tramite un certificato valido.
  3. La richiesta di certificato firmata diventa certificato e viene assegnato al figlio.
  4. Chiunque riconosce l'autorità del padre, automaticamente riconosce anche quella del figlio.
Chi ha spirito pratico, in tutto questo si sarà accorto di una cosa, e si chiederà: "e chi ha firmato il certificato del padre? il nonno? e chi quello del nonno?" e così via. Logicamente qui ci troviamo al discorso del "è nato prima l'uovo o la gallina?", ma la risposta è molto più semplice: il primo certificato si chiama self-signed, ovvero è un certificato autofirmato in cui il firmatario garantisce di essere chi dice di essere. Da un certificato di questo tipo possiamo far nascere la nostra CA, ovvero una certification authority, i cui "figli" saranno riconosciuti da chi ha considerato autorevole il certificato del padre, ovvero quello originario della nostra CA.
La gestione dei certificati all'interno di una linux box ricopre una parte vastissima perchè riguarda tutte le comunicazioni che si vogliono rendere sicure, e pensando alla sicurezza, sono aspetti imprescindibili e molto profondi, quindi conviene impararla velocemente, mettendo i puntini sulle "i" fin dall'inizio ed apprendendo tutto quello che serve. Il mio scopo è darvi delle brevi e semplici informazioni e molti dei comandi utili sotto forma di script, questo al fine di aiutarvi ad addentrarvi in openssl da subito... logicamente, come il solito, dove non arrivano le mie spiegazioni ci arriveranno quelle di qualcun altro che ha scritto un help, un howto o della documentazione varia resa disponibile attraverso internet.
Passando alla configurazione pratica, prima di tutto ci serve installare l'ambiente ed i comandi che ci serviranno per la nostra CA, quindi:
  • aptitude install openssl;
A questo punto a livello di comandi e configurazione avremo tutto quello che ci serve, ora dobbiamo solamente personalizzarlo modificando il file openssl.cnf (normalmente in /etc/ssl o /etc/pki/tls per le distribuzioni basate su RedHat) affinchè rispecchi i propri bisogni... io utilizzo i seguenti parametri (in Debian):
  • dir = /etc/ssl/YOUR_CA
  • private_key = $dir/private/cakey.unsec.pem # se la chiave non ha password
  • private_key = $dir/private/cakey.pem # se la chiave ha password
  • countryName_default = IT
  • stateOrProvinceName_default = Turin
  • localityName_default = Turin
  • 0.organizationName_default = YOUR organization
  • organizationalUnitName_default = host.domain from YOUR_CA
  • commonName = Common Name (eg, YOUR name as host or IP)
  • emailAddress_default = YOUR email address
  • challengePassword_default = longpasswordyouwant
Questi parametri presuppongono alcune strutture che io do per scontate nelle mie configurazioni e sono:
  • i percorsi a cui si fa riferimento in /etc/*/openssl.cnf sono di tipo assoluto;
  • la struttura della CA è locata all'interno di una directory del tipo /etc/*/CA;
  • il file openssl.cnf è nella stessa directory in cui vi è la CA;
  • il nome della CA viene utilizzato anche per il nome del certificato;
  • gli hash del certificato della CA vengono messi in /etc/*/certs.
A questo punto dobbiamo creare una struttura che ci permetta di svolgere i ruoli di una CA, ovvero coppia di chiavi pubblica/privata, un percorso in cui andare a salvare le richieste di certificato per elaborarle e trasformarle in certificato ed alcuni file necessari per la gestione "logica" della CA, compresa la CRL (Certificate Revocation List).
Il seguente script, da mettere in /etc/*/makeCA.sh, attingendo dai parametri immessi in openssl.cnf, prepara la struttura necessaria ad ospitare la CA.

#!/bin/bash

# Script per creazione della CA
opensslConf=$(find /etc -iname openssl.cnf|sort|head -1);
dir=$(grep "^[[:space:]]*dir[[:space:]]*=" ${opensslConf} | sed "s/[[:space:]]*dir[[:space:]]*=[[:space:]]*\([^[:space:]]*\)[[:space:]]*.*/\1/");
certificate=$(grep "^[[:space:]]*certificate[[:space:]]*=" ${opensslConf} | sed -e "s/[[:space:]]*certificate[[:space:]]*=[[:space:]]*\([^[:space:]]*\)[[:space:]]*.*/\1/" -e "s|\$dir|$dir|");
private_key=$(grep "^[[:space:]]*private_key[[:space:]]*=" ${opensslConf} | sed -e "s/[[:space:]]*private_key[[:space:]]*=[[:space:]]*\([^[:space:]]*\)[[:space:]]*.*/\1/" -e "s|\$dir|$dir|");
mkdir -pm 755 ${dir};
mkdir -pm 755 ${dir}/{certs,crl,newcerts};
mkdir -pm 700 ${dir}/private;
touch ${dir}/index.txt;
touch ${dir}/private/.rand;
echo 01 > ${dir}/serial;
echo -n "Vuoi generare una chiave privata senza password? (s/N) ";
read ANS;
case ${ANS} in
"S"|"s"|"Y"|"y") echo "Attenzione, la chiave privata sara' leggibile da chiunque!";
openssl genrsa -out ${private_key} 2048;
;;
"N"|"n"|"") echo "Attenzione, ad ogni accesso alla chiave privata si dovra' fornire la password!";
openssl genrsa -des3 -out ${private_key} 2048;
echo "Per la rimozione della password usare il seguente comando: openssl rsa -in ${private_key} -out ${private_key}.unsec";
;;
esac
openssl req -config ${opensslConf} -new -x509 -key ${private_key} -out ${certificate} -text -days 2922;
hash=$(openssl x509 -noout -in ${certificate} -hash);
ln -sf ${certificate} $(dirname ${dir})/$(basename ${dir}).crt;
ln -sf ${certificate} $(dirname ${dir})/certs/${hash}.0;

Ora la nostra CA è pronta a fare il suo dovere e mancano solamente più i certificati "figli".
Per scoprire come creare e gestire i certificati continuate a seguirmi, e vi fornirò le informazioni necessarie ad essere operativi... alla prossima!