Ghid de securitate · Moldova

Cum securizez baza de date PostgreSQL sau MySQL în producție?

Baza de date ține datele clienților, comenzile și facturile pe care le raportezi la SFS. O bază expusă pe internet, cu parola de la instalare, e cel mai scurt drum către o notificare la CNPDCP și o discuție neplăcută cu clientul din UE.

Actualizat la

Răspuns scurt

  1. Securizezi baza de date PostgreSQL sau MySQL în producție punând-o să asculte doar pe localhost sau pe rețeaua privată, niciodată pe adresa publică.
  2. Folosești autentificare scram-sha-256 în pg_hba.conf, caching_sha2_password în MySQL 8 sau ed25519 în MariaDB, și ștergi orice cont root sau postgres accesibil de la distanță.
  3. Creezi câte un rol pe aplicație, cu drepturi doar pe tabelele de care are nevoie, și separi rolul de migrare de rolul de rulare.
  4. Criptezi conexiunea aplicație–bază cu TLS chiar și în rețeaua privată și ții parolele într-un manager de secrete, nu în cod.
  5. Faci backup logic zilnic plus arhivare continuă a WAL pentru restaurare la un moment dat și testezi lunar.
PostgreSQL: unde ascultă
listen_addresses = 'localhost' sau IP-ul privat
PostgreSQL: metoda de autentificare
scram-sha-256, nu md5 și nu trust
MySQL: legare și conturi
bind-address = 127.0.0.1; fără 'root'@'%'
Restaurare la un moment dat
pgBackRest sau WAL-G; mysqlbinlog pentru MySQL

Prima linie: baza nu se vede din internet

Cele mai multe baze de date compromise nu au fost sparte, ci găsite. Un PostgreSQL pe 5432 sau un MySQL pe 3306 deschis către lume primește încercări de autentificare la câteva minute după pornire. Baza ascultă pe localhost dacă aplicația e pe același server, altfel pe adresa din rețeaua privată. Firewall-ul blochează portul dinspre exterior, ca a doua plasă, iar administratorul intră prin SSH sau VPN.

Roluri mici, parole bune, conexiuni criptate

Aplicația nu are nevoie de superuser. Creează un rol de rulare cu SELECT, INSERT, UPDATE și DELETE pe schema ei și unul separat pentru migrări, folosit doar din pipeline. Un SQL injection dintr-un formular rămâne atunci limitat la tabelele aplicației, nu la toată instanța. Parolele lungi, generate, stau într-un manager de secrete. TLS între aplicație și bază pare exagerat în rețeaua privată, dar acoperă un vecin compromis pe același switch.

  • rol per aplicație, fără SUPERUSER și fără CREATEDB
  • rol de migrare separat, folosit doar din CI
  • pg_hba.conf cu hostssl și scram-sha-256
  • MySQL: REQUIRE SSL pe conturile aplicației

Backup care se poate restaura

Un dump zilnic pierde până la 24 de ore de date: pentru un magazin din Chișinău, comenzi pierdute și facturi de refăcut. Arhivarea continuă a WAL în PostgreSQL, cu pgBackRest sau WAL-G, permite restaurarea la orice minut, de pildă dinaintea unui DELETE greșit; în MySQL, jurnalul binar face același lucru. Backupul pleacă criptat de pe server, iar restaurarea se repetă lunar pe o mașină curată.

Datele personale și obligațiile din Moldova

Baza unui magazin, a unei clinici sau a unei firme de outsourcing conține date cu caracter personal. Legea nr. 195/2024, în vigoare din 23 august 2026, cere măsuri tehnice și organizatorice adecvate riscului și notificarea CNPDCP la o încălcare a securității, fără întârziere nejustificată și, unde e posibil, în cel mult 72 de ore. Clienții din UE cer prin contractul de prelucrare criptare, control al accesului și jurnalizare; rolurile și jurnalul de conexiuni sunt dovada.

Setări de securitate pentru PostgreSQL și MySQL în producție
AspectPostgreSQLMySQL / MariaDBCe previne
Unde ascultălisten_addresses = 'localhost' sau IP privatbind-address = 127.0.0.1 sau IP privatdescoperirea bazei din internet
Autentificarescram-sha-256 în pg_hba.confMySQL 8: caching_sha2_password (implicit); MariaDB: ed25519 sau mysql_native_passwordatacuri pe hash-uri slabe
Conturi privilegiatepostgres doar local, prin peerfără 'root'@'%'acces administrativ de la distanță
Criptare în tranzithostssl + ssl = onrequire_secure_transport = ONinterceptare în rețea
Restaurare la momentarhivare WAL cu pgBackRest / WAL-Gbinlog + mysqlbinlogpierderea unei zile de date

Comenzi și configurări

PostgreSQL: rol de aplicație cu drepturi minime
CREATE ROLE magazin_app LOGIN PASSWORD 'parola-lunga-generata';
GRANT CONNECT ON DATABASE magazin TO magazin_app;
GRANT USAGE ON SCHEMA public TO magazin_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO magazin_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO magazin_app;
pg_hba.conf: doar local și doar criptat, cu scram
# TYPE  DATABASE  USER         ADDRESS        METHOD
local   all       postgres                    peer
hostssl magazin   magazin_app  10.10.0.0/24   scram-sha-256
host    all       all          0.0.0.0/0      reject
# în postgresql.conf: password_encryption = scram-sha-256, ssl = on
MySQL: legare locală și cont fără acces de la distanță
# /etc/mysql/mysql.conf.d/mysqld.cnf
# aplicația pe ACELAȘI server: bind-address = 127.0.0.1
# aplicația pe ALT nod: bind-address = IP-ul din rețeaua privată (exemplul de mai jos)
bind-address = 10.10.0.10
require_secure_transport = ON

-- în consolă
DROP USER IF EXISTS 'root'@'%';
-- MySQL 8:
CREATE USER 'magazin_app'@'10.10.0.%' IDENTIFIED WITH caching_sha2_password BY 'parola-lunga-generata' REQUIRE SSL;
-- MariaDB nu are caching_sha2_password:
-- INSTALL SONAME 'auth_ed25519';
-- CREATE USER 'magazin_app'@'10.10.0.%' IDENTIFIED VIA ed25519 USING PASSWORD('parola-lunga-generata') REQUIRE SSL;
GRANT SELECT, INSERT, UPDATE, DELETE ON magazin.* TO 'magazin_app'@'10.10.0.%';

Exemple din practică

Clinică privată din Chișinău, programări online

MySQL asculta pe toate interfețele, cu root accesibil de oriunde, fiindcă dezvoltatorul se conecta de acasă. După legarea pe localhost, tunel SSH și un cont dedicat aplicației, încercările de autentificare din jurnal au dispărut.

Outsourcing din Bălți, PostgreSQL pentru un client olandez

Contractul de prelucrare cerea criptare în tranzit și restaurare la un moment dat. Echipa a trecut pe hostssl cu scram-sha-256 și pgBackRest cu arhivare WAL într-un bucket separat. Testul lunar de restaurare e acum o linie în raportul către client.

Retailer din Cahul, ERP pe server dedicat

Aplicația folosea contul postgres, superuser, pentru tot, iar un plugin de raportare defect a putut citi tabelele de salarii. Acum fiecare modul are rolul lui, iar rapoartele rulează pe o replică de citire, doar pe schema de vânzări.

Greșeli frecvente

  • Lași listen_addresses = '*' sau bind-address = 0.0.0.0 fiindcă „firewall-ul oprește oricum”, dezactivat apoi la un restart.
  • Aplicația se conectează ca postgres sau root, deci orice defect din cod dă control total pe instanță.
  • Ții parola bazei în fișierul de configurare comis în Git, alături de codul aplicației.
  • Ai backup zilnic, dar nu ai încercat niciodată să-l restaurezi și nu știi cât durează.
  • Păstrezi md5 sau trust în pg_hba.conf, moștenite din instalarea inițială.

Cum te ajută 4hosting

  • PostgreSQL & ClickHouse proiectează replicarea, backupul PITR și tuningul bazei pe VPS-urile și serverele dedicate 4hosting.
  • Hardening & Compliance verifică accesul, secretele și cheile, cu raport de anexat la contractul de prelucrare cu clientul din UE.
  • Orele de DevOps incluse (1–8 lunar la VPS, 10 la dedicate și GPU) configurează pgBackRest sau arhivarea binlog și testul lunar de restaurare; le ceri din panoul de client; orele se consumă în luna calendaristică, fără reportare.
  • Datacentere în UE, la Frankfurt, cu DPA conform articolului 28 GDPR; factură în euro.

Întrebări conexe

  • Trebuie să criptez și discul pe care stă baza de date?

    Criptarea la repaus acoperă furtul fizic al discului sau un snapshot copiat. Pe un VPS sau server dedicat în datacenter, riscul principal rămâne accesul logic, deci prioritatea sunt rețeaua, rolurile și backupul. Criptarea discului se adaugă după, mai ales dacă o cere contractul.

  • Pot lăsa phpMyAdmin sau pgAdmin pe server pentru administrare?

    Doar în spatele VPN-ului sau al unui tunel SSH, niciodată pe un URL public. Panourile web de administrare sunt printre primele ținte scanate, iar un phpMyAdmin vechi a cauzat multe compromiteri. Alternativa e clientul local, prin tunel.

Cere o verificare de securitate

Acest ghid adună într-un singur loc măsurile care contează pentru un server de producție al unei firme din Moldova: de la cheia SSH până la copia de backup pe care nimeni nu o poate șterge. Fiecare capitol trimite la o pagină de întrebare cu pași, comenzi și exemple. Este scris pentru echipe care livrează clienților din UE, raportează la instituții locale sau vând online și nu își permit o zi de indisponibilitate.