Checklist

SSL/TLS шифрование

Наиболее безопасный вариант — поднять свою инфраструктуру публичного ключа. То есть самостоятельно выпускать SSL-сертификаты для своих сервисов, выступая как Certification Authority. Обслуживание и контроль за всеми сертификатами доставляет много проблем и оправдано только для масштабных проектов.

В общем случае для взаимодействия между сервисами достаточно использовать ssh и https с сертификатом, который подписан сторонним доверенным CA. Для автоматизации перевыпуска сертификатов возьмем скрипт getssl.

curl --silent https://raw.githubusercontent.com/srvrco/getssl/master/getssl \
> getssl ; chmod 700 getssl

Шаблон конфигурации создаем командой

./getssl -c petrashov.ru

Она создает в домашнем каталоге файл ~/.getssl/getssl.cfg с общими настройками и ~/.getssl/petrashov.ru/getssl.cfg с настройками для домена. Настроить нужно следующее:

~/.getssl/getssl.cfg

#Адрес центра сертификации.
#Для примера использую сервис LetsEntcrypt с бесплатными сертификатами
CA="https://acme-staging.api.letsencrypt.org"
ACCOUNT_EMAIL="s@petrashov.ru"

ACCOUNT_KEY="/home/petrashov/.getssl/account.key"
ACCOUNT_KEY_LENGTH=4096
PRIVATE_KEY_ALG="rsa"
# Перевыпускаем сертификат только если до истечения осталось меньше 30 дней
RENEW_ALLOW="30" 

~/.getssl/petrashov.ru/getssl.cfg

# Сертификат действует на 2 домена - s.petrashov.ru и petrashov.ru
SANS="s.petrashov.ru"

ACL=('/var/www/html/petrashov.ru/.well-known/acme-challenge')

USE_SINGLE_ACL="true"

DOMAIN_CERT_LOCATION="/etc/ssl/petrashov.ru/domain.crt"
DOMAIN_KEY_LOCATION="/etc/ssl/petrashov.ru/domain.key"
DOMAIN_CHAIN_LOCATION="/etc/ssl/petrashov.ru/domain.chained.key"

RELOAD_CMD="service nginx reload"

Аналогично создаем конфигурации для других доменов. Чтобы больше не думать о продлении сертификатов пишем cronjob

11 15 * * * /petrashov/scripts/getssl -u -a -q

Регулярный аудит работающих сервисов

Следить за тем, что происходит на сервере надо. Далее — по порядку, что проверять. Список не полный, но как минимум так.

  1. Работающие сервисы
systemctl list-units --type service --state running

Всё что обнаружилось неожиданно, удаляем с помощью apt remove или, если от пакета зависит другой нужный пакет, маскируем по средствам apt mask. Посмотреть все установленные пакеты на сервере:

dpkg --list

dpkg показывает кое-какую информацию о каждом пакете, подробности можно посмотреть через утилиту apt

apt show service-name
  1. Открытые порты
sudo netstat -tulpn

Смотрим какие порты слушают сервисы. Ненужные блокируем через ufw или удаляем сервис целиком. Чтобы узнать, какой пакет добавил сервис

dpkg -S $(which service-name)
  1. Обновления

В работе использовать только LTS дистрибутивы, особое внимание обращая на обновления безопасности.

sudo apt-get update && sudo apt-get upgrade

Автоматизировать эти рутинные команды не стоит. Перед обновлением критичных для сервера пакетов, лучше сделать дополнительный backup и внимательно изучить изменения.

  1. Логи

Чтобы не ходить каждый день на сервер, нужно генерировать себе регулярный отчет. Вариантов реализации этой задачи много, остановимся на простом – пакете Logwatch.

Устанавливается он из репозиториев. Файл конфигурации лежит в /usr/share/logwatch/default.conf/logwatch.conf. В нем настраиваем параметры:

MailTo = s@petrashov.ru
MailFrom = Logwatch
Range = yesterday
Detail = Low
Service = All

Добавить парсер логов nginx:

cp /usr/share/logwatch/scripts/services/http /etc/logwatch/scripts/services/nginx
cp /usr/share/logwatch/default.conf/services/http.conf /etc/logwatch/conf/services/nginx.conf

Формат логов у Apache очень схож с Nginx, поэтому я просто скопировал конфигурацию. В файле /etc/logwatch/conf/services/nginx.conf меняем:

Title = "nginx"

# Which logfile group...

LogFile = nginx

Создаём файл /etc/logwatch/conf/logfiles/nginx.conf с таким содержимым:

LogFile = nginx/*access.log

LogFile = nginx/*error.log

Проверяем logwatch и видим новый блок Nginx с примерно таким содержанием.

sudo logwatch
 ################### Logwatch 7.4.0 (05/29/13) ####################
        Processing Initiated: Fri Mar 17 09:35:06 2017
        Date Range Processed: yesterday
                              ( 2017-Mar-16 )
                              Period is day.
        Detail Level of Output: 0
        Type of Output/Format: stdout / text
        Logfiles for Host: petrashov.ru
 ##################################################################
 
  --------------------- nginx Begin ------------------------
  
    A total of 4 sites probed the server
    xxxxxxxxxxxxxx
    
    Requests with error response codes
    
    400 Bad Request
    null: 7 Time(s)
    404 Not Found
    /wp-login.php: 5 Time(s)
    500 Internal Server Error
    /x: 2 Time(s)
    
    This is a listing of log lines that were not parsed correctly.
    Perhaps the variable $LogFormat in file conf/services/http.conf
    is not correct?
    
    (Only the first ten are printed; there were a total of 188)
    ...
    
   ---------------------- nginx End -------------------------

Продолжение