0887 371 498 support@itservice-bg.net
29.06.2026 · Самуил Арсов · NIS2, Киберсигурност

Киберзащита за малкия бизнес (част 3): Nextcloud, Let’s Encrypt и hairpin NAT

Това е третата част от ръководството ни за защита на малкия и среден бизнес. Във втората част подготвихме сигурната основа на сървъра: затворихме изложения SSH с fail2ban и изградихме стабилен стек — Apache, PHP 8.5-FPM, MariaDB и Redis. Сега качваме върху тази основа реалното приложение: Nextcloud — частен облак за файлове, календари и контакти, изцяло под наш контрол.

В тази част: сваляне с проверка на автентичността, съхранение на данните върху отделен дисков масив, валиден Let’s Encrypt сертификат, защита на самото приложение с fail2ban и накрая hairpin NAT на рутера, за да работи публичното име и от вътрешната мрежа. Както и в предишните статии, всички адреси и имена са генерализирани.

Защо ръчна инсталация

Nextcloud може да се инсталира по няколко начина — snap пакет, Docker или ръчно от официалния архив. Избрахме ръчната инсталация по три причини: пълен контрол върху това къде се пазят данните (искаме ги на големия дисков масив, не на системния диск), чиста интеграция с fail2ban на самия хост и — не на последно място — защото целта на тази серия е да се разбере какво се случва, а не да се скрие зад черна кутия.

Стъпка 1: сваляне и проверка на автентичността

Никога не разопаковайте сляпо архив, свален от интернет — дори от официален източник. Сваляме архива, контролната сума и подписа, и проверяваме и двете:

cd /tmp
wget https://download.nextcloud.com/server/releases/latest-34.tar.bz2
wget https://download.nextcloud.com/server/releases/latest-34.tar.bz2.sha256
wget https://download.nextcloud.com/server/releases/latest-34.tar.bz2.asc
wget https://nextcloud.com/nextcloud.asc

# 1) контролна сума
sha256sum -c latest-34.tar.bz2.sha256

# 2) GPG подпис срещу официалния ключ на Nextcloud
gpg --import nextcloud.asc
gpg --verify latest-34.tar.bz2.asc latest-34.tar.bz2

Искаме да видим latest-34.tar.bz2: OK и Good signature from "Nextcloud Security". Ако едно от двете не съвпада — спираме. Тази проверка отнема 30 секунди и е разликата между „официален код“ и „нещо, подменено по пътя“.

Стъпка 2: кодът и данните — на различни места

Това е ключово архитектурно решение. Кодът на приложението стои на системния диск, но данните на потребителите ги насочваме към отделния голям дисков масив (в нашия случай монтиран на /mnt/storage). Така файловете на фирмата растат независимо от системата, а бекъпите и поддръжката стават много по-чисти.

# кодът
sudo tar -xjf /tmp/latest-34.tar.bz2 -C /var/www/
sudo chown -R www-data:www-data /var/www/nextcloud

# данните — на отделния масив
sudo mkdir -p /mnt/storage/nextcloud-data
sudo chown -R www-data:www-data /mnt/storage/nextcloud-data
sudo chmod 0770 /mnt/storage/nextcloud-data

Стъпка 3: инсталация през командния ред

Nextcloud има мощен инструмент за администриране — occ. Чрез него инсталираме „на тихо“, като веднага посочваме директорията за данните да е на големия масив:

sudo -u www-data php /var/www/nextcloud/occ maintenance:install \
  --database mysql --database-name nextcloud \
  --database-user nextcloud --database-pass 'СИЛНА_ПАРОЛА' \
  --admin-user admin --admin-pass 'СИЛНА_АДМИН_ПАРОЛА' \
  --data-dir /mnt/storage/nextcloud-data

Резултатът, който чакаме: Nextcloud was successfully installed.

Базови настройки

Сега „представяме“ Nextcloud на света — кои имена са доверени, че работим през HTTPS, и го свързваме с Redis за кеш и заключване:

