Один из важных аспектов настройки 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;
    }
}
...

Подпишись на мой канал в Телеграм!