12. SSL и HTTPS

SSL/TLS — протокол шифрования трафика между клиентом и сервером. HTTPS = HTTP + SSL. Без него браузеры показывают “Не защищено” и поисковики понижают в выдаче.
Как работает SSL
Заголовок раздела «Как работает SSL»1. Клиент подключается к серверу2. Сервер отправляет SSL сертификат (публичный ключ)3. Клиент проверяет сертификат у CA (Certificate Authority)4. Handshake — договариваются об алгоритме шифрования5. Весь трафик зашифрован симметричным ключом
CA (Certificate Authority):- Let's Encrypt (бесплатный, автоматический)- DigiCert, Comodo, GlobalSign (платные, для enterprise)Let’s Encrypt + Certbot
Заголовок раздела «Let’s Encrypt + Certbot»Бесплатные SSL сертификаты для всех. Обновляются автоматически.
# Установка Certbot (Ubuntu)sudo apt install certbot python3-certbot-nginx -y
# Получить сертификат для доменаsudo certbot --nginx -d example.com -d www.example.com
# Только получить сертификат (без изменения Nginx)sudo certbot certonly --nginx -d example.com
# Standalone (без Nginx, для других серверов)sudo certbot certonly --standalone -d example.comПосле получения файлы сохраняются в:
/etc/letsencrypt/live/example.com/├── fullchain.pem # сертификат + цепочка CA├── privkey.pem # приватный ключ (держи в секрете!)├── cert.pem # только сертификат└── chain.pem # только цепочка CAWildcard сертификат
Заголовок раздела «Wildcard сертификат»# Wildcard — один сертификат для всех поддоменов# Требует DNS валидацию
sudo certbot certonly \ --manual \ --preferred-challenges=dns \ -d "*.example.com" \ -d "example.com"
# Certbot попросит добавить TXT запись в DNS:# _acme-challenge.example.com TXT "xxxxxxxxxxxxx"Автоматическое обновление
Заголовок раздела «Автоматическое обновление»Сертификаты Let’s Encrypt действуют 90 дней. Certbot настраивает автообновление через systemd:
# Проверить статус автообновленияsudo systemctl status certbot.timer
# Тест обновления (dry run)sudo certbot renew --dry-run
# Принудительное обновлениеsudo certbot renew --force-renewal
# Хук после обновления (перезагрузить Nginx)sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh#!/bin/bashsystemctl reload nginxsudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.shNginx SSL конфигурация (оптимальная)
Заголовок раздела «Nginx SSL конфигурация (оптимальная)»# HTTP → HTTPS редиректserver { listen 80; listen [::]:80; server_name example.com www.example.com;
# ACME challenge для Certbot location /.well-known/acme-challenge/ { root /var/www/certbot; }
location / { return 301 https://$server_name$request_uri; }}
# HTTPSserver { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com;
# SSL сертификаты ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# SSL параметры (Mozilla Intermediate рекомендация) 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;
# HSTS (говорим браузеру всегда использовать HTTPS) add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP Stapling — быстрее валидация сертификата ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; resolver 8.8.8.8 1.1.1.1;
# Session cache ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;
# Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" always;
location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }}Self-signed сертификат (для разработки)
Заголовок раздела «Self-signed сертификат (для разработки)»# Создание self-signed (не для production!)openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/ssl/private/nginx-selfsigned.key \ -out /etc/ssl/certs/nginx-selfsigned.crt \ -subj "/C=RU/ST=Moscow/L=Moscow/O=MyCompany/CN=localhost"
# Использование в Nginxssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;# Для локальной разработки с HTTPS — лучше использовать mkcertbrew install mkcertmkcert -install # установить root CA в системеmkcert localhost 127.0.0.1 ::1
# Создаст:# localhost+2.pem — сертификат# localhost+2-key.pem — ключ# Браузер не будет ругаться!SSL для Node.js напрямую
Заголовок раздела «SSL для Node.js напрямую»import https from 'https';import fs from 'fs';import express from 'express';
const app = express();app.get('/', (req, res) => res.send('Hello HTTPS!'));
// Только для разработки — в production лучше Nginxconst options = { key: fs.readFileSync('./ssl/private.key'), cert: fs.readFileSync('./ssl/certificate.crt'),};
https.createServer(options, app).listen(443, () => { console.log('HTTPS server running on port 443');});Проверка SSL
Заголовок раздела «Проверка SSL»# Проверить сертификат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
# SSL Labs — полная проверка (онлайн)# https://www.ssllabs.com/ssltest/analyze.html?d=example.comКлючевые моменты
Заголовок раздела «Ключевые моменты»- HTTPS обязателен — без него браузеры и поисковики наказывают
- Let’s Encrypt + Certbot — бесплатные SSL сертификаты с автообновлением
- Certbot автоматически настраивает Nginx
- HSTS — говорит браузеру всегда использовать HTTPS
- Wildcard
*.example.com— один сертификат для всех поддоменов - Никогда не используй self-signed в production
ssl_protocols TLSv1.2 TLSv1.3— только современные протоколы
Интерактивный пример
Заголовок раздела «Интерактивный пример»Как работает HTTPS — визуализация TLS-рукопожатия: