Настройка HSTS при проксировании через cloudflare

nginx ssl

Для форсирования соединения по HTTPS со стороны браузера существует механизм, описываемый специикацией RFC-6797. Суть сводится к установке заголовков HTTP, которые браузер интерпретирует как указание менять обращения по HTTP на защищенные, по HTTPS. Это позволяет избежать ряда атак, наподобии воровства coockies (при обращении по HTTP очень легко прочитать данные, передаваемые без шифрования). Если же домен проксируется через cloudflare, то надо быть особо осторожным, т.к. оригинальный заголовок Strict-Transport-Security веб-сервера не перезаписываются.


Схема работы механизма очень проста, приведу типовой сценарий:

  1. => Браузер делает первый запрос к серверу по доменному имени
  2. <= Браузер получает ответ с перенаправлением на https
  3. => Запрос по HTTPS
  4. <= Ответ сервера с политиками HSTS в заголовках (заголовок Strict-Transport-Security)
  5. ... В рамках текущей сессии работа идет по HTTPS
  6. <= Переход на домен по HTTP. Браузер, помня политики, сразу делает запрос по HTTPS

Если злоумышленник может прослушивать трафик, то при использовании HTTP он может перехватить все передаваемые заголовки и содержимое запроса. Механизм HSTS усложняет проведение описанной атаки и подобных ей.

Немного подробнее про заголовок Strict-Transport-Security. В заголовке можно описать:

  • max-age - время политики в секундах
  • includeSubDomains (не обязательно) - распространить действие политик на поддомены текущего домена
  • preload (не обязательно) - использовать политику предзагрузки по статическому списку ()

Есть интересный момент что сервис cloudflare не переписыват оригинальные политики, поэтому при включении includeSubDomains все поддомены будут запрашиваться браузером по HTTPS протоколу. В результате после посещения основного домена все поддомены будут доступны в браузере только по HTTPS.

Пример моих настроек для nginx /etc/nginx/conf.d/ssl.conf:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:HIGH:!aNULL:!MD5";

# приоритет серверным шифрам
ssl_prefer_server_ciphers on;

# проверка цепочки скрепленных сертификатов
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=600s;
resolver_timeout 10s;

# время жизни SSL-сессий
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# добавляем заголовок для использования только HTTPS при наличии HTTP для того же хоста - чтобы исключить взлом в обход HTTPS
add_header Strict-Transport-Security "max-age=15768000";

С этим конфигом поддомены останутся доступны по HTTP.

Attachments