保护 WebSocket 流量
WebSocket 通过单个 TCP 连接提供持久的双向通信。初始连接建立后,客户端和服务器可以相互交换消息,无需为每次交互都创建新的 HTTP 请求。这使 WebSocket 适用于实时数据流、聊天、协作应用、多人游戏以及其他需要低延迟更新的工作负载。
每个 WebSocket 连接都从 HTTP 升级请求开始。网关必须在握手期间、连接成为持久通信通道之前完成身份认证决策。APISIX 可以将身份认证插件应用于升级请求,并在允许协议切换前拒绝未授权的客户端。
本指南会配置 key-auth 插件,并使用能在握手中添加凭证请求头的命令行客户端 websocat,验证被拒绝和已认证的连接。浏览器 WebSocket API 不允许应用设置任意请求头,因此浏览器应用应使用符合其客户端架构的身份认证方法和凭证传输方式。如果其他 APISIX 身份认证插件更适合该客户端和应用,同一握手也可以使用这些插件。
前置条件
- 安装 Docker。
- 安装 cURL,以通过 Admin API 配置 APISIX。
- 安装 websocat,以建立 WebSocket 连接。
- 按照入门教程在 Docker 中启动 APISIX 实例。
启动 WebSocket 上游
将 GATEWAY_CONTAINER 设置为正在运行的 APISIX 容器。 创建专用网络,并将网关连接到该网络:
export GATEWAY_CONTAINER=replace-with-apisix-container-name
docker network create gateway-websocket-net
docker network connect gateway-websocket-net "$GATEWAY_CONTAINER"
在共享网络上启动已固定版本的 WebSocket 示例服务器:
docker run -d \
--name websocket-server \
--network gateway-websocket-net \
jmalloc/echo-server:v0.3.7
该服务器公开了 /.ws 端点,并会回显收到的每条消息。
创建路由
创建一条启用 WebSocket 代理并要求 key-auth 凭证的路由:
- Admin API
- ADC
curl "http://127.0.0.1:9180/apisix/admin/routes/websocket-auth" -X PUT \
-d '{
"uri": "/.ws",
"enable_websocket": true,
"plugins": {
"key-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"websocket-server:8080": 1
}
}
}'
route.yaml
services:
- name: websocket-auth
labels:
docs-example: secure-websocket-traffic
routes:
- name: websocket-auth
uris:
- /.ws
enable_websocket: true
plugins:
key-auth: {}
upstream:
type: roundrobin
nodes:
- host: websocket-server
port: 8080
weight: 1
创建消费者
创建名为 john 的消费者,并为其配置 key-auth 凭证:
- Admin API
- ADC
创建消费者:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-d '{
"username": "john"
}'
创建凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/john/credentials" -X PUT \
-d '{
"id": "john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'
consumer.yaml
consumers:
- username: john
labels:
docs-example: secure-websocket-traffic
credentials:
- name: john-key-auth
type: key-auth
config:
key: john-key
ADC 会将服务和消费者作为期望状态进行对账。预览由此示例管理的更改,并确认差异中不包含意外的更新或删除:
adc diff -f route.yaml -f consumer.yaml \
--include-resource-type service \
--include-resource-type consumer \
--label-selector docs-example=secure-websocket-traffic
同步经审查的服务和消费者配置:
adc sync -f route.yaml -f consumer.yaml \
--include-resource-type service \
--include-resource-type consumer \
--label-selector docs-example=secure-websocket-traffic