Initial commit: ReTeamSpeak cross-platform TeamSpeak client
CI/CD / Build Frontend (push) Failing after 11s
CI/CD / Test (macos-latest) (push) Has been cancelled
CI/CD / Test (windows-latest) (push) Has been cancelled
CI/CD / Build Desktop (linux) (push) Has been cancelled
CI/CD / Build Desktop (macos) (push) Has been cancelled
CI/CD / Build Desktop (windows) (push) Has been cancelled
CI/CD / Release (push) Has been cancelled
CI/CD / Test (ubuntu-latest) (push) Failing after 2s
CI/CD / Build Frontend (push) Failing after 11s
CI/CD / Test (macos-latest) (push) Has been cancelled
CI/CD / Test (windows-latest) (push) Has been cancelled
CI/CD / Build Desktop (linux) (push) Has been cancelled
CI/CD / Build Desktop (macos) (push) Has been cancelled
CI/CD / Build Desktop (windows) (push) Has been cancelled
CI/CD / Release (push) Has been cancelled
CI/CD / Test (ubuntu-latest) (push) Failing after 2s
- tscore: Protocol implementation (packets, crypto, connection handshake) - tsaudio: Audio engine (capture, playback, codec, VAD, jitter buffer) - tsdb: SQLite database (identities, bookmarks, messages, settings) - shared: Core types and events - tauri-app: Tauri v2 desktop application with React frontend - docs: SRS, SAD, SDD documentation - CI/CD: GitHub Actions workflow - 32 unit tests passing
This commit is contained in:
@@ -0,0 +1,417 @@
|
||||
# TeamSpeak 3 协议分析
|
||||
|
||||
## 概述
|
||||
|
||||
TeamSpeak 3 使用基于 UDP 的自定义协议进行通信。协议设计支持加密、压缩和可靠传输。
|
||||
|
||||
## 协议层次
|
||||
|
||||
```
|
||||
应用层 (Commands/Notifications)
|
||||
↓
|
||||
消息层 (Messages)
|
||||
↓
|
||||
数据包层 (Packets)
|
||||
↓
|
||||
传输层 (UDP)
|
||||
```
|
||||
|
||||
## 1. 数据包结构
|
||||
|
||||
### 1.1 数据包头
|
||||
|
||||
**客户端 → 服务器**:
|
||||
```
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+---------//----------+
|
||||
| MAC | PId | CId |PT| Data |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+---------//----------+
|
||||
| \ Meta |
|
||||
\ Header /
|
||||
```
|
||||
|
||||
**服务器 → 客户端**:
|
||||
```
|
||||
+--+--+--+--+--+--+--+--+--+--+--+------------//-------------+
|
||||
| MAC | PId |PT| Data |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+------------//-------------+
|
||||
| \ Meta |
|
||||
\ Header /
|
||||
```
|
||||
|
||||
| 字段 | 大小 | 类型 | 说明 |
|
||||
|------|------|------|------|
|
||||
| MAC | 8 字节 | [u8] | EAX 消息认证码 |
|
||||
| PId | 2 字节 | u16 | 数据包 ID |
|
||||
| CId | 2 字节 | u16 | 客户端 ID (仅客户端→服务器) |
|
||||
| PT | 1 字节 | u8 | 数据包类型 + 标志 |
|
||||
| Data | ≤487/489 字节 | [u8] | 数据包负载 |
|
||||
|
||||
### 1.2 数据包类型
|
||||
|
||||
| 类型 | 值 | 说明 |
|
||||
|------|-----|------|
|
||||
| Voice | 0x00 | 语音数据 |
|
||||
| VoiceWhisper | 0x01 | 私语数据 |
|
||||
| Command | 0x02 | 命令数据 |
|
||||
| CommandLow | 0x03 | 低优先级命令 |
|
||||
| Ping | 0x04 | Ping 包 |
|
||||
| Pong | 0x05 | Pong 包 |
|
||||
| Ack | 0x06 | 确认包 |
|
||||
| AckLow | 0x07 | 低优先级确认 |
|
||||
| Init1 | 0x08 | 初始化包 |
|
||||
|
||||
### 1.3 标志位
|
||||
|
||||
```
|
||||
MSB LSB
|
||||
+--+--+--+--+--+--+--+--+
|
||||
|UE|CP|NP|FR| Type |
|
||||
+--+--+--+--+--+--+--+--+
|
||||
```
|
||||
|
||||
| 标志 | 位 | 说明 |
|
||||
|------|-----|------|
|
||||
| UE | 0x80 | 未加密 |
|
||||
| CP | 0x40 | 已压缩 |
|
||||
| NP | 0x20 | 新协议 |
|
||||
| FR | 0x10 | 已分片 |
|
||||
|
||||
## 2. 初始化握手
|
||||
|
||||
### 2.1 低级握手 (Init1)
|
||||
|
||||
握手过程包含 5 个步骤:
|
||||
|
||||
1. **Packet 0 (客户端→服务器)**:
|
||||
- 客户端版本 (4 字节时间戳)
|
||||
- 步骤号: 0x00
|
||||
- 当前时间戳 (4 字节)
|
||||
- 随机数 A0 (4 字节)
|
||||
- 保留字节 (8 字节)
|
||||
|
||||
2. **Packet 1 (服务器→客户端)**:
|
||||
- 步骤号: 0x01
|
||||
- 服务器数据 A1 (16 字节)
|
||||
- A0 反转 (4 字节)
|
||||
|
||||
3. **Packet 2 (客户端→服务器)**:
|
||||
- 客户端版本
|
||||
- 步骤号: 0x02
|
||||
- A1 (16 字节)
|
||||
- A0r (4 字节)
|
||||
|
||||
4. **Packet 3 (服务器→客户端)**:
|
||||
- 步骤号: 0x03
|
||||
- x (64 字节)
|
||||
- n (64 字节)
|
||||
- level (4 字节)
|
||||
- 服务器数据 A2 (100 字节)
|
||||
|
||||
5. **Packet 4 (客户端→服务器)**:
|
||||
- 客户端版本
|
||||
- 步骤号: 0x04
|
||||
- x, n, level
|
||||
- A2 (100 字节)
|
||||
- y = x^(2^level) mod n (64 字节)
|
||||
- clientinitiv 命令
|
||||
|
||||
### 2.2 高级握手
|
||||
|
||||
#### 2.2.1 clientinitiv (客户端→服务器)
|
||||
```
|
||||
clientinitiv alpha={alpha} omega={omega} ot={ot} ip={ip}
|
||||
```
|
||||
- `alpha`: 10 随机字节的 base64 编码
|
||||
- `omega`: ASN.1-DER 编码的 ECDH 公钥
|
||||
- `ot`: 固定为 1
|
||||
- `ip`: 服务器 IP 地址
|
||||
|
||||
#### 2.2.2 initivexpand/initivexpand2 (服务器→客户端)
|
||||
|
||||
**旧协议 (<3.1)**:
|
||||
```
|
||||
initivexpand alpha={alpha} beta={beta} omega={omega}
|
||||
```
|
||||
|
||||
**新协议 (≥3.1)**:
|
||||
```
|
||||
initivexpand2 l={l} beta={beta} omega={omega} ot={ot} proof={proof} tvd={tvd}
|
||||
```
|
||||
|
||||
#### 2.2.3 共享密钥计算
|
||||
|
||||
**旧协议**:
|
||||
```rust
|
||||
sharedSecret = ECDH(serverPublicKey, ownPrivateKey)
|
||||
x = sharedSecret.x.AsByteArray()
|
||||
sharedData = x[0..32] (填充到 32 字节)
|
||||
SharedIV = sha1(sharedData)
|
||||
SharedIV[0..10] ^= alpha.decode64()
|
||||
SharedIV[10..20] ^= beta.decode64()
|
||||
SharedMac = sha1(SharedIV)[0..8]
|
||||
```
|
||||
|
||||
**新协议**:
|
||||
```rust
|
||||
// 处理许可证链
|
||||
next_key = public_key * clamp(sha512(block[1..])[0..32]) + parent
|
||||
|
||||
// 计算共享密钥
|
||||
sharedData = next_key * client_private_key
|
||||
SharedIV = sha512(sharedData[0..32])
|
||||
SharedIV[0..10] ^= alpha.decode64()
|
||||
SharedIV[10..64] ^= beta.decode64()
|
||||
SharedMac = sha1(SharedIV)[0..8]
|
||||
```
|
||||
|
||||
## 3. 加密机制
|
||||
|
||||
### 3.1 EAX 模式加密
|
||||
|
||||
使用 AES-128-CTR + OMAC (EAX 模式) 加密数据包。
|
||||
|
||||
**加密参数生成**:
|
||||
```rust
|
||||
temporary[0] = 0x30 (服务器→客户端) 或 0x31 (客户端→服务器)
|
||||
temporary[1] = PT
|
||||
temporary[2..6] = PGId (网络字节序)
|
||||
temporary[6..26] = SIV[0..20] (旧协议) 或 temporary[6..70] = SIV[0..64] (新协议)
|
||||
|
||||
keynonce = sha256(temporary)
|
||||
key = keynonce[0..16]
|
||||
nonce = keynonce[16..32]
|
||||
key[0] ^= ((PId & 0xFF00) >> 8)
|
||||
key[1] ^= ((PId & 0x00FF) >> 0)
|
||||
```
|
||||
|
||||
### 3.2 数据包栈
|
||||
|
||||
```
|
||||
发送 接收
|
||||
+-----------+ +-----------+
|
||||
| Data | | Λ | Data |
|
||||
+-----------+ | | +-----------+
|
||||
| Compress | | | | Decompress|
|
||||
+-----------+ | | +-----------+
|
||||
| Split | | | | Merge |
|
||||
+-----------+ | | +-----------+
|
||||
| Encrypt | V | | Decrypt |
|
||||
+-----------+ +-----------+
|
||||
```
|
||||
|
||||
## 4. 命令协议
|
||||
|
||||
### 4.1 命令格式
|
||||
|
||||
命令使用类似 TeamSpeak 3 Query 的文本格式,UTF-8 编码。
|
||||
|
||||
**示例**:
|
||||
```
|
||||
clientinit client_nickname=MyName client_version=3.0.19.3 client_platform=Windows ...
|
||||
```
|
||||
|
||||
### 4.2 消息类型
|
||||
|
||||
1. **请求-响应**: 客户端发送命令,服务器返回响应
|
||||
2. **通知**: 服务器主动推送的事件通知
|
||||
3. **列表**: 分批返回的列表数据
|
||||
|
||||
### 4.3 关键命令
|
||||
|
||||
#### 客户端初始化
|
||||
```
|
||||
clientinit client_nickname client_version client_platform client_input_hardware client_output_hardware client_default_channel client_default_channel_password client_server_password client_meta_data client_version_sign client_key_offset client_nickname_phonetic client_default_token hwid
|
||||
```
|
||||
|
||||
#### 服务器初始化响应
|
||||
```
|
||||
initserver server_name server_platform server_version ...
|
||||
```
|
||||
|
||||
#### 频道列表
|
||||
```
|
||||
channellist -topic -flags -limits
|
||||
channellistfinished
|
||||
```
|
||||
|
||||
#### 客户端进入视图
|
||||
```
|
||||
notifycliententerview cfid ctid reasonid clid client_database_id client_nickname ...
|
||||
```
|
||||
|
||||
## 5. 数据结构
|
||||
|
||||
### 5.1 客户端数据
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| client_id | ClientId | 客户端 ID |
|
||||
| client_database_id | ClientDbId | 数据库 ID |
|
||||
| client_unique_identifier | Uid | 唯一标识符 |
|
||||
| client_nickname | str | 昵称 |
|
||||
| client_type | ClientType | 客户端类型 |
|
||||
| client_servergroups | ServerGroupId | 服务器组 |
|
||||
| client_channel_group_id | ChannelGroupId | 频道组 |
|
||||
| client_away | bool | 是否离开 |
|
||||
| client_away_message | str | 离开消息 |
|
||||
| client_talk_power | i32 | 说话权限 |
|
||||
| client_is_talker | bool | 是否有说话权 |
|
||||
| client_is_priority_speaker | bool | 是否优先发言者 |
|
||||
| client_is_channel_commander | bool | 是否频道指挥官 |
|
||||
| client_is_recording | bool | 是否录音中 |
|
||||
| client_input_muted | bool | 输入是否静音 |
|
||||
| client_output_muted | bool | 输出是否静音 |
|
||||
|
||||
### 5.2 频道数据
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| channel_id | ChannelId | 频道 ID |
|
||||
| channel_name | str | 频道名称 |
|
||||
| channel_topic | str | 频道主题 |
|
||||
| channel_codec | Codec | 编解码器 |
|
||||
| channel_codec_quality | u8 | 编解码器质量 |
|
||||
| channel_maxclients | i32 | 最大客户端数 |
|
||||
| channel_maxfamilyclients | i32 | 最大系列客户端数 |
|
||||
| channel_flag_permanent | bool | 是否永久频道 |
|
||||
| channel_flag_semi_permanent | bool | 是否半永久频道 |
|
||||
| channel_flag_default | bool | 是否默认频道 |
|
||||
| channel_flag_password | bool | 是否有密码 |
|
||||
| channel_needed_talk_power | i32 | 所需说话权限 |
|
||||
| channel_forced_silence | bool | 是否强制静音 |
|
||||
|
||||
### 5.3 服务器数据
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| virtualserver_name | str | 服务器名称 |
|
||||
| virtualserver_platform | str | 平台 |
|
||||
| virtualserver_version | str | 版本 |
|
||||
| virtualserver_maxclients | u16 | 最大客户端数 |
|
||||
| virtualserver_clientsonline | u16 | 在线客户端数 |
|
||||
| virtualserver_channelsonline | u64 | 频道数 |
|
||||
| virtualserver_uptime | DurationSeconds | 运行时间 |
|
||||
| virtualserver_codec_encryption_mode | CodecEncryptionMode | 编解码器加密模式 |
|
||||
| virtualserver_hostmessage | str | 主机消息 |
|
||||
| virtualserver_hostmessage_mode | HostMessageMode | 主机消息模式 |
|
||||
|
||||
## 6. 错误处理
|
||||
|
||||
### 6.1 错误码格式
|
||||
|
||||
错误响应格式:
|
||||
```
|
||||
error id=0 msg=ok
|
||||
```
|
||||
|
||||
### 6.2 常见错误码
|
||||
|
||||
| 错误码 | 名称 | 说明 |
|
||||
|--------|------|------|
|
||||
| 0x0000 | ok | 成功 |
|
||||
| 0x0200 | client_invalid_id | 无效客户端 ID |
|
||||
| 0x0201 | client_nickname_inuse | 昵称已被使用 |
|
||||
| 0x0208 | client_invalid_password | 无效密码 |
|
||||
| 0x0300 | channel_invalid_id | 无效频道 ID |
|
||||
| 0x0400 | server_invalid_id | 无效服务器 ID |
|
||||
| 0x0403 | server_maxclients_reached | 服务器已满 |
|
||||
|
||||
## 7. 版本兼容性
|
||||
|
||||
### 7.1 协议版本
|
||||
|
||||
- **旧协议**: <3.1,使用 initivexpand
|
||||
- **新协议**: ≥3.1,使用 initivexpand2,支持许可证验证
|
||||
|
||||
### 7.2 客户端版本
|
||||
|
||||
客户端版本使用时间戳格式:
|
||||
```
|
||||
3.0.19.3 [Build: 1466672534]
|
||||
```
|
||||
|
||||
版本时间戳计算:
|
||||
```
|
||||
version_timestamp = unix_timestamp - 1356998400
|
||||
```
|
||||
|
||||
## 8. 安全机制
|
||||
|
||||
### 8.1 RSA 拼图
|
||||
|
||||
防止 DoS 攻击的机制:
|
||||
- 服务器发送 RSA 模数 n、底数 x 和难度 level
|
||||
- 客户端计算 y = x^(2^level) mod n
|
||||
- 计算时间随 level 指数增长
|
||||
|
||||
### 8.2 Hashcash
|
||||
|
||||
身份验证的 hashcash 机制:
|
||||
```rust
|
||||
data = sha1(publicKey + keyOffset)
|
||||
level = count_leading_zero_bits(data)
|
||||
```
|
||||
|
||||
### 8.3 身份识别
|
||||
|
||||
客户端唯一标识符计算:
|
||||
```rust
|
||||
uid = base64(sha1(publicKey))
|
||||
```
|
||||
|
||||
## 9. 语音传输
|
||||
|
||||
### 9.1 编解码器
|
||||
|
||||
| 编解码器 | 说明 |
|
||||
|----------|------|
|
||||
| SpeexNarrowband | 8kHz, 单声道 |
|
||||
| SpeexWideband | 16kHz, 单声道 |
|
||||
| SpeexUltrawideband | 32kHz, 单声道 |
|
||||
| CeltMono | 48kHz, 单声道 |
|
||||
| OpusVoice | 48kHz, 单声道, 语音优化 |
|
||||
| OpusMusic | 48kHz, 立体声, 音乐优化 |
|
||||
|
||||
### 9.2 语音包格式
|
||||
|
||||
**客户端→服务器**:
|
||||
```
|
||||
+--+--+--+---------//---------+
|
||||
| VId |C | Data |
|
||||
+--+--+--+---------//---------+
|
||||
```
|
||||
|
||||
**服务器→客户端**:
|
||||
```
|
||||
+--+--+--+--+--+---------//---------+
|
||||
| VId | CId |C | Data |
|
||||
+--+--+--+--+--+---------//---------+
|
||||
```
|
||||
|
||||
### 9.3 私语
|
||||
|
||||
支持两种私语模式:
|
||||
1. **直接目标**: 指定客户端/频道 ID
|
||||
2. **组目标**: 指定服务器组/频道组
|
||||
|
||||
## 10. 连接管理
|
||||
|
||||
### 10.1 心跳
|
||||
|
||||
- 服务器定期发送 Ping 包
|
||||
- 客户端必须回复 Pong 包
|
||||
- 客户端也应主动发送 Ping 包
|
||||
|
||||
### 10.2 可靠传输
|
||||
|
||||
- 使用选择性重传机制
|
||||
- 超时后重传数据包
|
||||
- 30 秒无响应则断开连接
|
||||
- 使用指数退避算法避免网络拥塞
|
||||
|
||||
### 10.3 数据包 ID 管理
|
||||
|
||||
- 每种数据包类型和方向有独立的 ID 计数器
|
||||
- 客户端有 9 个出站计数器
|
||||
- ID 从 1 开始,溢出时增加代计数器
|
||||
- 代计数器用于加密参数生成
|
||||
Reference in New Issue
Block a user