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):
- ✅ 将任何过早关闭视为错误
- ✅ 将收到的数据视为可能被截断
- ✅ 发送关闭警报后再关闭连接
特殊情况:
- 没有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要求: 服务器必须优雅地从客户端关闭中恢复。
服务器应该:
- ✅ 准备好接收来自客户端的不完整关闭
- ✅ 愿意恢复这样关闭的 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 (关键安全要点)
-
证书验证是强制性的
- 客户端必须验证服务器证书
- 防止中间人攻击
-
正确的连接关闭
- 使用 TLS 关闭警报
- 检测数据截断攻击
-
主机名验证
- 防止证书替换攻击
- 使用 subjectAltName 优先于 CN
-
警惕不可信的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 2818 | HTTP Over TLS | 本文档 (2000年) |
| RFC 5246 | TLS 1.2 | 更新的TLS协议 |
| RFC 8446 | TLS 1.3 | 最新的TLS协议 |
| RFC 6125 | 证书验证 | 更详细的主机名验证 |
| 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 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: