Un site care funcționează bine nu este neapărat un site la care nu mai ai nimic de îmbunătățit. Paginile se încarcă, formularele funcționează, vizitatorii își văd de treabă, iar din exterior totul pare în regulă. În spatele site-ului însă există un întreg ecosistem: serverul web, PHP, baza de date, serviciile de administrare, regulile de acces, copiile de siguranță și multe alte componente care pot fi optimizate pe măsură ce tehnologiile și cerințele de securitate evoluează.

Am preluat recent administrarea unui server care găzduia un singur site WordPress. Site-ul era funcțional și stabil, dar configurația serverului fusese realizată cu ceva timp în urmă. Era, așadar, un candidat foarte bun pentru o revizie completă.

Obiectivul nostru a fost simplu: să păstrăm ceea ce funcționa, să reducem suprafața de atac și să folosim mai eficient resursele disponibile.

Am început cu securitatea.

Primul pas nu a fost să instalăm un plugin de cache sau să încercăm să câștigăm câteva milisecunde la încărcarea paginilor. Am început cu lucrurile mai importante: cine poate ajunge la server și ce servicii sunt expuse către internet.

Pagina de autentificare WordPress și zona /wp-admin erau accesibile public. Este configurația obișnuită pentru foarte multe site-uri WordPress, dar în cazul acesta nu era necesar ca întreaga lume să poată ajunge la ele.

Am decis să schimbăm acest lucru.

Am restricționat accesul la administrarea WordPress.

Am limitat accesul la /wp-admin și /wp-login.php la o listă de adrese IP de încredere, direct în nginx.

Orice altă adresă primește un răspuns 403 Forbidden înainte ca solicitarea să ajungă la WordPress sau PHP.

Lista conține adresele fixe de la care se face administrarea, dar exista și o situație mai interesantă: una dintre conexiuni folosește un IP dinamic, care se poate schimba.

Pentru aceasta folosim un nume Dynamic DNS (DDNS). Pe scurt, DDNS permite unui nume de domeniu să indice permanent către IP-ul curent al unei conexiuni, chiar dacă furnizorul de internet schimbă periodic acea adresă.

Un script rulează automat la intervale regulate, verifică adresa IP asociată numelui DDNS și actualizează lista de acces din nginx și regulile firewall-ului atunci când aceasta se schimbă.

În felul acesta, accesul rămâne permis din locația autorizată fără să fie nevoie să modificăm manual configurația de fiecare dată când se schimbă IP-ul.

Efectul asupra securității este important: chiar dacă cineva ar obține numele de utilizator și parola unui administrator WordPress, pagina de autentificare nici măcar nu îi este accesibilă dacă solicitarea nu vine dintr-o locație autorizată.

Atacurile automate de tip brute-force sunt astfel oprite înainte să ajungă la WordPress.

Am redus suprafața de atac WordPress.

Următorul pas a fost să verificăm funcționalitățile WordPress expuse public.

Am dezactivat xmlrpc.php, deoarece site-ul nu avea nevoie de această interfață. XML-RPC poate fi util în anumite scenarii, dar atunci când nu este folosit nu există un motiv bun să rămână disponibil public.

Am dezactivat și posibilitatea de enumerare a utilizatorilor prin REST API, astfel încât lista conturilor WordPress să nu poată fi obținută fără autentificare.

Am eliminat, de asemenea, informațiile inutile despre versiunile software transmise în răspunsurile serverului.

Niciuna dintre aceste măsuri nu reprezintă singură o soluție miraculoasă de securitate. Împreună însă reduc cantitatea de informații și numărul de puncte de acces disponibile unui eventual atacator.

Principiul este simplu: dacă o funcționalitate nu este necesară, nu există niciun motiv să fie expusă către internet.

Acces minim și drepturi minime.

Am continuat cu metodele prin care serverul putea fi administrat.

Accesul FTP a fost eliminat complet. Transferul și administrarea fișierelor se fac acum exclusiv prin SSH.

Autentificarea SSH cu parolă a fost dezactivată, iar accesul se face numai pe bază de chei criptografice.

Am păstrat un singur utilizator pentru administrarea site-ului, cu drepturile strict necesare. Acesta poate administra fișierele site-ului și poate executa operațiunile necesare asupra serviciilor nginx și php-fpm, fără să primească acces inutil la restul sistemului.

Firewall-ul permite accesul la serviciile de administrare numai din rețelele autorizate.

Aceeași regulă este aplicată și pentru phpMyAdmin. Interfața a fost actualizată și poate fi accesată numai din lista de adrese IP de încredere.

Cu alte cuvinte, serviciile care trebuie să fie publice sunt publice. Cele destinate administrării sunt accesibile doar administratorilor.

Am simplificat serverul.

O altă etapă importantă a fost inventarierea serviciilor instalate.

În timp, pe un server se pot acumula componente care au avut cândva un scop, dar care nu mai sunt necesare. Fiecare serviciu suplimentar înseamnă însă actualizări, memorie consumată și încă o componentă care trebuie urmărită din punct de vedere al securității.

Pe acest server rulau mai multe versiuni PHP, deși site-ul folosea una singură.

Am eliminat versiunile care nu mai erau necesare.

Am procedat la fel cu câteva servicii de monitorizare și geolocalizare care nu mai erau utilizate și am eliminat un subdomeniu rămas dintr-o configurație mai veche.

Rezultatul este un server mai simplu: mai puține servicii, mai puține componente de actualizat și o suprafață de atac mai mică.

Am actualizat configurația TLS.

Am revizuit și configurația conexiunilor HTTPS.

Serverul accepta inclusiv protocoale și opțiuni criptografice păstrate pentru compatibilitate cu clienți mai vechi. Pentru acest site nu mai exista însă un motiv real să menținem această compatibilitate.

Am restrâns conexiunile securizate la TLS 1.2 și TLS 1.3 și am actualizat configurația criptografică.

Este un exemplu bun de lucru care trebuie reevaluat periodic: o configurație considerată rezonabilă în urmă cu câțiva ani nu rămâne automat cea mai bună configurație pentru totdeauna.

Abia apoi am trecut la performanță.

După ce am terminat partea de securizare și simplificare a serverului, am trecut la performanță.

Aici am urmărit un principiu la fel de simplu: să evităm munca inutilă.

Am configurat și dimensionat OPcache, astfel încât PHP să poată păstra în memorie codul deja compilat în loc să proceseze aceleași fișiere de la zero pentru fiecare solicitare.

Am ajustat php-fpm în funcție de memoria real disponibilă pe server și de profilul site-ului, astfel încât numărul proceselor PHP să fie suficient pentru trafic fără să consume inutil memoria sistemului.

Am adăugat cache la nivel de server.

Una dintre cele mai eficiente optimizări a fost introducerea unui strat de cache la nivelul serverului web.

Pentru paginile care pot fi servite din cache, nginx poate răspunde direct vizitatorului fără să mai pornească întregul lanț WordPress → PHP → bază de date pentru fiecare accesare.

Diferența este importantă.

În loc ca fiecare solicitare să necesite execuție PHP și interogări către baza de date, o parte semnificativă dintre cereri poate fi rezolvată direct de serverul web.

Asta înseamnă atât timpi de răspuns mai mici, cât și mai puțină încărcare pe procesor și baza de date.

Am optimizat și baza de date.

WordPress depinde foarte mult de baza de date, așa că am revizuit și configurația acesteia.

Am mărit memoria disponibilă pentru cache-ul bazei de date astfel încât informațiile accesate frecvent să poată fi păstrate în RAM, reducând numărul operațiilor pe disc.

Nu este vorba despre a aloca pur și simplu cât mai multă memorie. PHP, baza de date, sistemul de operare și cache-ul serverului web folosesc aceeași resursă.

Important este echilibrul dintre ele.

Am mutat backup-urile în afara zonei publice.

Am verificat și copiile de siguranță.

Site-ul folosea UpdraftPlus, iar arhivele generate erau păstrate într-un director aflat în structura publică WordPress.

Chiar dacă accesul la astfel de fișiere poate fi restricționat prin configurația serverului web, preferăm o regulă mai simplă: dacă un fișier nu trebuie să fie accesibil prin web, atunci nu are ce căuta în directorul public al site-ului.

Am mutat backup-urile într-o zonă separată, inaccesibilă direct prin HTTP.

Astfel, o eventuală eroare de configurare a nginx sau WordPress nu poate transforma accidental o copie de siguranță într-un fișier descărcabil de pe internet.

Același site, un server mai bun.

Din perspectiva vizitatorului, schimbările sunt aproape invizibile.

Site-ul arată exact la fel și face exact ceea ce făcea înainte. În multe situații răspunde însă mai repede.

Diferența importantă este dedesubt.

Suprafața expusă către internet este mai mică. Accesul administrativ este controlat strict. Serviciile inutile au dispărut. Configurația criptografică este actualizată. PHP și baza de date folosesc mai eficient memoria, iar cache-ul reduce considerabil cantitatea de muncă necesară pentru servirea paginilor.

Niciuna dintre aceste modificări nu este spectaculoasă luată separat.

Împreună însă fac diferența dintre simplul fapt că un site „funcționează” și un serviciu de web hosting WordPress administrat activ, în care securitatea și performanța sunt urmărite permanent.

Asta înseamnă web hosting administrat.

La ServerHost, găzduirea web administrată nu înseamnă doar un server pe care este instalat WordPress.

Înseamnă să ne ocupăm de infrastructura din spatele site-ului: securizarea accesului, configurarea serverului web, PHP și baza de date, actualizările componentelor, monitorizarea resurselor, copiile de siguranță și optimizarea performanței.

Pentru că infrastructura se schimbă, software-ul evoluează, iar ceea ce reprezenta o configurație bună acum câțiva ani poate fi îmbunătățit astăzi.

Iar dacă ai deja un site WordPress găzduit pe un server propriu, VPS sau la un alt furnizor, putem prelua administrarea, analiza configurația existentă și identifica ce poate fi îmbunătățit din punct de vedere al securității, performanței și administrării.