Informatica per script kiddies 7 – Che succede quando andiamo su un sito

Eccoci di nuovo qui! Nell’episodio scorso abbiamo parlato di microcontrollori e piccoli pc, e da lì raggiungete i precedenti.

Oggi, invece, parliamo un po’ di come è fatto il web. Le cose possono ovviamente essere molto più semplici o molto più complesse di come le mostrerò qui, ma cercherò di dare un buon inizio per capire meglio come funzioni tutto l’accrocco, che non è sempre troppo chiaro.

Il web infatti nasce con un’idea molto semplice: dare a ogni risorsa un indirizzo composto dall’indirizzo del computer su cui risiede e dall’indirizzo della risorsa specifica. Digiti l’indirizzo in un browser (o clicchi su un link), e ottieni la risorsa. Le cose si sono però rapidamente fatte più complicate, principalmente perché i volumi di richieste sono diventati rapidamente molto grandi. Ma vediamo un po’ come funziona tutto.

Una premessa sugli indirizzi

Anche se è una cosa molto nota a molti, tocca prima di tutto fare un paio di premesse sulla struttura dell’indirizzamento delle risorse su web.

Una risorsa su Internet, e conseguentemente anche sul web, è identificata da uno URL, che è un particolare tipo di URI che mette come schema (la parte prima dei primi due punti nell’indirizzo) il protocollo di accesso alla risorsa (http, https, ftp…), seguito da un doppio slash e dal nome del server, a sua volta seguito dall’indirizzo della risorsa sul server.

Il “nome del server” può essere un indirizzo IP, o un vero e proprio nome, composto da stringhe separate da punti (come tldr.italyinformatica.org). Il nome si chiama “nome di dominio” (o nome DNS, che sta per domain name system), e ogni stringa a partire da destra è un livello. Quindi tldr.italyinformatica.org è un dominio di terzo livello, italyinformatica.org è di secondo e org è di primo.

La traduzione DNS

I nomi di dominio, purtroppo, sono una cosa pensata dalle persone ad uso delle persone: la rete, che utilizza solo indirizzi IP, se ne fa davvero poco. La prima cosa che succede quando digitiamo un dominio e premiamo invio, quindi, è quella che si chiama traduzione DNS, ovvero il cercare di capire a che indirizzo IP corrisponda il nome di dominio che abbiamo digitato.

Per prima cosa, il browser controlla se lo sa già. Il browser infatti conserva per un certo tempo le traduzioni in IP dei nomi richiesti piú recentemente, e nel caso usa la traduzione già nota.

Se non dovesse trovare nulla, il browser chiederà al sistema operativo, che a sua volta ha un archivio delle richieste recenti, fatte magari da altri software, e gli comunica l’indirizzo IP corretto.

Se nemmeno il sistema operativo ne sa nulla, il sistema stesso ha una lista di server esterni, i server DNS, a cui chiedere. A loro volta, questi server hanno una lista di cose che già sanno, oppure chiedono a ulteriori altri server, che a questo punto possono essere di due tipi:

  • Server autorevoli, ovvero server che sono riferimenti per una determinata “zona DNS”, ovvero solitamente per un dominio. Ci saranno i server autorevoli per il dominio di primo livello it, ad esempio. Se tali server sanno l’IP per il dominio di livello piú basso che gli viene chiesto lo restituiscono in risposta, altrimenti chiedono al server autorevole per la zona di rango inferiore, ad esempio quello autorevole per italyinformatica.org e via salendo di livello.
  • Server ricorsivi, ovvero server che rispondono con l’IP se lo hanno, oppure chiedono ai server che a loro volta hanno configurato come server che “ne sanno di più”.

Ognuno di questi due approcci ha svantaggi e vantaggi, ma non ne parlerò troppo qui (se qualcuno vuole scrivere un articolo sul DNS mi dica, è benvenutissimo in questa rubrica).

Insomma, la prima cosa che avviene quando premiamo invio non ha nulla a che fare con l’effettivo raggiungimento della risorsa: si chiede a qualcuno che indirizzo abbia davvero.

Raggiungere il server

A questo punto, conosciuto l’IP, il browser può effettivamente fare la richiesta per raggiungere il server dove si trova il sito. Tipicamente, l’IP che viene dato dal DNS non è davvero quello del server, ma è l’indirizzo di un sistema intermedio, che può essere di vario tipo ma è di solito un load balancer con eventuali funzioni di caching.

Il compito del load balancer è quello di non esporre direttamente un unico server, raggiunto da tutti, ma di distribuire il carico tra diverse macchine, con alcuni grandi vantaggi che vanno un po’ oltre il semplice alleggerire il carico sulle macchine. La presenza di un load balancer infatti evita che un malfunzionamento di un server ricada sul servizio (se “cade” un server, ci sono sempre gli altri), concetto che si chiama affidabilità, e permette di aggiungere senza altre modifiche infrastrutturali ulteriori server in caso di aumento del carico, concetto che si chiama scalabilità.

Se il load balancer ha funzionalità di caching (o, piú spesso, ha accesso a server di cache appositi), restituirà direttamente le risorse in cache senza disturbare uno dei server veri e propri.

A questo punto, la richiesta arriverà finalmente al server.

L’elaborazione

Se la richiesta arriva davvero fino al server senza essere sparata altrove dal load balancer, molto probabilmente è una richiesta che ha bisogno di essere elaborata. Il server, quindi, non ha al suo interno una risorsa da restituire, ma deve calcolarla appositamente per quella specifica richiesta.

Di solito, per farlo, necessita di leggere o scrivere dei dati, e farà quindi lui stesso richieste a una serie di server secondari. Di solito si tratta di server di storage (in sostanza server che permettono di leggere e scrivere file), database (server che permettono di leggere e scrivere dati strutturati) ed eventuali strutture complesse costruite per immagazzinare ed elaborare dati, le data warehouse. Inoltre, potrebbe effettuare richieste a normali sistemi terzi di vario genere, attraverso interfacce API, e richieste a suoi servizi interni che effettuano elaborazioni asincrone (tipicamente cose da mettere in coda, tipo “quando ti liberi fai questo e poi manda una notifica che hai finito, intanto io rispondo all’utente che stiamo lavorando per lui”).

Composta la risposta, la restituirà al browser che la ha richiesta. In genere la risposta contiene tutto il necessario a far sapere al browser cosa mostrare all’utente, senza però tutti i dati necessari. Cose come gli script, molti dei dati da fonti esterne (e non solo) e soprattutto le immagini non vengono incluse nella risposta.

Le richieste secondarie

Scaricata la risposta, quindi, il browser avrà poco più che tutto il necessario a scaricare i reali contenuti della pagina.

A questo punto, quindi, tutti i dati “a parte”, che chiamiamo un po’ impropriamente i media, verranno scaricati attraverso una serie di richieste idealmente simili a quella principale.

Tali richieste si dividono in richieste di contenuti statici (script, fogli di stile, media veri e propri) e richieste a contenuti dinamici (dati). Le seconde fanno un percorso sostanzialmente identico alla richiesta originale, attraverso un load balancer e verso un server. Le prime, invece, fanno una strada un po’ diversa.

Script, fogli di stile e media, e contenuti statici in generale, hanno infatti la caratteristica principale di essere, appunto, statici: tendono a non cambiare o a cambiare pochissimo nel tempo. Non c’è quindi bisogno alcuno di chiederli allo stesso server che fornisce contenuti elaborati.

In genere il loro URL non fa neanche riferimento al sistema dove risiede il “sito”, ma a un sistema a parte appositamente costruito, la CDN.

