Загрузка...
Загрузка...
Всё о SSL/TLS сертификатах: типы, получение, настройка, обновление. Let's Encrypt, Wildcard, EV-сертификаты. Практическое руководство для веб-разработчиков.
Поделитесь с коллегами или изучите другие материалы блога
HTTPS давно стал стандартом веба. В 2026 году браузеры помечают HTTP-сайты как небезопасные, а Google учитывает HTTPS как фактор ранжирования. Разберём всё о SSL-сертификатах: от теории до практической настройки.
SSL (Secure Sockets Layer) — устаревший протокол шифрования. Последняя версия SSL 3.0 признана небезопасной в 2015 году.
TLS (Transport Layer Security) — современный протокол, пришедший на смену SSL. Актуальные версии:
Термин «SSL-сертификат» используется по традиции, но технически это TLS-сертификат.
1. Клиент → Сервер: "Привет, поддерживаю TLS 1.3, шифры: X, Y, Z"
2. Сервер → Клиент: "Выбрал TLS 1.3, шифр X. Вот мой сертификат"
3. Клиент проверяет:
- Сертификат выдан доверенным CA
- Домен совпадает
- Срок действия не истёк
4. Клиент и сервер генерируют сессионный ключ
5. Дальнейшее общение зашифровано
1. DV (Domain Validation)
2. OV (Organization Validation)
3. EV (Extended Validation)
Single Domain
Защищает: example.com
Не защищает: www.example.com, blog.example.com
Wildcard
Защищает: *.example.com
Примеры: www.example.com, blog.example.com, api.example.com
Не защищает: example.com (нужен отдельный или SAN)
Multi-Domain (SAN)
Защищает несколько разных доменов:
- example.com
- example.ru
- another-site.com
Ubuntu/Debian:
sudo apt update
sudo apt install certbot python3-certbot-nginx
CentOS/RHEL:
sudo dnf install certbot python3-certbot-nginx
Для Nginx:
sudo certbot --nginx -d example.com -d www.example.com
Для Apache:
sudo certbot --apache -d example.com -d www.example.com
Standalone (без веб-сервера):
sudo certbot certonly --standalone -d example.com
Webroot (сервер работает):
sudo certbot certonly --webroot -w /var/www/html -d example.com
Требует DNS-проверку:
sudo certbot certonly --manual --preferred-challenges dns \
-d example.com -d "*.example.com"
Certbot попросит создать DNS TXT-запись:
_acme-challenge.example.com TXT "random-string-here"
# Проверка автообновления
sudo certbot renew --dry-run
# Crontab (обычно настраивается автоматически)
0 0,12 * * * root certbot renew --quiet
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# Сертификаты
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Современные протоколы
ssl_protocols TLSv1.2 TLSv1.3;
# Безопасные шифры
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
# Session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
root /var/www/example.com;
index index.html;
}
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder off
Header always set Strict-Transport-Security "max-age=31536000"
DocumentRoot /var/www/example.com
</VirtualHost>
# Информация о сертификате
openssl s_client -connect example.com:443 -servername example.com
# Срок действия
echo | openssl s_client -connect example.com:443 2>/dev/null | \
openssl x509 -noout -dates
# Цепочка сертификатов
openssl s_client -connect example.com:443 -showcerts
# TLS 1.3
openssl s_client -connect example.com:443 -tls1_3
# TLS 1.2
openssl s_client -connect example.com:443 -tls1_2
Проблема: страница загружается по HTTPS, но содержит HTTP-ресурсы.
<!-- ❌ Плохо -->
<img src="http://example.com/image.jpg">
<script src="http://cdn.example.com/script.js"></script>
<!-- ✅ Хорошо -->
<img src="https://example.com/image.jpg">
<script src="https://cdn.example.com/script.js"></script>
<!-- ✅ Или относительные протоколы -->
<img src="//example.com/image.jpg">
Автоматическое исправление через CSP:
add_header Content-Security-Policy "upgrade-insecure-requests";
Проблема: браузер не доверяет сертификату.
# Проверка цепочки
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt \
/etc/letsencrypt/live/example.com/fullchain.pem
Решение: используйте fullchain.pem, а не cert.pem.
# Принудительное обновление
sudo certbot renew --force-renewal
# Проверка таймера systemd
systemctl list-timers | grep certbot
Проблема: устаревшие протоколы или шифры.
# Обновите конфигурацию
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
HTTP Strict Transport Security заставляет браузер всегда использовать HTTPS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Внесение домена в список браузеров, которые загружают его только по HTTPS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
Важно: Отменить preload сложно! Убедитесь, что весь сайт работает по HTTPS.
#!/bin/bash
# check-ssl-expiry.sh
DOMAIN=$1
DAYS_WARNING=30
EXPIRY=$(echo | openssl s_client -connect ${DOMAIN}:443 2>/dev/null | \
openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "${EXPIRY}" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt $DAYS_WARNING ]; then
echo "WARNING: ${DOMAIN} expires in ${DAYS_LEFT} days"
exit 1
fi
echo "OK: ${DOMAIN} expires in ${DAYS_LEFT} days"
exit 0
# Crontab для ежедневной проверки
0 9 * * * /path/to/check-ssl-expiry.sh example.com
SSL-сертификат в 2026 году — это базовая необходимость. Let's Encrypt сделал сертификаты бесплатными и доступными. Ключевые рекомендации:
Не забывайте проверять заголовки безопасности через Security Headers — SSL это только часть безопасной конфигурации.