全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-14 10 分钟 ✍️ juanwangdev

HTTPS与TLS配置

HTTPS 通过 TLS/SSL 加密传输数据,保护用户隐私和数据完整性。

TLS 基础概念

握手流程

JavaScript
客户端                                    服务器
  |                                        |
  |-------- Client Hello --------------->  |  (支持的加密套件)
  |                                        |
  |<------- Server Hello ---------------  |  (选定的加密套件)
  |<------- Certificate -----------------  |  (服务器证书)
  |<------- Server Hello Done ----------   |
  |                                        |
  |-------- Client Key Exchange -------->  |  (预主密钥)
  |-------- Change Cipher Spec --------->  |
  |-------- Finished ------------------->  |
  |                                        |
  |<------- Change Cipher Spec ----------  |
  |<------- Finished -------------------  |
  |                                        |
  |======== 加密通信 ===================> |

证书类型

类型说明适用场景
DV域名验证,快速签发个人站点、开发测试
OV组织验证,显示公司名企业网站
EV扩展验证,最高信任金融、电商

Node.js HTTPS 服务

基本配置

JavaScript
const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
  ca: fs.readFileSync('ca-bundle.pem')  // 可选:中间证书
};

const server = https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('Hello HTTPS');
});

server.listen(443, () => {
  console.log('HTTPS server running on port 443');
});

Express HTTPS 配置

JavaScript
const express = require('express');
const https = require('https');
const fs = require('fs');

const app = express();

// HTTPS 服务器
const options = {
  key: fs.readFileSync('./certs/private.key'),
  cert: fs.readFileSync('./certs/certificate.crt'),
  ca: fs.readFileSync('./certs/ca_bundle.crt')
};

https.createServer(options, app).listen(443, () => {
  console.log('HTTPS server running on port 443');
});

// HTTP 重定向到 HTTPS
const http = require('http');
http.createServer((req, res) => {
  res.writeHead(301, { Location: `https://${req.headers.host}${req.url}` });
  res.end();
}).listen(80);

使用 helmet 增强安全

JavaScript
const helmet = require('helmet');

app.use(helmet());

// HSTS - 强制 HTTPS
app.use(helmet.hsts({
  maxAge: 31536000,        // 1年
  includeSubDomains: true, // 包含子域名
  preload: true            // 预加载到浏览器
}));

// 禁用不安全功能
app.use(helmet.frameguard({ action: 'deny' }));
app.use(helmet.noSniff());
app.use(helmet.xssFilter());

TLS 版本与加密套件

禁用不安全版本

JavaScript
const tls = require('tls');

// 创建安全上下文
const secureContext = tls.createSecureContext({
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
  // 禁用 SSLv2, SSLv3, TLSv1, TLSv1.1
  secureOptions: tls.constants.SSL_OP_NO_SSLv2 |
                 tls.constants.SSL_OP_NO_SSLv3 |
                 tls.constants.SSL_OP_NO_TLSv1 |
                 tls.constants.SSL_OP_NO_TLSv1_1
});

// 推荐配置
const options = {
  key: fs.readFileSync('private-key.pem'),
  cert: fs.readFileSync('certificate.pem'),
  minVersion: 'TLSv1.2',  // 最低版本
  maxVersion: 'TLSv1.3',  // 最高版本
  ciphers: [
    'TLS_AES_256_GCM_SHA384',
    'TLS_CHACHA20_POLY1305_SHA256',
    'TLS_AES_128_GCM_SHA256',
    'ECDHE-RSA-AES256-GCM-SHA384',
    'ECDHE-RSA-AES128-GCM-SHA256'
  ].join(':'),
  honorCipherOrder: true
};

推荐加密套件

Bash
const RECOMMENDED_CIPHERS = [
  // TLS 1.3
  'TLS_AES_256_GCM_SHA384',
  'TLS_CHACHA20_POLY1305_SHA256',
  'TLS_AES_128_GCM_SHA256',
  // TLS 1.2
  'ECDHE-ECDSA-AES256-GCM-SHA384',
  'ECDHE-RSA-AES256-GCM-SHA384',
  'ECDHE-ECDSA-AES128-GCM-SHA256',
  'ECDHE-RSA-AES128-GCM-SHA256',
  'ECDHE-ECDSA-CHACHA20-POLY1305',
  'ECDHE-RSA-CHACHA20-POLY1305'
].join(':');

