# Cloudflare WARP IPv6 代理 SOP — Docker / warp-cli / wgcf 三模式与 IP 轮转

**适用场景**：需要海量 IPv6 出口 / 国家级代理池 / 反指纹追踪的爬虫与自动化任务。
**核心理念**：利用 Cloudflare 官方 WARP 客户端将本机出口伪装为 IPv6；Docker 模式适用于服务器，warp-cli 模式适用于桌面及 CI 环境，wgcf 模式适用于系统级全局代理。

---

## 一、核心 SOP

WARP 通过 Cloudflare 网络（`2a09:bac5:xxxx` 段）提供几乎无限的 IPv6 IP 多样性。每次重新连接都会分配一个全新的 IPv6 出口地址，非常适合注册、爬虫以及任何需要 IP 轮转（IP rotation）的任务。

## 三种操作模式

### 模式 1：Docker 容器（本地/VPS）

✅ 最适合持久运行的服务器。使用 `caomingjun/warp` 镜像，内置 GOST 代理。

```bash
# Launch WARP proxy container
docker run -d --name warp-0 \
  -p 127.0.0.1:1080:1080 \
  --restart unless-stopped \
  caomingjun/warp:latest

# Verify (wait ~15s for initialization)
curl -x http://127.0.0.1:1080 https://cloudflare.com/cdn-cgi/trace | grep -E "^(ip|warp)="
# Expected: ip=2a09:bac5:xxxx:xxxx::xxx:xx  warp=on
```

**IP 轮转** — 重启容器即可：
```bash
docker restart warp-0
sleep 10
curl -x http://127.0.0.1:1080 https://cloudflare.com/cdn-cgi/trace | grep "^ip="
```

**多容器并行** — 实现并行 IP 多样性：
```bash
for i in 0 1 2; do
  docker run -d --name warp-$i -p 127.0.0.1:$((1080+i)):1080 --restart unless-stopped caomingjun/warp:latest
done
# Proxies: http://127.0.0.1:1080, :1081, :1082
```

**主机网络模式（host network mode）**（透明隧道，无需代理配置）：
```bash
docker run -d --name warp-host --network host --restart unless-stopped caomingjun/warp:latest
# All host traffic now routes through WARP — no proxy configuration needed
```

### 模式 2：warp-cli（CI / 临时环境）

✅ 最适合 GitHub Actions 及一次性环境。原生安装。

```bash
# Install
curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg \
  | sudo gpg --yes --dearmor -o /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
sudo apt-get update -qq && sudo apt-get install -y -qq cloudflare-warp

# Start service and register
sudo systemctl start warp-svc
warp-cli --accept-tos registration new
```

**隧道模式（tunnel mode）**（透明代理，推荐用于 CI）：
```bash
warp-cli --accept-tos connect
sleep 5
curl https://cloudflare.com/cdn-cgi/trace | grep "warp=on"
# All traffic goes through WARP — no proxy needed
```

**代理模式（proxy mode）**（显式 SOCKS5 代理）：
```bash
warp-cli --accept-tos mode proxy
warp-cli --accept-tos proxy port 1080
warp-cli --accept-tos connect
# SOCKS5 proxy at socks5://127.0.0.1:1080
# Note: Chrome/DrissionPage can't use socks5 directly — use tunnel mode instead
```

**IP 轮转** — 通过 warp-cli 实现：
```bash
warp-cli disconnect && sleep 1 && warp-cli connect && sleep 5
curl https://cloudflare.com/cdn-cgi/trace | grep "^ip="
```

### 模式 3：wgcf（系统级 WireGuard）

✅ 最适合需要将所有流量通过 WARP 出去的持久化 VPS。最轻量级的选择——无需 Docker，无需守护进程，仅依赖内核 WireGuard。每次执行 `wgcf register` 都会创建一个包含新密钥对（keypair）的全新 WARP 账号，从而获得真正不同的出口 IP（这与模式 1-2 使用相同身份重新连接不同）。

