RFC 2818 - 基于 TLS 的 HTTP (HTTPS)
- 状态: Informational
- 发布日期: May 2000
- Stream: IETF
- 被废弃: RFC9110
- 勘误: 无勘误
摘要 (Abstract)
本备忘录描述了如何使用 TLS 保护 Internet 上的 HTTP 连接. 当前的实际做法是将 HTTP 分层运行在 SSL (TLS 的前身) 之上, 通过使用不同的服务器端口来区分安全流量与非安全流量. 本文档记录了使用 TLS 的这一实践. 一份配套文档描述了在与普通 HTTP 相同的端口上使用 HTTP/TLS 的方法 [RFC2817].
重要性 (Importance)
RFC 2818 是 Web 安全的基石:
- 🔒 定义了 HTTPS 的基本机制
- 🌐 现代所有网站的安全基础
- 🔑 证书验证与身份确认
- ⚡ 安全连接的建立与关闭
1. 引言 (Introduction)
HTTP [RFC2616] 最初在 Internet 上以明文形式使用. 然而, 随着 HTTP 在敏感应用中的使用增加, 安全措施变得必不可少. SSL 及其后继者 TLS [RFC2246] 旨在提供面向通道的安全保护. 本文档描述了如何在 TLS 上使用 HTTP.
核心概念 (Core Concept)
HTTPS = HTTP + TLS
┌────────────────────────────────────────┐
│ HTTP/1.1 协议 │
│ (应用层协议) │
├────────────────────────────────────────┤
│ TLS/SSL 协议 │
│ (传输层安全) │
├────────────────────────────────────────┤
│ TCP 协议 │
│ (传输控制协议) │
└────────────────────────────────────────┘
1.1. 需求术语 (Requirements Terminology)
本文档中出现的关键词 "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT" 和 "MAY" 应按照 [RFC2119] 中的描述进行解释.
2. 基于 TLS 的 HTTP (HTTP Over TLS)
核心原则 (Core Principle)
概念上非常简单: HTTP/TLS 非常简单. 只需像在 TCP 上使用 HTTP 一样, 在 TLS 上使用 HTTP 即可.
2.1. 连接发起 (Connection Initiation)
过程:
1. 客户端 → 服务器: 建立 TCP 连接 (端口 443)
2. 客户端 → 服务器: 发送 TLS ClientHello
3. ↔ TLS 握手过程 ↔
4. 握手完成后: 客户端可以发起第一个 HTTP 请求
要求:
- ✅ HTTP 客户端扮演 TLS 客户端的角色
- ✅ 连接到适当的端口 (默认 443)
- ✅ 发送 TLS ClientHello 以开始握手
- ✅ 所有 HTTP 数据 MUST 作为 TLS "application data" (应用数据) 发送
流程示例:
客户端:
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 在关闭连接之前发起关闭警报交换
- ⚠️ 实现 MAY 在发送关闭警报后关闭连接 (无需等待响应)
- ❌ 发生提前关闭的连接 MUST NOT 重用会话
2.2.1. 客户端行为 (Client Behavior)
问题: HTTP 使用连接关闭来表示服务器数据的结束.
客户端 MUST:
- ✅ 将任何提前关闭视为错误
- ✅ 将接收到的数据视为可能已被截断
- ✅ 在关闭连接之前发送关闭警报
特殊情况:
- 无 Content-Length 的响应:
HTTP/1.1 200 OK
Content-Type: text/html
[连接关闭表示结束]
← 提前关闭无法区分是服务器正常关闭还是攻击者干预 →
- 有 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 要求: 服务器 MUST 从客户端的关闭中优雅地恢复.
服务器 SHOULD:
- ✅ 准备好接收来自客户端的不完全关闭
- ✅ 愿意恢复以此种方式关闭的 TLS 会话
- ✅ 尝试与客户端交换关闭警报
- ⚡ MAY 在发送关闭警报后关闭连接
实现说明:
不使用持久连接的 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 格式 (URI Format)
协议标识符: 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)
核心要求: 客户端 MUST 验证服务器身份, 以防止中间人攻击 (man-in-the-middle).
身份验证过程 (Identity Verification Process)
1. 客户端从 URI 中获取主机名
例如: https://www.example.com
2. 服务器在 TLS 握手期间提供证书
3. 客户端检查主机名是否与证书中的身份匹配
身份字段优先级 (Identity Field Priority)
优先级 1: subjectAltName (主题备用名称)
证书中的 subjectAltName 扩展 (dNSName 类型):
dNSName: www.example.com
dNSName: api.example.com
← MUST 使用此字段 (如果存在) →
优先级 2: Common Name (通用名称)
证书 Subject 字段中的 CN:
CN=www.example.com
← 仅在不存在 subjectAltName 时使用 →
← 已弃用, CA 应当使用 dNSName →
匹配规则 (Matching Rules)
1. 通配符匹配 (Wildcard Matching):
证书: *.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)
面向用户的客户端 (如浏览器):
- ✅ MUST 通知用户
- ⚠️ MAY 允许用户选择是否继续连接
- 或者终止连接
自动化客户端 (如 API 客户端):
- ✅ MUST 将错误记录到审计日志中
- ✅ SHOULD 终止连接
- ⚠️ MAY 提供配置选项来禁用此检查
安全警告 (Security Warning)
不可信的 URI 来源:
攻击场景:
1. 用户点击 HTTP 页面中的链接
2. HTTP 页面本身是未加密的
3. 中间人可能已经替换了该 URI
防护措施:
用户应当仔细检查服务器证书
3.2. 客户端身份 (Client Identity)
典型情况: 服务器通常没有关于客户端身份的外部已知信息.
如果服务器具备外部已知信息 (来自 HTTP 或 TLS 之外):
- 应当按照上述方式检查身份
客户端证书认证:
常见场景:
- 企业内部系统
- API 访问控制
- Mutual TLS (双向 TLS, mTLS)
验证:
- 证书链植根于适当的 CA
- 可选: 验证特定的客户端身份
安全考虑 (Security Considerations)
本文档的全部内容都与安全有关.
关键安全点 (Key Security Points)
-
证书验证是强制性的
- 客户端 MUST 验证服务器证书
- 防止中间人攻击
-
正确的连接关闭
- 使用 TLS 关闭警报
- 检测数据截断攻击
-
主机名验证
- 防止证书替换攻击
- 相比于 CN, 优先使用 subjectAltName
-
警惕不可信的 URI
- 通过 HTTP 获取的 URI 可能会被篡改
- 用户应当仔细检查证书
实用示例 (Practical Examples)
完整的 HTTPS 连接 (Complete HTTPS Connection)
客户端操作:
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
- Current: 2024-01-01
→ 拒绝连接
错误 3: 自签名证书 (Self-Signed Certificate)
- 不在受信任的 CA 列表中
→ 警告用户或拒绝连接
错误 4: 证书链不完整 (Incomplete Certificate Chain)
- 缺少中间证书
→ 无法验证, 拒绝连接
与现代标准的关系 (Relationship to Modern Standards)
RFC 2818 的后续标准 (Successors to RFC 2818)
虽然 RFC 2818 仍然有效, 但已有更新的规范:
| RFC | 标题 | 说明 |
|---|---|---|
| RFC 2818 | HTTP Over TLS | 本文档 (2000) |
| RFC 5246 | TLS 1.2 | 更新的 TLS 协议 |
| RFC 8446 | TLS 1.3 | 最新的 TLS 协议 |
| RFC 6125 | Certificate Validation | 更详细的主机名验证 |
| RFC 7230-7235 | HTTP/1.1 | 更新的 HTTP 规范 |
| RFC 7540 | HTTP/2 | HTTP/2 通常运行在 TLS 之上 |
现代实践更新 (Modern Practice Updates)
- TLS 版本:
RFC 2818: SSL/TLS (1.0/1.1)
现代实践: TLS 1.2+ (TLS 1.0/1.1 已弃用)
- 证书验证:
RFC 2818: 基本规则
RFC 6125: 详细规范
- HSTS:
RFC 6797: HTTP Strict Transport Security
强制浏览器使用 HTTPS
快速参考 (Quick Reference)
HTTPS vs HTTP
| 特性 | HTTP | HTTPS |
|---|---|---|
| 协议 | http:// | https:// |
| 端口 | 80 | 443 |
| 加密 | ❌ 明文 | ✅ TLS 加密 |
| 完整性 | ❌ 无保护 | ✅ MAC 保护 |
| 认证 | ❌ 无服务器认证 | ✅ 证书认证 |
| 隐私 | ❌ 可被窃听 | ✅ 加密传输 |
TLS 握手概述 (TLS Handshake Overview)
客户端 服务器
| |
|--- 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] - Key words for use in RFCs to Indicate Requirement Levels
- [RFC 2246] - The TLS Protocol
- [RFC 2459] - Internet X.509 Public Key Infrastructure Certificate and CRL Profile
- [RFC 2616] - Hypertext Transfer Protocol -- HTTP/1.1
资料性引用 (Informative References)
- [RFC 2817] - Upgrading to TLS Within HTTP/1.1
- [RFC 5246] - The Transport Layer Security (TLS) Protocol Version 1.2
- [RFC 6125] - Representation and Verification of Domain-Based Application Service Identity
- [RFC 6797] - HTTP Strict Transport Security (HSTS)
- [RFC 7230-7235] - Hypertext Transfer Protocol (HTTP/1.1) Updated Specifications
- [RFC 8446] - The Transport Layer Security (TLS) Protocol Version 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 (主题备用名称)
- 指定额外主机名的证书扩展
Common Name (通用名称)
- 证书 Subject 中的 CN 字段
返回: RFC 文档列表
相关 RFC: