Безопасная среда ч.3. Настройка Nginx
Один из важных аспектов настройки VPS и сервисов внутри является правильная настройка web-сервера (в нашем случа Nginx), так чтобы он обеспечивал безопасное соединение и не позволял злоумышленникам получить доступ туда куда им не следует. В этой заметке распишу настройку ssl с получением сертификатов, настройку современных шифров и немного хаков, чтобы снизить риски DDoS и прочих атак.
Получаем сертификаты⌗
Прежде всего для правильной работы SSL нам нужен сертификат, который можно получить через сервис Let’s Encrypt. Для этого надо установить утилиту certbot и плагин для работы с Nginx
sudo apt install certbot python3-certbot-nginx
После этого надо убедиться, что тот домен для которого мы хотим получить серт присутствует в /etc/nginx/sites-enabled
, если нет то, создаем симлинк
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
и перезапускаем Nginx
sudo systemctl restart nginx
Если все ок, то можно приступать к процедуре подтверждения домена
sudo certbot certonly -d mysite.domain
После этого в каталоге /etc/letsencrypt/live/
должна появиться директория mysite.domain cо следующим содержимым
cert.pem
chain.pem
fullchain.pem
privkey.pem
README
Так же, должен появиться файл /etc/cron.d/certbot
отвечающий за автоматическое обновление сертификатов.
Если так, значит можно переходит к настройке самого Nginx
Добавляем сертификаты в конфигурацию Nginx⌗
Для того чтобы Nginx начал принимать ssl-соединения в файле /etc/nginx/sites-enabled/mysite
должна быть секция следующего вида
server {
server_name mysite.domain;
listen [::]:443 ssl; # ssl на IPv6
listen 443 ssl; # ssl на IPv4
ssl_certificate /etc/letsencrypt/live/mysite.domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mysite.domain/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/mysite.domain/chain.pem;
...
# настройки location как для обычного http
...
}
Если после перезагрузки сервера поход в домен по адресу https://mysite.domain проходит успешно, тогда можно смело добавлять редирект с http -> https
server {
server_name mysite.domain;
listen [::]:80; # IPv6
listen 80; # IPv4
return 301 https://mysite.domain$request_uri;
}
Таким образом все запросы на 80 порт будут перенаправлены на 443 (https).
Улучшаем шифрование⌗
По-умолчанию в Nginx включено много скомпрометированных или устаревших шифров, убедиться в этом можно запустив тест на SSLlabs. Для повышения безопасности для клиентов которые подключаются к серверу надо жестко зафиксировать версии TLS и шифров в файле /etc/nginx/nginx.conf
ssl_protocols TLSv1.2 TLSv1.3; # отключаем старые версии TLS
ssl_session_cache shared:SSL:64m;
ssl_session_timeout 10m;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:EECDH+ECDSA+SHA384:EECDH+ECDSA+AESGCM:EECDH+CHACHA20:!SHA:!SHA256:ECDHE-ECDSA-AES256-GCM-SHA384; # используем стойкие шифры (по состоянию на 2022-04)
ssl_ecdh_curve secp521r1:secp384r1; # используем стойкие шифры на основе эллиптических кривых
ssl_prefer_server_ciphers on; # указываем, что настройка шифров сервера является главнее браузерной
После этих настроек тест должен пройти на твердую A.
Фильтруем клиентов по геолокации⌗
В предыдущем посте я уже касался этой темы, тут постараюсь более подробно расписать. Нам потребуется база соответствия ip - страна, для это поставим пакеты
sudo apt-get install geoip-database libgeoip1
Теперь должен появится файлик /usr/share/GeoIP/GeoIP.dat
, который подключим в Nginx (/etc/nginx/nginx.conf
).
geoip_country /usr/share/GeoIP/GeoIP.dat;
Дальше надо описать тривиальную логику в которой переменная принимает значение yes или no в зависимости от гео-принадлежности IP клиента. Коды стран можно подглядеть тут
map $geoip_country_code $allowed_country {
default no;
RU yes;
}
В данном примере переменная allowed_country будет содержать значение yes только в том случае если IP адрес клиента принадлежит Российскому диапазону адресов. Теперь эту переменную мы можем использовать в файлах конфигурации сайтов (например /etc/nginx/sites-enabled/mysite
) и возвращать статус 403 если пользователь пришел с неразрешенного диапазона
...
location / {
if ($allowed_country = no) {
return 403;
}
}
...
Подпишись на мой канал в Телеграм!