Skip to main content

RFC 2818 - 通过TLS的HTTP (HTTPS)

状态: 信息性文档
作者: E. Rescorla (RTFM, Inc.)
发布日期: 2000年5月

摘要

本文档描述如何使用 TLS (Transport Layer Security, 传输层安全) 保护 HTTP (Hypertext Transfer Protocol, 超文本传输协议) 连接。当前实践是将 HTTP 分层在 SSL (Secure Sockets Layer, 安全套接字层, TLS的前身) 之上, 通过使用不同的服务器端口来区分安全流量和非安全流量。本文档使用 TLS 记录了这一实践。

重要性

RFC 2818是Web安全的基石:

  • 🔒 定义HTTPS的基本机制
  • 🌐 所有现代网站的安全基础
  • 🔑 证书验证和身份识别
  • ⚡ 安全连接建立和关闭

1. Introduction (简介)

HTTP 最初在互联网上以明文形式使用。然而, HTTP 在敏感应用中的使用增加, 需要安全措施。SSL 及其继任者 TLS 被设计用来提供面向通道的安全性。本文档描述如何在 TLS 上使用 HTTP。

核心概念

HTTPS = HTTP + TLS

┌────────────────────────────────────────┐
│ HTTP/1.1 Protocol │
│ (Application Layer Protocol) │
├────────────────────────────────────────┤
│ TLS/SSL Protocol │
│ (Transport Layer Security) │
├────────────────────────────────────────┤
│ TCP Protocol │
│ (Transmission Control Protocol) │
└────────────────────────────────────────┘

1.1. Requirements Terminology (关键词定义)

本文档使用 RFC 2119 定义的关键词:

  • MUST / REQUIRED: 必须
  • SHOULD: 应该
  • MAY: 可以

2. HTTP Over TLS (TLS上的HTTP)

核心原则

概念上非常简单: 在 TLS 上使用 HTTP, 就像在 TCP (Transmission Control Protocol, 传输控制协议) 上使用 HTTP 一样精确。

2.1. Connection Initiation (连接建立)

流程:

1. 客户端 → 服务器: 建立TCP连接 (端口443)
2. 客户端 → 服务器: 发送TLS ClientHello
3. ↔ TLS握手过程 ↔
4. 握手完成后: 客户端可以发起第一个HTTP请求

要求:

  • ✅ HTTP 客户端作为 TLS 客户端
  • ✅ 连接到适当的端口 (默认443)
  • ✅ 发送 TLS ClientHello 开始握手
  • ✅ 所有 HTTP 数据必须 (MUST) 作为 TLS "应用数据" 发送

示例流程:

客户端:
1. TCP连接到 www.example.com:443
2. 发送 ClientHello

服务器:
3. 响应 ServerHello + Certificate (证书)
4. ServerHelloDone

客户端:
5. ClientKeyExchange
6. ChangeCipherSpec
7. Finished

服务器:
8. ChangeCipherSpec
9. Finished

← TLS握手完成 →

客户端:
10. 发送加密的HTTP请求:
GET / HTTP/1.1
Host: www.example.com

2.2. Connection Closure (连接关闭)

TLS 提供了安全连接关闭的设施。

Closure Alert (关闭警报)

定义:

  • Valid Closure (有效关闭): 收到正确的关闭警报
  • Incomplete Close (不完整关闭): 发送关闭警报后立即关闭连接
  • Premature Close (过早关闭): 未收到关闭警报就关闭连接

要求:

  • ✅ 实现必须 (MUST) 在关闭连接前发起关闭警报交换
  • ⚠️ 实现可以在发送关闭警报后关闭连接 (不等待对方)
  • ❌ 收到过早关闭的连接不得 (MUST NOT) 重用会话

2.2.1. Client Behavior (客户端行为)

问题: HTTP 使用连接关闭来标示服务器数据结束。

客户端必须 (MUST):

  • ✅ 将任何过早关闭视为错误
  • ✅ 将收到的数据视为可能被截断
  • ✅ 发送关闭警报后再关闭连接

特殊情况:

  1. 没有Content-Length的响应:
HTTP/1.1 200 OK
Content-Type: text/html
[连接关闭表示结束]

← 过早关闭无法区分是服务器还是攻击者 →
  1. 有Content-Length但未读完:
HTTP/1.1 200 OK
Content-Length: 1000
[只收到500字节就关闭]

← 无法判断是服务器错误还是攻击 →

例外: 如果收到的数据量与 Content-Length 匹配, 应视为完成。

客户端示例:

✅ 正常关闭:
客户端: 发送 closure_alert
等待服务器 closure_alert
关闭连接

⚡ 快速关闭:
客户端: 发送 closure_alert
立即关闭连接 (不等待)
← 这会在服务器端产生不完整关闭 →

2.2.2. Server Behavior (服务器行为)

RFC 2616要求: 服务器必须优雅地从客户端关闭中恢复。