证书获取与管理

Let's Encrypt 免费证书

JavaScript
# 使用 certbot
sudo apt install certbot
sudo certbot certonly --standalone -d example.com -d www.example.com

# 自动续期
sudo certbot renew --dry-run

# 定时任务
0 0 1 * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

Node.js 自动续期

nginx
const Greenlock = require('greenlock');

const greenlock = Greenlock.create({
  packageRoot: __dirname,
  configDir: './greenlock.d',
  maintainerEmail: 'admin@example.com'
});

// 自动管理证书
greenlock.manager.defaults({
  subscriberEmail: 'admin@example.com',
  agreeToTerms: true
}).then(() => {
  return greenlock.add({
    subject: 'example.com',
    altnames: ['example.com', 'www.example.com']
  });
});

证书文件说明

JavaScript
private.key       # 私钥(保密)
certificate.crt   # 服务器证书
ca_bundle.crt     # 中间证书链
fullchain.crt     # 完整证书链(证书+中间证书)

反向代理配置

Nginx HTTPS 配置

Bash
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_prefer_server_ciphers on;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# HTTP 重定向
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

Express 信任代理

Bash
// 信任反向代理
app.set('trust proxy', 1);

// 获取真实 IP
app.use((req, res, next) => {
  const ip = req.ip || req.headers['x-forwarded-for'];
  const protocol = req.protocol;  // 正确获取 https
  next();
});

安全配置检测

SSL Labs 测试

JavaScript
# 访问 https://www.ssllabs.com/ssltest/

# 目标:A+ 评级

命令行检测

JavaScript
# 检查 TLS 版本
openssl s_client -connect example.com:443 -tls1_2

# 检查证书信息
openssl x509 -in certificate.pem -text -noout

# 检查加密套件
nmap --script ssl-enum-ciphers -p 443 example.com

# 使用 testssl.sh
git clone https://github.com/drwetter/testssl.sh.git
./testssl.sh example.com

Node.js 检测脚本

Bash
const tls = require('tls');

function checkTLSConfig(hostname) {
  const socket = tls.connect(443, hostname, {
    servername: hostname,
    rejectUnauthorized: false
  }, () => {
    console.log('TLS Version:', socket.getProtocol());
    console.log('Cipher:', socket.getCipher());
    console.log('Certificate:', socket.getPeerCertificate().subject);
    socket.end();
  });

  socket.on('error', (err) => {
    console.error('TLS Error:', err.message);
  });
}

checkTLSConfig('example.com');

常见问题与解决

混合内容问题

text
// 强制 HTTPS 重定向
app.use((req, res, next) => {
  if (req.protocol === 'http') {
    return res.redirect(301, `https://${req.headers.host}${req.url}`);
  }
  next();
});

// 设置 HSTS 头
app.use((req, res, next) => {
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  next();
});

证书链不完整

text
# 合并证书链
cat certificate.crt ca_bundle.crt > fullchain.crt

# 验证证书链
openssl verify -CAfile ca_bundle.crt certificate.crt

注意:生产环境建议使用 Nginx/Caddy 等 Web 服务器处理 TLS,Node.js 应用监听本地端口。

要点总结

  • 使用 TLS 1.2+ 版本,禁用 SSLv3、TLSv1、TLSv1.1
  • 配置强加密套件,优先使用 ECDHE 和 AES-GCM
  • 启用 HSTS 强制 HTTPS,配置 maxAge 和 includeSubDomains
  • 使用 Let's Encrypt 免费证书,配置自动续期
  • 使用 SSL Labs 定期检测 HTTPS 配置安全性

📝 发现内容有误?点击此处直接编辑

← 上一篇 异步IO性能瓶颈分析
下一篇 → XSS与CSRF防护
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库