Настройки безопасности
Чтобы не светить версии nginx и php делаем следующее: в файле /etc/nginx/nginx.conf
в секции http
дописываем:
server_tokens off;
а в файле /etc/php.ini
дописываем:
expose_php = Off
Рестартуем сервисы:
sudo systemctl restart php-fpm.service
sudo systemctl restart nginx.service
Проверяем командой:
$ curl -I http://idoka.ru
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Keep-Alive: timeout=60
Vary: Accept-Encoding, Cookie
Cache-Control: max-age=3, must-revalidate
Cache-Control: public
Прикрутка GeoIP
Если по nginx -V
не находим опцию --with-http_geoip_module
, но у нас CentOS 7, то, начиная с версии nginx-1.10.0, выход есть:
sudo yum install -y nginx-module-geoip
Либа будет установлена в /usr/lib64/nginx/modules
:
ls -l /usr/lib64/nginx/modules/
ngx_http_geoip_module-debug.so
ngx_http_geoip_module.so
ngx_http_js_module-debug.so
ngx_http_js_module.so
Скачиваем и разворачиваем:
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz
gunzip GeoIP.dat.gz
gunzip GeoLiteCity.dat.gz
gunzip GeoIPASNum.dat.gz
Далее в секции http
конфига nginx прописываем пути к скаченным БД (страны, города, провайдеры):
geoip_country /path/../GeoIP.dat;
geoip_city /path/../GeoLiteCity.dat;
geoip_org /path/../GeoIPASNum.dat;
А вне любых секций конфига nginx добавить:
load_module "modules/ngx_http_geoip_module.so";
Теперь перегружаем nginx:
sudo systemctl restart nginx.service
Вообще говоря, в директиве geoip_org
можно указать БД провайдеров или организаций, но в nginx нельзя иметь одновременно подключенные обе БД - надо определиться с тем что подключать.
Теперь можно, там где надо, передавать необходимые fastcgi параметры (имеет смысл добавить эти параметры в конец файла /etc/nginx/fastcgi_params):
# для стран:
fastcgi_param GEOIP_ADDR $remote_addr;
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
# для городов:
fastcgi_param GEOIP_REGION $geoip_region;
fastcgi_param GEOIP_REGION_NAME $geoip_region_name;
fastcgi_param GEOIP_CITY $geoip_city;
fastcgi_param GEOIP_AREA_CODE $geoip_area_code;
fastcgi_param GEOIP_LATITUDE $geoip_latitude;
fastcgi_param GEOIP_LONGITUDE $geoip_longitude;
fastcgi_param GEOIP_POSTAL_CODE $geoip_postal_code;
# для провайдеров/организаций:
fastcgi_param GEOIP_ORGANIZATION $geoip_org;
Тестируем работоспособность, включив в секцию server следующий код (понадобится установленный и подключенный в конфиге модуль echo-nginx-module):
# Testing GeoIP
location ^~ /geoip/ {
add_header Content-Type application/json;
if ($geoip_country_code ~ "RU") {
echo '{"key":"russia","country":"$geoip_country_code"}';
}
if ($geoip_country_code !~ "RU") {
echo '{"key":"global","country":"$geoip_country_code"}';
}
}
либо кодом php:
<?php
echo "Your country is {$_SERVER['GEOIP_COUNTRY_NAME']} and your city is {$_SERVER['GEOIP_CITY']}.";
?>
Запрет посещения средствами nginx для определенных стран
В ситуации, когда необходимо заблокировать доступ к хосту пользователям из определенных стран, используются также базы GeoIP для определения принадлежности к стране. Одной из разновидностей задачи является показ сайта на языке, нативном для страны нахождения постетителя.
Впишем следующий маппинг в секцию http
конфига nginx:
map $geoip_country_code $allowed_country {
default yes;
CN no;
}
Это пример пермиссивной политики: доступ всем, кроме … Для того чтобы наоборот указать кому открыть доступ, перепишем:
map $geoip_country_code $allowed_country {
default no;
RU yes;
UA yes;
BY yes;
KZ yes;
}
Теперь осталось добавить в конфиг виртуального хоста (секция server
):
if ($allowed_country = no) {
return 404;
}
UPD: вариант с автообновлением GEOIP
Ставим:
sudo yum install -y GeoIP GeoIP-data GeoIP-update
GeoIP-update - для автообновления через крон. БД будут располагаться в /usr/share/GeoIP
. Теперь осталось прописать в конфиге:
geoip_country /usr/share/GeoIP/GeoIP.dat;
geoip_city /usr/share/GeoIP/GeoIPCity.dat;
geoip_org /usr/share/GeoIP/GeoIPASNum.dat;
Настройка Let’s Encrypt сертификатов в LEMP на CentOS 7
Если вкратце - не нужно поднимать сервер на 9999 порту, юзаем самый простой способ webroot, это значит что letsencrypt’у достаточно указать в какой папке будет лежать файл для обмена с сервером (подтверждение прав на домен).
Забираем с гитхаба:
git clone --depth=1 https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto
Просит рута, ну ок:
Package gcc-4.8.5-11.el7.x86_64 already installed and latest version
Package augeas-libs-1.4.0-2.el7.x86_64 already installed and latest version
Package 1:openssl-1.0.1e-60.el7.x86_64 already installed and latest version
Package 1:openssl-devel-1.0.1e-60.el7.x86_64 already installed and latest version
Package libffi-devel-3.0.13-18.el7.x86_64 already installed and latest version
Package redhat-rpm-config-9.1.0-72.el7.centos.noarch already installed and latest version
Package ca-certificates-2015.2.6-73.el7.noarch already installed and latest version
Package python-2.7.5-48.el7.x86_64 already installed and latest version
Package python-devel-2.7.5-48.el7.x86_64 already installed and latest version
Package python-virtualenv-1.10.1-3.el7.noarch already installed and latest version
Package python-tools-2.7.5-48.el7.x86_64 already installed and latest version
Package python2-pip-8.1.2-5.el7.noarch already installed and latest version
Питоническая шелуха имелась в системе, а теперь самое интересное: letsencrypt-auto настолько тупой, что не видит, что репозиторий EPEL уже установлен и докучи ставит зачем-то httpd, httpd-tools и mod_ssl (это жесть, господа!). Даже при вызове с опцией –dry-run!! Крайне рукожопный скрипт! Теперь при попытке удаления httpd он заодно сносит и php, а при установке php после таки-сноса httpd, тянет в качестве зависимости опять же httpd - чтоооооооооооо??????
Ладно, сертификаты важнее, идём дальше. Я не стал конфигурировать (и перезапускать) nginx, как того рекомендуют для указания размещения папки .well-known, если будет необходимость задать расположение .well-known вне папки сайта, синтаксис такой:
location /.well-known {
root /var/site/idoka.ru;
}
далее пробуем запустить letsencrypt-auto для нашего домена:
$ ./letsencrypt-auto certonly --agree-tos --register-unsafely-without-email --noninteractive --webroot --webroot-path /var/site/idoka.ru -d idoka.ru
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Registering without email!
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for idoka.ru
Using the webroot path /var/site/idoka.ru for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0001_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0001_csr-certbot.pem
Успех!
Для получения доп.сертификатов для поддоменов можно указывать несколько опций -d с именами поддоменов.
Настройка SSL в nginx сводится к добавлению:
######### SSL #########
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'HIGH:!aNULL:!MD5:!kEDH';
ssl_certificate /etc/letsencrypt/live/idoka.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/idoka.ru/privkey.pem;
Или вот настройки, которые предлагает сам letsencrypt в файле certbot-nginx/certbot_nginx/options-ssl-nginx.conf
:
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1440m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA ECDHE-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-SHA ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-SHA384 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES128-SHA DHE-RSA-AES256-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-SHA256 EDH-RSA-DES-CBC3-SHA";
Для OCSP stapling делаем следующее:
wget -O /etc/nginx/ssl/chain.pem "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem"
А в конфиг добавляем следующее:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
После чего перегружаем конфиг nginx:
sudo systemctl reload nginx.service
Последний штрих: автообновление сертификатов. Добавляем в /etc/crontab
:
0 2 1 * * letsencrypt-auto renew >> /dev/null 2>&1
Желательно также тамже рестартануть nginx:
5 2 1 * * systemctl reload nginx.service >> /dev/null 2>&1
первого числа каждого месяца в 2:00 будет осуществлен перевыпуск сертификатов, а в 2:05 перезачитывание конфигов nginx.
Актуальная версия справки: https://letsencrypt.readthedocs.io/en/latest/using.html#webroot