飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • HTTP 基础

    • 认识HTTP协议与应用层定位
    • HTTP消息格式与报文结构
    • HTTP请求方法与幂等性
    • HTTP状态码详解
  • 连接与缓存

    • HTTP持久连接与版本演进
    • HTTP缓存机制
  • 状态与协商

    • Cookie与Session状态管理
    • HTTP重定向与内容协商
    • HTTP条件请求与范围请求
  • 安全与加密

    • HTTP认证机制
    • HTTPS与TLS握手
  • 协议演进

    • HTTP2核心特性
    • HTTP3与QUIC
  • 架构与实战

    • HTTP代理服务器与Web缓存
    • HTTP常见攻击与防御
    • HTTP实践工具与抓包分析

答案:HTTPS与TLS握手

为什么 TLS 握手先用非对称加密(RSA/ECDHE),后用对称加密(AES)传输数据?对称加密和非对称加密各有什么优缺点?

答案:

TLS 握手的设计是"各取所长"——非对称加密解决"密钥配送问题",对称加密解决"性能问题"。

为什么握手阶段用非对称加密?

客户端和服务器一开始没有任何共享秘密,如果直接传对称密钥,中间人就能截获。非对称加密的特性是:公钥可以公开传输,私钥只保存在服务器。客户端用服务器公钥加密"预主密钥",只有服务器私钥能解密,中间人即使截获也无法破解。这就安全地完成了对称密钥的协商。

飞翔公司的翼王曾让图妹做过一个实验:用纯 RSA 加密传输 100MB 的视频文件,结果 CPU 占用率飙到 90%,耗时是对称加密的 100 倍以上。

两种加密的对比:

特性非对称加密(RSA/ECDHE)对称加密(AES)
速度慢(比对称加密慢 100~1000 倍)快(硬件加速,Gbps 级吞吐)
密钥管理简单(公钥公开,私钥保密)困难(N 个节点需要 N² 个密钥)
用途密钥交换、数字签名大量数据传输
数学基础大数分解/椭圆曲线离散对数置换、替换、混淆
# 用 OpenSSL 实测性能差异
# 非对称加密(RSA 2048)性能
openssl speed rsa2048
# 典型结果:每秒约 2000 次签名验证

# 对称加密(AES-128-GCM)性能
openssl speed aes-128-gcm
# 典型结果:每秒数 GB 数据量

因此 TLS 握手完成后,双方协商出对称密钥(如 AES-128-GCM),后续所有 HTTP 数据都用这个密钥加密——既安全又高效。


假设某个 CA 机构被黑客攻破,能随意签发 www.feixiang.net 的假证书。HSTS 能防御这种攻击吗?证书固定呢?

答案:

HSTS 无法防御这种攻击。

HSTS(HTTP Strict Transport Security)的作用是强制浏览器只用 HTTPS 访问网站,防止用户被劫持到 HTTP 钓鱼页面。但它不验证证书是谁签发的——只要证书是"合法 CA 签发的、域名匹配、未过期",浏览器就信任。如果黑客攻破了 CA,签发的假证书满足以上所有条件,HSTS 完全无法识别。

证书固定(Certificate Pinning)可以防御。

证书固定是把服务器证书(或公钥)的指纹"钉"在客户端(浏览器或 App)里。客户端连接时,只信任指纹匹配的服务器证书,不信任任何 CA 链。

在飞翔公司的官方 App 中,星宇(移动端负责人)就实现了证书固定:

// Android 证书固定示例(Kotlin + OkHttp)
val certificatePinner = CertificatePinner.Builder()
    .add("www.feixiang.net", 
         "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")  // 真实证书指纹
    .add("www.feixiang.net", 
         "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")  // 备用证书指纹
    .build()

val client = OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .build()

如果 CA 被攻破,假证书的指纹与固定的指纹不匹配,App 会立即拒绝连接并报警。凌叔(安全负责人)在飞翔公司的安全策略是:HSTS 是基线要求,证书固定是 App 层的额外保险。

但证书固定也有风险:如果服务器证书正常轮换(到期更新),而客户端没更新指纹,就会导致合法用户也无法访问。因此需要固定"备用证书"的指纹,或者采用 HPKP(HTTP Public Key Pinning,但已被主流浏览器废弃,推荐在 App 层实现)。


凌叔发现官网启用 HTTPS 后,部分老客户端(旧版 Android)无法访问。可能是什么原因?如何在不降低安全性的前提下兼容这些客户端?

答案:

旧版 Android(如 Android 4.x)无法访问,最常见的原因是 TLS 版本和密码套件不兼容:

  1. TLS 版本过高:旧版 Android 只支持 TLS 1.0,而服务器配置了最低 TLS 1.2
  2. 密码套件不匹配:服务器只启用了 ECDHE + AES-GCM 等现代套件,老客户端不支持
  3. SNI(Server Name Indication)问题:极老的 Android 不支持 SNI,而 CDN/云负载均衡依赖 SNI 分发证书

诊断方法:

# 测试旧版 Android 支持的 TLS 版本
curl -v --tlsv1.0 https://www.feixiang.net
# 如果服务器拒绝,会显示:curl: (35) error:1409442E:SSL routines:tlsv1 alert protocol version

# 用 nmap 扫描服务器支持的密码套件
nmap --script ssl-enum-ciphers -p 443 www.feixiang.net

不降低安全性的兼容方案:

  1. 分层配置,多端口服务:
    • 主域名 www.feixiang.net:严格 TLS 1.2+,现代密码套件(面向主流用户)
    • 兼容子域 legacy.www.feixiang.net:允许 TLS 1.0/1.1,但启用弱密码套件监控和限速(面向老客户端)
# Nginx 分层配置示例
server {
    listen 443 ssl;
    server_name www.feixiang.net;
    ssl_protocols TLSv1.2 TLSv1.3;  # 严格
    ssl_ciphers 'ECDHE+AESGCM:ECDHE+CHACHA20';
}

server {
    listen 4443 ssl;
    server_name legacy.www.feixiang.net;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;  # 兼容老客户端
    ssl_ciphers 'ECDHE+AESGCM:ECDHE+AES:RSA+AES';
    # 但限制该端口的访问频率和权限
}
  1. CDN 边缘适配:使用 Cloudflare/AWS CloudFront 的"兼容模式",它们会自动根据客户端能力协商 TLS 版本,而不降低源站安全性。

  2. 客户端升级引导:检测到旧版 Android 时,返回一个友好的 HTML 页面提示用户升级系统或使用飞翔公司 App 的最新版本。

风速(运维工程师)在飞翔公司的实际做法是:通过 CDN 的 User-Agent 分析,发现受影响用户不到 0.1%,于是决定主站保持严格 TLS 1.2+,同时在 CDN 层对这部分用户做降级协商,并在页面顶部显示"您的设备版本过低,建议升级"的横幅。