Laborator 7: Securizarea aplicației web pentru gestionarea imaginilor

În cadrul acestui laborator ne vom axa pe implementarea securității Mutual TLS (mTLS) pentru comunicația MQTT din cadrul aplicației web.

Ce este mTLS?

Mutual TLS (mTLS) este un mecanism de autentificare bidirecțională în care:

  1. Serverul se autentifică față de client (TLS standard)
  2. Clientul se autentifică față de server (autentificare mutuală/bidirecțională)

Acest lucru asigură că:

  • Datele sunt criptate în tranzit
  • Doar dispozitivele autorizate se pot conecta la broker
  • Atacurile de tip man-in-the-middle sunt prevenite

Fișiere de modificat

Fișier Scop Modificări Necesare
broker/mosquitto.conf Configurare Broker Activarea listener-ului securizat pe portul 8883
docker-compose.yml Configurare Servicii Montarea secretelor și expunerea porturilor
server/main.go Backend Implementarea configurației TLS pentru clientul MQTT
scripts/send_image.py Script Python Configurarea contextului SSL/TLS

Cerințe preliminare

  • OpenSSL instalat (brew install openssl pe macOS)
  • Acces la directorul secrets/ din rădăcina proiectului

Pasul 1: Generarea certificatelor

1.1 Crearea Autorității de Certificare (CA)

mkdir -p secrets
cd secrets
 
# Generarea cheii private a CA
openssl genrsa -out ca.key 4096
 
# Generarea certificatului CA (valabil 10 ani)
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
    -subj "/C=RO/ST=Romania/L=Bucharest/O=SS-Web/OU=Security/CN=SS-Web-CA"

1.2 Crearea certificatului de server (pentru brokerul Mosquitto)

# Generarea cheii private a serverului
openssl genrsa -out server.key 2048
 
# Generarea cererii de semnare a certificatului de server (CSR)
openssl req -new -key server.key -out server.csr \
    -subj "/C=RO/ST=Romania/L=Bucharest/O=SS-Web/OU=Broker/CN=broker"
 
# Semnarea certificatului de server cu CA (valabil 1 an)
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out server.crt
 
# Curățare CSR
rm server.csr

1.3 Crearea certificatului de client (pentru API-ul Go și scripturile Python)

# Generarea cheii private a clientului
openssl genrsa -out web.key 2048
 
# Generarea cererii de semnare a certificatului de client (CSR)
openssl req -new -key web.key -out web.csr \
    -subj "/C=RO/ST=Romania/L=Bucharest/O=SS-Web/OU=WebClient/CN=web"
 
# Semnarea certificatului de client cu CA (valabil 1 an)
openssl x509 -req -days 365 -in web.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out web.crt
 
# Curățare CSR
rm web.csr

1.4 Verificarea certificatelor

# Verificarea certificatului CA
openssl x509 -in ca.crt -text -noout
 
# Verificarea certificatului de server
openssl verify -CAfile ca.crt server.crt
 
# Verificarea certificatului de client
openssl verify -CAfile ca.crt web.crt

Pasul 2: Configurarea brokerului Mosquitto

Editați broker/mosquitto.conf pentru a adăuga listener-ul securizat:

mosquitto.conf
# MQTT simplu (doar pentru dezvoltare - dezactivați în producție)
listener 1883
allow_anonymous true
 
# MQTT securizat cu mTLS
listener 8883
cafile /run/secrets/ca.crt
certfile /run/secrets/server.crt
keyfile /run/secrets/server.key
require_certificate true
use_subject_as_username true
allow_anonymous true
 
# Logare
log_type all
connection_messages true
log_timestamp true

Explicarea setărilor cheie:

  • cafile: Certificatul CA pentru verificarea certificatelor clienților
  • certfile/keyfile: Certificatul propriu al serverului și cheia privată
  • require_certificate true: Activează mTLS - clienții trebuie să prezinte un certificat valid
  • use_subject_as_username true: Folosește CN-ul certificatului ca nume de utilizator MQTT

Pasul 3: Configurarea Docker Compose

Actualizați docker-compose.yml pentru a monta secretele:

docker-compose.yml
services:
  go-api:
    # ... alte configurări ...
    secrets:
      - ca.crt
      - web.crt
      - web.key

  broker:
    # ... alte configurări ...
    ports:
      - "8883:8883"  # MQTT securizat
      - "1883:1883"  # MQTT simplu (dezactivați în producție)
    secrets:
      - ca.crt
      - server.crt
      - server.key

