Świeżo uruchomiony serwer VPS po podłączeniu do Internetu bardzo szybko staje się celem automatycznych skanerów, botnetów oraz prób brute-force. Dlatego jego zabezpieczenie nie może być traktowane jako kosmetyczny dodatek, lecz jako podstawowy etap wdrożenia infrastruktury. Poniżej przedstawiono spójne, krok po kroku, podejście do zabezpieczania nowego VPS, którego filarami są aktualizacje systemu, twardnienie dostępu SSH, poprawna konfiguracja zapory sieciowej oraz włączenie Fail2ban. Omówiono zarówno narzędzia wysokiego poziomu (UFW, firewalld), jak i konfigurację niższego poziomu opartą o iptables lub nftables, wraz z przykładami reguł chroniących SSH, HTTP/HTTPS oraz wrażliwe usługi, przy jednoczesnym zachowaniu dostępności serwera dla uprawnionych administratorów. Pokazano też, jak logicznie połączyć konfigurację SSH, firewalla i Fail2ban w jeden mechanizm obronny. SSH ogranicza wektor ataku poprzez klucze i wyłączenie haseł, firewall redukuje powierzchnię ekspozycji, a Fail2ban reaguje na próby włamania.
Filarami skutecznego startu bezpieczeństwa nowego VPS są:
- aktualizacje systemu – bieżące łatki oraz automatyzacja poprawek bezpieczeństwa;
- zabezpieczenie SSH – logowanie kluczami, wyłączenie haseł i dostępu root, opcjonalna zmiana portu;
- zapora sieciowa – domyślne blokowanie ruchu przychodzącego i selektywne otwarcia dla SSH/HTTP/HTTPS;
- Fail2ban – dynamiczne blokowanie źródeł nadużyć na podstawie logów.
Kontekst bezpieczeństwa świeżego serwera VPS
Charakterystyka zagrożeń dla nowego VPS
Bezpieczeństwo świeżego VPS warto zacząć od zrozumienia, jak wygląda jego ekspozycja zaraz po uruchomieniu i przypisaniu publicznego adresu IP. Już w ciągu kilku minut od podłączenia do sieci serwer jest typowo skanowany przez boty poszukujące otwartych portów, w szczególności SSH na porcie 22, HTTP/HTTPS, a także popularne porty paneli administracyjnych i baz danych. Boty te działają masowo, próbując wykorzystać znane podatności, słabe hasła lub domyślne konfiguracje usług. Kluczowy wniosek: ataki następują automatycznie i niezależnie od tego, czy serwer jest ważny, czy testowy – pierwsze minuty i godziny działania VPS są krytyczne.
Z tego powodu duzi dostawcy infrastruktury zalecają, aby zabezpieczanie VPS rozpocząć natychmiast po pierwszym zalogowaniu: aktualizacja systemu, utworzenie użytkownika z ograniczonymi uprawnieniami, skonfigurowanie klucza SSH oraz zapory sieciowej to niezbędne minimum.
Współczesne zagrożenia obejmują też skanery aplikacyjne szukające plików konfiguracyjnych (np. .env) czy paneli administracyjnych CMS-ów. Fail2ban z filtrami dla Nginx oraz WordPress wykrywa charakterystyczne wzorce ruchu generowanego przez popularne skanery (sqlmap, nikto, masscan, nmap, wpscan) i automatycznie blokuje adresy IP. Ochrona warstwy transportowej (firewall, SSH) jest konieczna, ale niewystarczająca – trzeba również brać pod uwagę warstwę aplikacyjną i logikę ruchu HTTP/HTTPS. Dlatego w tym artykule firewall, SSH i Fail2ban są traktowane jako elementy jednego systemu obronnego.
Nie wolno też zapominać o czynniku ludzkim i operacyjnym. Błędna konfiguracja firewalla może doprowadzić do utraty dostępu do VPS, jeśli administrator włączy zaporę bez wcześniejszego zezwolenia na SSH. Dobra praktyka: utrzymuj drugą, zapasową sesję SSH oraz możliwość awaryjnego dostępu konsolowego w panelu dostawcy VPS, aby w razie błędu móc przywrócić działanie serwera. Zabezpieczenie świeżego VPS to element szerszego procesu, który obejmuje plan awaryjny, dokumentowanie zmian i ich weryfikację po każdej modyfikacji.
Model zagrożeń i założenia projektowe
Przyjmujemy, że serwer znajduje się w nieufnym środowisku publicznego Internetu, gdzie atakujący może wykonywać nieograniczone skany portów, inicjować wiele jednoczesnych prób logowania oraz wykorzystywać znane podatności. Administrator działa z zaufanego komputera lokalnego, gdzie generuje parę kluczy SSH i bezpiecznie przechowuje klucz prywatny.
Po stronie serwera SSH włączona jest wyłącznie autoryzacja kluczem publicznym, a logowanie za pomocą hasła jest całkowicie wyłączone. Bezpośredni dostęp użytkownika root przez SSH zostaje zablokowany, a administracja odbywa się z konta bez uprawnień najwyższego poziomu z użyciem sudo. Zmiana portu SSH na niestandardowy ogranicza „szum” skanerów, ale nie zastępuje właściwych mechanizmów bezpieczeństwa.
W obszarze firewalla przyjmuje się profil: domyślne odrzucanie wszystkich połączeń przychodzących oraz domyślne zezwalanie na połączenia wychodzące, przy jednoczesnym eksplicytnym zezwoleniu jedynie na niezbędne porty (SSH, HTTP, HTTPS). Wskazane jest limitowanie liczby nowych połączeń na port SSH oraz możliwość blokowania ruchu z wybranych podsieci.
Fail2ban analizuje logi, wykrywa wzorce nadużyć i po przekroczeniu progów automatycznie banuje adresy IP poprzez reguły zapory. To dynamiczna warstwa obrony, która redukuje „szum” w logach oraz ryzyko udanego ataku.
Przygotowanie systemu VPS i podstawowe kroki bezpieczeństwa
Aktualizacja systemu operacyjnego i pakietów
Pierwszym technicznym krokiem po otrzymaniu dostępu do świeżego VPS jest pełna aktualizacja systemu operacyjnego i pakietów. Na Debian/Ubuntu użyj:
sudo apt update && sudo apt upgrade
W środowiskach produkcyjnych można dodać -y, ale na świeżym serwerze warto świadomie potwierdzać zmiany. Na CentOS/Rocky Linux stosuje się sudo yum update lub sudo dnf update.
Szczególnie ważne są aktualizacje „security”. Na Debian/Ubuntu skorzystaj z automatycznych aktualizacji bezpieczeństwa (unattended-upgrades):
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
Włącz automatyczne aktualizacje bezpieczeństwa i zaplanuj politykę restartów usług i jądra.
Tworzenie użytkownika nie-root i zasada najmniejszych uprawnień
Zrezygnuj z pracy bezpośrednio na koncie root i utwórz użytkownika z ograniczonymi uprawnieniami, który korzysta z sudo. Na Debian/Ubuntu wykonaj:
sudo adduser deploy
sudo usermod -aG sudo deploy
su - deploy
Na CentOS/Rocky Linux dodaj użytkownika do właściwych grup i skonfiguruj sudoers. Pilnuj uprawnień katalogu .ssh:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
sudo chown -R adminuser:adminuser ~/.ssh
Zasada najmniejszych uprawnień (least privilege) dotyczy wszystkich kont i usług. Ogranicz dostęp do sudo, przeglądaj konta z wysokim UID, wyłącz nieużywane usługi:
sudo systemctl disable bluetooth
sudo systemctl disable avahi-daemon
sudo systemctl disable cups
Przygotowanie dostępu awaryjnego i weryfikacja stanu początkowego
Przed zmianami w SSH i firewallu przygotuj awaryjny dostęp do serwera i udokumentuj stan początkowy. Otwórz drugą, zapasową sesję SSH, aby w razie błędu móc przywrócić reguły. Zapewnij dostęp do konsoli awaryjnej (VNC/serial) u dostawcy VPS. Przyda się audyt:
sudo ss -tulpen
sudo systemctl --type=service --state=running
getent passwd | awk -F: '$3 >= 1000 {print $1 ":" $7}'
sudo last -a | head
Sprawdź, czy obraz systemowy nie ma już aktywnych narzędzi (np. firewalld, Fail2ban), aby dostosować kolejne kroki.
Twardnienie dostępu SSH na VPS
Generowanie klucza SSH i konfiguracja logowania bezhasłowego
Najważniejszym krokiem jest przejście na logowanie kluczami SSH i całkowite wyłączenie haseł. Klucz generuj na zaufanej maszynie (Ed25519):
ssh-keygen -t ed25519 -C "twoj-email@example.com"
ssh-keygen -t ed25519 -a 64 -f ~/.ssh/hmc-deploy-2026
Skopiuj klucz publiczny na serwer:
ssh-copy-id deploy@twoj-serwer-ip
ssh-copy-id -p 2222 adminuser@twoj-serwer-ip
Lub wykonaj to ręcznie poleceniem:
cat ~/.ssh/id_ed25519.pub | ssh adminuser@your_server_ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Przetestuj logowanie przed wyłączeniem haseł/roota:
ssh adminuser@your_server_ip
ssh -p 2222 adminuser@your_server_ip
Wyłączenie logowania hasłem i blokada dostępu root
Wyłącz logowanie hasłem i bezpośredni dostęp root – to jeden z najsilniejszych środków ochrony przed brute-force. W pliku /etc/ssh/sshd_config ustaw:
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
# opcjonalnie:
# AuthenticationMethods publickey
# KbdInteractiveAuthentication no
Zweryfikuj efektywną konfigurację:
sshd -T | grep permitrootlogin
Zmiana portu SSH i kontrola dostępu wg użytkowników
Zmiana portu zmniejsza „szum” w logach (np. 49152-65535). W sshd_config ustaw nowy port i zrestartuj usługę:
# Port 2222
sudo systemctl restart sshd
Dostosuj klienta i firewall, np. UFW:
sudo ufw allow 2222/tcp
sudo nano /etc/ssh/sshd_config # Port 22 -> Port 2222
sudo systemctl restart sshd
ssh -p 2222 user@server_ip
sudo ufw delete allow ssh
sudo ufw delete allow 22/tcp
Ogranicz logowanie do wybranych użytkowników/grup w sshd_config:
AllowUsers tony alice bob
AllowGroups sshusers administrators
DenyUsers guest test
Logowanie, monitoring i weryfikacja konfiguracji SSH
Sprawdź poprawność konfiguracji przed restartem usługi:
sudo sshd -t
Ustaw szczegółowość logów, aby ułatwić analizę i integrację z Fail2ban:
LogLevel VERBOSE
Regularnie weryfikuj, że logowanie kluczem działa, root nie ma bezpośredniego dostępu, a logowanie hasłem jest wyłączone. Testuj także scenariusze błędnych logowań z konta testowego.
Konfiguracja zapory sieciowej na VPS
Koncepcje bezpieczeństwa zapory – domyślna blokada i jawne zezwolenia
Zapora powinna domyślnie odrzucać połączenia przychodzące i zezwalać na wychodzące, a potrzebne porty należy otwierać eksplicytnie. Typowo: SSH (22 lub niestandardowy), HTTP (80), HTTPS (443). Przed włączeniem zapory bezwzględnie zezwól na ruch SSH (np. sudo ufw allow ssh), aby nie odciąć dostępu. Poniżej omówiono implementacje w UFW, iptables/nftables i firewalld.
UFW na Debian/Ubuntu – konfiguracja podstawowa i rozszerzona
Najpierw zainstaluj UFW i włącz obsługę IPv6 (w pliku /etc/default/ufw ustaw IPV6=yes):
sudo apt update
sudo apt install ufw -y
Wykonaj podstawową konfigurację polityk i portów:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Dodaj limitowanie prób na SSH:
sudo ufw limit ssh
sudo ufw limit 2222/tcp
Przykład ograniczenia dostępu po adresie źródłowym:
sudo ufw allow from 203.0.113.10 to any port 22
Iptables i nftables – konfiguracja ręczna i zaawansowana
Przykładowe reguły iptables z domyślną blokadą przychodzących i otwartymi portami HTTP(S) oraz SSH:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -j DROP
Rate limiting dla SSH, aby zmniejszyć intensywność prób logowania:
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m limit --limit 3/min --limit-burst 5 -j ACCEPT
Utrwal reguły, aby przetrwały restart systemu:
iptables-save > /etc/iptables/rules.v4
nftables – instalacja i aktywacja usługi, wraz z kopią zapasową i weryfikacją konfiguracji:
sudo apt update
sudo apt install -y nftables
sudo systemctl enable --now nftables
sudo systemctl status nftables --no-pager
sudo cp -a /etc/nftables.conf /etc/nftables.conf.bak.$(date +%F)
sudo nft -c -f /etc/nftables.conf
sudo nft -f /etc/nftables.conf
sudo nft list ruleset
Na systemach z firewalld przed migracją do nftables wyłącz firewalld:
sudo systemctl disable --now firewalld
Firewalld na CentOS/Rocky – konfiguracja stref i usług
Zainstaluj i uruchom firewalld, ustawiając strefę domyślną:
sudo dnf install firewalld -y
sudo systemctl start firewalld
sudo systemctl enable firewalld
sudo firewall-cmd --state
sudo firewall-cmd --set-default-zone=public
Otwórz wymagane usługi/porty i sprawdź konfigurację:
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Po zmianie portu SSH (np. na 2222) zaktualizuj reguły:
firewall-cmd --permanent --add-port=2222/tcp
firewall-cmd --permanent --remove-port=22/tcp
firewall-cmd --reload
Fail2ban jako warstwa ochrony przed nadużyciami
Idea działania Fail2ban i jego rola w architekturze bezpieczeństwa
Fail2ban przeszukuje logi, rozpoznaje wzorce nadużyć i automatycznie blokuje źródłowe adresy IP przy użyciu zapory. Działa w oparciu o „jails” zdefiniowane filtrami i akcjami (np. dodanie reguł iptables, modyfikacja firewalld, powiadomienia e-mail). Jest szczególnie skuteczny przeciwko brute-force na SSH oraz przy ochronie warstwy aplikacyjnej (Nginx/WordPress).
Instalacja Fail2ban na Debian/Ubuntu i CentOS/Rocky
Na Debian/Ubuntu zainstaluj i uruchom usługę:
sudo apt install fail2ban -y
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo fail2ban-client ping
sudo systemctl status fail2ban
Na CentOS/Rocky Linux (z repozytorium EPEL i aktualizacją polityk SELinux):
sudo yum install epel-release
sudo yum install fail2ban fail2ban-systemd
sudo yum update -y selinux-policy*
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Konfiguracja bazowa – kopiowanie jail.conf do jail.local
Utwórz lokalny plik konfiguracyjny i edytuj ustawienia:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo -e /etc/fail2ban/jail.local
Przykładowe ustawienia globalne:
[DEFAULT]
ignoreip = 127.0.0.1/8 203.0.113.10
bantime = 3600
findtime = 600
maxretry = 5
Po zmianach przeładuj usługę:
sudo systemctl restart fail2ban
Specyficzne „jails” dla SSH, Nginx i WordPress
Aktywuj ochronę SSH (Debian/Ubuntu – logi w /var/log/auth.log):
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 120
Nginx – prosty filtr na popularne skanery (plik filtra w /etc/fail2ban/filter.d/nginx-secure.conf):
[Definition]
^<HOST> - .* "(?:GET|POST|HEAD|PUT|DELETE|OPTIONS|PATCH|PROPFIND|CONNECT) .*" d{3} .* "(?:[^"]*)" "(?:[^"]*(?:sqlmap|nikto|masscan|zgrab|nmap|acunetix|wpscan|dirbuster|gobuster)[^"]*)" .*
Powiązana definicja „jail” dla Nginx:
[nginx-secure]
enabled = true
port = http,https
filter = nginx-secure
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 300
WordPress (wp-fail2ban – przykładowy filtr) – pobierz filtr do katalogu /etc/fail2ban/filter.d/:
sudo wget https://plugins.svn.wordpress.org/wp-fail2ban/trunk/filters.d/wordpress-hard.conf -O /etc/fail2ban/filter.d/wordpress.conf
Następnie włącz „jail” dla WordPress:
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/auth.log
maxretry = 3
port = http,https
bantime = 300
Po zmianach sprawdź statusy wybranych „jails”:
sudo systemctl restart fail2ban
fail2ban-client status sshd
fail2ban-client status nginx-secure
fail2ban-client status wordpress
Integracja SSH, firewalla i Fail2ban – testy i operacje
Bezpieczna procedura wprowadzania zmian – druga sesja SSH i konsola
Zanim zmienisz reguły zapory lub ustawienia SSH, otwórz drugą, zapasową sesję SSH. Upewnij się też, że masz dostęp do konsoli awaryjnej dostawcy. Dokumentuj zmiany, aby łatwo wycofać błędną konfigurację.
Weryfikacja otwartych portów, aktywnych usług i reguł firewalla
Sprawdź nasłuchujące porty i procesy:
sudo ss -tulpen
Zweryfikuj reguły zapory w używanym narzędziu:
sudo ufw status verbose
sudo nft list ruleset
sudo iptables -L
sudo firewall-cmd --list-all
Wyświetl listę aktywnych usług systemowych:
sudo systemctl --type=service --state=running
Testowanie Fail2ban i analiza logów
Wykonaj podstawową weryfikację działania:
sudo fail2ban-client status
sudo fail2ban-client status sshd
Symuluj podejrzany ruch HTTP (Nginx) i sprawdź reakcję:
for i in 1 2 3 4 5; do curl -I https://twoja-domena.pl/.env; done
fail2ban-client status nginx-secure
W razie potrzeby odblokuj błędnie zbanowane IP:
fail2ban-client set nginx-secure unbanip TWOJE_IP
Analizuj /var/log/fail2ban.log i /var/log/auth.log w poszukiwaniu przyczyn banów i prób nadużyć.
Scenariusze zaawansowane i utrzymanie bezpieczeństwa VPS
Ograniczanie dostępu do SSH po adresach IP i podsieciach
W środowiskach produkcyjnych rozważ ograniczenie dostępu do SSH wyłącznie z wybranych adresów IP lub podsieci. Poniżej przykłady dla UFW:
sudo ufw allow from 203.0.113.10 to any port 22
sudo ufw deny from 198.51.100.0/24
iptables – blokada konkretnego źródła (podmień na właściwy adres):
iptables -A INPUT -s niechciany_adres_ip -j DROP
Pamiętaj o możliwych zmianach adresów administratorów oraz ewentualnym wykorzystaniu VPN. Skonfiguruj też ignoreip w Fail2ban dla zaufanych źródeł.
Sysctl, SELinux i inne mechanizmy twardnienia jądra
Wzmocnij parametry sieci w /etc/sysctl.d/99-security.conf (np. kontrola źródła pakietów, ograniczenia ICMP, ip_forward), a następnie zastosuj zmiany i zweryfikuj wpływ na usługi:
sudo sysctl -p /etc/sysctl.d/99-security.conf
SELinux jako mechanizm Mandatory Access Control może znacząco zwiększyć bezpieczeństwo. Upewnij się, że polityki SELinux nie blokują Fail2ban ani dostępu do logów i modyfikacji reguł zapory.
Automatyczne aktualizacje, kopie zapasowe i audyt bezpieczeństwa
Bezpieczeństwo VPS to proces ciągły, wymagający regularnych aktualizacji, kopii zapasowych i audytów. Na Debian/Ubuntu stosuj unattended-upgrades i zaplanuj restarty. Twórz i testuj kopie zapasowe konfiguracji (np. sshd_config, nftables.conf, jail.local) oraz snapshoty serwera.
Przygotuj prosty skrypt audytowy, który po wdrożeniu lub restarcie sprawdza: sshd -T, ufw status / nft list ruleset, ss -tulpen, fail2ban-client status – to szybki sposób na wykrycie odchyleń od oczekiwanej konfiguracji.
Typowe błędy i sposoby ich uniknięcia
Włączanie firewalla bez zezwolenia na SSH
Włączenie zapory bez wcześniejszego zezwolenia na ruch SSH prowadzi do natychmiastowego odcięcia administratora od serwera. Zawsze dodaj regułę dla portu SSH przed aktywacją zapory i trzymaj otwartą drugą sesję SSH oraz przygotowaną konsolę awaryjną.
Pozostawienie logowania hasłem i dostępu root
Pozostawienie aktywnego logowania hasłem i bezpośredniego SSH dla roota naraża serwer na masowe ataki brute-force. Traktuj PasswordAuthentication no i PermitRootLogin no jako absolutne minimum.
Brak synchronizacji między SSH, firewallem i Fail2ban
Zmiany w jednym komponencie wymagają natychmiastowej aktualizacji pozostałych. Po zmianie portu w sshd_config zaktualizuj firewall i upewnij się, że „jail” w Fail2ban używa port = ssh zamiast sztywnego numeru.
Niedocenianie roli logów i audytu
Niski poziom logowania i brak audytu utrudniają analizę incydentów i wykrywanie odchyleń. Ustaw LogLevel VERBOSE w SSH, regularnie przeglądaj /var/log/auth.log i /var/log/fail2ban.log, korzystaj ze skryptów audytowych.
Artykuł sponsorowany.