```bash
# Install WireGuard + wgcf
apt install -y wireguard-tools
curl -fsSL -o /usr/local/bin/wgcf \
  'https://github.com/ViRb3/wgcf/releases/download/v2.2.22/wgcf_2.2.22_linux_amd64'
chmod +x /usr/local/bin/wgcf

# Generate initial identity
cd /tmp && wgcf register --accept-tos && wgcf generate
```

创建 `/etc/wireguard/warp.conf`——⚠️ 其中的 PostUp/PostDown 规则通过将 VPS 的真实 IP 路由至主路由表而非 WARP，来保持 SSH 连接的正常工作：

```ini
[Interface]
PrivateKey = <from wgcf-profile.conf>
Address = 172.16.0.2/32
Address = <IPv6 from wgcf-profile.conf>/128
DNS = 1.1.1.1,8.8.8.8,8.8.4.4,2606:4700:4700::1111,2001:4860:4860::8888,2001:4860:4860::8844
MTU = 1420
PostUp = ip -4 rule add from <VPS_REAL_IPv4> lookup main
PostDown = ip -4 rule delete from <VPS_REAL_IPv4> lookup main
PostUp = ip -6 rule add from <VPS_REAL_IPv6> lookup main
PostDown = ip -6 rule delete from <VPS_REAL_IPv6> lookup main

[Peer]
PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
AllowedIPs = 0.0.0.0/0,::/0
Endpoint = engage.cloudflareclient.com:2408
PersistentKeepalive = 30
```

```bash
wg-quick up warp
curl https://cloudflare.com/cdn-cgi/trace | grep -E "^(ip|warp)="
# Expected: warp=on, ip=104.28.x.x (Cloudflare exit)
```

**IP 轮转** — 生成一个全新的 WARP 身份：
```bash
cd /tmp && rm -f wgcf-account.toml wgcf-profile.conf
wgcf register --accept-tos && wgcf generate
# Extract new PrivateKey and IPv6 from wgcf-profile.conf
# Update /etc/wireguard/warp.conf with new values (keep PostUp/PostDown rules!)
wg-quick down warp && sleep 2 && wg-quick up warp
```

这是一次完整的身份轮转——新密钥对、新 Cloudflare 账号、新出口 IP。这比模式 1/2 中复用相同身份（可能从相同 PoP 节点获取相似 IP）的简单重连要强大得多。

**针对自定义 Web 应用的自动化轮转**：参考自定义部署技能（示例：`<your-deploy-skill>`），其中包含自定义脚本（示例：`warp-rotate.sh`，基于 Cron 的 429 检测与自动轮转）和自定义管理脚本（示例：`web-manager.sh`，带进程监控的统一管理器）。

### 模式对比

| | Docker | warp-cli | wgcf |
|--|--------|----------|------|
| **部署方式** | `docker run` | `apt install` + 守护进程 | `wg-quick up` |
| **代理类型** | HTTP :1080 | SOCKS5 或隧道 | 透明隧道 |
| **内存占用** | 约 200MB | 约 100MB（守护进程） | 约 0（内核模块） |
| **轮转方式** | 重启容器（相同身份） | 断开/连接（相同身份） | `wgcf register`（新身份） |
| **适用场景** | 需要显式代理的应用 | CI / 临时环境 | VPS 全流量隧道 |
| **SSH 安全性** | 不适用（容器隔离） | 不适用（隧道模式） | 必须配置 PostUp 规则 |

## GitHub Actions 集成

```yaml
- name: Setup WARP (IPv6 tunnel)
  run: |
    curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg \
      | sudo gpg --yes --dearmor -o /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
    echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" \
      | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
    sudo apt-get update -qq && sudo apt-get install -y -qq cloudflare-warp
    sudo systemctl start warp-svc || true
    sleep 2
    warp-cli --accept-tos registration new || true
    warp-cli --accept-tos connect
    sleep 5
    echo "--- WARP status ---"
    curl -s https://cloudflare.com/cdn-cgi/trace | grep -E "^(ip|warp)="
```

对于注册工作流中的 IP 轮转，可设置环境变量 `WARP_CLI=1` 并使用以下代码：
```python
import subprocess, time, requests
def rotate_ip():
    subprocess.run(["warp-cli", "disconnect"], capture_output=True, timeout=10)
    time.sleep(1)
    subprocess.run(["warp-cli", "connect"], capture_output=True, timeout=10)
    time.sleep(5)
    r = requests.get("https://cloudflare.com/cdn-cgi/trace", timeout=10)
    ip = next((l.split("=")[1] for l in r.text.splitlines() if l.startswith("ip=")), "unknown")
    print(f"New IP: {ip}")
```

## 浏览器自动化集成

**DrissionPage** 仅支持 HTTP 代理（通过 Chrome `--proxy-server` 参数）。它**不支持** `socks5://`。

| 模式 | DrissionPage 配置 | 工作原理 |
|------|-------------------|--------------|
| Docker 代理 | `co.set_proxy("http://127.0.0.1:1080")` | 容器内 GOST 提供 HTTP 代理 |
| warp-cli 隧道 | 无需代理 | 所有流量透明路由通过 WARP |
| warp-cli SOCKS5 | 不直接支持 | 请改用隧道模式 |

✅ **CI 环境推荐**：使用 warp-cli 隧道模式且不配置代理——最简单可靠。

✅ **本地环境推荐**：使用 Docker 容器的 `http://127.0.0.1:1080` 代理。

## 验证方法

在开始工作前，务必验证 WARP 是否已激活：

```bash
# Through proxy
curl -x http://127.0.0.1:1080 https://cloudflare.com/cdn-cgi/trace

# Direct (tunnel mode)
curl https://cloudflare.com/cdn-cgi/trace
```

预期输出应包含：
- `warp=on` —— WARP 已激活
- `ip=2a09:bac5:...` 或 `ip=2a09:bac6:...` —— IPv6 出口地址

## 故障排除

**容器显示 "unhealthy"**：通常由容器内 NTP 同步失败引起。这仅是表面现象——代理依然正常工作。请使用 `curl -x http://127.0.0.1:1080 https://cloudflare.com/cdn-cgi/trace` 验证。如果代理可用，请忽略该健康状态。

**通过 WARP 时 DNS 解析失败**：某些 DNS 解析器（如 systemd-resolved）在 WARP 激活时，可能会拦截被标记为危险的域名。解决方案：
- 使用 `dig @8.8.8.8 domain.com` 通过外部 DNS 进行测试
- 在 `/etc/systemd/resolved.conf` 中配置 `DNS=1.1.1.1 8.8.8.8`

**轮转后 IP 未改变**：重新连接后请等待更长时间（5-10 秒）。WARP 需要时间建立新隧道。对于 Docker，执行 `docker restart` 后需等待 10-15 秒。

**"Registration missing" 错误**：再次运行 `warp-cli --accept-tos registration new`。在 CI 运行器上，请添加 `|| true`，因为重复注册是幂等（idempotent）的。

## 429 感知自动 IP 轮转（wgcf 模式）

当 WARP 用于注册/爬虫等持续任务时，需要自动检测限流并轮转 IP。以下是经过生产验证的双触发轮转机制。

### 核心思路

```
Cron (每5分钟) → 检查冷却期 → 检测429 OR 达到基线时间 → rotate_warp()
```

**双触发策略：**
- **被动触发**：检测应用日志中 429 错误数 ≥ 阈值 → 立即轮转
- **基线触发**：无论是否有 429，每 N 分钟强制轮转（防止 IP 被慢速标记）
- **冷却保护**：两次轮转间隔不低于 5 分钟，避免过度轮转

### 429 检测函数

```bash
THRESHOLD_429=5        # 最近 100 行日志中 429 数量阈值
APP_LOG="<YOUR_APP_LOG_PATH>"  # 你的应用日志路径

check_429_rate() {
    [ ! -f "$APP_LOG" ] && return 1
    local c429
    c429=$(tail -100 "$APP_LOG" 2>/dev/null | grep -c 429) || c429=0
    [ "$c429" -ge "$THRESHOLD_429" ]
}
```