occ() { sudo -u www-data php /var/www/nextcloud/occ "$@"; }

occ config:system:set trusted_domains 1 --value=oblak.firma.bg
occ config:system:set overwrite.cli.url --value=https://oblak.firma.bg
occ config:system:set overwriteprotocol --value=https
occ config:system:set memcache.local   --value='\OC\Memcache\APCu'
occ config:system:set memcache.locking --value='\OC\Memcache\Redis'
occ config:system:set redis host --value=/run/redis/redis-server.sock
occ config:system:set redis port --value=0 --type=integer
occ config:system:set default_phone_region --value=BG
occ config:system:set default_language --value=bg

За да работи Redis през по-бързия Unix socket, го включваме в /etc/redis/redis.conf и добавяме потребителя на уеб сървъра към групата на Redis:

unixsocket /run/redis/redis-server.sock
unixsocketperm 770
sudo usermod -aG redis www-data
sudo systemctl restart redis-server php8.5-fpm

Стъпка 4: уеб адрес и Let’s Encrypt сертификат

Създаваме виртуален хост за Apache на /etc/apache2/sites-available/nextcloud.conf. Същината: посочваме корена на сайта и насочваме PHP към FPM:

<VirtualHost *:80>
    ServerName oblak.firma.bg
    DocumentRoot /var/www/nextcloud

    <Directory /var/www/nextcloud/>
        Require all granted
        AllowOverride All
        Options FollowSymLinks MultiViews
    </Directory>

    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.5-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>
sudo a2ensite nextcloud
sudo a2dissite 000-default
sudo systemctl reload apache2

Сега идва красивата част. Let’s Encrypt издава безплатни, доверени SSL сертификати, а certbot прави всичко вместо нас — издаване, настройка на Apache и автоматично пренасочване от HTTP към HTTPS:

sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d oblak.firma.bg \
     --non-interactive --agree-tos -m admin@firma.bg --redirect

За да работи това, рутерът трябва вече да пренасочва порт 80 от интернет към сървъра (направихме го в първата статия) — Let’s Encrypt проверява владеенето на домейна именно през него. След няколко секунди имаме валиден сертификат и работещо HTTPS. Добавяме и HSTS заглавка в SSL хоста, за да „заключим“ браузърите към криптирана връзка:

Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"

Сертификатите на Let’s Encrypt са валидни 90 дни, но certbot ги подновява автоматично. Проверяваме, че това наистина работи, преди да сме забравили за него:

sudo certbot renew --dry-run

Стъпка 5: фонови задачи

Nextcloud има вътрешни задачи за поддръжка (чистене, известия, индексиране). Препоръчаният начин е чрез системния cron, на всеки 5 минути:

occ background:cron
# в crontab на потребителя www-data:
*/5 * * * * php -f /var/www/nextcloud/cron.php

Стъпка 6: защита на самото приложение с fail2ban

В първата част защитихме SSH. Сега правим същото за уеб приложението — защото публикуван облак неминуемо ще бъде атакуван с налучкване на пароли. Добавяме филтър, който разпознава неуспешните входове в дневника на Nextcloud, и нов „jail“.

Филтър /etc/fail2ban/filter.d/nextcloud.conf:

[Definition]
_groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)
failregex = ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
            ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%dT%%H:%%M:%%S%%z"

И секцията в /etc/fail2ban/jail.local — обърнете внимание, че логът се чете от масива с данните:

[nextcloud]
enabled  = true
port     = 80,443
protocol = tcp
filter   = nextcloud
logpath  = /mnt/storage/nextcloud-data/nextcloud.log
maxretry = 4

Един важен детайл, който често обърква хората. Целият трафик от интернет влиза през рутера с пренасочване (NAT), но при правилно настроен port-forward сървърът вижда реалния IP адрес на нападателя, а не адреса на рутера. Затова fail2ban банва точните адреси. Преди да включите jail-а, винаги проверявайте филтъра срещу реален запис в лога:

