
SOCKS5 proxy tunneled through Cloudflare R2 object storage, with Python and dependency-free C++ agents relaying TCP traffic via encrypted R2 objects for covert access.
SOCKS5 proxy tunneled through Cloudflare R2 buckets.
[Client App] ◄─SOCKS5─► [Proxy] ◄─── R2 Bucket ───► [Agent] ◄─TCP─► [Target]
The proxy runs a local SOCKS5 server on the operator's machine. Every CONNECT request is serialized as binary packets and stored as R2 objects. The agent polls the same bucket from the target network, picks up connection requests, establishes real TCP connections, and relays data back through R2.
| Component | Language | File | Description |
|---|---|---|---|
| Proxy | Python | r2socks.py | SOCKS5 server (operator side) |
| Agent | Python | r2socks.py | Target-side relay (agent mode) |
| Agent | C++ | r2agent.cpp | Standalone Windows agent, zero dependencies |
The C++ agent is protocol-compatible with the Python proxy. It uses only Windows-native APIs (WinHTTP, bcrypt, Winsock2) no external libraries required.
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>
The proxy generates a channel ID and prints the command to start the 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
Remove all R2 objects from a channel when done:
python r2socks.py clean -b my-bucket -a <account_id> -c <channel_id>
Binary packet format shared between proxy and agent:
┌──────────┬────────────────────┬────────────┬──────────────────┐
│ CMD (1B) │ ConnectionID (16B) │ Len (4B BE)│ Payload (var) │
└──────────┴────────────────────┴────────────┴──────────────────┘
Multiple packets are batched into a single R2 object (up to 4MB) to reduce API calls. Objects are named with microsecond timestamps for ordering and deleted after consumption.
Optional AES-256-GCM encryption for all R2 payloads:
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"
The key is derived using PBKDF2-SHA256 with 600,000 iterations.
From a Visual Studio Developer Command Prompt:
cl /std:c++17 /EHsc /O2 r2agent.cpp /link ws2_32.lib winhttp.lib bcrypt.lib
Both proxy and agent use adaptive sleep intervals:
This balances responsiveness against API call volume. Stats are logged every 30 seconds showing active connections, objects transferred, and bytes moved.
SignatureDoesNotMatchw32tm /resync /force (Windows) or sudo ntpdate pool.ntp.org (Linux)RequestTimeTooSkewedw32tm /resync /force
AccessDeniedProxy (Python):
boto3 (required)cryptography (optional, for encryption)Agent (C++):
| Command | Code | Direction | Payload |
|---|
| 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 |