You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OnlineMsgServer/ReadMe.md

203 lines
5.2 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# OnlineMsgServer
在线消息中转服务WebSocket + RSA支持客户端鉴权、单播转发、广播、签名校验、防重放、限流。
## 当前默认行为
- 服务端默认 `REQUIRE_WSS=false`(便于内外网测试)
- 仍支持 `WSS(TLS)`,可通过环境变量启用
- 客户端需要完成 challenge-response 鉴权后才能发业务消息
## 快速开始
### 1) 测试模式(推荐先跑通)
```bash
cd /Users/solux/Codes/OnlineMsgServer
bash deploy/deploy_test_ws.sh
```
这个脚本会自动:
- 生成/复用服务端 RSA 私钥(`deploy/keys`
- 构建镜像并重启容器
-`REQUIRE_WSS=false` 启动服务
- 输出可直接使用的 `ws://` 地址
### 2) 安全模式WSS + 局域网证书)
```bash
cd /Users/solux/Codes/OnlineMsgServer
bash deploy/redeploy_with_lan_cert.sh
```
这个脚本会自动:
- 重新生成带当前 LAN IP 的 TLS 证书(`deploy/certs`
- 构建镜像并重启容器
-`REQUIRE_WSS=true` 启动服务
- 输出可直接使用的 `wss://` 地址
### 3) 生产准备(证书 + 镜像 + 部署产物)
```bash
cd /Users/solux/Codes/OnlineMsgServer
DOMAIN=chat.example.com \
TLS_CERT_PEM=/path/fullchain.pem \
TLS_KEY_PEM=/path/privkey.pem \
TLS_CHAIN_PEM=/path/chain.pem \
CERT_PASSWORD='change-me' \
bash deploy/prepare_prod_release.sh
```
脚本会自动:
- 准备服务端协议私钥(`deploy/keys`
- 生成运行时 `server.pfx``deploy/certs`
- 构建生产镜像(默认 `onlinemsgserver:prod`
- 导出部署产物到 `deploy/output/prod``prod.env`、镜像 tar、运行示例脚本
如果你暂时没有 CA 证书,也可用自签名兜底(仅测试):
```bash
DOMAIN=chat.example.com SAN_LIST='DNS:www.chat.example.com,IP:10.0.0.8' GENERATE_SELF_SIGNED=true bash deploy/prepare_prod_release.sh
```
## 手动 Docker 启动示例
### WS测试
```bash
docker run -d --name onlinemsgserver --restart unless-stopped \
-p 13173:13173 \
-v /Users/solux/Codes/OnlineMsgServer/deploy/keys:/app/keys:ro \
-e REQUIRE_WSS=false \
-e SERVER_PRIVATE_KEY_PATH=/app/keys/server_rsa_pkcs8.b64 \
onlinemsgserver:latest
```
### WSS生产/半生产)
```bash
docker run -d --name onlinemsgserver --restart unless-stopped \
-p 13173:13173 \
-v /Users/solux/Codes/OnlineMsgServer/deploy/certs:/app/certs:ro \
-v /Users/solux/Codes/OnlineMsgServer/deploy/keys:/app/keys:ro \
-e REQUIRE_WSS=true \
-e TLS_CERT_PATH=/app/certs/server.pfx \
-e TLS_CERT_PASSWORD=changeit \
-e SERVER_PRIVATE_KEY_PATH=/app/keys/server_rsa_pkcs8.b64 \
onlinemsgserver:latest
```
## 协议说明(客户端 -> 服务端)
### 加密方式
- RSA-2048-OAEP-SHA256
- 明文分块 190 字节加密
- 密文按 256 字节分块解密
- 传输格式为 base64 字符串
### 通用包结构
```json
{
"type": "publickey|forward|broadcast",
"key": "",
"data": {}
}
```
### 1) 鉴权登记 `type=publickey`
- `key`:用户名(可空)
- `data`
```json
{
"publicKey": "客户端公钥(base64 SPKI)",
"challenge": "服务端下发挑战值",
"timestamp": 1739600000,
"nonce": "随机字符串",
"signature": "签名(base64)"
}
```
签名串:
```text
publickey\n{userName}\n{publicKey}\n{challenge}\n{timestamp}\n{nonce}
```
### 2) 单播转发 `type=forward`
- `key`:目标公钥
- `data`
```json
{
"payload": "消息内容",
"timestamp": 1739600000,
"nonce": "随机字符串",
"signature": "签名(base64)"
}
```
签名串:
```text
forward\n{targetPublicKey}\n{payload}\n{timestamp}\n{nonce}
```
### 3) 广播 `type=broadcast`
- `key`:可空
- `data`:同 `forward`
签名串:
```text
broadcast\n{key}\n{payload}\n{timestamp}\n{nonce}
```
### 连接流程
1. 客户端连接后,服务端先返回未加密 `publickey`含服务端公钥、challenge、TTL、证书指纹
2. 客户端发送签名鉴权包(`type=publickey`)。
3. 鉴权成功后发送 `forward` / `broadcast` 业务包。
## 环境变量
- `LISTEN_PORT`:监听端口(默认 `13173`
- `REQUIRE_WSS`:是否启用 WSS默认 `false`
- `TLS_CERT_PATH`证书路径WSS 必填)
- `TLS_CERT_PASSWORD`:证书密码(可空)
- `SERVER_PRIVATE_KEY_B64`服务端私钥PKCS8 base64
- `SERVER_PRIVATE_KEY_PATH`:服务端私钥文件路径(与上面二选一)
- `ALLOW_EPHEMERAL_SERVER_KEY`:允许仅内存临时私钥(默认 `false`
- `MAX_CONNECTIONS`:最大连接数
- `MAX_MESSAGE_BYTES`:最大消息字节数
- `RATE_LIMIT_COUNT`:限流窗口内最大消息数
- `RATE_LIMIT_WINDOW_SECONDS`:限流窗口秒数
- `IP_BLOCK_SECONDS`:触发滥用后 IP 封禁秒数
- `CHALLENGE_TTL_SECONDS`challenge 有效期
- `MAX_CLOCK_SKEW_SECONDS`:允许时钟偏差
- `REPLAY_WINDOW_SECONDS`:防重放窗口
## 前端React
前端目录:`/Users/solux/Codes/OnlineMsgServer/web-client`
```bash
cd /Users/solux/Codes/OnlineMsgServer/web-client
npm install
npm run dev
```
当前前端能力:
- 默认隐藏协议细节,手动地址放在“高级连接设置”
- 支持广播/私聊、查看并复制自己的公钥
- 每条消息支持一键复制
- 自动处理超长消息换行,不溢出消息框
- 用户名和客户端私钥本地持久化,刷新后继续使用
更多前端说明见 `web-client/README.md`