HTTP/HTTPS 协议
HTTP 协议基础
请求方法
| 方法 | 语义 | 幂等 | 安全 | 常见场景 |
|---|---|---|---|---|
| GET | 获取资源 | ✅ | ✅ | 查询数据 |
| POST | 创建资源 | ❌ | ❌ | 提交表单 |
| PUT | 替换资源 | ✅ | ❌ | 全量更新 |
| PATCH | 部分更新 | ❌ | ❌ | 增量更新 |
| DELETE | 删除资源 | ✅ | ❌ | 删除数据 |
| HEAD | 获取响应头 | ✅ | ✅ | 检查资源是否存在 |
| OPTIONS | 预检请求 | ✅ | ✅ | CORS 跨域 |
HTTP 状态码
| 范围 | 分类 | 常见状态码 |
|---|---|---|
| 1xx | 信息 | 100 Continue、101 Switching Protocols |
| 2xx | 成功 | 200 OK、201 Created、204 No Content |
| 3xx | 重定向 | 301 永久重定向、302 临时重定向、304 Not Modified |
| 4xx | 客户端错误 | 400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found、429 Too Many Requests |
| 5xx | 服务端错误 | 500 Internal Error、502 Bad Gateway、503 Service Unavailable、504 Gateway Timeout |
运维必记状态码
- 502 Bad Gateway:Nginx/LB 无法连接后端。检查后端服务是否存活。
- 503 Service Unavailable:服务过载或维护中。检查后端容量、限流配置。
- 504 Gateway Timeout:后端响应超时。检查
proxy_read_timeout配置和后端处理时间。 - 301 vs 302:301 浏览器会缓存重定向,302 不缓存。域名迁移用 301。
HTTP 版本对比
| 特性 | HTTP/1.0 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|---|
| 连接方式 | 短连接 | Keep-Alive | 多路复用 | 多路复用 |
| 队头阻塞 | 有 | 有 | 应用层解决 | 完全解决 |
| 头部压缩 | 无 | 无 | HPACK | QPACK |
| 服务端推送 | 无 | 无 | ✅ | ✅ |
| 传输层 | TCP | TCP | TCP | QUIC (UDP) |
| 加密 | 可选 | 可选 | 事实上必须 TLS | 强制 TLS 1.3 |
HTTPS 与 TLS
TLS 握手流程(TLS 1.2)
TLS 1.3 优化
TLS 1.3 优势
- 更快:1-RTT 握手(TLS 1.2 需要 2-RTT),支持 0-RTT 恢复
- 更安全:移除了不安全的密码套件(RC4、3DES、SHA-1 等)
- 推荐所有新服务使用 TLS 1.3
证书管理
# 查看证书信息
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -text -noout
# 检查证书过期时间
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
# 验证证书链
openssl verify -CAfile ca-bundle.crt server.crt
# 生成自签名证书(测试用)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes \
-subj "/CN=example.com"
Let's Encrypt 免费证书
# 安装 certbot
apt install certbot python3-certbot-nginx # Debian/Ubuntu
yum install certbot python3-certbot-nginx # CentOS
# 申请证书(自动配置 Nginx)
certbot --nginx -d example.com -d www.example.com
# 申请证书(手动模式,不修改 Nginx 配置)
certbot certonly --webroot -w /var/www/html -d example.com
# 证书续期(建议加入 crontab)
certbot renew --dry-run # 测试续期
certbot renew # 正式续期
# 自动续期 crontab
0 3 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
证书过期是常见事故
建议设置证书过期监控:
#!/bin/bash
# 证书过期检查脚本
DOMAIN="example.com"
DAYS_WARN=30
EXPIRY=$(echo | openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} 2>/dev/null | \
openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt $DAYS_WARN ]; then
echo "WARNING: ${DOMAIN} 证书将在 ${DAYS_LEFT} 天后过期!"
# 发送告警通知
fi
HTTP 运维实践
curl 常用技巧
# 基础请求
curl -v https://example.com # 显示详细信息(含 TLS 握手)
curl -I https://example.com # 只获取响应头
curl -o /dev/null -s -w "HTTP %{http_code} | %{time_total}s\n" URL # 状态码+耗时
# 指定请求方法和数据
curl -X POST -d '{"key":"value"}' -H "Content-Type: application/json" URL
# 跟踪重定向
curl -L URL # 自动跟随重定向
curl -L -w "重定向次数: %{num_redirects}\n" URL
# 下载文件
curl -O URL # 保存原文件名
curl -o output.file URL # 指定文件名
curl -C - URL # 断点续传
# 测试性能
curl -o /dev/null -s -w \
"DNS: %{time_namelookup}s\n\
TCP: %{time_connect}s\n\
TLS: %{time_appconnect}s\n\
首字节: %{time_starttransfer}s\n\
总时间: %{time_total}s\n\
HTTP状态: %{http_code}\n" \
https://example.com
# 指定 Host 头(不经过 DNS 解析)
curl -H "Host: example.com" http://10.0.0.1/
# 忽略证书验证(仅调试用)
curl -k https://self-signed.example.com
HTTP 缓存头
# 强缓存
Cache-Control: max-age=31536000 # 缓存 1 年
Cache-Control: no-cache # 每次需要验证
Cache-Control: no-store # 不缓存
# 协商缓存
ETag: "abc123" # 内容哈希
Last-Modified: Wed, 01 Jan 2024 # 最后修改时间
# CDN 相关
Cache-Control: s-maxage=3600 # CDN 缓存时间(覆盖 max-age)
Vary: Accept-Encoding # 区分 gzip/br 缓存
HTTP 安全头
nginx.conf - 安全头配置
# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN" always;
# 防止 MIME 嗅探
add_header X-Content-Type-Options "nosniff" always;
# XSS 保护
add_header X-XSS-Protection "1; mode=block" always;
# HSTS(强制 HTTPS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 内容安全策略
add_header Content-Security-Policy "default-src 'self'" always;
# Referrer 控制
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
抓包分析
tcpdump 抓 HTTP 流量
# 抓取 80 端口 HTTP 明文流量
tcpdump -i eth0 port 80 -A | grep -E "^(GET|POST|HTTP/)"
# 抓取并保存为 pcap 文件(用 Wireshark 分析)
tcpdump -i eth0 port 443 -w https_traffic.pcap -c 1000
# 抓取特定主机的流量
tcpdump -i any host 10.0.0.1 and port 80
# 只抓 SYN 包(分析连接建立)
tcpdump -i eth0 "tcp[tcpflags] & (tcp-syn) != 0"
常见面试问题
Q1: HTTP 和 HTTPS 的区别?
答案:
| 维度 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 加密 | 明文传输 | TLS/SSL 加密 |
| 证书 | 不需要 | 需要 CA 证书 |
| 性能 | 无额外开销 | TLS 握手增加延迟 |
| SEO | 无优势 | Google 优先收录 |
HTTPS = HTTP + TLS,在 TCP 连接建立后、HTTP 请求前,增加了 TLS 握手,协商对称密钥后加密通信。
Q2: 502 Bad Gateway 如何排查?
答案:
502 表示反向代理(Nginx/LB)无法连接到后端服务。排查步骤:
- 后端服务是否存活:
ss -tlnp | grep PORT、systemctl status 服务 - 后端日志:查看应用日志是否有 OOM、崩溃
- Nginx 日志:
/var/log/nginx/error.log,关注upstream错误 - 连接被拒:防火墙、安全组、SELinux
- 超时配置:
proxy_connect_timeout、proxy_read_timeout - 资源耗尽:后端端口、文件描述符、内存
Q3: 如何用 curl 排查 HTTPS 证书问题?
答案:
# 查看完整 TLS 握手信息
curl -v https://example.com 2>&1 | grep -A 10 "SSL connection"
# 查看证书详情
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \
openssl x509 -text -noout | head -20
# 常见证书错误:
# - SSL certificate problem: certificate has expired → 证书过期
# - SSL certificate problem: unable to get local issuer certificate → 缺少中间证书
# - SSL: no alternative certificate subject name matches → 域名不匹配
Q4: HTTP/2 相比 HTTP/1.1 的优势?
答案:
- 多路复用:单连接上并行传输多个请求/响应,解决了 HTTP/1.1 的队头阻塞
- 头部压缩(HPACK):减少重复头部传输,降低带宽消耗
- 二进制分帧:更高效的协议解析
- Server Push:服务端主动推送资源
- 流优先级:可以设置请求优先级
Nginx 开启 HTTP/2:
listen 443 ssl http2;