În cadrul acestui laborator ne vom axa pe implementarea securității Mutual TLS (mTLS) pentru comunicația MQTT din cadrul aplicației web.
Mutual TLS (mTLS) este un mecanism de autentificare bidirecțională în care:
Acest lucru asigură că:
| 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 |
brew install openssl pe macOS)secrets/ din rădăcina proiectuluimkdir -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"
# 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
# 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
# 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
Editați broker/mosquitto.conf pentru a adăuga listener-ul securizat:
# 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țilorcertfile/keyfile: Certificatul propriu al serverului și cheia privatărequire_certificate true: Activează mTLS - clienții trebuie să prezinte un certificat validuse_subject_as_username true: Folosește CN-ul certificatului ca nume de utilizator MQTT
Actualizați docker-compose.yml pentru a monta secretele:
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
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 ... }
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)
docker compose up -d
python3 scripts/send_image.py
docker logs broker
openssl x509 -in cert.crt -noout -dates
docker logs broker
client.tls_insecure_set(True)secrets/ în .gitignore
După implementare, directorul secrets/ ar trebui să conțină:
secrets/ ├── ca.crt ├── ca.key ├── server.crt ├── server.key ├── web.crt └── web.key