Киберзащита за малкия бизнес (част 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



