TLS и HTTPS: безопасное соединение
HTTPS — это HTTP с шифрованием TLS. Рассмотрим как это работает и как правильно настроить. TLS обеспечивает конфиденциальность, целостность и аутентификацию данных при передаче. Без HTTPS любое соединение уязвимо для перехвата и подмены данных.
Как работает TLS
TLS handshake — это процесс установления безопасного соединения между клиентом и сервером. Во время handshake стороны согласовывают версию протокола, выбирают шифры и обмениваются ключами.
Handshake
Процесс начинается с того, что клиент отправляет список поддерживаемых шифров. Сервер выбирает подходящий и отправляет свой сертификат.
Client Server
| |
|-------- ClientHello -------->|
|<------ ServerHello ----------|
|<------ Certificate ----------|
|<------ ServerKeyExchange ----|
|<------ CertificateRequest ---|
|<------ ServerHelloDone ------|
|-------- Certificate -------->|
|-------- ClientKeyExchange -->|
|-------- CertificateVerify -->|
|-------- ChangeCipherSpec --->|
|-------- Finished ----------->|
|<------- ChangeCipherSpec ----|
|<------- Finished ------------|
| |
|======= Encrypted Data ======>|
|<======= Encrypted Data ======|
Версии TLS
Протокол TLS эволюционировал с течением времени. Каждая новая версия улучшает безопасность и производительность.
- TLS 1.0 — устарел (1999), уязвимости BEAST, POODLE
- TLS 1.1 — устарел (2006), редко поддерживается
- TLS 1.2 — текущий стандарт (2008), широко используется
- TLS 1.3 — современный (2018), быстрее и безопаснее
Для новых проектов рекомендуется использовать только TLS 1.3.
Сертификаты
Сертификат подтверждает, что публичный ключ действительно принадлежит владельцу домена. Сертификаты выпускаются центрами сертификации (CA).
Типы сертификатов
Разные типы сертификатов предлагают разный уровень проверки:
- DV — Domain Validation (проверка домена), быстро, дёшево
- OV — Organization Validation (проверка организации), требует документов
- EV — Extended Validation (расширенная проверка), максимальное доверие
Для большинства сайтов достаточно DV сертификата.
Получение сертификата
Let’s Encrypt (бесплатно)
Let’s Encrypt — бесплатный центр сертификации, автоматизирующий выдачу сертификатов через протокол ACME.
# Certbot
sudo apt install certbot python3-certbot-nginx
# Получение сертификата
sudo certbot --nginx -d example.com -d www.example.com
# Автообновление
sudo certbot renew --dry-run
Certbot автоматически обновляет сертификаты через cron. Сертификаты Let’s Encrypt действительны 90 дней.
ACME клиент
// Node.js - certbot-zerossl
import { certificate } from 'acme-client';
const client = new certificate({
email: 'admin@example.com',
agreeTos: true
});
const { csr, privateKey } = await client.generateCsr({
commonName: 'example.com'
});
const cert = await client.sign(csr, {
altNames: ['www.example.com']
});
Настройка Nginx
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name 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;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
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;
}
}
Node.js HTTPS сервер
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
minVersion: 'TLSv1.2',
ciphers: 'ECDHE-ECDSA-AES128-GCM-SHA256'
};
const server = https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('Hello, HTTPS!');
});
server.listen(443);
HTTP Strict Transport Security
// Express с Helmet
const helmet = require('helmet');
app.use(helmet.hsts({
maxAge: 63072000, // 2 года
includeSubDomains: true,
preload: true
}));
Certificate Pinning
// HPKP - больше не рекомендуется
// Вместо этого - CT (Certificate Transparency)
// Проверка сертификата
const https = require('https');
const tls = require('tls');
const options = {
host: 'example.com',
port: 443,
checkServerIdentity: (host, cert) => {
if (cert.subject.CN !== 'example.com') {
return new Error('Invalid certificate');
}
// Проверка fingerprint
const fingerprint = cert.fingerprint256;
const allowed = 'SHA256:...';
if (fingerprint !== allowed) {
return new Error('Certificate not trusted');
}
}
};
Mixed Content
<!-- CSP для предотвращения mixed content -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
Проверка SSL
# SSL Labs
openssl s_client -connect example.com:443 -showcerts
# Проверка
ssllabs-scan example.com
# Тест
curl -Iv https://example.com
Best Practices
- TLS 1.3 — используйте последнюю версию
- HSTS — включите Strict-Transport-Security
- OCSP Stapling — ускоряет проверку
- Let’s Encrypt — бесплатные сертификаты
- Автообновление — настройте renew
- Certificate Transparency — мониторинг
Заключение
HTTPS обязателен для современных веб-приложений. Правильная настройка TLS обеспечивает безопасную передачу данных.