secrets:
  ca.crt:
    file: ./secrets/ca.crt
  web.crt:
    file: ./secrets/web.crt
  web.key:
    file: ./secrets/web.key
  server.crt:
    file: ./secrets/server.crt
  server.key:
    file: ./secrets/server.key

Pasul 4: Configurarea serverului Go

Actualizați server/main.go pentru a folosi TLS:

import (
    "crypto/tls"
    "crypto/x509"
    "os"
)
 
func NewTLSConfig() *tls.Config {
    // Încărcarea certificatului CA
    certpool := x509.NewCertPool()
    pemCerts, err := os.ReadFile("/run/secrets/ca.crt")
    if err != nil {
        panic(err)
    }
    certpool.AppendCertsFromPEM(pemCerts)
 
    // Încărcarea certificatului de client
    cert, err := tls.LoadX509KeyPair("/run/secrets/web.crt", "/run/secrets/web.key")
    if err != nil {
        panic(err)
    }
 
    return &tls.Config{
        RootCAs:            certpool,
        ClientCAs:          certpool,
        Certificates:       []tls.Certificate{cert},
        InsecureSkipVerify: false,
    }
}
 
func main() {
    // ... configurare MongoDB ...
 
    tlsconfig := NewTLSConfig()
 
    opts := mqtt.NewClientOptions()
    opts.AddBroker("ssl://broker:8883")
    opts.SetClientID("web").SetTLSConfig(tlsconfig)
 
    // ... restul codului ...
}

Pasul 5: Configurarea scripturilor Python

Actualizați scripturile Python pentru a folosi TLS:

import ssl
 
# Configurare
PORT = 8883  # Port securizat
 
# Căile către certificate
SECRETS_DIR = os.path.join(PROJECT_ROOT, "secrets")
CA_CRT = os.path.join(SECRETS_DIR, "ca.crt")
CLIENT_CRT = os.path.join(SECRETS_DIR, "web.crt")
CLIENT_KEY = os.path.join(SECRETS_DIR, "web.key")
 
# Crearea clientului MQTT
client = mqtt.Client(client_id="device-id")
 
# Configurarea TLS
client.tls_set(
    ca_certs=CA_CRT,
    certfile=CLIENT_CRT,
    keyfile=CLIENT_KEY,
    tls_version=ssl.PROTOCOL_TLSv1_2
)
# Omiterea verificării hostname-ului pentru testarea locală
client.tls_insecure_set(True)
 
# Conectare
client.connect(BROKER, PORT, 60)

Pasul 6: Testarea conexiunii

  • Porniți serviciile:
docker compose up -d
  • Testați conexiunea:
python3 scripts/send_image.py
  • Verificați log-urile brokerului:
docker logs broker

Depanare

Verificarea certificatului a eșuat

  • Asigurați-vă că toate certificatele sunt semnate de același CA
  • Verificați datele de expirare:
openssl x509 -in cert.crt -noout -dates

Conexiune refuzată pe portul 8883

  • Verificați dacă brokerul ascultă:
docker logs broker
  • Verificați setările firewall-ului

Verificarea hostname-ului a eșuat

  • Pentru testare locală, folosiți client.tls_insecure_set(True)
  • Pentru producție, asigurați-vă că CN-ul certificatului corespunde hostname-ului

Bune practici de securitate

  1. Nu comiteți niciodată certificate în git — Adăugați secrets/ în .gitignore
  2. Folosiți certificate cu durată scurtă de viață — Schimbați-le periodic
  3. Dezactivați MQTT simplu în producție — Eliminați listener-ul pe portul 1883
  4. Folosiți dimensiuni mari ale cheilor — 4096 biți pentru CA, minim 2048 biți pentru server/client
  5. Stocați cheile private în siguranță — Folosiți Docker secrets sau variabile de mediu

Lista de verificare a fișierelor

După implementare, directorul secrets/ ar trebui să conțină:

secrets/
├── ca.crt
├── ca.key
├── server.crt
├── server.key
├── web.crt
└── web.key
ss/laboratoare/07.txt · Last modified: 2026/04/20 16:55 by ciprian.popescu0411
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0