Mapa kroków i punkt startowy: co zabezpieczasz i jak to zmierzysz
Minimalna baza przed zmianami
Cel jest prosty: utwardzić serwer WWW na Linuksie bez przestojów i bez niespodzianek. Zanim cokolwiek zmienisz, zbierz krótki obraz stanu. To ułatwi szybkie cofnięcie zmian i jasną ocenę postępów.
Inwentaryzacja:
Domeny i subdomeny, które obsługuje serwer (produkcyjne i testowe).
Wirtualne hosty i stos: Nginx lub Apache, ewentualnie reverse proxy, PHP-FPM, Node.js, Tomcat.
Aktualne certyfikaty: ścieżki plików, terminy wygaśnięcia, czy jest automatyczne odnawianie.
Wersje pakietów: openssl, nginx/apache, php-fpm, systemd, kernel.
System plików aplikacji: katalog główny, prawa dostępu, właściciele, użytkownicy procesów.
Kopia bazy danych oraz uploadów (jeżeli aplikacja je przechowuje lokalnie).
Szybki test odtwarzania na serwerze staging lub w kontenerze.
Okno zmian: kiedy możesz przeładować usługi bez wpływu na użytkowników.
Kryteria sukcesu i narzędzia do pomiaru
Aby nie wpaść w pułapkę „wydaje się bezpieczniej”, przyjmij twarde kryteria gotowości i od razu przygotuj narzędzia do testów.
HTTPS:
Wymuszone przekierowanie HTTP → HTTPS dla wszystkich hostów.
Wynik A lub A+ w testach SSL Labs (min. TLS 1.2, preferowany TLS 1.3).
OCSP stapling aktywny i łańcuch certyfikatów kompletny.
Nagłówki bezpieczeństwa:
Mozilla Observatory na poziomie co najmniej B+, docelowo A- lub A.
Obecne: Strict-Transport-Security, Content-Security-Policy (lub Report-Only podczas wdrożenia), X-Content-Type-Options, Referrer-Policy, Permissions-Policy, X-Frame-Options (lub frame-ancestors w CSP).
Uprawnienia i separacja:
Brak plików/katalogów z uprawnieniami 777/775 zapisywalnych dla „others”.
Usługi www nie działają jako root (wyjątek: procesy master z dropem uprawnień).
Aktualizacje:
Automatyczne aktualizacje bezpieczeństwa włączone.
Plan okna serwisowego dla aktualizacji większych (kernel, OpenSSL, Nginx/Apache).
Kiedy wdrażać, a kiedy uważać
Nie każda zmiana jest neutralna dla aplikacji. Nowa polityka CSP może zablokować skrypty na froncie, a agresywne HSTS zamknie drogę do cofnięcia się na HTTP. Kilka wskazówek:
Wdrażaj w godzinach mniejszego ruchu i miej plan szybkiego powrotu.
CSP najpierw w trybie Report-Only, dopiero potem egzekwowanie.
HSTS preload tylko wtedy, gdy wszystkie subdomeny konsekwentnie wspierają HTTPS.
AppArmor/SELinux aktywuj etapami, z monitorowaniem naruszeń i wyjątków.
Włącz i wymuś HTTPS: certyfikaty, TLS i przekierowania
Kolejność działań
Klient ACME:
Debian/Ubuntu: apt install certbot python3-certbot-nginx lub python3-certbot-apache.
RHEL/Alma/Rocky: dnf install certbot python3-certbot-nginx lub python3-certbot-apache.
Alternatywa bez root: acme.sh (lekki, bez ingerencji w systemowe pakiety).
Prosty scenariusz: po włączeniu CSP obrazki z data: przestały się ładować – dodaj img-src 'self' data:. Jeśli używasz zewnętrznego CDN dla JS, rozszerz script-src o jego domenę lub wprowadź nonce’y.
# Apache – zestaw po dopracowaniu CSP
Header set always Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; img-src 'self' data:; style-src 'self'; script-src 'self'"
Header set always X-Content-Type-Options "nosniff"
Header set always Referrer-Policy "strict-origin-when-cross-origin"
Header set always Permissions-Policy "geolocation=(), microphone=(), camera=()"
# Jeśli nie używasz frame-ancestors w CSP:
Header set always X-Frame-Options "SAMEORIGIN"
# Drobne twardnienia:
Header unset X-Powered-By
Kryterium: po włączeniu sprawdź w devtools (Network → Response Headers), że każdy zasób HTML niesie komplet nagłówków.
Uwaga: nie dubluj tych samych nagłówków w bloku server i w location – w razie konfliktu przeglądarka weźmie ostatnią wartość.
Izolacja origin: COOP/COEP/CORP – kiedy warto, a kiedy uważać
Jeśli aplikacja to SPA/PWA lub przetwarza dane z innych źródeł, rozważ dodatkowe nagłówki zwiększające izolację. Dają realne korzyści, ale potrafią odciąć cross-origin zasoby.
Scenariusz: SSO przez domenę trzecią może wymagać SameSite=None; Secure. Zidentyfikuj te ciasteczka i nadpisuj selektywnie (np. po prefiksie).
Kontrola: w devtools → Application → Cookies sprawdź, czy każdy cookie przenoszący sesję ma Secure/HttpOnly.
Dodatkowe twardnienia serwera
# Nginx
server_tokens off; # nie ujawniaj wersji
autoindex off; # brak listingów katalogów
# Apache
ServerTokens Prod
ServerSignature Off
<Directory "/var/www/example">
Options -Indexes
</Directory>
Po zmianach zrób szybki test: curl -I https://example.com/nieistniejacy – nagłówek „Server” nie powinien zdradzać pełnej wersji, a katalogi nie mogą się listować.
Ogranicz uprawnienia plików, kont i procesów
Krok 1: właścicielstwo i prawa w katalogu aplikacji
Cel: tylko proces aplikacji może pisać, www może czytać, „others” bez zapisu. Zacznij od inwentaryzacji.
# Załóżmy użytkownika 'webapp' i grupę 'www-data' (Debian/Ubuntu) lub 'nginx'/'apache'
chown -R webapp:www-data /var/www/example
# Katalogi 750, pliki 640 (lub 444 dla statycznych niezmiennych)
find /var/www/example -type d -exec chmod 750 {} ;
find /var/www/example -type f -exec chmod 640 {} ;
# Wyszukaj ryzykowne prawa
find /var/www/example -perm -o=w -ls
Jeśli deploy pisze do /var/www/example/storage lub uploads, daj prawa zapisu tylko tam (770) i zachowaj setgid na katalogu, by nowe pliki dziedziczyły grupę: chmod g+s uploads.
Krok 2: serwer www bez uprawnień roota w pracy
Proces master może startować jako root, ale workers muszą spaść do niskoprzywilejowego użytkownika.
# Nginx (globalnie w nginx.conf)
user www-data;
# Apache (domyślnie) – sprawdź:
grep -E 'User|Group' /etc/apache2/apache2.conf /etc/httpd/conf/httpd.conf
PHP-FPM: osobny pool per aplikacja, z własnym user/group. Ogranicz powierzchnię przez listen.mode i katalogi tymczasowe.
Jedna usługa – jeden użytkownik systemowy. Oddzielne katalogi, osobne logi i pule FPM.
Ogranicz metody HTTP na ścieżkach administracyjnych. Prosty przykład:
# Nginx – tylko GET/HEAD/POST dla całej aplikacji
limit_except GET HEAD POST { deny all; }
# Apache – dla /admin/
<Location "/admin">
<LimitExcept GET POST HEAD>
Require all denied
</LimitExcept>
</Location>
Źródło: Pexels | Autor: Pixabay
Krok 4: MAC – AppArmor/SELinux bez szoku
Zacznij w trybie obserwacji, zbierz naruszenia, dopiero potem egzekwuj.
Kryterium: curl -I -L http://www.example.com/test powinno kończyć na https://example.com/test z kodem 200 i bez kolejnych łańcuchów przekierowań.
HSTS – ostrożnie z includeSubDomains i preload
Zacznij od krótkiego TTL, dopiero po tygodniu-dwóch zwiększ do roku. Preload dopiero, gdy wszystkie subdomeny działają na HTTPS.
# Nginx
add_header Strict-Transport-Security "max-age=2592000" always; # 30 dni na start
# docelowo:
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Apache
Header always set Strict-Transport-Security "max-age=2592000"
Kontrola: curl -sI https://example.com | grep -i strict-transport-security – nagłówek ma być na każdej odpowiedzi HTML i 3xx w HTTPS.
Ostrzeżenie: includeSubDomains; preload zablokuje dostęp do dowolnej subdomeny po HTTP. Jeśli masz np. stary panel iot.example.com na http – najpierw go zmigruj.
Źródło: Pexels | Autor: Markus Spiske
OCSP stapling i porządek w łańcuchu certyfikatów
Bez poprawnego łańcucha przeglądarka lubią przedłużać handshake. Włącz stapling i wskaż systemowy store CA.
Typowy problem: brak łańcucha (fullchain). Jeśli widzisz „Verify return code: 21 (unable to verify the first certificate)”, podmień ścieżkę na fullchain.pem.
Kontrola: nft list ruleset – reguły załadowane; z zewnątrz nmap -Pn -p 22,80,443 example.com – 22 otwarty tylko z zaufanych.
Ostrzeżenie: jeśli łączysz się przez VPN/zmienne IP – daj awaryjnie „okno” SSH (np. 1h) z całego świata lub awaryjną konsolę z panelu serwera.
ufw: szybka konfiguracja bez zaskoczeń
Gdy nie chcesz dotykać nftables bezpośrednio, użyj ufw – wystarczy na pojedynczy host.
# IPv6 włączone
sed -i 's/IPV6=.*/IPV6=yes/' /etc/default/ufw
ufw default deny incoming
ufw default allow outgoing
# HTTP/HTTPS dla wszystkich
ufw allow 80/tcp
ufw allow 443/tcp
# SSH tylko z zaufanych (powtórz dla wielu adresów)
ufw allow from 203.0.113.10 to any port 22 proto tcp
# Łagodny rate-limit na SSH
ufw limit 22/tcp
# Włącz i sprawdź
ufw enable
ufw status numbered
Bezpieczne uruchomienie zdalnie: najpierw dodaj regułę dla swojego IP, dopiero potem ufw enable.
Rate limiting: loginy, API i „złe sąsiedztwo”
Blokuj nadużycia jeszcze przed aplikacją. Najpierw na poziomie WWW, precyzyjniej niż firewall.
# Nginx – kolejka żądań per IP dla /login i /api
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=peripconn:10m;
server {
...
location /login {
limit_req zone=perip burst=20 nodelay;
limit_conn peripconn 5;
try_files $uri @app;
}
location /api/ {
limit_req zone=perip burst=50 delay=20;
limit_conn peripconn 20;
try_files $uri @api;
}
}
Ubuntu 24.04 LTS zaskakuje nowymi funkcjonalnościami! Wśród najważniejszych zmian znajdziemy odświeżony interfejs oraz ulepszone narzędzia bezpieczeństwa. Pierwsze wrażenia użytkowników są pozytywne, a system obiecuje płynniejszą pracę. Czas na aktualizację!