服务器应该:

  • ✅ 准备好接收来自客户端的不完整关闭
  • ✅ 愿意恢复这样关闭的 TLS 会话
  • ✅ 尝试与客户端交换关闭警报
  • ⚡ 可以在发送关闭警报后关闭连接

实现注意:

不使用持久连接的HTTP:
- 服务器通过关闭连接来标示数据结束
- 但客户端可能已发送关闭警报并断开

2.3. Port Number (端口号)

默认端口: 443

原理:

HTTP服务器期望: Request-Line (如 GET / HTTP/1.1)
TLS服务器期望: ClientHello

← 无法在同一端口区分 →

解决方案: 使用不同端口
- HTTP: 80
- HTTPS: 443

示例:

# HTTP (明文)
curl http://www.example.com:80/

# HTTPS (加密)
curl https://www.example.com:443/

2.4. URI Format (URI格式)

协议标识符: https:// (而不是 http://)

示例:

https://www.example.com/~smith/home.html
https://api.example.com:8443/v1/users
https://192.168.1.1/admin

URI组件:

https://www.example.com:443/path?query#fragment
↑ ↑ ↑ ↑ ↑ ↑
scheme host port path query fragment

3. Endpoint Identification (端点识别)

3.1. Server Identity (服务器身份)

核心要求: 客户端必须验证服务器身份, 防止 Man-in-the-Middle Attack (中间人攻击)。

Identity Verification Process (身份验证流程)

1. 客户端从URI获得主机名 (hostname)
例如: https://www.example.com

2. 服务器在TLS握手中提供证书 (certificate)

3. 客户端检查主机名与证书身份是否匹配

Identity Field Priority (身份字段优先级)

优先级1: subjectAltName (Subject Alternative Name, 主体备用名称)

证书中的 subjectAltName 扩展 (dNSName类型):
dNSName: www.example.com
dNSName: api.example.com

← 必须使用此字段 (如果存在) →

优先级2: Common Name (通用名称)

证书 Subject 字段中的 CN:
CN=www.example.com

← 仅在没有 subjectAltName 时使用 →
← 已废弃, CA (Certificate Authority, 证书颁发机构) 应使用 dNSName →

Matching Rules (匹配规则)

1. 通配符匹配:

证书: *.example.com
✅ 匹配: foo.example.com
❌ 不匹配: bar.foo.example.com

证书: f*.com
✅ 匹配: foo.com
❌ 不匹配: bar.com

2. IP地址:

URI: https://192.168.1.1/
证书必须包含: iPAddress subjectAltName
值必须精确匹配: 192.168.1.1

3. 多个身份:

如果证书包含多个 dNSName:
- www.example.com
- api.example.com
- *.app.example.com

← 匹配其中任何一个即可 →

Behavior When No Match (不匹配时的行为)

用户导向的客户端 (浏览器):

  • ✅ 必须通知用户
  • ⚠️ 可以给用户继续的选项
  • 或终止连接

自动化客户端 (API客户端):

  • ✅ 必须记录错误到审计日志
  • ✅ 应该终止连接
  • ⚠️ 可以提供禁用检查的配置选项

Security Warning (安全警告)

URI来源不可信:

攻击场景:
1. 用户点击HTTP页面中的链接
2. HTTP页面本身未加密
3. 中间人可能已替换URI

防护:
用户应仔细检查服务器证书

3.2. Client Identity (客户端身份)

通常情况: 服务器没有客户端身份的外部知识。

如果服务器有外部知识 (来自HTTP或TLS之外):

  • 应该按照上述方式检查身份

客户端证书认证:

常见场景:
- 企业内部系统
- API访问控制
- 双向TLS (mTLS, Mutual TLS)

验证:
- 证书链根植于适当的CA
- 可选: 验证特定的客户端身份

Security Considerations (安全考虑)

本文档全部关于安全

Key Security Points (关键安全要点)

  1. 证书验证是强制性的

    • 客户端必须验证服务器证书
    • 防止中间人攻击
  2. 正确的连接关闭

    • 使用 TLS 关闭警报
    • 检测数据截断攻击
  3. 主机名验证

    • 防止证书替换攻击
    • 使用 subjectAltName 优先于 CN
  4. 警惕不可信的URI

    • 通过 HTTP 获得的 URI 可能被篡改
    • 用户应检查证书

Practical Examples (实践示例)

Complete HTTPS Connection (完整的HTTPS连接)

客户端操作:

1. 解析URI: https://www.example.com/page.html
→ 主机名: www.example.com
→ 端口: 443 (默认)

2. TCP连接到 www.example.com:443

3. TLS握手:
ClientHello →
← ServerHello + Certificate
验证证书中的主机名
...握手完成...

4. 发送加密的HTTP请求:
GET /page.html HTTP/1.1
Host: www.example.com

5. 接收加密的HTTP响应:
HTTP/1.1 200 OK
Content-Length: 1234
...

6. 关闭连接:
发送 closure_alert
关闭TCP连接

Certificate Verification Example (证书验证示例)