Le CDN sono delle grandi reti di server dislocati in giro per il mondo (e per i provider di connessione), e contenenti copie identiche (mirror) di una serie di contenuti statici, spesso comuni a moltissimi siti e sistemi diversi (uno script JavaScript potrebbe essere utilizzato da migliaia di diversi siti, e un logo da diverse decine). Quando una risorsa viene richiesta ad una CDN, meccanismi equiparabili – ma spesso non identici – a load balancer fanno sì che il contenuto venga servito dal server piú vicino (non geograficamente ma a livello di rete), in modo da ridurre al minimo sia il ritardo nel riceverlo sia il carico di rete “del mondo”. I media sono infatti spesso pesanti ed è meglio tengano occupato uno spezzone di rete piccolo. Se mi vedo un film su Netflix, insomma, è meglio che il film venga da un server nella stessa rete del mio provider di connessione che da un server negli Stati Uniti.

In tutto questo va tenuto conto che il browser ha sempre una sua cache interna, e se ha scaricato il logo o lo script tale venti minuti fa, non si sogna neanche di chiederlo alla CDN, lo serve e basta. Anche se lo ha scaricato per tutt’altro sito, ovviamente.

E non è finita

Una volta scaricata e rappresentata la pagina, oggigiorno, il browser non smette di lavorare: sia le interazioni dell’utente che il server continueranno probabilmente ad aggiungere contenuti che andranno comunicati al browser. Le cose derivanti dall’interazione dell’utente sono tipicamente altre micro-richieste che funzionano nella stessa maniera delle richieste precedenti, e finiscono su una CDN o a un server che le elabora. Esiste però un’eccezione: gli script presenti nella pagina possono richiedere la creazione di un canale di comunicazione a due vie con un server (tipicamente usato per inviare notifiche, ma non solo), attraverso il protocollo websockets. Su tale canale potranno continuare a transitare dati in entrambi i sensi, dal browser al server websockets e vice versa, aggiungendo così l’ultimo tipo di comunicazione che in genere avviene mentre visitiamo siti internet.

Spero così di aver chiarito un po’ sia cosa fa il nostro browser dopo che premiamo invio, sia soprattutto che architettura ci sia grossomodo dietro un sistema web di medie dimensioni, che chiarisce pure perché a volte le cose vadano storte in maniera “strana”, con siti parzialmente funzionanti. Per qualunque chiarimento, chiedete pure, che a questo giro abbiamo appena scalfito la superficie!

Informatica per script kiddies 6 – Arduino, Raspberry Pi e quelle cose

Eccoci di nuovo la nostra rubrica mensile preferita. Ci siamo spostati sul blog di ItalyInformatica, dove prossimamente metterò in copia gli altri articoli per avere tutto insieme. L’episodio precedente era sul contact tracing, e da lì raggiungete i precedenti.

Oggi parliamo di cose che molti percepiscono come “schede piccole con cui fare cose strane”, e nemmeno a torto, ma che vengono di solito chiamati col nome piú tecnico di “sistemi embeded”.

(altro…)

Informatica e COVID-19

Comprensibilmente, il tema di questi giorni su /r/ItalyInformatica è stato soprattutto il SARS-CoV-2, che sta costringendo tutti noi a casa. Fortunatamente, il virus non impatta direttamente sulle nostre professioni, che si possono spessissimo svolgere da casa senza troppo rischio di ammalarci di COVID, e quindi moltissimi di noi si sono dati da fare nel grande sforzo che si sta facendo per mitigare, e risolvere il prima possibile, questa crisi.

(altro…)

Libmodule: libreria C per creare progetti modulari

Ciao a tutti! Sono u/nierro. Forse vi ricorderete di quando vi raccontai di un mio progetto proprio qui: https://tldr.italyinformatica.org/2017/05/clight-demone-utente-per-linux/.

Bene, libmodule nasce come “spin-off” di quel progetto: il codice di clight è molto modulare, e ha al suo interno tutta una serie di accorgimenti per gestire questi “moduli”.

Circa un mesetto fa mi resi conto che da un lato per clight questa gestione dei moduli era over-engineered, e dall’altro mi tornava utile in tanti progetti, personali e lavorativi.

Decisi quindi di mettermi al lavoro per creare una libreria come si deve, con lo scopo ultimo che dovesse essere semplice ed elegante.

Nasce così libmodule.

