通过 Cloudflare R2 存储桶隧道传输的 SOCKS5 代理。
[客户端应用] ◄─SOCKS5─► [代理] ◄─── R2 存储桶 ───► [Agent] ◄─TCP─► [目标]
代理在操作者机器上运行本地 SOCKS5 服务器。每个 CONNECT 请求都被序列化为二进制数据包,并作为 R2 对象存储。Agent 从目标网络轮询同一个存储桶,获取连接请求,建立真实的 TCP 连接,并通过 R2 中继数据。
| 组件 | 语言 | 文件 | 描述 |
|---|---|---|---|
| 代理 | Python | r2socks.py | SOCKS5 服务器(操作者侧) |
| Agent | Python | r2socks.py | 目标侧中继(agent 模式) |
| Agent | C++ | r2agent.cpp | 独立 Windows agent,零依赖 |
C++ agent 与 Python 代理协议兼容。它仅使用 Windows 原生 API(WinHTTP、bcrypt、Winsock2),无需外部库。
dash.cloudflare.com/<ACCOUNT_ID>/r2/...pip install boto3
python r2socks.py proxy -b my-bucket -a <account_id> \
--access-key <R2_ACCESS_KEY> --secret-key <R2_SECRET_KEY>
代理会生成一个通道 ID,并打印启动 agent 的命令。
Python agent:
python r2socks.py agent -b my-bucket -a <account_id> -c <channel_id> \
--access-key <R2_ACCESS_KEY> --secret-key <R2_SECRET_KEY>
C++ agent(Windows):
.\r2agent.exe -b my-bucket -a <account_id> -c <channel_id> -k <access_key> -s <secret_key>
python r2socks.py proxy [options]
Required:
-b, --bucket BUCKET R2 bucket name
-a, --account-id ID Cloudflare account ID
Optional:
-c, --channel ID Channel ID (auto-generated if omitted)
-l, --listen ADDR Listen address (default: 127.0.0.1:1080)
--access-key KEY R2 API token Access Key ID
--secret-key KEY R2 API token Secret Access Key
--socks-user USER Enable SOCKS5 user/pass authentication
--socks-pass PASS SOCKS5 password
-p, --password PWD AES-256-GCM encryption password
-v, --verbose Debug logging
Python:
python r2socks.py agent [options]
Required:
-b, --bucket BUCKET R2 bucket name
-a, --account-id ID Cloudflare account ID
-c, --channel ID Channel ID (from proxy output)
C++(Windows):
r2agent.exe [options]
Required:
-b, --bucket BUCKET R2 bucket name
-a, --account-id ID Cloudflare account ID
-c, --channel ID Channel ID (from proxy output)
Credentials (flags override env vars):
-k, --access-key KEY R2 API token Access Key ID
-s, --secret-key KEY R2 API token Secret Access Key
Optional:
-v, --verbose Debug logging
完成后移除通道中的所有 R2 对象:
python r2socks.py clean -b my-bucket -a <account_id> -c <channel_id>
代理与 agent 之间共享的二进制数据包格式:
┌──────────┬────────────────────┬────────────┬──────────────────┐
│ CMD (1B) │ ConnectionID (16B) │ Len (4B BE)│ Payload (var) │
└──────────┴────────────────────┴────────────┴──────────────────┘
多个数据包被批量合并为单个 R2 对象(最大 4MB),以减少 API 调用。对象以微秒时间戳命名以便排序,并在消费后删除。
对所有 R2 载荷可选启用 AES-256-GCM 加密:
pip install cryptography
# Both sides must use the same password
python r2socks.py proxy -b bucket -a account_id -p "my-secret-password"
python r2socks.py agent -b bucket -a account_id -c channel -p "my-secret-password"
密钥使用 PBKDF2-SHA256 派生,迭代次数为 600,000 次。
从 Visual Studio Developer Command Prompt 中执行:
cl /std:c++17 /EHsc /O2 r2agent.cpp /link ws2_32.lib winhttp.lib bcrypt.lib
代理和 agent 都使用自适应休眠间隔:
这在响应能力与 API 调用量之间取得平衡。每 30 秒记录一次统计信息,显示活动连接数、传输的对象数和移动的字节数。
SignatureDoesNotMatchw32tm /resync /force(Windows)或 sudo ntpdate pool.ntp.org(Linux)RequestTimeTooSkewedw32tm /resync /force
AccessDenied代理(Python):
boto3(必需)cryptography(可选,用于加密)Agent(C++):
| 命令 | 代码 | 方向 | 载荷 |
|---|
| NEW | 0x01 | Proxy→Agent | ATYP + Address + Port |
| ACK | 0x02 | Agent→Proxy | 1 byte status (0=success) |
| DATA | 0x03 | Bidirectional | Raw TCP data (up to 1MB) |
| CLOSE | 0x04 | Bidirectional | Empty |
| PING | 0x05 | Bidirectional | Empty |