sudo fail2ban-regex /mnt/storage/nextcloud-data/nextcloud.log \
     /etc/fail2ban/filter.d/nextcloud.conf

Искаме да видим, че редовете със неуспешни входове са matched. (И не забравяйте: доверените мрежи от ignoreip в първата част важат и тук — собствените ви адреси никога не се банват.)

Стъпка 7: hairpin NAT — публичното име да работи и отвътре

Остава един типичен, но досаден проблем. Служителите в офиса искат да достъпват облака по същия адрес както отвън — https://oblak.firma.bg. Но когато машина от вътрешната мрежа се обърне към публичния адрес на собствения си рутер, по подразбиране връзката се чупи: рутерът пренасочва заявката към сървъра, ала отговорът тръгва по пряк път и сесията увисва (т.нар. асиметрично маршрутизиране).

Решението се нарича hairpin NAT (или NAT loopback) — рутерът „завърта“ трафика обратно и го маскира така, че отговорът да мине пак през него. На MikroTik добавяме две неща, без да пипаме работещите правила за външния достъп (за да не рискуваме издаването на сертификата):

/ip firewall nat
add chain=dstnat action=dst-nat protocol=tcp dst-port=80 \
    in-interface-list=LAN dst-address=203.0.113.10 \
    to-addresses=192.168.1.100 to-ports=80 comment="hairpin web 80"
add chain=dstnat action=dst-nat protocol=tcp dst-port=443 \
    in-interface-list=LAN dst-address=203.0.113.10 \
    to-addresses=192.168.1.100 to-ports=443 comment="hairpin web 443"

add chain=srcnat action=masquerade protocol=tcp \
    src-address=192.168.1.0/24 dst-address=192.168.1.100 \
    dst-port=80,443 out-interface=bridge1 comment="hairpin masq"

Първите две правила пренасочват заявките от вътрешната мрежа към публичния адрес обратно към сървъра; третото маскира източника, за да се затвори обратният път коректно. Добавяме и едно разрешаващо правило в защитната стена, за да пропусне този „завъртян“ трафик. Резултат: едно и също име работи безпроблемно и отвън, и отвътре.

Проверка от край до край

Никоя задача не е завършена без проверка. Минаваме по целия път:

  • Състояние на приложението: occ status и occ setupchecks — без грешки и предупреждения (кеш настроен, заключване работи, cron минал скоро, директорията с данни защитена).
  • Външен достъп: от машина извън офиса — https://oblak.firma.bg отваря Nextcloud, с валиден сертификат и автоматично пренасочване от HTTP.
  • Hairpin: от машина в офиса същият адрес стига до облака, а не до рутера.
  • fail2ban: fail2ban-client status sshd и ... status nextcloud — двата пазача са активни.
  • Данните са на правилното място: качваме тестов файл и проверяваме, че реално се записва под /mnt/storage/nextcloud-data/<потребител>/files.

Когато всичко това е зелено, имате частен облак, който е наистина ваш — и на хардуера, и на данните, и на достъпа.

Заключение

В тези три части преминахме от обикновен офис рутер до работещ, защитен частен облак: затворен SSH с fail2ban, стабилен стек, Nextcloud със собствени данни на отделен масив, безплатен и автоматично подновяван SSL сертификат, защита на приложението срещу налучкване и hairpin NAT за безпроблемен достъп отвсякъде. Всичко това — на собствено оборудване, без месечни абонаменти и без външен да държи ключа към данните ви.

Остава едно: да виждаме какво се случва — натоварване, дисково пространство, опити за пробив, състояние на услугите. На това ще посветим четвъртата част от серията: мониторинг на рутера и сървъра в реално време. До скоро.

Тази серия е част от усилията ни сериозната киберзащита да стане достъпна за българския малък и среден бизнес.

Достъп с Браузър Firefox

Приложение за Android