### 全身份轮转函数（wgcf）

每次轮转生成全新 WARP 账号 + 密钥对（keypair） + 出口 IP，比简单重连（reconnect）更彻底：

```bash
WARP_CONF=/etc/wireguard/warp.conf
COOLDOWN_FILE="$HOME/.warp-cooldown"
COOLDOWN_SECONDS=300   # 最小轮转间隔 5 分钟
MAX_AGE_SECONDS=600    # 基线：每 10 分钟强制轮转

rotate_warp() {
    cd /tmp && rm -f wgcf-account.toml wgcf-profile.conf
    wgcf register --accept-tos && wgcf generate || return 1

    local new_key new_addr_v6
    new_key=$(grep '^PrivateKey' wgcf-profile.conf | awk '{print $3}')
    new_addr_v6=$(grep 'Address.*2606:' wgcf-profile.conf | awk '{print $3}')
    [ -z "$new_key" ] && return 1

    sudo cp "$WARP_CONF" "${WARP_CONF}.bak"
    # 用 new_key 和 new_addr_v6 更新 warp.conf 的 PrivateKey 和 Address 字段
    # ⚠️ 保留 PostUp/PostDown 规则（SSH 路由保护）不变
    sudo sed -i "s|^PrivateKey = .*|PrivateKey = ${new_key}|" "$WARP_CONF"
    sudo sed -i "s|^Address = 2606:.*|Address = ${new_addr_v6}|" "$WARP_CONF"

    sudo wg-quick down warp 2>/dev/null; sleep 2
    sudo wg-quick up warp || {
        sudo cp "${WARP_CONF}.bak" "$WARP_CONF"
        sudo wg-quick up warp; return 1
    }

    date +%s > "$COOLDOWN_FILE"
    sleep 3
    echo "New IP: $(curl -s --max-time 5 https://api64.ipify.org 2>/dev/null)"
    rm -f /tmp/wgcf-account.toml /tmp/wgcf-profile.conf
}
```

### 主逻辑 + Cron 集成

```bash
# 主逻辑（写入 warp-rotate.sh）
elapsed=$(( $(date +%s) - $(cat "$COOLDOWN_FILE" 2>/dev/null || echo 0) ))
if [ "$elapsed" -lt "$COOLDOWN_SECONDS" ]; then
    exit 0  # 冷却期内，跳过
fi
if check_429_rate; then
    rotate_warp       # 被动触发
elif [ "$elapsed" -ge "$MAX_AGE_SECONDS" ]; then
    rotate_warp       # 基线触发
fi
```

**Cron 一行命令（每 5 分钟检查）：**
```bash
*/5 * * * * /path/to/warp-rotate.sh >> /var/log/warp-rotate.log 2>&1
```

### 性能参考

| 指标 | 数值 |
|------|------|
| 每个 IP 可用注册数 | 6-10 次（触发 429 前） |
| 轮转间隔 | 基线 10 分钟 / 被动 5 分钟 |
| 单次轮转耗时 | 约 8 秒（register + generate + wg-quick） |

### 适用场景

- 批量注册（Web 账号、API Token）
- 持续爬虫（IP 被标记后自动切换）
- 任何需要 IP 多样性的长时间自动化任务

---

## 关键事实

- IPv6 地址段：`2a09:bac5:xxxx` / `2a09:bac6:xxxx` —— 几乎无限的 IP
- Docker 镜像：`caomingjun/warp:latest` —— 入口点 `/entrypoint.sh`，内置 GOST 监听 `:1080`
- warp-cli 首次使用时始终需要 `--accept-tos` 参数
- 在执行任何 warp-cli 命令前，必须运行 `sudo systemctl start warp-svc`
- 每次重新连接（重启/断开+连接）都会分配一个全新的 IPv6 出口
- WARP 流量表现为合法的 Cloudflare 流量，而非 VPN/代理