Cos’è libmodule?

È una libreria C, che ad oggi supporta linux, osx e BSD (tornerò su questo punto più in là), per scrivere progetti modulari e standardizzati.

L’approccio è piuttosto simile all’OOP; in particolare mi sono fortemente ispirato ad akka (https://akka.io/) e più in generale all’Actor Model per l’API.

Cos’è un modulo?

Un modulo è, manco a dirlo, l’entità chiave di libmodule; ogni modulo espone determinate callback che verranno usate per gestire il suo ciclo di vita.

Un modulo può inoltre reagire agli eventi, mettendosi in ascolto su dei File Descriptor.

Libmodule offre poi un loop interno che automaticamente ascolta su tutti gli eventi di tutti i moduli chiamando le callback corrette per ciascuno.

Supporta il mio OS?

Libmodule usa, per il suo loop interno, una struttura a compile-time-plugins; dipendentemente dalla piattaforma su cui viene compilato, seleziona il plugin corretto per implementare l’interfaccia di poll.
Ad oggi supporta epoll() su linux, e kqueue() su osx e bsd.

Lo svantaggio è che questi “plugins” dovranno avere una interfaccia simile a epoll.

Questa è una scelta specifica: l’ovvia soluzione portabile sarebbe stata usare poll(); trovo però l’API di kqueue/epoll molto più elegante e flessibile.

Esiste della documentazione?
Ovviamente: una libreria è completamente inutile se non esiste della documentazione.

La si può trovare qui: http://libmodule.readthedocs.io/en/latest/?badge=latest.

Tutto bello..ora però tira fuori il codice!

Mi sembra corretto ricompensare quei pochi coraggiosi giunti fin qui mostrando loro un breve esempio.


#include <module/modules.h>
#include <module/module.h>
#include 

MODULE("Test");

static void module_pre_start(void) {

}

static void init(void) {
     m_add_fd(STDIN_FILENO);
}

static int check(void) {
     return 1;
}

static int evaluate(void) {
     return 1;
}

static void receive (const msg_t *msg; const void *userdata) {
     if (!msg->msg) {
          char c;
          read(msg->fd,&c,sizeof(char));
               if (c=='q'){
               modules_quit();
          }
     }
}

int main () {
     modules_loop();
     return 0;
}

Per compilare, è sufficiente linkare libmodule tramite il linker flag “-lmodule” o usando lo script pkg-config installato.

Questo semplice programma crea un modulo, che si chiamerà “Test”, che ascolta su stdin.

Alla pressione di ‘q’, il programma uscirà.

Ben più utile, al fine di capire come funziona la libreria, è l’output generato (libreria compilata in debug, che la rende verbosa):

./sample.out Libmodule: Initializing libmodule 1.0.0. Libmodule: Creating context ‘default’. Libmodule: Registering module ‘Test’. a b c q Libmodule: Deregistering module ‘Test’. Libmodule: Destroying context ‘default’. Libmodule: Destroying libmodule.

 

Da qui appare ben chiaro lo scopo della macro MODULE(): registra un modulo in libmodule automaticamente all’avvio del programma, proprio come un ctor.

Il modulo viene poi de-registrato automaticamente da un dtor implicito.

Non mi dilungo su cosa sia un context, nella documentazione è ben spiegato.

Dall’esempio si possono evincere le caratteristiche principali di libmodule:

* Modularità (ovviamente)

* Semplicità

* Compattezza

Idealmente, ogni modulo costituisce un sorgente separato annotato dalla macro MODULE (anche se questa regola può essere aggirata utilizzando la “complex API”, che poi non è altro che l’API usata internamente dalla macro); forzando di fatto una standardizzazione del proprio progetto.

Hai citato gli actor, non vedo nulla però…

I moduli possono anche dialogare tra loro con un sistema PubSub: possono quindi inviare un messaggio a un altro modulo, o pubblicarlo su un “topic” che verrà ricevuto da tutti i moduli sottoscritti al suddetto topic.

Last, but not least (aka “la roba pallosa”)

Al momento mi sto concentrando sulla scrittura di unit test prima di rilasciare la prima versione stabile. Si noti che i test sono eseguiti automaticamente tramite travis sia su linux che su osx; inoltre su linux sono anche testati per la ricerca di memleak con valgrind.

L’API è in freeze in attesa della release; non ho comunque in mente alcun api break nel breve periodo.

Qualora per sbaglio dovessi aver stimolato il vostro interesse o la vostra curiosità, vi invito a farvi un giro al repo github: https://github.com/FedeDP/libmodule 🙂

La Forza Kinectica

Il sensore Kinect è ben famoso nella community videoludica, infatti era principalmente indirizzato ai giocatori quando Microsoft lo ha creato. La prima versione del dispositivo era per la console Xbox 360 e col suo sensore 3D ha introdotto un nuovo modo di giocare, cioè usare l’intero corpo o almeno le braccia dell’utente. Può facilmente tracciare l’intero corpo umano e dare in output una collezione completa di informazioni sulle posizioni e sui movimenti di ogni articolazione. Nella figura seguente si può vedere a cosa mi riferisco con articolazione, sono i ”Joints” che formano lo ”Skeleton” di un utente.

(altro…)

Alla scoperta di D: un completo linguaggio di programmazione

Negli ultimi anni abbiamo assistito all’ascesa di un gran numero di linguaggi di programmazione, in particolare [Go](2009), [Rust](2010), [Kotlin] (2011), [Elixir](2011), [Crystal] (2014), [Pony](2014).
Questa esplosione di nuovi linguaggi è dovuta, fra le molte motivazioni, alla necessità di adottare paradigmi di programmazione non immediatamente recenti come cittadini di primo tipo.
(altro…)

Mantieni la tua rete sotto controllo con Nidan

Buongiorno a tutti, sono o-zone1978, un sistemista informatico che lavora nel CED di un Ente pubblico toscano. Sono quasi 20 anni che lavoro nel settore informatico ed ho iniziato a programmare in C a 14 anni su un Amiga 600. Mi sono poi indirizzato verso lo sviluppo di applicativi web, in PHP, ed ultimamente ho ripreso a sviluppare in Python per la sua ampia disponibiltià anche su sistemi embedded. Grazie alla disponibilità dei ragazzi di /r/ItalyInformatica, oggi vi presento Nidan, un progetto a cui sto lavorando attivamente ormai da qualche mese. Ma andiamo con ordine… (altro…)

I testi generati ovvero le catene di Markov

Per chi non mi conoscesse, sono /u/timendum , il creatore di /u/italy_SS , cioè il /r/SubredditSimulator per i contenuti in Italiano.

In questo articolo cercherò di spiegarvi il meccanismo dietro la generazione di testi casuali usati in questi due subreddit.

(altro…)

Crackare password? Facciamolo!

Questo articolo sarà un po’ diverso dagli altri: oltre a parlarvi dell’argomento (Crackare password n.d.r.), voglio proporvi una piccola sfida.

Sappiamo che le password devono essere lunghe, devono essere complesse e solo una di queste due proprietà non basta: avere la stessa password per ogni sito web, sappiamo, non è cosa giusta. Tutte queste accortezze per cosa? Per non farsi rubare le password ovviamente: ma se volessi provarci? Vi è mai capitato di crackare password?

(altro…)

Entrare nella community di Envato? Difficile ma si può!

Envato, con oltre 1 milione di utenti, è sicuramente uno dei più grandi market mondiali per quanto riguarda la vendita di contenuti multimediali quali temi per ogni cms, plugins, addons, audio, video, app totalmente modificabili dall’utente finale se acquistati. In envato troviamo themeforest, videohive, graphicriver, audiojungle, 3docean, photodune, codecanyon. Se vuoi guadagnare qualcosa dal tuo codice, Envato è quello che fa per te (o quasi). In questo articolo vorrei raccontare la mia breve esperienza su cosa e come ho fatto per farmi accettare un plugin WooCommerce in Envato.

(altro…)