Киберзащита за малкия бизнес (част 2): защитен сървър зад рутера

Тази статия е продължение на инициативата ни за защита на малките и средните предприятия в България. В първата част превърнахме един обикновен офис рутер в напълно защитена входна точка — с IPS, IDS, защита срещу brute-force, blacklist, anti-spoofing и anti-DDoS. Сега идва следващата логична стъпка: сървърът зад този рутер.
Защото защитеният рутер е само половината от историята. Зад него обикновено стои машина, която реално пази данните на фирмата — файлове, база данни, поща. И тук е първият урок, който ще повтаряме през цялата статия:
Зад защитен рутер не значи защитен сървър.
В тази (втора) част изграждаме сигурната основа на сървъра. В следващата (трета) част ще качим върху нея реално приложение — частен облак (Nextcloud) със собствено съхранение и валиден SSL сертификат. Всички IP адреси и имена в примерите са генерализирани от съображения за сигурност — заменете ги с вашите.
Защо собствен облак
Все повече фирми държат файловете и календарите си в чужди облачни услуги. Удобно е — до момента, в който се замислите къде точно са данните ви, кой има достъп до тях и какво ще стане при увеличение на цената или спиране на услугата. За бизнес, който обработва лични данни, въпросът е и юридически: GDPR и новата директива NIS2 поставят отговорността върху вас.
Частен облак на собствен сървър връща контрола: данните са физически при вас, достъпът е изцяло във ваши ръце, а разходът е еднократен — хардуер, който и без това често стои в офиса. Целта на тази серия е да покажем, че това е напълно постижимо и за малка фирма.
Изходна точка: одит преди действие
Сървърът е машина с Ubuntu 26.04 LTS, достатъчно RAM и процесорни ядра и голям дисков масив за данните. Рутерът вече пренасочва (port-forward) портове 22, 80 и 443 към него, а публичното име oblak.firma.bg сочи към публичния адрес на офиса.
Първото правило при всяка такава задача: първо одит, после действие. Какво слуша, какво е изложено, какво липсва:
ss -tulnp # кои услуги слушат и на кои портове ufw status # има ли локална защитна стена? systemctl is-active fail2ban sshd -T | grep -Ei "passwordauthentication|permitrootlogin"
Резултатът беше показателен:
- Слушаше само SSH (порт 22) — дотук добре.
- UFW: неактивен. Никаква локална филтрация.
- fail2ban: не е инсталиран.
- SSH с паролна автентикация — включена, а портът е изложен към целия интернет.
С други думи: вратата за отдалечен достъп беше широко отворена към света, с пароли и без никаква защита срещу налучкване. Точно каквото ботовете обичат. Когато по-късно включихме fail2ban, само за минути той вече беше регистрирал реални опити за пробив отвън — заплахата не е теоретична, тя е денонощна.
⚠️ Стъпка 1: fail2ban и защита на SSH — преди всичко друго
Приоритет номер едно е да затворим най-голямата дупка — изложения SSH. Инсталираме fail2ban:
sudo apt update sudo apt install -y fail2ban
Сега най-важният детайл, който мнозина пропускат. fail2ban банва IP адреси след определен брой неуспешни опити. Но ако управлявате сървъра отдалечено, лесно можете да забраните сами себе си. Затова първото нещо в конфигурацията е „белият списък“ с доверените мрежи.
Създаваме /etc/fail2ban/jail.local:
[DEFAULT] # Никога не банвай нашите доверени мрежи (управление + локална мрежа) + localhost ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 198.51.100.0/24 backend = systemd findtime = 10m maxretry = 4 # Нарастващ бан: 1 час база, удвоява се при рецидив, таван 1 седмица bantime = 1h bantime.increment = true bantime.factor = 2 bantime.maxtime = 1w [sshd] enabled = true port = 22
Защо изглежда точно така:
ignoreipвключва нашата мрежа за управление (198.51.100.0/24) и локалната мрежа. Това е спасителният колан срещу самозаключване — направете го преди да включите услугата.maxretry = 4за 10 минути е достатъчно строго срещу ботове, но прощаващо за човек, който сбърка паролата веднъж-дваж.- Нарастващият бан (
bantime.increment) е елегантен: упорит нападател получава все по-дълги наказания (1ч → 2ч → 4ч … до седмица), докато случайна грешка коства само час.
Включваме и проверяваме:
sudo systemctl enable --now fail2ban sudo fail2ban-client status sshd
Готово — изложеният SSH вече има пазач. Едва сега продължаваме нататък. Подредбата не е случайна: винаги затваряйте най-голямата дупка, преди да добавяте нови услуги.
Стъпка 2: стекът — Apache, PHP, MariaDB, Redis
За частен облак ни трябват уеб сървър, PHP, база данни и кеш. Избрахме комбинация, която е едновременно стабилна, бърза и добре документирана:
| Компонент | Избор | Защо |
|---|---|---|
| Уеб сървър | Apache 2.4 (MPM event) | Зрял и предсказуем; работи „извън кутията“ с приложения, които разчитат на .htaccess |
| PHP | PHP 8.5 през FPM | Родната версия на Ubuntu 26.04; FPM е по-бърз и изолиран от уеб сървъра |
| База данни | MariaDB 11.8 | Стандартът за този тип приложения, отлична поддръжка |
| Кеш / заключване | Redis | Памет-кеш и заключване на файлове при едновременен достъп (file locking) |
Инсталираме всичко наведнъж, заедно с нужните PHP разширения:
sudo apt install -y \ apache2 mariadb-server redis-server \ php8.5-fpm php8.5-cli php8.5-gd php8.5-mysql php8.5-curl php8.5-mbstring \ php8.5-intl php8.5-bcmath php8.5-gmp php8.5-zip php8.5-xml php8.5-apcu \ php8.5-redis php8.5-imagick imagemagick
Свързваме Apache с PHP-FPM и включваме нужните модули:
sudo a2enmod proxy_fcgi setenvif rewrite headers env mime dir ssl http2 sudo a2enconf php8.5-fpm sudo systemctl restart php8.5-fpm apache2
Настройки на PHP за реална работа
Стойностите по подразбиране в PHP са консервативни. За приложение, през което ще минават големи файлове, ги вдигаме чрез отделен файл — например /etc/php/8.5/fpm/conf.d/99-app.ini (същото и за cli):
memory_limit = 1G upload_max_filesize = 16G post_max_size = 16G max_execution_time = 3600 date.timezone = Europe/Sofia ; OPcache — съществено за производителност opcache.enable = 1 opcache.enable_cli = 1 opcache.interned_strings_buffer = 16 opcache.max_accelerated_files = 10000 opcache.memory_consumption = 256 opcache.revalidate_freq = 60 ; APCu в командния ред (нужно за фоновите задачи) apc.enable_cli = 1
Малък, но коварен детайл: apc.enable_cli = 1. Без него фоновите задачи, които се пускат от командния ред, не виждат кеша и приложението започва да се оплаква в проверките си. Лесно за пропускане, досадно за дебъгване.
Стъпка 3: база данни с правилните настройки
MariaDB на Ubuntu по подразбиране пуска root през Unix socket — тоест sudo mariadb работи без парола. Създаваме отделна база и потребител само за приложението (принцип на най-малката привилегия — приложението никога не бива да ползва root):
CREATE DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY 'СИЛНА_ПАРОЛА'; GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'localhost'; FLUSH PRIVILEGES;
Добавяме и няколко настройки в /etc/mysql/mariadb.conf.d/60-app.cnf, които приложението очаква:
[mysqld] transaction_isolation = READ-COMMITTED binlog_format = ROW innodb_file_per_table = 1 innodb_buffer_pool_size = 2G
READ-COMMITTED е важна — много приложения (включително Nextcloud) изрично я препоръчват, за да избегнат ненужни заключвания при едновременен достъп от много потребители.
Какво постигнахме дотук
Сървърът вече има:
- ✅ fail2ban с пазач за SSH и — критично — бял списък, който не ни заключва.
- ✅ Стабилен, бърз стек: Apache + PHP 8.5-FPM + MariaDB + Redis.
- ✅ Отделна база с минимални права и правилни настройки.
Това е здравата основа. Все още нямаме приложение, нито SSL, нито защита на самото приложение — точно те идват в третата част, където качваме реален частен облак: Nextcloud със собствено съхранение на голям дисков масив, валиден Let’s Encrypt сертификат, защита на приложението с fail2ban и hairpin NAT на рутера, за да работи публичното име и от вътрешната мрежа.
Тази серия е част от усилията ни сериозната киберзащита да стане достъпна за българския малък и среден бизнес.