Улучшение безопасности TLS конфигураций Apache

                
                Улучшение безопасности TLS конфигураций Apache
Эта статья показывает, как превратить обычный HTTPS-виртуал Apache в жёстко защищённый шлюз для вашего проекта. Мы берём стандартный VirtualHost для продакшн-сервера и по шагам усиливаем его: от выбора протоколов TLS до фильтрации пользовательских медиафайлов. Всё изложено в практическом формате «почему это важно, как ломают без этого, что делать».

1. Переход на шифрованный порт

 

Cлушаем только 443 для защищённого трафика. Это убирает соблазн держать функционал на нешифрованном HTTP и сокращает поверхность атак типа MitM.

Как ломают без этого: перехват и подмена трафика, кража cookies/сессий, даунгрейд до HTTP.

 

Listen 443

 

Базовая гигиена — всё чувствительное только по TLS.

 

2. Изолированный виртуал по умолчанию

 

_default_:443 гарантирует, что любой хост, пришедший на 443 без явного VirtualHost, попадёт в безопасный профиль.

 

<VirtualHost _default_:443>
    ServerAdmin admin@example.com
    ServerName  example.com
    DocumentRoot "C:/Apache24/htdocs"
    
    
#</VirtualHost> будет в конце

 

3. Включение TLS и корректные сертификаты

 

Включаем TLS и указываем цепочку/ключ. Правильные файлы и права доступа к ним — основа доверия.

Как ломают без этого: самоподписанные/битые цепочки → фишинг через предупреждения; утечка приватного ключа → полная компрометация.

 

	SSLEngine on
	SSLCertificateFile     "C:/Apache24/conf/ssl/domain.cert.pem"
	SSLCertificateKeyFile  "C:/Apache24/conf/ssl/private.key.pem"

 

Держите ключи вне web-root, с правами только для пользователя службы.

 

4. Политика протоколов и шифров

 

Отключаем устаревшие протоколы и слабые шифры, навязываем порядок выбора сервером.

Как ломают без этого: даунгрейд до TLS 1.0/1.1, атаки на CBC/3DES/RC4/MD5, BEAST/Lucky13 и пр.

 

	SSLProtocol             -all +TLSv1.2 +TLSv1.3
	SSLCipherSuite          HIGH:!aNULL:!MD5:!3DES
	SSLHonorCipherOrder     On
	SSLCompression          Off

 

Итого: Минимум — TLS 1.2/1.3, запрет компрессии (CRIME) и мусорных шифров.

 

5. Проверка статуса сертификата (OCSP stapling)

 

Сервер сам прикладывает свежий статус сертификата. Клиентам не нужно ходить к OCSP-серверу.

Без этого приватность хуже (утечки запросов к OCSP), нестабильность проверки => пользователи игнорируют предупреждения.

 

	SSLUseStapling On

 

Stapling повышает и приватность, и производительность.

 

6. Принудительный HSTS

 

Заставляем браузер использовать только HTTPS, включая поддомены, и разрешаем preload.

Как ломают без этого: даунгрейд до HTTP, перехват куки, смешанный контент.

 

    <IfModule headers_module>
        Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    </IfModule>

 

Вывод: включайте HSTS только после того, как весь домен реально готов жить на HTTPS.

7. Точка входа WSGI с минимальными правами

 

Явное сопоставление корня к WSGI-приложению и запрет листинга.

Как ломают без этого: случайные статики/служебные файлы оказываются доступны, обход роутинга до файлов.

 

    WSGIScriptAlias / "C:/Apache24/htdocs/our_project/our_project/wsgi.py"


<Directory "C:/Apache24/htdocs/our_project/our_project/">
    <Files wsgi.py>
        Require all granted
        Options -Indexes
    </Files>
</Directory>

 

8. Статика: открываем, но без индексов

 

Раздаём статические файлы без автолистинга, чтобы не светить структуру проекта.

 

    Alias /static "C:/Apache24/htdocs/our_project/staticfiles/"
    <Directory "C:/Apache24/htdocs/our_project/staticfiles/">
        Require all granted
        Options -Indexes
    </Directory>

 

Вывод: видно — только то, что явно адресовано

 

9. Медиа: запрет опасных расширений + кэш

 

Раздаём пользовательские файлы, но блокируем всё, что может исполняться.

Как ломают без этого: загрузка и запуск .py/.exe/.ps1 и др. → RCE/привилегии, хранение payload’ов на домене.

 

    Alias /media/ "C:/Apache24/htdocs/our_project/media/"
    <Directory "C:/Apache24/htdocs/our_project/media/">
        Require all granted
        Options -Indexes
        <FilesMatch "\.(py|pyc|pyo|sh|bat|cmd|ps1|exe)$">
            Require all denied
        </FilesMatch>
        <IfModule mod_expires.c>
            ExpiresActive On
            ExpiresDefault "access plus 7 days"
        </IfModule>
    </Directory>

 

Медиа — это данные, а не код. Запрещаем исполняемые форматы и задаём безопасный TTL.

 

10. Ограничение размера тела запроса

 

Ставим ограничение против перегрузок бэкенда и злоупотреблений загрузками.

Предотвращаем DoS большими телами, попытки пронести огромные архивы/словарные атаки по upload.

 

    LimitRequestBody 26214400  # 25 MiB

 

Подстраивайте лимит под реальные нужды; лучше меньше, чем «как-нибудь потом».

 

11. Раздельные логи для TLS-виртуала

 

Отдельные файлы ошибок/доступа упрощают расследование инцидентов по HTTPS.

Как ломают без этого: шум общей ротации скрывает аномалии, теряется контекст.

 

    ErrorLog  "logs/ssl_error.log"
    CustomLog "logs/ssl_access.log" combined
</VirtualHost>

 

Лично я скармливаю логи ИИ для анализа. Как и в прошлой статье, я признаюсь, это костыль. Но, видимо, пока меня не взломают, я не займусь автоматизацией.

 

Итого

 

+- Вот так должно выглядеть у вас:

 

Listen 443

ServerAdmin admin@example.com
ServerName  example.com
DocumentRoot "C:/Apache24/htdocs"

SSLEngine on
SSLCertificateFile     "C:/Apache24/conf/ssl/domain.cert.pem"
SSLCertificateKeyFile  "C:/Apache24/conf/ssl/private.key.pem"
SSLProtocol             -all +TLSv1.2 +TLSv1.3
SSLCipherSuite          HIGH:!aNULL:!MD5:!3DES
SSLHonorCipherOrder     On
SSLCompression          Off
SSLUseStapling On

<IfModule headers_module>
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</IfModule>

WSGIScriptAlias / "C:/Apache24/htdocs/our_project/our_project/wsgi.py"

<Directory "C:/Apache24/htdocs/our_project/our_project/">
    <Files wsgi.py>
        Require all granted
        Options -Indexes
    </Files>
</Directory>

Alias /static "C:/Apache24/htdocs/our_project/staticfiles/"
<Directory "C:/Apache24/htdocs/our_project/staticfiles/">
    Require all granted
    Options -Indexes
</Directory>

Alias /media/ "C:/Apache24/htdocs/our_project/media/"
<Directory "C:/Apache24/htdocs/our_project/media/">
    Require all granted
    Options -Indexes
    <FilesMatch "\.(py|pyc|pyo|sh|bat|cmd|ps1|exe)$">
        Require all denied
    </FilesMatch>
    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresDefault "access plus 7 days"
    </IfModule>
</Directory>

LimitRequestBody 26214400

ErrorLog  "logs/ssl_error.log"
CustomLog "logs/ssl_access.log" combined