跳到主要内容

10. 安全考虑

WebSocket 协议的设计考虑了多种安全威胁. 本章描述主要安全考虑和建议的缓解措施.

10.1 非浏览器客户端

WebSocket 协议可由任何客户端使用, 不限于 Web 浏览器. 非浏览器客户端没有浏览器同源策略的保护.

风险:

  • 可以伪造 Origin 头部
  • 可以绕过 CORS 限制
  • 可以发起大量连接

缓解措施:

  • 服务器必须实现额外认证
  • 使用令牌验证, 例如 JWT
  • 实施速率限制
  • 验证所有输入数据
// Server-side verification example
function verifyClient(info, callback) {
const allowedOrigins = ['https://example.com'];
if (!allowedOrigins.includes(info.origin)) {
callback(false, 403, 'Forbidden');
return;
}

const token = info.req.url.split('?token=')[1];
if (!isValidToken(token)) {
callback(false, 401, 'Unauthorized');
return;
}

callback(true);
}

10.2 Origin 考虑

Origin 头部是一项关键安全机制.

推荐做法:

  1. 验证 Origin: 服务器应验证 Origin 头部
  2. 白名单方式: 使用白名单而不是黑名单
  3. 动态 Origin: 如果需要动态 Origin, 使用数据库配置

注意: 非浏览器客户端可以伪造 Origin, 因此不要只依赖 Origin 验证.

10.3 针对基础设施的攻击

缓存投毒攻击

WebSocket 使用掩码机制来防止缓存投毒:

  • 所有客户端到服务器的帧 MUST 进行掩码处理
  • 服务器到客户端的帧 MUST NOT 进行掩码处理
  • 使用随机掩码密钥

中间人攻击

缓解措施:

  • 使用 wss:// (TLS 加密)
  • 验证服务器证书
  • 实现证书固定
// Browser: Always use wss://
const ws = new WebSocket('wss://example.com/socket');

// Server: Enforce TLS
if (!request.connection.encrypted) {
response.status(403).send('TLS required');
}

10.4 实现特定限制

实现应设置合理限制, 以防止资源耗尽攻击.

推荐限制

1. 消息大小限制

const MAX_MESSAGE_SIZE = 1024 * 1024; // 1MB

ws.on('message', (data) => {
if (data.length > MAX_MESSAGE_SIZE) {
ws.close(1009, 'Message too big');
}
});

2. 连接数量限制

const MAX_CONNECTIONS = 10000;
const connections = new Set();

function acceptConnection(ws) {
if (connections.size >= MAX_CONNECTIONS) {
ws.close(1008, 'Server overloaded');
return false;
}
connections.add(ws);
return true;
}

3. 消息速率限制

const RATE_LIMIT = 100; // 100 messages per second

function checkRateLimit(clientId) {
const count = messageCount.get(clientId) || 0;
if (count > RATE_LIMIT) {
return false;
}
messageCount.set(clientId, count + 1);
return true;
}

10.5 WebSocket 客户端认证

认证方法

1. 握手期间的 Cookie 认证 2. URL 参数中的令牌 3. 首条消息认证 4. 自定义握手头部

10.6 连接保密性和完整性

TLS/SSL 要求

生产环境必须使用 wss://:

TLS 优点:

  • 加密所有传输数据
  • 防止窃听
  • 防止数据篡改
  • 服务器认证

ws:// 风险:

  • 明文传输
  • 容易被截获
  • 无法验证服务器身份

10.7 无效数据处理

实现必须正确处理无效数据, 以防止安全漏洞.

无效 UTF-8 文本

协议违规

检测到协议违规时, 连接 MUST 被关闭.

10.8 WebSocket 握手对 SHA-1 的使用

握手使用 SHA-1 哈希算法. 虽然 SHA-1 存在已知碰撞攻击, 但在握手上下文中是安全的.

安全检查清单

实现 WebSocket 服务时, 请检查:

  • 使用 wss:// (TLS) 而不是 ws://
  • 验证 Origin 头部
  • 实现认证和授权
  • 设置消息大小限制
  • 设置连接数量限制
  • 实施速率限制
  • 验证所有输入数据
  • 正确处理协议违规
  • 记录安全事件
  • 定期更新 TLS 配置
  • 监控异常连接模式
  • 实现超时机制

参考链接