Update
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
---
|
||||
tags: [CS, DB, database]
|
||||
create time: 2026-04-17
|
||||
---
|
||||
|
||||
# 数据库
|
||||
|
||||
## 概述
|
||||
|
||||
数据库是有组织的数据集合,数据库管理系统(DBMS)是一套管理数据的软件系统,用于创建、维护和访问数据库。
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 关系型数据库
|
||||
- SQL语言
|
||||
- 表结构设计
|
||||
- 索引与查询优化
|
||||
- 事务处理(ACID)
|
||||
- 规范化理论
|
||||
|
||||
### NoSQL数据库
|
||||
- 文档型数据库(MongoDB)
|
||||
- 键值数据库(Redis)
|
||||
- 列族数据库(Cassandra)
|
||||
- 图数据库(GraphDB)
|
||||
|
||||
### 数据库设计
|
||||
- 实体关系模型(ER)
|
||||
- 数据建模
|
||||
- 性能调优
|
||||
- 分库分表
|
||||
|
||||
### ACID特性
|
||||
- 原子性(Atomicity)
|
||||
- 一致性(Consistency)
|
||||
- 隔离性(Isolation)
|
||||
- 持久性(Durability)
|
||||
|
||||
## 学习重点
|
||||
|
||||
- SQL语言精通
|
||||
- 数据库选型与设计
|
||||
- 查询性能优化
|
||||
- 事务处理机制
|
||||
> 数据库备份与恢复
|
||||
|
||||
## 实践建议
|
||||
|
||||
- 在实际项目中应用
|
||||
- 使用不同类型数据库
|
||||
- 学习SQL调优技巧
|
||||
- 理解分布式数据库
|
||||
@@ -0,0 +1,553 @@
|
||||
---
|
||||
tags: [CS, NET, security, authorization, web, authentication-flow]
|
||||
create time: 2026-04-17
|
||||
---
|
||||
|
||||
# Web Application Authorization Flow
|
||||
|
||||
## 概述
|
||||
|
||||
**Authorization(授权)** 在 Web 应用中是 HTTP 层面的认证令牌验证机制。本文聚焦浏览器、服务器、Token 的交互流程和加密验证过程。
|
||||
|
||||
## HTTP Authorization 流程
|
||||
|
||||
### 完整授权流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant B as Browser
|
||||
participant S as Server
|
||||
participant DB as Database
|
||||
|
||||
Note over B,S: 1. 登录获取 Token
|
||||
B->>S: POST /login (username, password)
|
||||
S->>DB: 验证凭证
|
||||
DB-->>S: 用户数据
|
||||
S->>S: HMAC-SHA256(payload, secret)
|
||||
S-->>B: {access_token: "eyJhbGc...", expires_in: 3600}
|
||||
|
||||
Note over B,S: 2. 带授权头访问资源
|
||||
B->>B: 存储 Token (LocalStorage/Memory)
|
||||
B->>S: GET /api/resource
|
||||
Note right of B: Authorization: Bearer eyJhbGc...
|
||||
|
||||
Note over S: 3. 验证 Token
|
||||
S->>S: 提取 Token
|
||||
S->>S: 验证签名 (HMAC)
|
||||
S->>S: 检查过期时间
|
||||
S->>S: 验证 Issuer/Audience
|
||||
S->>DB: 根据 user_id 查询权限
|
||||
|
||||
Note over S: 4. 授权决策
|
||||
alt Token 有效
|
||||
S-->>B: 200 OK + 数据
|
||||
else Token 无效
|
||||
S-->>B: 401 Unauthorized
|
||||
else 权限不足
|
||||
S-->>B: 403 Forbidden
|
||||
end
|
||||
```
|
||||
|
||||
### JWT Token 验证过程
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[接收 Authorization: Bearer <token>] --> B[解析三部分]
|
||||
B --> C[Header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9]
|
||||
B --> D[Payload: eyJ1c2VyX2lkIjoiMTIzIiw...]
|
||||
B --> E[Signature: SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c]
|
||||
|
||||
C --> F[获取签名算法 HS256]
|
||||
D --> G[获取用户数据]
|
||||
E --> H[签名部分]
|
||||
|
||||
F --> I[重新计算签名]
|
||||
G --> I
|
||||
H --> I
|
||||
|
||||
I --> J{签名匹配?}
|
||||
J -->|是| K[检查过期时间 exp]
|
||||
J -->|否| L[拒绝: 401 Unauthorized]
|
||||
|
||||
K -->|未过期| M[检查 nbf 时间]
|
||||
K -->|已过期| L
|
||||
|
||||
M -->|有效| N[检查 iss 签发者]
|
||||
M -->|无效| L
|
||||
|
||||
N -->|匹配| O[验证通过]
|
||||
N -->|不匹配| L
|
||||
|
||||
O --> P[从 payload 提取 user_id]
|
||||
P --> Q[查询用户权限]
|
||||
Q --> R[返回受保护资源]
|
||||
```
|
||||
|
||||
## 浏览器行为详解
|
||||
|
||||
### 浏览器如何处理 Authorization
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[用户请求资源] --> B[检查 Token]
|
||||
B --> C{Token 存在于?}
|
||||
|
||||
C -->|LocalStorage| D[从 LS 读取]
|
||||
C -->|SessionStorage| E[从 SS 读取]
|
||||
C -->|Memory| F[从变量读取]
|
||||
C -->|Cookie| G[浏览器自动发送]
|
||||
|
||||
D --> H[构造 Authorization Header]
|
||||
E --> H
|
||||
F --> H
|
||||
G --> I[无需手动添加<sup>*</sup>]
|
||||
|
||||
H --> J[发起 XHR/Fetch 请求]
|
||||
I --> J
|
||||
|
||||
J --> K[设置 headers]
|
||||
K --> L[发送到服务器]
|
||||
|
||||
style G fill:#ff9999
|
||||
style H fill:#90EE90
|
||||
style I fill:#90EE90
|
||||
|
||||
subgraph 注
|
||||
G1[Cookie 方式需要 SameSite 属性]
|
||||
G2[防止 CSRF 攻击]
|
||||
end
|
||||
|
||||
G1 -.-> G
|
||||
G2 -.-> G
|
||||
```
|
||||
|
||||
**浏览器自动发送 Cookie,但需要手动添加 Bearer Token**
|
||||
|
||||
### 浏览器存储 Token 的方式
|
||||
|
||||
| 存储方式 | 特点 | 安全性 | 跨域访问 |
|
||||
|---------|------|--------|---------|
|
||||
| LocalStorage | 持久化,手动管理 | ❌ XSS 风险 | ✅ 支持 |
|
||||
| SessionStorage | 会话结束清除 | ❌ XSS 风险 | ❌ 仅同源 |
|
||||
| Memory | 页面刷新丢失 | ✅ 最安全 | ❌ 仅当前页面 |
|
||||
| Cookie | 可设置 HttpOnly | ✅ 防 XSS | ⚠️ 需 SameSite |
|
||||
|
||||
### 前端实现 (JavaScript)
|
||||
|
||||
```javascript
|
||||
// 1. 登录后存储 Token
|
||||
async function login(username, password) {
|
||||
const response = await fetch('/api/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password })
|
||||
});
|
||||
|
||||
const { access_token } = await response.json();
|
||||
localStorage.setItem('token', access_token);
|
||||
}
|
||||
|
||||
// 2. 带认证头访问 API
|
||||
async function fetchProtectedResource() {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
const response = await fetch('/api/resource', {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
// Token 过期,需要刷新或重新登录
|
||||
handleTokenExpired();
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// 3. Axios 拦截器自动添加 Token
|
||||
axios.interceptors.request.use(config => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
});
|
||||
```
|
||||
|
||||
## 加密与签名机制
|
||||
|
||||
### JWT 签名算法对比
|
||||
|
||||
| 算法类型 | 算法 | 密钥类型 | 特点 |
|
||||
| ----- | ----- | ----- | ------------------- |
|
||||
| HMAC | HS256 | 对称密钥 | 服务器签发和验证都 uses 同一密钥 |
|
||||
| HMAC | HS512 | 对称密钥 | 更强的哈希,性能稍低 |
|
||||
| RSA | RS256 | 非对称密钥 | 私钥签名,公钥验证 |
|
||||
| RSA | RS512 | 非对称密钥 | 更强的签名算法 |
|
||||
| ECDSA | ES256 | 椭圆曲线 | 比更短但同样安全 |
|
||||
|
||||
### HMAC-SHA256 签名流程
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[原始数据] --> B[Base64URL 编码 Header]
|
||||
A --> C[Base64URL 编码 Payload]
|
||||
|
||||
B --> D[拼接 Header.Payload]
|
||||
C --> D
|
||||
|
||||
D --> E[HMAC-SHA256 拼接结果]
|
||||
E --> F[使用 Secret Key]
|
||||
F --> G[生成 256-bit 签名]
|
||||
|
||||
G --> H[Base64URL 编码签名]
|
||||
H --> I[拼接 final JWT]
|
||||
|
||||
I --> J[Header.Payload.Signature]
|
||||
|
||||
style E fill:#ff9999
|
||||
style F fill:#ff9999
|
||||
style G fill:#lightblue
|
||||
```
|
||||
|
||||
**签名 = HMAC-SHA256(Base64URL(Header) + "." + Base64URL(Payload), Secret)**
|
||||
|
||||
### Go 实现签名与验证
|
||||
|
||||
```go
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type JWTBuilder struct {
|
||||
secretKey []byte
|
||||
}
|
||||
|
||||
// 生成签名
|
||||
func (j *JWTBuilder) sign(header, payload string) string {
|
||||
data := strings.Join([]string{header, payload}, ".")
|
||||
h := hmac.New(sha256.New, j.secretKey)
|
||||
h.Write([]byte(data))
|
||||
signature := base64.RawURLEncoding.EncodeToString(h.Sum(nil))
|
||||
return signature
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
func (j *JWTBuilder) verify(token string) bool {
|
||||
parts := strings.Split(token, ".")
|
||||
if len(parts) != 3 {
|
||||
return false
|
||||
}
|
||||
|
||||
header, payload, signature := parts[0], parts[1], parts[2]
|
||||
|
||||
// 重新计算签名
|
||||
expectedSignature := j.sign(header, payload)
|
||||
|
||||
// 比较签名 (恒定时间比较,防止计时攻击)
|
||||
return hmac.Equal([]byte(signature), []byte(expectedSignature))
|
||||
}
|
||||
```
|
||||
|
||||
## 服务器验证流程
|
||||
|
||||
### 详细的验证步骤
|
||||
|
||||
```go
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
UserID string `json:"user_id"`
|
||||
exp int64 `json:"exp"`
|
||||
iat int64 `json:"iat"`
|
||||
iss string `json:"iss"`
|
||||
aud string `json:"aud"`
|
||||
}
|
||||
|
||||
func (m *AuthMiddleware) validateToken(token string) (*Claims, error) {
|
||||
// 步骤 1: 分割三部分
|
||||
parts := strings.Split(token, ".")
|
||||
if len(parts) != 3 {
|
||||
return nil, fmt.Errorf("invalid token format")
|
||||
}
|
||||
|
||||
// 步骤 2: 验证签名
|
||||
if !m.verifySignature(token) {
|
||||
return nil, fmt.Errorf("invalid signature")
|
||||
}
|
||||
|
||||
// 步骤 3: 解码 Payload
|
||||
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid payload encoding")
|
||||
}
|
||||
|
||||
// 步骤 4: 解析 Claims
|
||||
var claims Claims
|
||||
if err := json.Unmarshal(payload, &claims); err != nil {
|
||||
return nil, fmt.Errorf("invalid payload json")
|
||||
}
|
||||
|
||||
// 步骤 5: 验证过期时间
|
||||
if time.Now().Unix() > claims.exp {
|
||||
return nil, fmt.Errorf("token expired")
|
||||
}
|
||||
|
||||
// 步骤 6: 验证签发者
|
||||
if claims.iss != "my-app" {
|
||||
return nil, fmt.Errorf("invalid issuer")
|
||||
}
|
||||
|
||||
// 步骤 7: 验证受众
|
||||
if claims.aud != "api-users" {
|
||||
return nil, fmt.Errorf("invalid audience")
|
||||
}
|
||||
|
||||
return &claims, nil
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
func (m *AuthMiddleware) verifySignature(token string) bool {
|
||||
parts := strings.Split(token, ".")
|
||||
signatureData := parts[0] + "." + parts[1]
|
||||
providedSignature := parts[2]
|
||||
|
||||
// 计算期望的签名
|
||||
expectedSignature := m.sign(signatureData)
|
||||
|
||||
// 恒定时间比较
|
||||
return hmac.Equal(
|
||||
[]byte(providedSignature),
|
||||
[]byte(expectedSignature),
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### HTTP 中间件
|
||||
|
||||
```go
|
||||
// AuthMiddleware 验证每个请求
|
||||
func (m *AuthMiddleware) Handler(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 1. 提取 Authorization 头
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
http.Error(w, "Missing Authorization header", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 解析 Bearer Token
|
||||
if !strings.HasPrefix(authHeader, "Bearer ") {
|
||||
http.Error(w, "Invalid authorization scheme", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
token := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
|
||||
// 3. 验证 Token
|
||||
claims, err := m.validateToken(token)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// 4. 将用户信息存入 Context
|
||||
ctx := context.WithValue(r.Context(), "user_id", claims.UserID)
|
||||
ctx = context.WithValue(ctx, "claims", claims)
|
||||
|
||||
// 5. 继续处理请求
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## 常见 Authorization Scheme
|
||||
|
||||
### Basic Auth(基础认证)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant B as Browser
|
||||
participant S as Server
|
||||
participant DB as Database
|
||||
|
||||
B->>S: GET /resource
|
||||
S-->>B: 401 Unauthorized
|
||||
Note right of B: WWW-Authenticate: Basic realm="Secure Area"
|
||||
|
||||
B->>B: 用户输入用户名密码
|
||||
B->>B: Base64("username:password")
|
||||
B->>S: GET /resource
|
||||
Note right of B: Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
|
||||
|
||||
S->>B: 解码 Base64
|
||||
S->>DB: 验证用户名密码
|
||||
DB-->>S: 验证结果
|
||||
S-->>B: 200 OK + 资源
|
||||
```
|
||||
|
||||
**问题**:每次请求都需要用户名密码,不安全,不推荐
|
||||
|
||||
### Digest Auth(摘要认证)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Client
|
||||
participant S as Server
|
||||
|
||||
C->>S: GET /resource
|
||||
S-->>C: 401 Unauthorized
|
||||
Note right of C: WWW-Authenticate: Digest<br/>realm="Protected",<br/>nonce="xyz123",<br/>qop="auth"
|
||||
|
||||
C->>C: 计算 response<br/>MD5(username:realm:password)<br/>MD5(method:uri)<br/>HA1 = MD5(username:realm:password)<br/>HA2 = MD5(method:uri)<br/>response = MD5(HA1:nonce:HA2)
|
||||
|
||||
C->>S: GET /resource
|
||||
Note right of C: Authorization: Digest<br/>username="user",<br/>realm="Protected",<br/>nonce="xyz123",<br/>uri="/resource",<br/>response="abc123"
|
||||
|
||||
S->>S: 重新计算 response
|
||||
S-->>C: 200 OK
|
||||
```
|
||||
|
||||
**优点**:密码不直接传输,更安全
|
||||
**缺点**:实现复杂,需要多次往返
|
||||
|
||||
### Bearer Token(持有者令牌)
|
||||
|
||||
✅ **现代 Web 应用的标准选择**
|
||||
|
||||
```http
|
||||
# 请求示例
|
||||
GET /api/user/profile HTTP/1.1
|
||||
Host: api.example.com
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzIiwidXNlcm5hbWUiOiJqb2huIiwiZXhwIjoxNzI4MjQ4MDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
|
||||
|
||||
# 响应示例
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"user_id": "123",
|
||||
"username": "john",
|
||||
"email": "john@example.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Refresh Token 机制
|
||||
|
||||
### Access Token vs Refresh Token
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Access Token] --> B[有效期短<br/>15-30分钟]
|
||||
A --> C[用于 API 访问]
|
||||
A --> D[存储在浏览器]
|
||||
|
||||
E[Refresh Token] --> F[有效期长<br/>数天至数周]
|
||||
E --> G[用于获取新 Access Token]
|
||||
E --> H[存储在 HttpOnly Cookie]
|
||||
|
||||
style A fill:#90EE90
|
||||
style E fill:#ffcc00
|
||||
```
|
||||
|
||||
### Token 刷新流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant B as Browser
|
||||
participant S as Server
|
||||
|
||||
Note over B,S: Access Token 过期
|
||||
B->>S: POST /api/refresh
|
||||
Note right of B: Body: {refresh_token: "..."}
|
||||
|
||||
S->>S: 验证 Refresh Token
|
||||
S->>S: 生成新的 Access Token
|
||||
S-->>B: {access_token: "new_jwt..."}
|
||||
|
||||
Note over B,S: 使用新 Token 继续请求
|
||||
B->>S: GET /api/resource
|
||||
Note right of B: Authorization: Bearer new_jwt...
|
||||
|
||||
S-->>B: 200 OK
|
||||
```
|
||||
|
||||
**Refresh Token 优势**:
|
||||
- ✅ Access Token 短期有效,减少泄露风险
|
||||
- ✅ Refresh Token 可随时撤销
|
||||
- ✅ 用户无感知自动续期
|
||||
|
||||
## 安全最佳实践
|
||||
|
||||
### Token 安全传输
|
||||
|
||||
| 措施 | 说明 | Go 实现 |
|
||||
|-----|------|---------|
|
||||
| **HTTPS 强制** | 防止 Token 被窃取 | RedirectHTTPS 中间件 |
|
||||
| **短期有效期** | 降低被滥用风险 | Token 15-30 分钟 |
|
||||
| **签名验证** | 防止 Token 被篡改 | HMAC/RSA 签名 |
|
||||
| **黑名单机制** | 主动撤销 Token | Redis 存储 revoked_tokens |
|
||||
|
||||
### 浏览器安全设置
|
||||
|
||||
```javascript
|
||||
// ✅ 推荐:HttpOnly Cookie 存储 Refresh Token
|
||||
document.cookie = `refresh_token=${refreshToken}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=604800`;
|
||||
|
||||
// ⚠️ 谨慎:LocalStorage 存储 Access Token
|
||||
localStorage.setItem('access_token', accessToken);
|
||||
// 需要 XSS 防护
|
||||
|
||||
// ❌ 避免:明文传输 Token
|
||||
// 必须使用 HTTPS
|
||||
```
|
||||
|
||||
### CORS 和 SameSite
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[前端应用<br/>example.com] --> B[后端 API<br/>api.example.com]
|
||||
|
||||
B --> C[CORS 策略]
|
||||
C --> D[Access-Control-Allow-Origin: https://example.com]
|
||||
C --> E[Access-Control-Allow-Credentials: true]
|
||||
|
||||
B --> F[SameSite Cookie]
|
||||
F --> G[Strict: 严格模式]
|
||||
F --> H[Lax: 放宽模式]
|
||||
|
||||
style D fill:#90EE90
|
||||
style G fill:#90EE90
|
||||
```
|
||||
|
||||
**Go CORS 配置**:
|
||||
```go
|
||||
func setupCORS() *cors.Cors {
|
||||
return cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"https://example.com"},
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
|
||||
AllowedHeaders: []string{"Authorization", "Content-Type"},
|
||||
AllowCredentials: true,
|
||||
MaxAge: 3600,
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## 相关笔记
|
||||
|
||||
- [[金山办公作业/Week05/用户认证]] - 认证的实现方式
|
||||
- [[CS/NET/HTTPS]] - SSL/TLS 加密传输
|
||||
- [[CS/DB/访问控制]] - 数据库层面权限
|
||||
@@ -0,0 +1,349 @@
|
||||
---
|
||||
tags: [CS, NET, algorithm, data-stream, heavy-hitter]
|
||||
create time: 2026-04-17 13:45
|
||||
---
|
||||
|
||||
# HeavyKeeper
|
||||
|
||||
## 概述
|
||||
|
||||
HeavyKeeper 是一种用于高速数据流中检测 Heavy Hitters(频繁项)的高效算法。它在保持常数内存空间的同时,能够准确地识别出出现频率超过设定阈值的数据项,广泛应用于网络流量监测、热点检测等场景。
|
||||
|
||||
## 算法原理
|
||||
|
||||
### 核心思想
|
||||
|
||||
HeavyKeeper 结合了 Count-Min Sketch 和守桶策略,通过多层哈希守桶机制来提高准确性。其核心目标是区分"大象流"和"老鼠流"。
|
||||
|
||||
#### 什么是大象流和老鼠流?
|
||||
|
||||
在数据流分析中,通常将数据流按频率分为两类:
|
||||
|
||||
| 类型 | 特征 | 频率占比 | 典型例子 |
|
||||
|------|------|----------|---------|
|
||||
| **大象流**(Elephant Flow) | 高频出现 | 占总流量的大部分 | 热门IP、热门搜索词、DDoS攻击流量 |
|
||||
| **老鼠流**(Mouse Flow) | 低频偶发 | 数量众多但频率极低 | 少量用户访问、正常连接请求 |
|
||||
|
||||
**关键洞察**:在很多场景中,**80-90%的流量来自不到1%的源**,这就是大象流。HeavyKeeper 的目标就是高效识别这些大象流,过滤掉老鼠流。
|
||||
|
||||
### 守桶机制
|
||||
|
||||
#### 什么是"守桶"?
|
||||
|
||||
"守桶"(Keeper)是 HeavyKeeper 的核心创新。每个桶会"守护"一个特定的数据项:
|
||||
|
||||
- 当数据流中的一个项到来时,哈希到某个桶
|
||||
- 如果这个项正好是该桶"守护"的项,就直接计数
|
||||
- 如果不是,则根据概率决定是否"抢夺"守护权
|
||||
|
||||
**底层原理**:让大象流(高频项)能够长期占据守桶位置,而老鼠流(低频项)很难长期占用桶的资源。
|
||||
|
||||
#### 桶的结构
|
||||
|
||||
每个桶维护以下信息:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| **item** | 数据项 | 当前守护的数据项 |
|
||||
| **count** | 整数 | 守护项的精确计数 |
|
||||
| **error** | 整数 | 误差估计(记录非守护项经过的次数) |
|
||||
|
||||
#### 守桶策略:大象流如何压制老鼠流
|
||||
|
||||
**替换概率公式**:
|
||||
```python
|
||||
替换概率 = min(1, 新项估计频率 / 当前守护项计数)
|
||||
```
|
||||
|
||||
这个公式的直观含义:
|
||||
|
||||
| 情况 | 新项类型 | 替换概率 | 结果 |
|
||||
|------|---------|---------|------|
|
||||
| 大象流 vs 老鼠流 | 老鼠流(freq≈1) | 1/count | 极小,**老鼠流无法撼动大象流** |
|
||||
| 老鼠流 vs 老鼠流 | 老鼠流(freq≈2) | 2/count | 较小,随机性强 |
|
||||
| 大象流 vs 老鼠流 | 大象流(freq=50) | 50/5=1 | 必然替换,**新大象流抢占桶** |
|
||||
| 大象流 vs 大象流 | 大象流(freq=98) | 98/95≈1 | 可能替换,两个大象流竞争 |
|
||||
|
||||
**例子**:
|
||||
```
|
||||
桶#100 当前守护:IP=10.0.0.1 (count=100, error=5) ← 大象流
|
||||
新到来:IP=10.0.0.2 → 哈希到桶#100 ← 老鼠流
|
||||
|
||||
替换概率 = min(1, 1/100) = 0.01
|
||||
|
||||
结果:0.95(随机数)> 0.01 → 不替换
|
||||
解释:大象流继续守护,老鼠流只能默默增加error
|
||||
```
|
||||
|
||||
#### 多层哈希的作用
|
||||
|
||||
单层哈希可能发生冲突(多个项哈希到同一个桶),多层哈希通过冗余来解决:
|
||||
|
||||
- 同一个项会由L个不同的哈希函数映射到L层的不同桶
|
||||
- 查询时取所有层的最小值(保守估计)
|
||||
- 即使部分桶冲突,也能获得准确的下界
|
||||
|
||||
**最终计数** = min(所有层中该项的count值)
|
||||
|
||||
#### Heavy Hitters 检测流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[数据流新项 x] --> B[计算L个哈希]
|
||||
B --> C[访问L个桶]
|
||||
|
||||
C --> D{是否为守护项?}
|
||||
D -->|是| E[count++]
|
||||
D -->|否| F[计算替换概率]
|
||||
|
||||
F --> G{触发替换?}
|
||||
G -->|是| H[替换并重置count=1]
|
||||
G -->|否| I[error++]
|
||||
|
||||
E --> J[继续]
|
||||
H --> J
|
||||
I --> J
|
||||
```
|
||||
|
||||
查找Top K时,只需遍历所有桶,收集 `count ≥ 阈值` 的候选项。
|
||||
|
||||
### 衰减机制
|
||||
|
||||
#### 为什么需要衰减?
|
||||
|
||||
**问题场景**:
|
||||
```
|
||||
10:00-10:05 IP=10.0.0.1 出现 1000 次 → 成为大象流,占据桶
|
||||
10:06-12:00 IP=10.0.0.1 不再出现,但其count=1000依然存在
|
||||
12:01 IP=10.0.0.2 频繁出现,但无法抢占count=1000的桶
|
||||
```
|
||||
|
||||
如果不衰减,过时的大象流会持续占用资源,阻碍新大象流的检测。
|
||||
|
||||
#### 衰减机制的工作原理
|
||||
|
||||
HeavyKeeper 通过周期性衰减来解决这个问题:
|
||||
|
||||
**方法1:时间窗口衰减(推荐)**
|
||||
```python
|
||||
def periodic_decay():
|
||||
每经过 Δt 时间,所有桶的 count 和 error 乘以衰减因子 α
|
||||
count = count × α
|
||||
error = error × α
|
||||
其中 α ∈ (0, 1),通常 α = 0.9 或 0.99
|
||||
```
|
||||
|
||||
**方法2:基于老化(Aging)**
|
||||
```python
|
||||
def aging(bucket, current_time):
|
||||
elapsed = current_time - bucket.last_update_time
|
||||
decay = exp(-λ × elapsed) # λ 是衰减速率
|
||||
bucket.count = bucket.count × decay
|
||||
```
|
||||
|
||||
#### 衰减机制的数学效果
|
||||
|
||||
**时间窗口视角**:
|
||||
```
|
||||
衰减因子 α = 0.99,窗口大小 = N
|
||||
|
||||
N时刻前的权重:0.99^N ≈ 0.366 ← 仅保留36.6%
|
||||
2N时刻前的权重:0.99^2N ≈ 0.134 ← 只保留13.4%
|
||||
```
|
||||
|
||||
这意味着:越久远的计数对当前统计影响越小,让算法能够"遗忘"过时的流。
|
||||
|
||||
#### 衰减规则示例
|
||||
|
||||
| 场景 | 原 count | 衰减后 count | 解析 |
|
||||
|------|----------|-------------|------|
|
||||
| 持续活跃的大象流 | 1000 | 990 (×0.99) | 持续补充,衰减不影响地位 |
|
||||
| 最近消失的大象流 | 1000 | 366 (×0.99^100) | 100个周期后快速衰减,让出桶 |
|
||||
| 新大象流 | 0 → 10 | 10 (刚开始) | 有机会竞争已衰减的桶 |
|
||||
|
||||
#### 衰减带来的好处
|
||||
|
||||
| 优势 | 说明 |
|
||||
|------|------|
|
||||
| **自适应流行度漂移** | 热点变化时,旧热点会自动失去守桶权 |
|
||||
| **滑动窗口效果** | 只关注最近时间窗口内的频率,而非历史总和 |
|
||||
| **防止资源垄断** | 过时的大象流不会长期占用桶资源 |
|
||||
|
||||
#### 衰减与守桶的协同
|
||||
|
||||
衰减机制和守桶机制协同工作,形成一个动态平衡:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[大象流活跃] --> B[count快速累积]
|
||||
B --> C[占据守桶位置]
|
||||
|
||||
C --> D{时间流逝}
|
||||
D -->|持续活跃| E[保持守桶]
|
||||
D -->|停止活跃| F[衰减降低count]
|
||||
|
||||
F --> G{新竞争者?}
|
||||
G -->|有| H[被替换,让出桶]
|
||||
G -->|无| I[继续衰减直至清理]
|
||||
```
|
||||
|
||||
## 关键参数
|
||||
|
||||
| 参数 | 说明 | 典型值 |
|
||||
|------|------|--------|
|
||||
| **m** | 每层桶的数量 | 2^15 ~ 2^20 |
|
||||
| **L** | 哈希层数 | 3 ~ 5 |
|
||||
| **θ** | 频率阈值 | 0.001 ~ 0.01 |
|
||||
| **α** | 衰减因子 | 0.9 ~ 0.99 |
|
||||
| **Δt** | 衰减周期 | 根据应用场景 |
|
||||
|
||||
## 性能特征
|
||||
|
||||
### 空间复杂度
|
||||
- 空间复杂度: **O(m × L)**
|
||||
- 每桶存储: item (~8字节) + count (~4字节) + error (~4字节)
|
||||
|
||||
### 时间复杂度
|
||||
|
||||
| 操作 | 时间复杂度 | 说明 |
|
||||
|------|-----------|------|
|
||||
| **插入** | O(L) | 对每层进行哈希和更新 |
|
||||
| **查询** | O(L) | 取所有层最小值 |
|
||||
| **衰减** | O(m×L) | 批量处理所有桶 |
|
||||
|
||||
## 优势与局限
|
||||
|
||||
### 优势
|
||||
- **大象流识别准确**: 守桶机制确保高频项持续占据资源
|
||||
- **老鼠流过滤**: 低频项很难干扰大象流统计
|
||||
- **自适应流行度变化**: 衰减机制处理热点漂移
|
||||
- **内存高效**: 恒定空间,不受数据流规模影响
|
||||
|
||||
### 局限性
|
||||
- **参数敏感**: m、L、α 等参数需要根据数据特征调优
|
||||
- **哈希冲突**: 极端情况下可能产生误报或漏报
|
||||
- **衰减延迟**: 热点切换时需要一定时间生效
|
||||
|
||||
## 应用场景
|
||||
|
||||
### 典型用例
|
||||
|
||||
1. **网络流量分析**: 识别高频 IP 地址或端口(大象流)
|
||||
2. **DDoS 防护**: 检测异常高频流量,过滤老鼠流
|
||||
3. **实时推荐**: 发现用户偏好热点,利用衰减实现热点漂移
|
||||
4. **CDN 缓存**: 识别热门内容进行预加载
|
||||
5. **日志分析**: 快速定位高频错误或异常事件
|
||||
|
||||
### 实际部署考虑
|
||||
|
||||
| 场景 | 大象流示例 | 老鼠流示例 | 衰减建议 |
|
||||
|------|-----------|-----------|---------|
|
||||
| 网络带宽监控 | P2P下载、视频流 | 正常网页浏览 | 较慢衰减(α=0.99) |
|
||||
| DDoS检测 | 攻击源IP | 正常用户IP | 快速衰减(α=0.9) |
|
||||
| 搜索热门 | 热门关键词 | 长尾搜索 | 中等衰减(α=0.95) |
|
||||
|
||||
## 参考实现
|
||||
|
||||
### 伪代码
|
||||
|
||||
```python
|
||||
class HeavyKeeper:
|
||||
def __init__(self, m, L, threshold, decay_factor):
|
||||
self.m = m # 每层桶数
|
||||
self.L = L # 哈希层数
|
||||
self.threshold = threshold
|
||||
self.decay_factor = decay_factor # 衰减因子
|
||||
|
||||
# 初始化多层 sketch
|
||||
self.buckets = [[KeeperBucket() for _ in range(m)]
|
||||
for _ in range(L)]
|
||||
|
||||
# 初始化哈希函数
|
||||
self.hash_funcs = [get_hash_func(i) for i in range(L)]
|
||||
|
||||
def insert(self, item, timestamp):
|
||||
for layer in range(self.L):
|
||||
idx = self.hash_funcs[layer](item) % self.m
|
||||
bucket = self.buckets[layer][idx]
|
||||
|
||||
if bucket.item == item:
|
||||
# 守护项匹配,直接计数(大象流强化)
|
||||
bucket.count += 1
|
||||
bucket.last_seen = timestamp
|
||||
else:
|
||||
# 计算替换概率
|
||||
estimated_freq = self._estimate_freq(item)
|
||||
replace_prob = min(1, estimated_freq / bucket.count)
|
||||
|
||||
if random.random() < replace_prob:
|
||||
# 替换为新项(大象流夺权)
|
||||
bucket.item = item
|
||||
bucket.count = 1
|
||||
bucket.error = bucket.count
|
||||
bucket.last_seen = timestamp
|
||||
else:
|
||||
# 不替换,仅增加误差(老鼠流被阻拦)
|
||||
bucket.error += 1
|
||||
|
||||
def apply_decay(self, current_time):
|
||||
"""应用衰减机制"""
|
||||
for layer in range(self.L):
|
||||
for bucket in self.buckets[layer]:
|
||||
elapsed = current_time - bucket.last_seen
|
||||
if elapsed > DECAY_INTERVAL:
|
||||
bucket.count *= self.decay_factor
|
||||
bucket.error *= self.decay_factor
|
||||
|
||||
# 归零清理
|
||||
if bucket.count < 1:
|
||||
bucket.item = None
|
||||
bucket.count = 0
|
||||
bucket.error = 0
|
||||
|
||||
def query(self, item):
|
||||
"""查询Item的频率估计"""
|
||||
min_count = float('inf')
|
||||
for layer in range(self.L):
|
||||
idx = self.hash_funcs[layer](item) % self.m
|
||||
bucket = self.buckets[layer][idx]
|
||||
if bucket.item == item:
|
||||
min_count = min(min_count, bucket.count)
|
||||
|
||||
return min_count if min_count != float('inf') else 0
|
||||
|
||||
def get_top_k(self, k):
|
||||
"""获取Top K大象流"""
|
||||
candidates = {}
|
||||
for layer in range(self.L):
|
||||
for bucket in self.buckets[layer]:
|
||||
if bucket.count >= self.threshold and bucket.item:
|
||||
item = bucket.item
|
||||
candidates[item] = max(candidates.get(item, 0),
|
||||
bucket.count)
|
||||
|
||||
# 返回 Top-k
|
||||
return sorted(candidates.items(),
|
||||
key=lambda x: x[1],
|
||||
reverse=True)[:k]
|
||||
```
|
||||
|
||||
## 相关算法对比
|
||||
|
||||
| 算法 | 空间复杂度 | 大象流准确性 | 老鼠流过滤 | 衰减支持 | 适用场景 |
|
||||
|------|-----------|------------|-----------|---------|---------|
|
||||
| **HeavyKeeper** | O(m×L) | 高 | 优秀 | 原生支持 | 高速数据流,需检测热点漂移 |
|
||||
| **Count-Min** | O(m×L) | 中 | 无 | 需额外实现 | 通用频率统计 |
|
||||
| **SpaceSaving** | O(k) | 中 | 好 | 手动实现 | 固定数量Top-K |
|
||||
| **LossyCounter** | O(kε) | 高 | 一般 | 手动实现 | 离线精确统计 |
|
||||
|
||||
## 参考资料
|
||||
|
||||
- HeavyKeeper: Streaming Heavy Hitters Detection with Known Error Bounds (2020)
|
||||
- Count-Min Sketch: An Improved Data Stream Summary
|
||||
- Streaming Algorithms for Finding Heavy Hitters
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[CS/NET/Count-Min-Sketch.md]]
|
||||
- [[CS/DS/HashMap.md]]
|
||||
- [[CS/NET/Network-Flow-Analysis.md]]
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
tags: [CS, NET, network]
|
||||
create time: 2026-04-17
|
||||
---
|
||||
|
||||
# 计算机网络
|
||||
|
||||
## 概述
|
||||
|
||||
计算机网络是物理上分散的计算机通过通信线路连接起来,在网络软件的管理下实现资源共享和信息传递的系统。
|
||||
|
||||
## 核心概念
|
||||
|
||||
### OSI七层模型
|
||||
- 物理层、数据链路层、网络层
|
||||
- 传输层、会话层、表示层、应用层
|
||||
|
||||
### TCP/IP协议栈
|
||||
- IP协议、TCP/UDP协议
|
||||
- HTTP/HTTPS、DNS、SMTP等应用层协议
|
||||
- 网络地址与路由
|
||||
|
||||
### 网络架构
|
||||
- 客户端-服务器架构
|
||||
- P2P架构
|
||||
- 分布式系统
|
||||
|
||||
### 网络安全
|
||||
- 加密与解密
|
||||
- SSL/TLS
|
||||
- 防火墙与VPN
|
||||
|
||||
## 学习重点
|
||||
|
||||
- TCP/IP协议详解
|
||||
- HTTP协议与Web服务
|
||||
- 套接字编程
|
||||
- 网络性能优化
|
||||
|
||||
## 实践建议
|
||||
|
||||
- 使用Wireshark抓包分析
|
||||
- 编写网络应用
|
||||
- 搭建本地网络环境
|
||||
- 理解常见网络问题
|
||||
@@ -0,0 +1,208 @@
|
||||
---
|
||||
tags: [network, protocol, theory, cs]
|
||||
create time: 2026-04-17 12:15
|
||||
---
|
||||
|
||||
# 网络协议分析基础
|
||||
|
||||
## 概述
|
||||
|
||||
网络协议分析是理解网络通信的核心技术,通过分析数据包的结构和内容,可以深入理解网络协议的工作原理和通信机制。
|
||||
|
||||
## 正文
|
||||
|
||||
### TCP 三次握手与四次挥手
|
||||
|
||||
#### 三次握手 (SYN, SYN-ACK, ACK)
|
||||
|
||||
```
|
||||
客户端 服务器
|
||||
| |
|
||||
| --- SYN, seq=x --------------------> |
|
||||
| |
|
||||
| <--- SYN, ACK, seq=y, ack=x+1 ------ |
|
||||
| |
|
||||
| --- ACK, seq=x+1, ack=y+1 ---------> |
|
||||
| | 连接建立
|
||||
```
|
||||
|
||||
**各字段含义:**
|
||||
- **SYN**: 同步标志,用于建立连接
|
||||
- **ACK**: 确认标志,表示确认收到
|
||||
- **seq**: 序列号,确保数据有序传递
|
||||
- **ack**: 确认号,表示期望收到的下一个序列号
|
||||
|
||||
**抓包特征:**
|
||||
1. 第一个包:SYN 标志位为 1,ACK 为 0
|
||||
2. 第二个包:SYN 和 ACK 都为 1
|
||||
3. 第三个包:ACK 为 1,SYN 为 0
|
||||
|
||||
#### 四次挥手 (FIN, ACK, FIN, ACK)
|
||||
|
||||
```
|
||||
客户端 服务器
|
||||
| |
|
||||
| --- FIN, seq=x --------------------> | 主动关闭
|
||||
| |
|
||||
| <--- ACK, seq=y, ack=x+1 ----------- |
|
||||
| | 半关闭
|
||||
| <--- FIN, seq=y ------------------- | 被动关闭
|
||||
| |
|
||||
| --- ACK, seq=x+1, ack=y+1 ---------> |
|
||||
| | 连接关闭
|
||||
```
|
||||
|
||||
**状态转换:**
|
||||
- FIN_WAIT_1: 主动关闭方发送 FIN
|
||||
- FIN_WAIT_2: 主动关闭方收到 ACK,等待对方 FIN
|
||||
- CLOSE_WAIT: 被动关闭方收到 FIN,进入半关闭状态
|
||||
- LAST_ACK: 被动关闭方发送 FIN
|
||||
- TIME_WAIT: 主动关闭方收到 FIN,等待 2MSL 后完全关闭
|
||||
|
||||
### HTTP 协议分析
|
||||
|
||||
#### 请求结构
|
||||
|
||||
```
|
||||
Method Request-URI HTTP-Version\r\n
|
||||
Header-Name: Header-Value\r\n
|
||||
\r\n
|
||||
Message-Body
|
||||
```
|
||||
|
||||
**常见方法:**
|
||||
- **GET**: 获取资源
|
||||
- **POST**: 提交数据
|
||||
- **PUT**: 更新资源
|
||||
- **DELETE**: 删除资源
|
||||
- **HEAD**: 获取响应头
|
||||
- **OPTIONS**: 获取支持的方法
|
||||
|
||||
**常用请求头:**
|
||||
```
|
||||
Host: example.com
|
||||
User-Agent: Mozilla/5.0
|
||||
Accept: text/html,application/json
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer token
|
||||
Cookie: session=xxx
|
||||
```
|
||||
|
||||
#### 响应结构
|
||||
|
||||
```
|
||||
HTTP-Version Status-Code Reason-Phrase\r\n
|
||||
Header-Name: Header-Value\r\n
|
||||
\r\n
|
||||
Message-Body
|
||||
```
|
||||
|
||||
**状态码分类:**
|
||||
- **2xx**: 成功 (200 OK, 201 Created, 204 No Content)
|
||||
- **3xx**: 重定向 (301 Moved Permanently, 302 Found, 304 Not Modified)
|
||||
- **4xx**: 客户端错误 (400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found)
|
||||
- **5xx**: 服务器错误 (500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable)
|
||||
|
||||
**常用响应头:**
|
||||
```
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Content-Length: 1234
|
||||
Cache-Control: max-age=3600
|
||||
ETag: "abc123"
|
||||
Set-Cookie: session=xxx; Path=/; HttpOnly
|
||||
```
|
||||
|
||||
### TLS/SSL 加密通信
|
||||
|
||||
#### TLS 握手流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as 客户端
|
||||
participant S as 服务器
|
||||
|
||||
C->>S: ClientHello<br/>(支持的加密套件、随机数)
|
||||
S-->>C: ServerHello<br/>(选择的加密套件、随机数、证书)
|
||||
S-->>C: Certificate<br/>(服务器证书)
|
||||
S-->>C: ServerHelloDone
|
||||
|
||||
C->>S: ClientKeyExchange<br/>(预主密钥,用服务器公钥加密)
|
||||
C->>S: ChangeCipherSpec<br/>(通知后续使用加密通信)
|
||||
C->>S: Finished<br/>(握手完成,加密验证)
|
||||
|
||||
S-->>C: ChangeCipherSpec
|
||||
S-->>C: Finished
|
||||
|
||||
Note over C,S: 开始加密通信
|
||||
```
|
||||
|
||||
**关键概念:**
|
||||
- **证书链**: 从服务器证书到根证书的信任链
|
||||
- **预主密钥**: 通过非对称加密传输,用于生成会话密钥
|
||||
- **会话密钥**: 通过预主密钥和双方随机数生成,用于对称加密
|
||||
- **SSL Pinning**: 客户端验证服务器证书,防止中间人攻击
|
||||
|
||||
### 数据包分析要点
|
||||
|
||||
#### 抓包指标
|
||||
|
||||
**性能指标:**
|
||||
- **RTT (Round Trip Time)**: 往返时延
|
||||
- **吞吐量**: 单位时间传输的数据量
|
||||
- **丢包率**: 丢失的数据包比例
|
||||
- **重传率**: 重发数据包的比例
|
||||
|
||||
**连接指标:**
|
||||
- **TCP 窗口大小**: 接收窗口和拥塞窗口
|
||||
- **连接状态**: ESTABLISHED, TIME_WAIT 等
|
||||
- **连接复用**: Keep-Alive, HTTP/2 连接复用
|
||||
|
||||
#### 过滤技巧
|
||||
|
||||
**基于协议过滤:**
|
||||
```
|
||||
# HTTP/HTTPS
|
||||
http or http2 or ssl
|
||||
|
||||
# TCP 特定标志
|
||||
tcp.flags.syn == 1 # SYN 包
|
||||
tcp.flags.ack == 1 # ACK 包
|
||||
tcp.flags.fin == 1 # FIN 包
|
||||
tcp.flags.reset == 1 # RST 包
|
||||
```
|
||||
|
||||
**基于内容过滤:**
|
||||
```
|
||||
# 特定 User-Agent
|
||||
http.user_agent contains "Chrome"
|
||||
|
||||
# 特定域名
|
||||
http.host == "example.com"
|
||||
|
||||
# HTTP 错误
|
||||
http.response.code >= 400
|
||||
|
||||
# 请求体内容
|
||||
http.file_data contains "keyword"
|
||||
```
|
||||
|
||||
**基于网络层过滤:**
|
||||
```
|
||||
# 源/目标地址
|
||||
ip.src == 192.168.1.1
|
||||
ip.dst == 192.168.1.1
|
||||
|
||||
# 端口范围
|
||||
tcp.port >= 1024 and tcp.port <= 65535
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[CS/TOOLS/网络抓包]]
|
||||
- [[CS/SECURITY/网络安全基础]]
|
||||
- [[CS/OS/TCP 协议详解]]
|
||||
|
||||
## 参考资源
|
||||
|
||||
- RFC 文档: https://www.rfc-editor.org/
|
||||
- Wireshark 指南: https://www.wireshark.org/docs/wsug_html_chunked/
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
tags: [CS, OS, operating-systems]
|
||||
create time: 2026-04-17
|
||||
---
|
||||
|
||||
# 操作系统
|
||||
|
||||
## 概述
|
||||
|
||||
操作系统是管理计算机硬件与软件资源的系统软件。它是计算机系统中最基础的系统软件,为应用程序提供运行环境。
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 进程管理
|
||||
- 进程与线程
|
||||
- 进程调度算法
|
||||
- 进程间通信(IPC)
|
||||
- 同步与互斥
|
||||
|
||||
### 内存管理
|
||||
- 虚拟内存
|
||||
- 分页与分段
|
||||
- 内存分配与回收
|
||||
- 缓存机制
|
||||
|
||||
### 文件系统
|
||||
- 文件的存储结构
|
||||
- 目录管理
|
||||
- 文件操作接口
|
||||
- 权限管理
|
||||
|
||||
### I/O管理
|
||||
- 设备驱动
|
||||
- 中断处理
|
||||
- 缓冲区管理
|
||||
|
||||
## 学习重点
|
||||
|
||||
- Linux/Unix系统原理
|
||||
- 系统调用机制
|
||||
- 操作系统设计原则
|
||||
- 性能优化方法
|
||||
|
||||
## 实践建议
|
||||
|
||||
- 在Linux环境下进行实验
|
||||
- 使用系统调用的程序
|
||||
- 研究开源操作系统代码
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
tags: [CS, foundations]
|
||||
create time: 2026-04-17
|
||||
---
|
||||
|
||||
# 计算机科学
|
||||
|
||||
## 概述
|
||||
|
||||
计算机科学是研究计算机系统、软件设计、算法和数据处理的学科。本目录包含了计算机科学的基础理论知识和核心技术领域。
|
||||
|
||||
## 核心领域
|
||||
|
||||
### 操作系统 ([[OS|OS]])
|
||||
- 进程管理、内存管理、文件系统
|
||||
- 学习目标: 理解计算机系统如何管理资源
|
||||
|
||||
### 计算机网络 ([[NET|NET]])
|
||||
- 网络协议、网络架构、通信原理
|
||||
- 学习目标: 掌握数据在网络中传输的机制
|
||||
|
||||
### 数据库 ([[DB|DB]])
|
||||
- 关系型数据库、NoSQL、查询优化
|
||||
- 学习目标: 学习数据存储和检索技术
|
||||
|
||||
### 工具使用 ([[TOOLS|TOOLS]])
|
||||
- 开发工具、版本控制、容器化、CLI
|
||||
- 学习目标: 掌握日常开发必备工具
|
||||
|
||||
## 学习建议
|
||||
|
||||
建议从操作系统和网络开始打好基础,再深入数据库技术。工具使用贯穿整个学习过程,可以边学边用。
|
||||
|
||||
### 理论与实践结合
|
||||
- 阅读理论笔记后进行实践
|
||||
- 在软件开发中应用所学知识
|
||||
- 通过项目加深理解
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
tags: [CS, TOOLS, dev-tools]
|
||||
create time: 2026-04-17
|
||||
---
|
||||
|
||||
# 工具使用
|
||||
|
||||
## 概述
|
||||
|
||||
工欲善其事,必先利其器。高效的工具使用可以极大提升开发和学习的效率。
|
||||
|
||||
## 核心工具类别
|
||||
|
||||
### 开发工具
|
||||
- **编辑器/IDE**: Vim、VS Code、IntelliJ
|
||||
- **代码补全与Linting**: Copilot、ESLint、golangci-lint
|
||||
- **调试工具**: GDB、Chrome DevTools、Delve
|
||||
|
||||
### 版本控制
|
||||
- **Git**: 版本管理、分支策略
|
||||
- **GitHub/GitLab**: 代码托管、协作开发
|
||||
- **Git工作流**: Git Flow、GitHub Flow
|
||||
|
||||
### 容器化与部署
|
||||
- **Docker**: 容器化应用
|
||||
- **Docker Compose**: 多容器编排
|
||||
- **Kubernetes**: 容器编排(可选)
|
||||
|
||||
### 命令行工具
|
||||
- **Shell编程**: Bash/Zsh脚本
|
||||
- **包管理器**: apt, brew, npm, go modules
|
||||
- **系统工具**: grep, sed, awk, ssh, tmux
|
||||
|
||||
### 构建与测试
|
||||
- **构建工具**: Make, Webpack, Vite
|
||||
- **测试框架**: Jest, Go Test, PyTest
|
||||
- **持续集成**: GitHub Actions, Travis CI
|
||||
|
||||
## 学习重点
|
||||
|
||||
- Git的高级用法
|
||||
- Shell脚本编程
|
||||
- Docker容器化
|
||||
- 命令行效率提升
|
||||
|
||||
## 实践建议
|
||||
|
||||
- 在日常工作中持续使用
|
||||
- 学习快捷键和最佳实践
|
||||
- 定期更新工具版本
|
||||
- 关注工具生态发展
|
||||
@@ -0,0 +1,576 @@
|
||||
---
|
||||
tags: [network, tools, whistle, packet-capture, proxy]
|
||||
create time: 2026-04-17 12:20
|
||||
---
|
||||
|
||||
# 网络抓包
|
||||
|
||||
## 概述
|
||||
|
||||
网络抓包是调试和分析网络请求的核心技术。本文档以 whistle 支持的抓包功能为核心,介绍网络请求的抓取、分析、修改和重放方法。
|
||||
|
||||
理论性的协议分析内容请参考 [[CS/NET/网络协议分析基础]]。
|
||||
|
||||
## 正文
|
||||
|
||||
### 代理状态下的网络请求流程
|
||||
|
||||
在配置代理后,网络请求会经过代理服务器转发。以下是完整的请求流程:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端 (浏览器/应用)
|
||||
participant Proxy as 代理服务器 (Whistle)
|
||||
participant Target as 目标服务器
|
||||
|
||||
%% 1. 客户端发起请求
|
||||
Client->>Proxy: ✅ 1. 发起 HTTP/HTTPS 请求
|
||||
Note over Client,Proxy: URL: https://api.example.com/data<br/>Method: GET<br/>Headers: {...}
|
||||
|
||||
%% 2. 代理接收并解析
|
||||
Proxy->>Proxy: 🔍 2. 接收请求并解析
|
||||
Note over Proxy: 检查规则匹配<br/>- 规则: reqHeaders?<br/>- 规则: resBody?<br/>- 规则: 映射?
|
||||
|
||||
%% 分支: 是否有转发规则
|
||||
alt 有转发规则
|
||||
Proxy->>Proxy: 📝 3. 应用转发规则
|
||||
Note over Proxy: 执行修改操作<br/>- 修改请求头<br/>- 替换域名<br/>- 重写路径
|
||||
end
|
||||
|
||||
%% 分支: HTTPS 请求
|
||||
alt HTTPS 请求
|
||||
Proxy->>Proxy: 🔒 4. SSL/TLS 握手
|
||||
Note over Proxy: - 代理充当中间人<br/>- 使用自签名证书<br/>- 解密请求内容
|
||||
end
|
||||
|
||||
%% 3. 代理转发请求
|
||||
Proxy->>Target: ⬆️ 5. 转发请求到目标服务器
|
||||
Note over Proxy,Target: 处理后的请求<br/>Header + Body
|
||||
|
||||
%% 4. 目标服务器处理
|
||||
Target->>Target: ⚙️ 6. 处理请求
|
||||
Note over Target: 业务逻辑处理<br/>生成响应数据
|
||||
|
||||
%% 5. 目标服务器返回响应
|
||||
Target-->>Proxy: ⬇️ 7. 返回响应
|
||||
Note over Target,Proxy: Status: 200<br/>Headers: {...}<br/>Body: {...}
|
||||
|
||||
%% 6. 代理接收并记录
|
||||
Proxy->>Proxy: 💾 8. 接收并记录响应
|
||||
Note over Proxy: - 记录到抓包列表<br/>- 计算耗时<br/>- 保存完整信息
|
||||
|
||||
%% 分支: 是否有响应修改规则
|
||||
alt 有响应修改规则
|
||||
Proxy->>Proxy: 🎭 9. 应用响应规则
|
||||
Note over Proxy: - 修改响应头<br/>- 替换响应体<br/>- 修改状态码<br/>- Mock 数据
|
||||
end
|
||||
|
||||
%% 7. 代理转发响应
|
||||
Proxy-->>Client: ✅ 10. 返回响应给客户端
|
||||
Note over Proxy,Client: 最终的响应数据<br/>Client 可以正常处理
|
||||
|
||||
%% 循环: 请求重放
|
||||
rect rgba(0, 255, 0, 0.1)
|
||||
Client->>Proxy: 🔄 11. 重放请求 (可选)
|
||||
Proxy->>Client: 📤 12. 返回重放结果
|
||||
Note over Client,Proxy: 复现 Bug<br/>接口调试<br/>压力测试
|
||||
end
|
||||
```
|
||||
|
||||
**流程说明:**
|
||||
|
||||
1. **请求发起**: 客户端(浏览器或应用)向配置的代理服务器发送请求
|
||||
2. **代理解析**: 代理服务器接收请求,解析 URL、方法、头部等信息
|
||||
3. **规则匹配**: 代理检查配置的转发规则,包括请求/响应修改、域名映射等
|
||||
4. **HTTPS 处理**: 对于 HTTPS 请求,代理通过中间人模式解密和重新加密请求
|
||||
5. **转发请求**: 代理将处理后的请求转发到目标服务器
|
||||
6. **响应处理**: 目标服务器处理请求并返回响应
|
||||
7. **记录数据**: 代理记录完整的请求/响应信息到抓包列表
|
||||
8. **应用规则**: 如果配置了响应修改规则,代理会修改响应内容
|
||||
9. **返回响应**: 代理将最终响应返回给客户端
|
||||
10. **请求重放**: 可以对已记录的请求进行重放,用于调试和测试
|
||||
|
||||
**Whistle 的核心作用:**
|
||||
- 🔍 **可见性**: 记录所有经过代理的请求
|
||||
- 🎭 **可控性**: 可以修改和重放请求
|
||||
- 🔄 **灵活性**: 支持域名映射和数据 Mock
|
||||
- 📊 **调试性**: 提供详细的请求/响应分析
|
||||
|
||||
### Whistle 工具介绍
|
||||
|
||||
#### 为什么选择 Whistle
|
||||
|
||||
Whistle 是一款基于 HTTP 代理的跨平台调试工具,相比传统抓包工具具有以下优势:
|
||||
|
||||
- 跨平台支持 (Windows, Mac, Linux)
|
||||
- 内置抓包功能,支持 HTTP/HTTPS
|
||||
- 便捷的请求修改和重放
|
||||
- 支持域名映射、远程调试
|
||||
- 界面友好,操作简单
|
||||
- 支持插件扩展
|
||||
- 配置灵活,规则强大
|
||||
|
||||
#### 安装与启动
|
||||
|
||||
```bash
|
||||
# 全局安装
|
||||
npm install -g whistle
|
||||
|
||||
# 启动服务
|
||||
w2 start
|
||||
|
||||
# 启动指定端口
|
||||
w2 start -p 8899
|
||||
|
||||
# 停止服务
|
||||
w2 stop
|
||||
|
||||
# 重启服务
|
||||
w2 restart
|
||||
```
|
||||
|
||||
![[Pasted image 20260417125039.png]]
|
||||
![[Pasted image 20260417125713.png]]
|
||||
**访问界面:**
|
||||
- 默认地址: http://127.0.0.1:8899
|
||||
- 默认账号: whistle (首次安装无密码)
|
||||
|
||||
#### 代理配置
|
||||
|
||||
**命令行配置:**
|
||||
```bash
|
||||
# Mac/Linux
|
||||
export http_proxy=http://127.0.0.1:8899
|
||||
export https_proxy=http://127.0.0.1:8899
|
||||
|
||||
# Windows
|
||||
set http_proxy=http://127.0.0.1:8899
|
||||
set https_proxy=http://127.0.0.1:8899
|
||||
```
|
||||
|
||||
**系统代理配置:**
|
||||
1. 打开系统网络设置
|
||||
2. 配置 HTTP/HTTPS 代理为 127.0.0.1:8899
|
||||
3. 应用并保存
|
||||
|
||||
**手机代理配置:**
|
||||
1. 确保手机和电脑在同一局域网
|
||||
2. 查看电脑 IP 地址 (如 192.168.1.100)
|
||||
3. 手机 WiFi 设置中配置代理:
|
||||
- 服务器: 192.168.1.100
|
||||
- 端口: 8899
|
||||
4. 浏览器访问 https://rootca.pro 安装信任证书
|
||||
|
||||
### 核心功能
|
||||
|
||||
#### 1. 抓包查看
|
||||
|
||||
**功能特性:**
|
||||
- 显示所有 HTTP/HTTPS 请求
|
||||
- 显示请求/响应头和内容
|
||||
- 支持 WebSocket 抓包
|
||||
- 支持长连接和断点续传
|
||||
- 按域名、状态码、方式筛选
|
||||
|
||||
**界面说明:**
|
||||
- **请求列表**: 显示所有请求的摘要信息 (URL、方法、状态码、耗时)
|
||||
- **请求详情**: 点击请求查看完整信息 (请求头、响应头、请求体、响应体)
|
||||
- **时间线**: 显示请求的时间顺序和耗时
|
||||
- **统计**: 显示请求总数、成功数、失败数等统计信息
|
||||
|
||||
#### 2. 请求修改
|
||||
|
||||
**修改方法:**
|
||||
|
||||
1. **Values 方式 (规则面板)**:
|
||||
```
|
||||
# 修改请求头
|
||||
example.com reqHeaders://{test}
|
||||
|
||||
# 在 Values 中定义变量
|
||||
test:
|
||||
x-custom-header: custom-value
|
||||
x-another-header: another-value
|
||||
```
|
||||
|
||||
2. **正则匹配修改**:
|
||||
```
|
||||
# 修改所有匹配的请求
|
||||
/^https:\/\/example\.com\/(.*)/ reqHeaders://{test}
|
||||
```
|
||||
|
||||
3. **修改请求体**:
|
||||
```
|
||||
example.com reqBody://{test-body}
|
||||
|
||||
# Values
|
||||
test-body:
|
||||
{"modified": "data"}
|
||||
```
|
||||
|
||||
4. **修改响应**:
|
||||
```
|
||||
# 修改响应头
|
||||
example.com resHeaders://{test-res}
|
||||
|
||||
# 修改响应体
|
||||
example.com resBody://{test-body}
|
||||
|
||||
# 修改响应状态码
|
||||
example.com statusCode://404
|
||||
```
|
||||
|
||||
#### 3. 请求重放
|
||||
|
||||
**功能作用:**
|
||||
- 复现问题 bug
|
||||
- 压力测试
|
||||
- 接口调试
|
||||
- 自动化脚本测试
|
||||
|
||||
**操作步骤:**
|
||||
1. 在请求列表中选择要重放的请求
|
||||
2. 点击"重放"按钮
|
||||
3. 选择重放次数
|
||||
4. 开始重放
|
||||
|
||||
**批量重放:**
|
||||
- 支持选中多个请求批量重放
|
||||
- 支持导出请求列表为脚本
|
||||
- 支持自定义重放间隔
|
||||
|
||||
#### 4. 域名映射
|
||||
|
||||
**本地开发映射:**
|
||||
```
|
||||
# 映射到本地服务
|
||||
api.example.com 127.0.0.1:3000
|
||||
|
||||
# 映射到远程服务
|
||||
api.example.com www.test-api.com
|
||||
|
||||
# 路径映射
|
||||
example.com/api local.path/to/api
|
||||
```
|
||||
|
||||
**多环境切换:**
|
||||
```
|
||||
# 开发环境
|
||||
dev.example.com api-dev.example.com
|
||||
|
||||
# 测试环境
|
||||
test.example.com api-test.example.com
|
||||
|
||||
# 生产环境
|
||||
prod.example.com api.example.com
|
||||
```
|
||||
|
||||
#### 5. 接口 Mock
|
||||
|
||||
**数据 Mock:**
|
||||
```
|
||||
# Mock 接口响应
|
||||
api.example.com/user/info resBody://{mock-user}
|
||||
|
||||
# Values 中定义 Mock 数据
|
||||
mock-user:
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"name": "测试用户",
|
||||
"age": 25,
|
||||
"avatar": "https://example.com/avatar.png"
|
||||
},
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
**Mock 模板:**
|
||||
```
|
||||
# 文件 Mock
|
||||
api.example.com/list resBody://{./mock/list.json}
|
||||
|
||||
# 使用 mockjs 语法
|
||||
api.example.com/list resBody://{./mock/list.js}
|
||||
```
|
||||
|
||||
### 高级用法
|
||||
|
||||
#### 1. Bypass 跳过代理
|
||||
|
||||
**配置跳过规则:**
|
||||
```
|
||||
# 跳过特定域名
|
||||
www.google.com bypass://*
|
||||
|
||||
# 跳过 IP 地址
|
||||
192.168.1.100 bypass://*
|
||||
|
||||
# 跳过本地地址
|
||||
192.168.* bypass://*
|
||||
10.* bypass://*
|
||||
```
|
||||
|
||||
#### 2. 插件使用
|
||||
|
||||
**常用插件:**
|
||||
```
|
||||
# 安装插件
|
||||
w2 install whot
|
||||
|
||||
# 使用插件
|
||||
example.com whot://
|
||||
|
||||
# 查看插件
|
||||
w2 list
|
||||
```
|
||||
|
||||
#### 3. WebSocket 调试
|
||||
|
||||
**WebSocket 抓包:**
|
||||
1. 在网络列表中找到 WebSocket 请求
|
||||
2. 点击查看连接详情
|
||||
3. 实时查看发送和接收的消息
|
||||
4. 支持文本和二进制消息
|
||||
|
||||
#### 4. HTTPS 处理
|
||||
|
||||
**自签名证书概念:**
|
||||
|
||||
**什么是自签名证书?**
|
||||
|
||||
自签名证书是指不由受信任的证书颁发机构(CA,如 DigiCert、Let's Encrypt 等)签发的 SSL/TLS 证书,而是由服务器自己生成并签名的证书。
|
||||
|
||||
**与传统证书的区别:**
|
||||
|
||||
| 特性 | 受信任证书 | 自签名证书 |
|
||||
|------|------------|------------|
|
||||
| **签发者** | 受信任的 CA 机构 | 服务器自己 |
|
||||
| **浏览器信任** | ✅ 自动信任 | ❌ 警告不安全 |
|
||||
| **成本** | 付费(免费付费都有) | 免费 |
|
||||
| **验证流程** | CA 验证身份 | 无验证 |
|
||||
| **适用场景** | 生产环境、对外服务 | 开发测试、内网代理 |
|
||||
|
||||
**为什么代理抓包需要自签名证书?**
|
||||
|
||||
在 HTTPS 抓包中,代理服务器使用自签名证书的原理:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph 正常HTTPS流程
|
||||
A1[客户端] -->|建立加密连接| B1[目标服务器]
|
||||
B1 -->|发送官方证书<br>由CA签发| A1
|
||||
A1 -->|验证CA信任| B1
|
||||
end
|
||||
|
||||
subgraph 代理抓包流程
|
||||
A2[客户端] -->|建立加密连接| B2[代理服务器]
|
||||
B2 -->|发送自签名证书<br>代理自己签发| A2
|
||||
A2 -->|❓ 证书无效?|
|
||||
A2 -->|⚠️ 需要手动信任| C{是否信任代理证书}
|
||||
C -->|是| B2
|
||||
C -->|否| D[连接失败]
|
||||
|
||||
B2 -->|解密查看内容| E[代理检查内容<br/>应用修改规则]
|
||||
E -->|重新加密| B2
|
||||
B2 -->|转发到真实服务器| F[目标服务器]
|
||||
F -->|响应| B2
|
||||
B2 -->|返回给客户端| A2
|
||||
end
|
||||
```
|
||||
|
||||
**代理使用自签名证书的原因:**
|
||||
|
||||
1. **中间人攻击(MITM)的本质**:
|
||||
- HTTPS 的目的是防止中间人攻击
|
||||
- 代理抓包本质上就是"合法的中间人"
|
||||
- 需要解密 HTTPS 流量才能查看和修改
|
||||
|
||||
2. **无法动态生成官方证书**:
|
||||
- 代理无法为每个域名申请真实证书
|
||||
- 代理需要处理成千上万个不同域名的请求
|
||||
- 自签名证书是最灵活的解决方案
|
||||
|
||||
3. **时间成本和工作效率**:
|
||||
- 为每个抓包域名单独申请证书不现实
|
||||
- 自签名证书可以立即生成和使用
|
||||
|
||||
**Whistle 证书工作原理:**
|
||||
|
||||
```
|
||||
1. 用户访问 https://api.example.com
|
||||
↓
|
||||
2. Whistle 拦截请求
|
||||
↓
|
||||
3. Whistle 为 api.example.com 动态生成自签名证书
|
||||
(证书上的域名是 api.example.com)
|
||||
↓
|
||||
4. Whistle 将此证书发送给浏览器
|
||||
↓
|
||||
5. 浏览器识别出这不是受信任的 CA 签发的证书
|
||||
(因为根证书不在浏览器信任列表中)
|
||||
↓
|
||||
6. 如果用户手动导入了 Whistle 的根证书并信任
|
||||
↓
|
||||
7. 浏览器信任该证书,连接建立成功
|
||||
↓
|
||||
8. Whistle 可以解密并查看 HTTPS 内容
|
||||
```
|
||||
|
||||
**信任证书:**
|
||||
1. 访问 https://rootca.pro 下载证书
|
||||
2. 安装到系统信任根证书
|
||||
3. 移动端需要额外配置
|
||||
|
||||
**SSL Pinning 绕过:**
|
||||
- 开发环境可以关闭 SSL Pinning
|
||||
- 使用测试证书配置
|
||||
- 使用移动端调试工具 (如 Frida)
|
||||
|
||||
### 实践场景
|
||||
|
||||
#### 场景 1: 前端开发调试
|
||||
|
||||
**需求:**
|
||||
- 查看接口请求和响应
|
||||
- 修改接口数据进行测试
|
||||
- Mock 接口用于前端开发
|
||||
|
||||
**配置:**
|
||||
```
|
||||
# 查看接口日志
|
||||
api.example.com log://
|
||||
|
||||
# 修改接口响应
|
||||
api.example.com resBody://{mock-data}
|
||||
|
||||
# 映射到本地服务
|
||||
api.example.com 127.0.0.1:8080
|
||||
```
|
||||
|
||||
#### 场景 2: 移动端开发调试
|
||||
|
||||
**需求:**
|
||||
- 抓取手机应用的网络请求
|
||||
- 查看和修改接口数据
|
||||
- 解决跨域问题
|
||||
|
||||
**配置:**
|
||||
```
|
||||
# 启用 CORS
|
||||
api.example.com resCors:// *
|
||||
|
||||
# 允许所有域
|
||||
api.example.com reqHeaders://{test}
|
||||
|
||||
test:
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Credentials: true
|
||||
```
|
||||
|
||||
#### 场景 3: 接口测试和压测
|
||||
|
||||
**需求:**
|
||||
- 重复某接口的请求
|
||||
- 测试并发请求
|
||||
- 验证接口性能
|
||||
|
||||
**操作:**
|
||||
1. 选择目标接口
|
||||
2. 点击"重放" → "多次重放"
|
||||
3. 设置重放次数和间隔
|
||||
4. 查看结果和统计
|
||||
|
||||
#### 场景 4: 问题复现
|
||||
|
||||
**需求:**
|
||||
- 在本地复现线上问题
|
||||
- 使用线上数据调试
|
||||
- 分离前端和后端问题
|
||||
|
||||
**配置:**
|
||||
```
|
||||
# 使用线上接口,本地前端
|
||||
localhost:8080/api online.example.com/api
|
||||
|
||||
# 使用本地接口,线上前端
|
||||
www.example.com/api 127.0.0.1:8080/api
|
||||
```
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### 1. 抓不到 HTTPS 请求
|
||||
|
||||
**解决方法:**
|
||||
- 确认已安装并信任根证书
|
||||
- 检查系统代理是否配置正确
|
||||
- 重启浏览器和应用
|
||||
- 清除浏览器缓存
|
||||
|
||||
#### 2. 证书不信任
|
||||
|
||||
**解决方法:**
|
||||
- Windows: 安装到"受信任的根证书颁发机构"
|
||||
- Mac: 安装钥匙串并设置为"始终信任"
|
||||
- 移动端: 进入设置 → 通用 → 关于本机 → 证书信任设置
|
||||
|
||||
#### 3. 代理配置后无法上网
|
||||
|
||||
**解决方法:**
|
||||
- 检查 whistle 是否启动
|
||||
- 确认代理地址和端口正确
|
||||
- 检查防火墙设置
|
||||
- 尝试使用 bypass:// 规则
|
||||
|
||||
#### 4. 规则不生效
|
||||
|
||||
**排查步骤:**
|
||||
1. 检查规则语法是否正确
|
||||
2. 确认规则没有冲突
|
||||
3. 查看规则优先级
|
||||
4. 使用 log:// 查看匹配情况
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 规则组织
|
||||
|
||||
```
|
||||
# 按功能分类
|
||||
# ----- 本地开发 -----
|
||||
api-dev.example.com 127.0.0.1:3000
|
||||
static-dev.example.com 127.0.0.1:8080
|
||||
|
||||
# ----- 测试环境 -----
|
||||
api-test.example.com test-api.example.com
|
||||
|
||||
# ----- Mock 数据 -----
|
||||
api.example.com/user resBody://{./mock/user.json}
|
||||
api.example.com/list resBody://{./mock/list.json}
|
||||
|
||||
# ----- 特殊规则 -----
|
||||
google.com bypass://*
|
||||
```
|
||||
|
||||
#### 2. 性能优化
|
||||
|
||||
- 及时清理过多的抓包记录
|
||||
- 使用过滤器只关注相关请求
|
||||
- 对于高流量场景使用 bypass:// 规则
|
||||
|
||||
#### 3. 安全建议
|
||||
|
||||
- 不要在公共WiFi下使用代理抓包
|
||||
- 及时清理缓存中的敏感信息
|
||||
- 不要在生产环境使用长时间的代理
|
||||
- 定期备份重要的配置和规则
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[CS/NET/网络协议分析基础]]
|
||||
- [[CS/SECURITY/网络安全基础]]
|
||||
- [[DEV/DEBUG/调试技巧总结]]
|
||||
|
||||
## 参考资源
|
||||
|
||||
- Whistle 官方文档: https://wproxy.org/whistle/
|
||||
- Whistle GitHub: https://github.com/avwo/whistle
|
||||
Reference in New Issue
Block a user