# Python示例 (概念性)
import ssl
import socket

# 创建SSL上下文
context = ssl.create_default_context()

# 连接到服务器
sock = socket.create_connection(('www.example.com', 443))
ssock = context.wrap_socket(sock, server_hostname='www.example.com')

# wrap_socket会自动验证:
# 1. 证书链有效
# 2. 主机名匹配
# 3. 证书未过期

# 获取证书信息
cert = ssock.getpeercert()
print(f"Subject: {cert['subject']}")
print(f"Issuer: {cert['issuer']}")
print(f"SANs: {cert.get('subjectAltName', [])}")

Common Error Handling (常见错误处理)

错误1: 证书主机名不匹配
Certificate Hostname Mismatch
- 证书: *.example.com
- 访问: www.different.com
→ 终止连接或警告用户

错误2: 证书过期
Certificate Expired
- Not After: 2023-12-31
- 当前: 2024-01-01
→ 拒绝连接

错误3: 自签名证书
Self-Signed Certificate
- 不在信任的CA列表中
→ 警告用户或拒绝

错误4: 证书链不完整
Incomplete Certificate Chain
- 缺少中间证书
→ 无法验证, 拒绝连接

Relationship to Modern Standards (与现代标准的关系)

Successors to RFC 2818 (RFC 2818的继任者)

虽然 RFC 2818 仍然有效, 但已有更新的规范:

RFC标题说明
RFC 2818HTTP Over TLS本文档 (2000年)
RFC 5246TLS 1.2更新的TLS协议
RFC 8446TLS 1.3最新的TLS协议
RFC 6125证书验证更详细的主机名验证
RFC 7230-7235HTTP/1.1更新的HTTP规范
RFC 7540HTTP/2HTTP/2通常在TLS上运行

Modern Practice Updates (现代实践更新)

  1. TLS版本:
RFC 2818: SSL/TLS (1.0/1.1)
现代: TLS 1.2+ (TLS 1.0/1.1已废弃)
  1. 证书验证:
RFC 2818: 基本规则
RFC 6125: 详细规范
  1. HSTS:
RFC 6797: HTTP Strict Transport Security
强制浏览器使用HTTPS

Quick Reference (快速参考)

HTTPS vs HTTP

特性HTTPHTTPS
协议http://https://
端口80443
加密❌ 明文✅ TLS加密
完整性❌ 无保护✅ MAC保护
认证❌ 无服务器认证✅ 证书认证
隐私❌ 可被窃听✅ 加密传输

TLS Handshake Overview (TLS握手概览)

客户端                           服务器
| |
|--- ClientHello --------------->|
| |
|<-- ServerHello, Certificate ---|
|<-- ServerHelloDone ------------|
| |
|--- ClientKeyExchange --------->|
|--- ChangeCipherSpec ---------->|
|--- Finished ------------------>|
| |
|<-- ChangeCipherSpec -----------|
|<-- Finished -------------------|
| |
|=== 加密通道建立 ================|
| |
|--- 加密的HTTP请求 ------------->|
|<-- 加密的HTTP响应 --------------|

Common Tools (常用工具)

# OpenSSL查看证书
openssl s_client -connect www.example.com:443 -showcerts

# 测试TLS版本
openssl s_client -connect www.example.com:443 -tls1_2

# 查看证书详情
echo | openssl s_client -connect www.example.com:443 2>/dev/null | \
openssl x509 -noout -text

# cURL使用HTTPS
curl -v https://www.example.com

References (参考文献)

Normative References (规范性参考)

  • [RFC 2119] - 关键词定义
  • [RFC 2246] - TLS协议
  • [RFC 2459] - X.509证书和CRL配置文件
  • [RFC 2616] - HTTP/1.1

Informative References (信息性参考)

  • [RFC 2817] - 在HTTP/1.1中升级到TLS
  • [RFC 5246] - TLS 1.2
  • [RFC 6125] - 证书验证中的服务标识表示
  • [RFC 6797] - HTTP严格传输安全 (HSTS)
  • [RFC 7230-7235] - HTTP/1.1更新规范
  • [RFC 8446] - TLS 1.3

Glossary (术语表)

Core Terms (核心术语)

TLS (Transport Layer Security, 传输层安全)

  • 传输层安全协议, SSL的继任者

SSL (Secure Sockets Layer, 安全套接字层)

  • TLS的前身, 已废弃

Certificate (证书)

  • 包含公钥和身份信息的数字文档

CA (Certificate Authority, 证书颁发机构)

  • 签发可信证书的机构

Closure Alert (关闭警报)

  • TLS提供的安全连接关闭机制

Premature Close (过早关闭)

  • 未正确关闭TLS连接

Man-in-the-Middle Attack (中间人攻击)

  • 攻击者拦截并可能修改通信

subjectAltName (Subject Alternative Name, 主体备用名称)

  • 证书扩展, 指定额外的主机名

Common Name (通用名称)

  • 证书主题中的CN字段

返回: RFC文档列表

相关RFC: