Archivi categoria: Uncategorized

AWS EC2 Instance Recovery: how to deal with StatusCheckFailed_System and automate the creation of the alarm for your instances

If you are an experienced AWS User, you know, AWS sponsors the use of the EC2 instances as cattle, not pets ( https://devops.stackexchange.com/questions/653/what-is-the-definition-of-cattle-not-pets). Instances can spin up, live and terminate in a totally orchestrated way, and this is reality in the DevOps world 🙂

However, I’m sure that even the most “I-CODE-ALL-MY-INFRASTRUCTURE” person has some pet instance, somewhere 🙂

You should know that AWS doesn’t perform well with single EC2 instances (it’s not their goal), so the Service Level Agreement ( https://aws.amazon.com/it/compute/sla/ ) says that an instance is guaranteed to be up, running and available 90% of the time for every hour. Many of you, probably, never experienced that “10%” downtime…but since it’s agreed in the contract, what happens when you hit that kind of issue?

Well, EC2 instances runs on shared hardware, and hardware can break. When it breaks, the instance can be “retired” or “terminated”, and you have to do some manual work to put it up&running again. You have to start a new instance, to attach EBS volumes again, to attach Elastic IP…and you’ll lose all the metadata (tags, for example), Instance ID etc.

How to deal with this?

AWS says: create a StatusCheckFailed_System in CloudWatch and trigger a Recovery action (and you should, moreover, send an alert e-mail when it happens). Easy: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-recover.html

However, let’s say that you applied the previous guide to an instance, but now you have 40 or 400 other instances and you want to do this job for *all of them*…maybe automatically.

So this is what I did: at a first step, I created a CloudFormation template: https://gist.github.com/lombax85/565d4199317627aacb64eb140d597c3a

With this template, you can create a Cloudformation Stack, and simply inserting the EC2 ARN + the SNS Topic to Alert, it will create the alarm *automagically* 😄

But this still needs to be done for *each* of your instances. Unfortunately, CloudFormation doesn’t have the concept of “loops”, so you can’t say “for each instance, apply the alarm”. So I decided to switch to CDK https://aws.amazon.com/en/cdk/

CDK, explained in “simple words”, is an automation tool can be “programmed” in your favorite language (in my case I used TypeScript), and can “compile” a CloudFormation template. So you can, for example, create a TypeScript source code that loops through all your EC2 instances, and then apply the alarm on them (for example basing on a tag). I attach an example: https://gist.github.com/lombax85/d385da90fd6efe7f27d086fd39d043b6

With this, and a simple “cdk deploy” command, you can directly create a single CloudFormation Stack that adds all the needed status check.

Some warnings: CDK doesn’t provide a way to list all your instances, so I integrated the AWS SDK and used it to retrieve the instances via the describeInstances api call. This is not considered a best practice, since CDK rely on “Custom Resources” ( https://cdk-advanced.workshop.aws/sample/source-construct/custom-resource.html ) to do this kind of things (for example a Custom Resource can create a Lambda Function which is called onUpdate of the stack, and returns the list of your EC2 instances).

But…it works, and it was enough for me and for sharing here 😃 feel free to comment if you have any question. For the moment I can’t publish the complete project repository (there are some reserved information and it need some cleanup), so if some passage is not clear (for example when you need to inject the AWS SDK credentials) let me know. Bye!

Cpu throttling issues on MacBook Pro 16″ + external display

In this article, I’ll investigate on MacBook Pro 16” cpu throttling issues when using one or more external display.

Let’s start with the software and hardware specifications of this test:

Hardware:

  • MacBook Pro (16-inch, 2019)
    • 2,3 GHz Intel Core i9 8 core
    • 32 GB 2667 MHz DDR4
    • AMD Radeon Pro 5500M 4 GB
    • Intel UHD Graphics 630 1536 MB
  • Monitor Asus VP28U (3840 x 2160) plugged via Apple USBC to HDMI Connector model A2119
  • Monitor LEN L27q-10 (2560 x 1440) plugged via Apple USBC to HDMI Connector model A2119

Software:

  • macOS Catalina 10.15.6 (19G2021)
  • iStat Menus 6.40
  • Intel Power Gadget 3.7
  • “yes” for the stress test
  • htop to monitor cpu usage

Test environment:

For each test, I simply span 16 (8 cores + hyperthreading) “yes > /dev/null” in the terminal:

yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null & \
yes > /dev/null &


then wait about 1-2 minutes for the stats to “stabilyze”.

The temperature in the room is 27 C°

The setup is in this picture (I didn’t use the rightmost display in the tests) :

Test 1: notebook mode: no external display, lid open

Results:
3.2 GHZ
note that “radeon high side” is at 0 watt, since only the Intel gpu is used

Test 2:  1 * 4K external display + internal display (lid open)

Results:
2.6 GHZ
note that “radeon high side” is 20 watt, which is one of the highest value I saw during the test

Test 3:  1 * 4K external display, lid closed

Results:
2.9 GHZ
“radeon high side” is 10 watt

Test 4:  1 * QHD (2560 x 1440) external display, lid closed

Results:
2.5 GHZ
we see that the “radeon high side” is about 20 watt, so it’s normal that the performance are similar to Test 2 (a little bit worst, but may be related to the better thermal management with the lid open in the test 2?)

Test 5:  1 * QHD (2560 x 1440) external display *forced to 1080p resolution*, lid closed

Results:
2.8 GHZ
note that “radeon high side” is 10 watt, results similar to test 3

Conclusion:

in this test, you can see three different behaviors:

  • Behavior 1: Radeon GPU not used: best thermal management and less cpu throttling
  • Behavior 2: Radeon GPU “partially loaded” (10 watt): still decent thermal management , medium cpu throttling
  • Behavior 3: Radeon GPU “fully loaded” (20 watt): high cpu throttling

It seems that the Radeon GPU usage (and then, the heat and the throttling) is impacted by:

  • the usage of the internal display only (in this case, Radeon GPU is not used) causes Behavior 1, so best performances and less cpu throttling
  • the usage of *only one* display, with the lid closed, and a resolution of 4K or FullHD, causes Behavior 2 (medium throttling)
  • the usage of more than one display *or* a resolution different from 4K or FullHD (in my tests I used 2560 x 1440) causes Behavior 3, with the high cpu throttling

Other thoughts:

  • it seems that opening the lid can improve a little bit the thermal management only when more than one display is used. Opening it when only one display is used, adds a second display, the Radeon goes in “Behavior 3” and the overall situation get worst

So What?

For the best performance, use your MacBook Pro *without ANY External display, use the integrated display only*.

If you need an external display, the best trade-off is with:

  • only one external display
  • lid closed
  • resolution of 4K or 1080p

The worst performance are when:

  • you use more than one display (two external or one external + integrated)
  • you use a different resolution than 4K or 1080p (need to do more tests with different resolutions, I only tested 2560 x 1440 by now)

Let me know in the comment if you have any question or you have made similar tests with different results.

Bye

Fabio

Estrazione di chiavi AES da App Android

Nei giorni scorsi ho dovuto analizzare i sistemi di sicurezza implementati in un’App iOS/Android. 

L’App – di cui ho tolto i riferimenti per rispettare NDA – permette a utenti registrati di interagire tra loro inviandosi messaggi privati, file, videochiamate, e il mio scopo era capire il livello di sicurezza delle informazioni degli utenti:

  • Può un utente accedere alle informazioni (dati personali, contenuti, media) di altri?
  • È possibile leggere o eseguire dump dei dati presenti nel backend?
  • È possibile eseguire azioni per conto di altri utenti, scavalcando il sistema di permessi?

In questo articolo vi voglio raccontare della procedura utilizzata, che per forza di cose non sarà identica per tutte le App che analizzerete, ma può:

  • essere un punto di partenza per capire come muovervi 🙂
  • fare da vademecum sugli strumenti da utilizzare
  • darvi qualche “insight” su cosa cercare e dove

Tornando a noi, mi sono quindi focalizzato sull’analisi dei protocolli usati dall’app, e il primo step è stato quello di un Man In The Middle attack per sniffare il traffico tra app e backend.

Per fare questo, ho utilizzato:

  • Uno smartphone Android * (vedi note)
  • Il mio Mac, utilizzato in questo caso come router abilitando la Condivisione internet. La scheda wifi utilizzata come “Access Point” a cui collegare lo smartphone Android, e la rete cablata come WAN.
Condivisione Internet
Burp Suite Community Edition

Alcune note sugli strumenti scelti * : 

Sono principalmente un Mac e iOS user, infatti i primi test sull’app li ho fatti tramite iOS.
Tuttavia, su iOS è molto complicato decompilare un’app: tutte le app disponibili su Apple Store sono cifrate, e le chiavi di crittografia sono conservate nei secure enclave di iPhone/iPad. L’unico modo per decompilare un’app iOS è quindi avere il sorgente decrittato – recuperabile tramite un dump diretto dalla memoria di iOS, procedura possibile solo su iPhone Jailbroken.

BURP SUITE

Imposteremo Burp Suite per un man in the middle attack, se sai già come impostarlo puoi saltare questo paragrafo

Burp Suite permette di attivare un proxy solo su porte specifiche, e non su un range-wildcard. 

Va configurato come da seguente immagine, quindi port 8080, bind to all interfaces, “invisible” e “per-host” certificate

Burp Suite Proxy

Per ovviare al discorso delle porte e non creare decine di regole, ho modificato il file /etc/pf.conf del mio Mac come segue

scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"
rdr on bridge100 inet proto tcp to any port 1:65535 -> 127.0.0.1 port 8080
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"

La riga incriminata è quella in grassetto, e praticamente dice: su bridge100 (l’interfaccia di rete che viene creata attivando la Condivisione Internet), tutti i pacchetti tcp che vengono ricevuti su tutte le porte – range 1:65535 – devono essere ruotati su localhost alla porta 8080 (quella che usiamo su Burp Suite come proxy)

A questo punto possiamo dare un:

sudo pfctl -f /etc/pf.conf
sudo pfctl -e

per ricaricare le regole di packet filtering e rendere attivo il file appena modificato.

Rimane solo una cosa da fare: Burp Suite può fare Man In The Middle su SSL, a patto che:

  • l’app da analizzare non usi Certificate Pinning ( https://security.stackexchange.com/questions/29988/what-is-certificate-pinning )
  • ci sia pieno controllo del device target, quindi sia possibile installare un certificato Self Signed e impostarlo come trusted. In questo modo Burp Suite inietterà nelle request un suo certificato, decripterà il payload per presentarvelo in chiaro, e poi lo reencrypterà prima di inviarlo al backend, e viceversa.

Una volta avviato Burp Suite, sarà sufficiente collegarsi dallo Smartphone Android a http://burp e seguire la procedura indicata per l’installazione e trust del certificato SSL ( https://support.portswigger.net/customer/portal/articles/1783087-installing-burp-s-ca-certificate-in-firefox )

Se abbiamo fatto tutto correttamente, vedremo riempirsi la history HTTP (e nel caso dell’app che ho analizzato, anche websocket)

Burp Calls
Burp Websocket

ANALISI

Dopo un po’ di di analisi dei payload transitanti su Burp Suite, ho notato che all’invio di un messaggio chat, seguivano alcuni messaggi websocket, quindi mi sono focalizzato su quelli.

Peccato che l’output fosse incomprensibile

Output

Per questo motivo, dopo un po’ di tentativi di “deoffuscamento”, ho cambiato strategia e mi sono focalizzato sul decompilare l’APK.

Ho deciso di scaricare l’APK tramite questo sito: https://m.apkpure.com/e l’ho dato in pasto a Jadx ( https://github.com/skylot/jadx ), un decompilatore Java.

Dopo un po’ di ricerche nel codice parzialmente offuscato, sono approdato su una classe chiamata Crypto

Decompiled

e in particolare i metodi m36022a() e m36020a() che rispettivamente si occupano di Encrypt e Decrypt di un array di bytes. 

Seguendo il flusso del codice, ho capito che il messaggio Websocket in uscita segue il seguente path:

  • viene generato a partire da oggetti (Model e servizi) che vengono assemblati insieme per creare il Payload del messaggio, una cosa del genere:
{
"event" : {
"dbName" : "xxx",
"action" : 1111,
"v" : "1.1.1",
"name" : "database"
},
"objects" : [
{
"userID" : "123123123123"
}
]
}
  • questi JSON vengono a inviati passati alla funzione di encrypt che restituisce un array di bytes
  • vengono inviati all’Application Server tramite Websocket binario

E, in ingresso, il flusso è al contrario.

A questo punto, chiarito il flusso, ho cercato di capire:

  • – il tipo di encryption usata
  • – le chiavi di cifratura

Problema: le variabili di istanza sono parzialmente offuscate, per colpa di Kotlin ( https://kotlinlang.org ).

Non conosco a fondo l’ecosistema Android, ma ho capito che si tratta di un linguaggio nativo che sta diventando lo standard de facto su Android, e che compila binari Java-compatibili.

Per questo motivo riusciamo a decompilare qualcosa che somiglia a Java, ma che ha delle “stranezze”

Metadata

Per esempio, l’annotation @Metadata contiene un sacco di dati encodati che poi vengono utilizzati a runtime per popolare le variabili di istanza statiche che ho cerchiato.

In Java f25721B = f25721B non significa nulla, ma il vero valore della static String f25721B è in quei metadata, di cui ho trovato pochissima documentazione.

Purtroppo, però, non sono riuscito a trovare un decompilatore Kotlin, quindi ho proseguito con le mie indagini seguendo altre strade.

Ho quindi analizzato altri 2 metodi della classe Crypto, che vengono richiamati durante l’init della classe Cypher ( https://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html )

instance.init(1, new SecretKeySpec(f25746a.m36021a(), C3944ae.m18613e() ? f25743X : f25744Y), new IvParameterSpec(f25746a.m36023b()));
AES
IV

Analizzando la signature del metodo init di Cypher e del constructor di IvParameterSpec(), ho capito che si tratta dei metodi che generano le chiavi di crittografia.

In particolare, recuperano rispettivamente 32 e  16 variabili di istanza e le accodano una a una fino a formare una chiave.

Altro problema, le variabili referenziate sono quelle viste poco sopra:

Variables

e quindi siamo nuovamente a un punto morto, non abbiamo accesso ai byte che compongono le chiavi di crittografia.

Decido quindi di indagare ulteriormente su Kotlin, e scopro che il processo di decompilazione fatto da Jadx, prevede vari passaggi intermedi, tra cui l’estrazione del bytecode dell’applicazione prima di decompilarla.

Mi chiedo quindi…che succede se frugo nel bytecode?

Per estrarlo, uso apktool:

apktool d nome_app.apk

che spacchetta l’apk in una directory contenente diversi file con varie estensioni, tra cui dei file con estensione *.smali che sono quelli contenenti il bytecode dell’app.

Smali

Decido quindi di cercare in tutti i file la stringa Crypto, il nome della classe su cui sto lavorando:

find ./ -iname *.smali -exec grep -H Crypto {} \;
Smali2

e trovo un file a.smali che contiene alcune info interessanti:

  • Una serie di stringhe statiche, di 1 singolo carattere ciascuna. E sono 48 (32 + 16), quelle che cercavo!
Static Fields
  • Il bytecode dei metodi che ho mostrato poco più sopra, quelli che generano la key.
Smali3

In questo modo ho:

  • il contenuto di 48 variabili di istanza  (32 + 16)
  • i dettagli delle assegnazioni, mi spiego meglio:
    • alla riga 115 vediamo che viene generato l’array vuoto
    • alla riga 117, viene assegnata la prima variabile, che è ->C
    • alla riga 118, viene assegnata la seconda, che è ->u
    • e così via

Se torniamo al primo elenco, vedremo che alla lettera C (maiuscola) corrisponde la seguente static var:

che contiene la lettera “q”.

Nel restante bytecode sono anche riuscito a trovare i dettagli dell’encryption usata:

AES

Mi è bastato quindi ricostruire la chiave con il metodo precedente, e tramite quest’ottimo tool online leggere finalmente il payload del messaggio websocket: https://gchq.github.io/CyberChef

Questa specifica app analizzata non utilizza altri metodi di autenticazione e autorizzazione “per user”, quindi la decodifica dei payload permette cose interessanti. I payload possono essere quindi intercettati, modificati e reinviati al backend, eseguendo azioni per conto di altri utenti.

Non è lo scopo di questo post consigliare sugli adeguati metodi di protezione da implementare nelle vostre app, questi metodi dipendono fortemente dalla tipologia di app trattata, ma provo a riassumere alcuni punti fermi:

  • Se la vostra app lavora con dati di utenti (quindi esiste una procedura di login), non reinventate la ruota e usate degli standard. Dopo il login, rilasciate all’utente un token (ad esempio un bel token JWT https://jwt.io ) e utilizzatelo per autorizzare ogni singola chiamata. Una cosa del genere:
{
"event" : {
"dbName" : "xxx",
"action" : 1111,
"v" : "1.1.1",
"name" : "database"
},
"objects" : [
{
"userID" : "123123123123",
"token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
]
}

Il vostro backend dovrà accettare solo request effettuate con token validi e firmati, inoltre dovrà verificare che le azioni richieste dal payload siano permesse all’utente “proprietario” del token.

Il token può essere comunque letto tramite un attacco MITM come quello che abbiamo appena fatto, ma sarà “per user”, quindi un eventuale attaccante potrà solo fare chiamate con token a lui assegnati (quindi sarà identificabile), e solo azioni che il backend gli permette.

Inoltre, è vero che il token JWT è un normale base64, quindi il suo contenuto leggibile, ma non può essere alterato senza conoscere la sua chiave (in caso di alterazione la sua firma non sarebbe più valida)

Nota importante: il token JWT va generato (“staccato”) direttamente dal backend, e non va generato dall’app, altrimenti siamo punto e a capo, perchè significa che in qualche modo la chiave JWT sarà nota all’app.

  • Non affidatevi esclusivamente all’approccio “Security through obscurity”. Se mettete tutta la logica applicativa, inclusa la validazione e l’autorizzazione, direttamente nell’app client, praticamente state lasciando a un attaccante le chiavi di casa vostra, sono solo nascoste. Magari per l’attaccante sarà difficile scoprire dove nascondete le chiavi, ma con sufficiente pazienza riuscirà a trovarle. (e tipicamente, a meno che non siate un’azienda che investe davvero *tanto* in sicurezza, avrà più tempo e pazienza di voi). Spostate le logiche su backend e trattate le app, anche se fatte al 100% da voi, come oggetti “not trusted”. Possono essere manomesse.

È tutto, fatemi sapere cosa ne pensate e se avete bisogno di altre informazioni nei commenti.

Proof of concept of NGINX + JWT Validation

A short article to inform you that I’ve just published a proof of concept of JWT token validation with NGINX using NJS.
NJS is a subset of Javascript that allows extending NGINX functionalities: https://nginx.org/en/docs/njs/

Please note: NGINX can already validate JWT Tokens, but only if you pay for the Plus subscription. Thanks to NJS we can now validate JWT Tokens with the free version of NGINX.

You can find the code on Github here: https://github.com/lombax85/nginx-jwt

Moreover, you can find a benchmark here: https://github.com/lombax85/nginx-njs-benchmark


Performance cost of AWS Lambda@Edge on CloudFront

In this article we’ll take a look at the performance cost (or “overhead”) of using AWS Lambda@Edge ( https://aws.amazon.com/lambda/edge/ ) on a CloudFront distribution.

Note: In this article I won’t explain how to create these resources (you can find detailed instructions on the official AWS pages), but I want to focus on the test cases.

You can use Lambda@Edge to execute arbitrary Lambda Functions on your requests, for example to authenticate an user through a JSON Web Token ( https://jwt.io ) before routing them to a static asset.

The main advantage of Lambda@Edge is that the code (Javascript) is executed “near to the edge”, so really clouse to the edge location, and so with a small performance cost.

So, for testing this:

  • I created an S3 bucket with two files: a sample image (124KB) and an empty txt file
  • I created two CloudFront distributions pointing to the same bucket, one distribution triggering a Lambda@Edge function that takes the querystring and adds it in a custom header, and the other simply serving the content without further check
  • A Lambda@Edge function as explained above

So let’s say we have:

This Lambda@Edge function:

'use strict';
exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
const headers = response.headers;
headers['test-header'] = [{
key: 'test-header',
value: event.Records[0].cf.request.querystring
}];
callback(null, response);
};

And these two requests

REQUEST 1:
http://abc.cloudfront.net/cat.jpg?EXAMPLEQUERYSTRING

REQUEST 2:
http://xyz.cloudfront.net/cat.jpg?EXAMPLEQUERYSTRING

The first request pass through the Lambda@Edge function, so its response headers will be like these:

Content-Type: image/jpeg

test-header: EXAMPLEQUERYSTRING

X-Cache: Hit from cloudfront

As you can see, there is a `test-header` with the content of the querystring.
This is unuseful in a real world situation, but we use it to understand how much is the overhead of a REALLY simple Lambda function

Since the second request doesn’t pass through the Lambda function, its header doesn’t show the custom header

Content-Type: image/jpeg

X-Cache: Hit from cloudfront

Finally, we are ready to test it.
For the tests, I choose to use an AWS EC2 instance to minimize the networking overhead (hopefully there is a good networking between EC2 and Cloudfront) 🙂

I used this simple script to collect the response times. It makes 1000 requests and adds the response time to a file:

TIMEFORMAT=%R

for i in {1..1000}
do
(time $(curl -s http://abc.cloudfront.net/cat.jpg?EXAMPLEQUERYSTRING > /dev/null)) >> 1.txt 2>&1
done

for i in {1..1000}
do
(time $(curl -s http://xyz.cloudfront.net/cat.jpg?EXAMPLEQUERYSTRING > /dev/null)) >> 2.txt 2>&1
done

Here you can see the results:

In Orange, you see the distribution of the calls without the Lambda function, and in Blue the distribution of the calls WITH the Lambda function.

Finally, I decided to do some tests with ab (Apache Bench), in this cased I used 10.000 connections with 100 concurrent

As you can see in the Excel, there is a performance cost, since the mean moves from 0,015sec to 0,058sec.
In the ab tests (with the empty.txt file), the mean moves from 9.3msec to 38.5msec.
So rawly 4X.

But these timing are, in absolute, still pretty fast if we consider that they can be executed really close to the final user, and so no need to round trip to your compute-servers.

The next time I will try CloudFlare Workers, that claims to be 2X faster than AWS Lambda@Edge

Ciao!

LombaX

L’HomeLab di LombaX – seconda puntata

Home-assistant – telecamere e automazioni

Ed eccoci arrivati al secondo appuntamento della serie #LombaXHomeLab , potete trovare gli altri articoli semplicemente cliccando sull’hashtag.

Iniziamo ad analizzare più nel dettaglio le varie componenti del mio HomeLab, ho deciso di partire da Home Assistant (o Hass, in breve), che forse è un po’ il “cuore” del progetto. Tutto è iniziato da Home Assistant, inizialmente installato su un piccolo Raspberry Pi.

Raspberry

Poi, col tempo, le mie esigenze sono cambiate e ho dovuto potenziare il tutto con un Intel Nuc, ma questa è un’altra storia.

Cos’è Home Assistant? 

Dal sito ufficiale:

> “Open source home automation that puts local control and privacy first.“

Quindi, in poche parole, un Hub per tutti i dispositivi IoT di casa nostra, con un forte focus su controllo locale e privacy.

In questo articolo però non mi voglio focalizzare su cos’è Home Assistant o su informazioni “base” per installarlo, quindi non prendetelo come un tutorial, ma piuttosto uno stimolo alla vostra creatività. Non esitate, però, a commentare e chiedere chiarimenti qualora qualcosa non fosse chiaro.

Infine, dato che con Hass faccio tante cose, l’articolo sarebbe un po’ troppo “corposo” quindi lo spezzerò in varie puntate.

Questa è la schermata principale del mio Home Assistant:

Hass

É totalmente personalizzabile nel mood grafico, cosa che però non ho fatto e non penso che farò, perchè sono totalmente incapace in tutto ciò che ha a che fare con grafica e UX 🙂 quindi mi sono concentrato più su quello che c’è sotto il cofano.

Bando alle ciance, un breve indice e poi si parte.

Di cosa parleremo in questa serie di articoli?

  • Videosorveglianza: collegare e gestire telecamere, accenderle e spegnerle quando necessario
  • Controllo luci: gestione di luci di vari generi e vendor, automazioni per gestirle in base agli orari o a determinate condizioni
  • Comandi vocali: utilizziamo Siri per gestire luci, e magari anche la TV
  • Controllo temperature e alert: fa freddo? fa caldo? E se fa troppo caldo, ti avviso.
  • Tempi di viaggio previsti: a che ora parto per andare a lavoro?
  • Teniamo d’occhio i consumi di corrente: Engage Efergy

Videosorveglianza

In alto a sinistra vediamo le Telecamere, i primi componenti che ho iniziato a controllare con Home Assistant, che in questa immagine sono spente. Why?

La prima esigenza è nata proprio così: ho 2 telecamere D-Link (vecchiotte), che supportano 2 funzionalità importanti, motion detection e alert via e-mail. Purtroppo però non sono programmabili gli orari di attivazione, senza contare che questi orari non sono sempre prevedibili. Come attivare la videosorveglianza ma evitare di ricevere alert quando io o mia moglie siamo in casa? E come rispettare la nostra privacy?

Ho sfruttato alcune componenti di Home Assistant e un po’ di hardware “di riciclo”, che avevo in casa.

Perchè il bello di Home Assistant è proprio questo: 
oggi supporta circa 1.200 componenti, quindi è altamente probabile 
che il vecchio device IoT che avete comprato 2 anni fa, e che ora è 
chiuso in una scatola perchè non si integra con nulla, possa essere 
gestito con Home Assistant

Hardware:

  • Per l’accensione/spegnimento delle telecamere, ho usato due Belkin Wemo switch
  • Ovviamente le telecamere 🙂 , due D-Link di cui non ricordo il modello e forse poco importa

Wemo

Dlink

Software:

  • Hass gestisce nativamente gli switch Belkin Wemo, se sono sulla stessa rete locale li autorileva e può controllarli senza bisogno di far nulla. Tutti i device che possiedono un interruttore, sono chiamati “switch” su Hass, e vengono visualizzati con un semplice interruttore on-off nell’interfaccia.
  • Geolocalizzazione: un altro componente di Hass è il “device_tracker”, componente che rileva la posizione/presenza di un device (tipicamente un cellulare) in vari modi. Può eseguire scansioni temporizzate all’interno della rete con NMap per rilevare se il Mac Address del vostro cellulare è connesso, può basarsi sulla presenza rilevata tramite Bluetooth, oppure (come ho fatto io), sul GPS dei vostri cellulari.
  • Automazioni: un altro componente importante di Home Assistant è “automation”, che permette di eseguire automaticamente alcune attività solo se si presentano determinate condizioni.
  • OwnTracks: App disponibile su iOS e Android, traccia costantemente la posizione del vostro cellulare e la invia a un MQTT Broker di vostra scelta. Hass offre questa funzionalità anche con la sua App nativa, ma si tratta di una funzionalità implementata in un secondo momento, che non ho ancora testato.
  • MQTT: si tratta di un protocollo di messaging “machine to machine” molto leggero, lo useremo per “trasportare” le informazioni di localizzazione da OwnTracks a Hass. Necessità di un server MQTT, nel mio caso ho deciso di utilizzarne uno cloud e gratuito chiamato CloudMQTT. Hass dovrebbe avere un MQTT server integrato, ma anche in questo caso si tratta di una funzionalità aggiunta in seguito, che non ho ancora testato.

NB: Hass ha moltissimi “componenti”, ma un altro componente core che vale la pena citare anche se in questo caso non è stato utilizzato, si chiama “sensor”.
Un Sensor permette di rilevare lo stato di qualsiasi cosa. Esistono sensori fisici (es. un termometro digitale, un rilevatore di movimento, un rilevatore di gas), sensori “virtuali” (es che rilevano le previsioni del tempo, quando il sole sorgerà o tramonterà).

Ora che abbiamo tutti gli ingredienti, la ricetta:

Sorvolo sul collegamento di Switch Belkin Wemo e delle Telecamere, in pochi minuti sarete in grado di collegarli e fare in modo di accendere/spegnere le telecamere dall’interfaccia di Hass.

Una volta fatto ciò, dobbiamo collegare Hass al nostro MQTT Broker, in configuration.yaml andiamo a inserire i dati di CloudMQTT (dopo esservi iscritti, li trovate nella vostra area personale)

In configuration.yaml andiamo a inserire i seguenti dati (NB yaml è sensibile all’indentazione, quindi ricontrollatela bene perchè potrebbe essere “saltato” qualche spazio durante il copia e incolla)

mqtt:
  broker: xxx.cloudmqtt.com
  port: 10109
  username: “your_username”
  password: “your_password”

questi stessi dati andranno inseriti su OwnTracks, con l’aggiunta di un id che identifichi il cellulare (chiamato Topic nel gergo di MQTT). Nel mio caso avremo 2 topic, uno per il mio cellulare (es marito) e uno per mia moglie.

A questo punto, nel file known_devices.yaml di Hass andiamo a inserire 2 nuovi devices:

your_username_marito:
  name: MaritoiPhone
  track: yes
  hide_if_away: no

your_username_moglie:
  name: MoglieiPhone
  track: yes
  hide_if_away: no

Mancano ancora un paio di cose. Sempre in configuration.yaml dobbiamo inserire la posizione di casa

zone:
  name: home
  latitude: 11.12345
  longitude: 22.23456
  radius: 250

(NB ho scelto un raggio un po’ ampio, 250 metri, ma nulla vi vieta di modificarlo. Fate un po’ di prove, la scelta giusta dipende anche dalla precisione del vostro cellulare)

A questo punto, Hass dovrebbe essere in grado di rilevare se siete in casa o no:

Infine, dobbiamo creare un “gruppo” per la famiglia (per rilevare quando almeno un membro della famiglia è in casa), e uno con gli switch delle Telecamere (per accenderle/spegnerle entrambe contemporaneamente)

group:
  family:
    name: Famiglia
    view: yes
    entities:
      - device_tracker.your_username_moglie
      - device_tracker.your_username_marito
  telecamere:
    name: Telecamere
    entities:
      - switch.telecamera_sala
      - switch.telecamera_studio

A questo punto siamo pronti per creare la nostra automation

automation:
  - alias: Turn on camera when family outside
    trigger:
      platform: state
      entity_id: group.family
      from: 'home'
    action:
      - service: switch.turn_on
        entity_id: group.telecamere
      - service: notify.ios_iphone_di_lombax
        data:
          message: "Telecamere accese"
          data:
            push:
              badge: 0
              category: "DEFAULT_NOTIFICATION"
  - alias: Turn off camera when family inside
    trigger:
      platform: state
      entity_id: group.family
      to: 'home'
    action:
      - service: switch.turn_off
        entity_id: group.telecamere
      - service: notify.ios_iphone_di_lombax
        data:
          message: "Telecamere spente"
          data:
            push:
              badge: 0
              category: "DEFAULT_NOTIFICATION"

Molto semplice, come potete vedere.

Nella prima automation stiamo dicendo che quando lo “state” del gruppo “family” non è più “home” (ricordate come abbiamo chiamato la zona di casa nostra?), deve scattare una action “switch.turn_on” sul gruppo “telecamere”. Nel secondo, viceversa.

In questa configurazione vedete anche un “service” specifico per le notifiche. Si tratta di un tema che vedremo in uno dei prossimi articoli, vi basti sapere che…quando l’automazione si verifica, ricevo una notifica push sul mio cellulare.

Per oggi è tutto, alla prossima puntata!

L’HomeLab di LombaX – prima puntata

Da appassionato di tutto ciò che è il mondo informatico, ho sempre avuto voglia di “toccare con mano” le tecnologie che ritengo più interessanti. Un po’ come il garage è “la stanza dei giochi” per un appassionato di meccanica o bricolage, l’HomeLab è la stanza dei giochi dell’appassionato di informatica, qualcosa che nasce per hobby, e viene coltivato sempre per hobby. Poi, nel tempo, diventa utile…probabilmente (almeno nel mio caso) non indispensabile…perchè poter dire “ehi Siri, accendi il Natale” per far accendere l’albero e varie luci colorate è cool, ma si può vivere anche senza 🙂

Questa sarà l’intro di una serie di articoli più tecnici e hands on, penso che una premessa – prima di entrare nei dettagli dei singoli servizi e tecnologie utilizzate per realizzare il mio HomeLab – sia d’obbligo. Farà anche un po’ da indice per i prossimi articoli.

Quindi…com’è il mio HomeLab? Cosa fa? A che serve? Come è organizzato?

Intel Nuc

 

Postazione

​Io direi di partire dai servizi, principalmente domotica, automazione, monitoring e multimedia in casa:

– fa da hub per tutti i dispositivi domotici che ho in casa (lampadine Philips Hue, switch Belkin Wemo e Sonoff, termometri “artigianali” sviluppati su Raspberry Pi, TV), permettendomi di accenderli e spegnerli da remoto (pc o cellulare), di controllare le temperature ecc…

– si interfaccia con Siri e HomeKit di Apple, permettendo a me e mia moglie di controllare gli stessi dispositivi con comandi vocali ai nostri iPhone o Apple Watch. “Ehi Siri, accendi le luci della Sala”, “spegni le luci della Camera”, “imposta luci calde in Studio”, “dimmi che temperatura c’è in Soggiorno”.

– gestisce la TV (Samsung Smart TV), permettendoci di accenderla, spegnerla, gestire canali e volumi sempre tramite controllo vocale

– ci permette di memorizzare file (documenti, foto, video) in una condivisione di grandi dimensioni e al tempo stesso proteggerli (encryption + backup offsite – in  particolare su Amazon AWS S3), ci permette di vederli direttamente in tv condividendoli con il protocollo DLNA.

– gestisce il nostro “mini” impianto di videosorveglianza, la casa è piccola ma abbiamo un paio di telecamere, tuttavia per rispetto della nostra privacy preferiamo che si spegnano quando io o mia moglie siamo a casa. Quindi, tramite geolocalizzazione sul cellulare e protocollo MQTT, non appena uno dei due entra in casa, le telecamere si disattivano.

– ci avvisa, tramite notifiche sul cellulare, se qualcosa non va: temperature troppo alte, rilevato movimento dalle telecamere

– gestisce un minimo di automazione: se siamo fuori casa facciamo accendere le luci al crepuscolo, così da non lasciare il cane al buio

– permette di monitorare consumi elettrici, banda internet, temperature delle varie stanze, con grafici facilmente esplorabili

– protegge, filtra e monitora la navigazione internet (tramite Pi-hole e protocollo SNMP)

…e questa lista è in continua evoluzione 🙂

Il componenti principali, ad oggi, sono:

Software

– Home Assistant: è l’hub di automazione principale, in brevissimo, si connette a tutti i device IOT della casa e permette di interagirci da un’unica interfaccia, integrata con HomeKit (e anche con la concorrenza… 🙂 ). Scriverò un articolo specifico in proposito, ma nel frattempo potete informarvi meglio quì: Home Assistant

Home Assistant

– Grafana: software per creare dashboard come queste

Grafana

– InfluxDB, memorizza tutte le metriche da HomeAssistant e altri servizi, permettendo poi di visualizzarle su Grafana

– Pi-hole, dns server che blocca la maggior parte dei domini di advertising, phishing e malevoli, rendendo più sicura e anonima la navigazione internet

Pihole

– MiniDLNA per condividere in rete i file multimediali e vederli dalla tv

– Un po’ di software custom (linguaggi principali utilizzati: PHP, Javascript con Node.js, Python e un bel po’ di sano bash scripting) scritto per fare da “collante” dove necessario.

– VMWare ESXi 6.7 per virtualizzare il tutto

vmware 1

vmware 2

 

XSIBackup per il backup delle macchine virtuali

– OS: il mio OS principale è MacOS, ma adoro anche Linux e in casa mia non viene discriminato nemmeno Windows, in questo momento (tra portatili, fissi e virtuali) almeno una 15ina di macchine: 2 mac, 3 windows, il resto Linux (Ubuntu o Raspbian, in generale sono della squadra Debian) 🙂

– Apple Homekit per i comandi vocali

– OWNTracks su cellulare per la geolocalizzazione

– Altri servizi esterni: quando necessario, mi appoggio ad Amazon AWS (in questo momento S3 per i backup) e OVH (macchina virtuale su cui risiede questo sito e alcuni script di controllo). CloudMQTT come broker MQTT per geolocalizzazione e temperature

Hardware

– Intel NUC 7th gen. i3, NVMe Samsun Evo 970 da 500GB per le virtual, Seagate BarraCuda da 2TB per storage, 16GB di RAM

nuc

 

samsung evo nvmenvme speed

– Alcuni dischi USB esterni per i backup delle macchine virtuali

– Hub e luci Philips HUE

– Hub Engage Efergy per il controllo dei consumi elettrici

– Vari Belkin Wemo e Sonoff come smart switch

– Telecamere D-Link

– UPS

– 4 Raspberry Pi sparsi per casa per controllare temperature (sensori DHT-22) o fare da Thin Client verso le macchine virtuali

Raspberry

– 3 Monitor (Lenovo 27″ 4K, Samsung 24″ FullHD, Samsung 19″ “di servizio”)

I motivi di queste scelte saranno dettagliati negli articoli di approfondimento, ma è bene tener presente alcuni “constraints” che mi hanno portato a farle:

– come detto a inizio articolo, tutto nasce principalmente per hobby. Voglia di provare delle tecnologie, hype, voglia di imparare un particolare linguaggio o usare uno strumento…quindi non cercate troppa logica in quello che ho fatto. Sicuramente si poteva “ingegnerizzare” meglio, ma lo scopo principale era uno solo: intrattenermi, e vi assicuro che ad oggi lo scopo è raggiunto 😉

– spendere “il giusto”. Ognuno di noi ha un concetto, totalmente personale, di quanto sia “il giusto”, e non è sempre uguale in ogni momento della vita. Il mio HomeLab è nato un pezzo alla volta, in alcuni momenti si è evoluto più velocemente, in altri meno. Lo espando per “iterazioni”. Generalmente, se in 2-3 occasioni all’anno sono più libero e mi avanzano 200-300€, mi “coccolo” regalandomi qualche pezzo di hardware nuovo (telecamere, switch, dischi ecc ecc). Tranne questo Natale che ho fatto evaporare una parte consistente di 13esima…ma questa è un’altra storia che leggerete nell’approfondimento dedicato all’Intel NUC.

– limitare i consumi elettrici: l’HomeLab (monitor esclusi, quindi Intel Nuc, disco esterno, router Internet + Wifi, UPS e qualche Raspberry) consuma appena 40watt! Con i 2 monitor principali accesi, arrivo a 120watt!

Direi che per la premessa è tutto.

Ora ci dobbiamo concentrare sui dettagli tecnici – più divertenti – relativi ai vari punti. I prossimi articoli quindi andranno a esplorare nel dettaglio tutti i punti sopra riportati, uno alla volta (man mano aggiungerò link a questo articolo).

Se avete domande o preferenze su quale argomento trattare per primo non esitate a commentare.

Soluzioni per Live Streaming

NB: questo articolo è stato scritto velocemente, ma vuole riassumere diverse giornate di analisi delle tecnologie e del mercato.
Se non capite qualche parte o volete maggiori dettagli, contattatemi pure. Con il tempo aggiungerò dettagli.

Parliamo delle tecnologie di Live Streaming, sistemi per trasmettere live e a migliaia di persone, in tempo reale, un flusso video.

Ho effettuato questa analisi per esigenza aziendale.

Nel nostro caso l’esigenza era duplice: in alcuni casi, trasmettere un evento live a qualche migliaio di persone (troupe video presente). In altri casi, effettuare brevi trasmissioni da parte di singoli (responsabili dei ns clienti), non assistiti (quindi tecnologia *semplice*), a diverse centinaia di persone.

Prima di entrare nei dettagli, è bene analizzare le varie parti dello stack di cui un Live Streaming si compone


 

Fase di ripresa e acquisizione (transcoding):

Questa prima fase è, banalmente, il momento in cui effettuate le riprese. Dato che parliamo di “Live”, il flusso video deve essere catturato e trasmesso in tempo reale. Qualunque sia il vostro sistema video per le riprese (telecamere professionali, webcam, cellulari), il vostro scopo è quello di far arrivare un segnale video a un pc, che dovrà poi codificarlo secondo uno standard e trasmetterlo a un server.

Esistono inoltre delle App per cellulari che facilitano il compito: acquisiscono il segnale dalla telecamera on-board, lo impacchettano e spediscono direttamente secondo lo standard.
Per la fase di trasmissione, ci focalizziamo sullo standard RTMP ( https://it.wikipedia.org/wiki/Real_Time_Messaging_Protocol ). E’ possibile usare anche RTSP ( https://it.wikipedia.org/wiki/Real_Time_Streaming_Protocol ). Non ho analizzato altri standard.


 

Fase di creazione dello stream:

Questa fase viene effettuata da un server dedicato, quello a cui state inviando il flusso RTMP. Il server riceve il flusso video, lo transcodifica ulteriormente (producendo i chunk video a varie risoluzioni/bitrate e formati) e li rende disponibili per la fruizione.


 

Fase di distribuzione:

il server che crea lo stream non ha una banda sufficiente a servire tutti i vostri utenti. Per questo motivo non viene esposto direttamente su internet, viene piuttosto utilizzato un sistema di distribuzione (tipicamente una CDN https://it.wikipedia.org/wiki/Content_Delivery_Network ). Quindi il vostro server di encoding carica lo stream definitivo sulla CDN rendendolo disponibile agli utenti


 

Fase di fruizione:

i vostri utenti tipicamente (ma non necessariamente) si collegano al sito internet dove ospitate il video. In questo sito è inserito un player, che tipicamente è un’applicazione Flash o un player HTML5. All’avvio della fruizione, il player contatta l’url CDN e inizia a scaricare il video. Anche in questa fase, esistono diversi standard e tecnologie: quelle che ho analizzato sono sempre RTMP (può essere usato indipendentemente sia per la fase di upload che per quella di download), oppure HLS (standard più recente)
Una variabile importante, se lavorate su siti internet, è la possibilità di vedere il video direttamente dalla pagina che lo ospita (embed), senza farlo aprire in un popup. Altra variabile importante è la possibilità di scegliere diversi bitrate manualmente o in automatico (a seconda della banda disponibile lato client). In questo caso parleremo di JWPlayer ( https://www.jwplayer.com ) che gestisce tutte queste casistiche.


 

Ora che abbiamo parlato delle varie parti dello stack, passiamo a un po’ di nomi, tecnologie e consigli. Iniziamo con il fai da te, se volete dei servizi che coprono tutta questa parte in pieno outsourcing staltate pure questa parte. Anche se vi consiglio caldamente di leggerla per imparare qualcosa 😉

Per la fase di ripresa
possiamo utilizzare telecamere professionali con uscita analogica o digitale, acquisendo poi il segnale con una scheda di acquisizione tipo questa:

http://www.amazon.it/Blackmagic-Design-Intensity-Shuttle-Thunderbolt/dp/B007ZDHDRS

Oppure è possibile usare direttamente la webcam.
In questa fase vogliamo encodare il segnale in ingresso in un flusso RTMP da inviare al nostro server.
Esistono diversi software per questa fase, io personalmente consiglio Wirecast: http://www.telestream.net/wirecast/overview.htm

Il setup è semplice, una volta acquisito correttamente il segnale video dovrete impostare i dati del server RTMP che riceverà il flusso video. Tipicamente saranno un indirizzo ip, uno username e una password.

Se volete un setup più semplice per eseguire le prime prove, scaricate un’app all-in-one, su iPhone posso consigliare questa: https://itunes.apple.com/it/app/broadcast-me/id491982406?mt=8 (esiste anche una versione RTSP, ma in questo caso noi vogliamo usare la versione RTMP)

per la fase di creazione dello stream:
il nostro server riceverà lo stream RTMP e dovrà encodarlo secondo i diversi standard che vogliamo poi fornire al nostro player (passando per la CDN).
Gli strumenti consigliati in questa fase sono due:
*Apple Media Encoder e altri software a supporto (ostico ma sicuramente il più configurabile)
*Adobe Media Encoder (non l’ho usato personalmente)

In questa fase consiglio di creare uno stream HLS ( https://en.wikipedia.org/wiki/HTTP_Live_Streaming ), in particolare l’encoder prende il video live e lo segmenta in piccoli pezzi (da 10 secondi ciascuno), in tante risoluzioni diverse, e li carica sulla CDN. L’encoder mantiene aggiornato un file di index (file .m3u8) che viene usato dal player per referenziare correttamente i file man mano che vengono aggiunti.

per la fase di distribuzione:

in questa fase ci servirà appoggiarci a una CDN e depositare i file sullo storage ad essa associato. In alcuni casi sarà la CDN a recuperare i file (tramite una http request a un vostro server, anche direttamente al media server se volete).
Poco da dire, facciamo qualche nome:
• Akamai
• CDNetworks
• Edgecast
• Limelight

ce ne sono tante altre, ma queste hanno un particolare: possono ricevere (e poi redistribuire) uno stream RTMP direttamente, senza la necessità di un encoder intermedio come da punto due. In questa guida non copriamo questa casistica, ma è giusto saperlo. Io comunque vi sconsiglio questo setup, in quanto RTMP è superato per la parte di distribuzione, in favore del più recente e flessibile HLS.

per la fase di fruizione:

anche in questo caso poche parole, vi consiglio di usare JWPlayer che ha già il supporto nativo per HLS e un player HTML5 nativo (o flash in fallback nel caso il vostro device non supporti html5).
A questa pagina trovate dettagli per il setup: https://support.jwplayer.com/customer/portal/articles/1430218-using-hls-streaming


 

Una volta parlato del fai da te, è giusto dire che non è sempre corretto reinventare la ruota. Esistono servizi che, a fronte di un costo mensile, coprono in tutto o in parte le varie parti dello stack.

Il più completo che ho trovato è Ustream: copre l’intero stack. Fornisce un’interfaccia web per l’acquisizione, con la possibilità di acquisire dalla webcam direttamente all’interno del browser e, nella versione pro, fornisce il codice embed per il player. Insomma, copre tutte e 4 le fasi in maniera molto semplice.
Si possono utilizzare telecamere professionali ed effettuare lo streaming anche tramite un software dedicato, Ustream producer. Inoltre vi permette di inviare il vostro flusso RTMP direttamente (se volete usare un’app o uno streamer hardware).

Altri nomi di cui scriverò più avanti: DaCast, StreamZilla.


 

Vi lascio alcuni link utili:
Bibbia dello streaming video by Apple

Strumenti server Apple

Alcuni transcoder:
https://zencoder.com/en/hls
https://www.wowza.com/forums/content.php?304-How-to-set-up-and-run-Wowza-Transcoder-for-live-streaming#swReq
http://knowledge.kaltura.com/live-streaming-using-kaltura-live-streaming-hds-hls-dash

Alcune app per streaming da iPhone
http://www.dacast.com/blog/how-to-stream-live-from-iphone/
https://itunes.apple.com/it/app/broadcast-me/id491982406?mt=8
https://itunes.apple.com/it/app/os-broadcaster/id632458541?mt=8