# Misbruik van Cloudflare Workers as pass-through proxies (IP-rotasie, FireProx-style)

{{#include ../../banners/hacktricks-training.md}}

Cloudflare Workers kan gedeploy word as deursigtige HTTP pass-through proxies waar die upstream target URL deur die kliënt verskaf word. Versoeke verlaat Cloudflare se netwerk, sodat die teiken Cloudflare IP's sien in plaas van die kliënt se IP. Dit weerspieël die goed-bekende FireProx-tegniek op AWS API Gateway, maar gebruik Cloudflare Workers.

### Belangrike vermoëns
- Support vir alle HTTP methods (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)
- Target kan verskaf word via 'n query-parameter (?url=...), 'n header (X-Target-URL), of selfs gekodeer in die path (bv. /https://target)
- Headers en body word deur die proxy deurgegee met hop-by-hop/header filtering soos nodig
- Responses word terugge-relay, met behoue status code en meeste headers
- Opsionele spoofing van X-Forwarded-For (indien die Worker dit stel vanaf 'n gebruiker-beheerde header)
- Uiters vinnige/eenvoudige rotasie deur verskeie Worker endpoints te ontplooi en versoeke te versprei

### Hoe dit werk (flow)
1) Kliënt stuur 'n HTTP-versoek na 'n Worker URL (`<name>.<account>.workers.dev` of 'n custom domain route).
2) Worker haal die target uit óf 'n query-parameter (?url=...), die X-Target-URL header, of 'n path-segment indien geïmplementeer.
3) Worker stuur die inkomende method, headers, en body na die gespesifiseerde upstream URL (filtreer problematiese headers).
4) Upstream response word teruggestroom na die kliënt deur Cloudflare; die oorsprong sien Cloudflare se uitgaande IP's.

### Worker implementation example
- Lees target URL vanaf query param, header, of path
- Kopieer 'n veilige substel van headers en stuur die oorspronklike method/body voort
- Opsioneel stel X-Forwarded-For deur 'n deur-gebruiker-beheerde header (X-My-X-Forwarded-For) of 'n ewekansige IP te gebruik
- Voeg permissiewe CORS by en hanteer preflight

<details>
<summary>Voorbeeld Worker (JavaScript) vir pass-through proxying</summary>
```javascript
/**
* Minimal Worker pass-through proxy
* - Target URL from ?url=, X-Target-URL, or /https://...
* - Proxies method/headers/body to upstream; relays response
*/
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
try {
const url = new URL(request.url)
const targetUrl = getTargetUrl(url, request.headers)

if (!targetUrl) {
return errorJSON('No target URL specified', 400, {
usage: {
query_param: '?url=https://example.com',
header: 'X-Target-URL: https://example.com',
path: '/https://example.com'
}
})
}

let target
try { target = new URL(targetUrl) } catch (e) {
return errorJSON('Invalid target URL', 400, { provided: targetUrl })
}

// Forward original query params except control ones
const passthru = new URLSearchParams()
for (const [k, v] of url.searchParams) {
if (!['url', '_cb', '_t'].includes(k)) passthru.append(k, v)
}
if (passthru.toString()) target.search = passthru.toString()

// Build proxied request
const proxyReq = buildProxyRequest(request, target)
const upstream = await fetch(proxyReq)

return buildProxyResponse(upstream, request.method)
} catch (error) {
return errorJSON('Proxy request failed', 500, {
message: error.message,
timestamp: new Date().toISOString()
})
}
}

function getTargetUrl(url, headers) {
let t = url.searchParams.get('url') || headers.get('X-Target-URL')
if (!t && url.pathname !== '/') {
const p = url.pathname.slice(1)
if (p.startsWith('http')) t = p
}
return t
}

function buildProxyRequest(request, target) {
const h = new Headers()
const allow = [
'accept','accept-language','accept-encoding','authorization',
'cache-control','content-type','origin','referer','user-agent'
]
for (const [k, v] of request.headers) {
if (allow.includes(k.toLowerCase())) h.set(k, v)
}
h.set('Host', target.hostname)

// Optional: spoof X-Forwarded-For if provided
const spoof = request.headers.get('X-My-X-Forwarded-For')
h.set('X-Forwarded-For', spoof || randomIP())

return new Request(target.toString(), {
method: request.method,
headers: h,
body: ['GET','HEAD'].includes(request.method) ? null : request.body
})
}

function buildProxyResponse(resp, method) {
const h = new Headers()
for (const [k, v] of resp.headers) {
if (!['content-encoding','content-length','transfer-encoding'].includes(k.toLowerCase())) {
h.set(k, v)
}
}
// Permissive CORS for tooling convenience
h.set('Access-Control-Allow-Origin', '*')
h.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD')
h.set('Access-Control-Allow-Headers', '*')

if (method === 'OPTIONS') return new Response(null, { status: 204, headers: h })
return new Response(resp.body, { status: resp.status, statusText: resp.statusText, headers: h })
}

function errorJSON(msg, status=400, extra={}) {
return new Response(JSON.stringify({ error: msg, ...extra }), {
status, headers: { 'Content-Type': 'application/json' }
})
}

function randomIP() { return [1,2,3,4].map(() => Math.floor(Math.random()*255)+1).join('.') }
```
</details>

### Automatiseer ontplooiing en rotasie met FlareProx

FlareProx is 'n Python-instrument wat die Cloudflare API gebruik om baie Worker endpoints te ontplooi en oor hulle te roteer. Dit bied FireProx-like IP rotation vanaf Cloudflare se netwerk.

Opstelling
1) Skep 'n Cloudflare API Token met behulp van die “Edit Cloudflare Workers” template en kry jou Account ID vanaf die dashboard.
2) Konfigureer FlareProx:
```bash
git clone https://github.com/MrTurvey/flareprox
cd flareprox
pip install -r requirements.txt
```
**Skep die konfigurasielêer flareprox.json:**
```json
{
"cloudflare": {
"api_token": "your_cloudflare_api_token",
"account_id": "your_cloudflare_account_id"
}
}
```
**CLI gebruik**

- Skep N Worker proxies:
```bash
python3 flareprox.py create --count 2
```
- Lys endpoints:
```bash
python3 flareprox.py list
```
- Gesondheidstoets endpoints:
```bash
python3 flareprox.py test
```
- Verwyder alle endpoints:
```bash
python3 flareprox.py cleanup
```
**Verkeer deur 'n Worker herlei**
- Vorm van navraagparameters:
```bash
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/ip"
```
- Kopvorm:
```bash
curl -H "X-Target-URL: https://httpbin.org/ip" https://your-worker.account.workers.dev
```
- Padvorm (indien geïmplementeer):
```bash
curl https://your-worker.account.workers.dev/https://httpbin.org/ip
```
- Metodevoorbeelde:
```bash
# GET
curl "https://your-worker.account.workers.dev?url=https://httpbin.org/get"

# POST (form)
curl -X POST -d "username=admin" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/post"

# PUT (JSON)
curl -X PUT -d '{"username":"admin"}' -H "Content-Type: application/json" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/put"

# DELETE
curl -X DELETE \
"https://your-worker.account.workers.dev?url=https://httpbin.org/delete"
```
**`X-Forwarded-For` beheer**

As die Worker `X-My-X-Forwarded-For` respekteer, kan jy die upstream `X-Forwarded-For` waarde beïnvloed:
```bash
curl -H "X-My-X-Forwarded-For: 203.0.113.10" \
"https://your-worker.account.workers.dev?url=https://httpbin.org/headers"
```
**Programmatiese gebruik**

Gebruik die FlareProx-biblioteek om endpoints te skep/lys/toets en versoeke vanaf Python te routeer.

<details>
<summary>Python-voorbeeld: Stuur 'n POST via 'n ewekansige Worker-endpoint</summary>
```python
#!/usr/bin/env python3
from flareprox import FlareProx, FlareProxError
import json

# Initialize
flareprox = FlareProx(config_file="flareprox.json")
if not flareprox.is_configured:
print("FlareProx not configured. Run: python3 flareprox.py config")
exit(1)

# Ensure endpoints exist
endpoints = flareprox.sync_endpoints()
if not endpoints:
print("Creating proxy endpoints...")
flareprox.create_proxies(count=2)

# Make a POST request through a random endpoint
try:
post_data = json.dumps({
"username": "testuser",
"message": "Hello from FlareProx!",
"timestamp": "2025-01-01T12:00:00Z"
})

headers = {
"Content-Type": "application/json",
"User-Agent": "FlareProx-Client/1.0"
}

response = flareprox.redirect_request(
target_url="https://httpbin.org/post",
method="POST",
headers=headers,
data=post_data
)

if response.status_code == 200:
result = response.json()
print("✓ POST successful via FlareProx")
print(f"Origin IP: {result.get('origin', 'unknown')}")
print(f"Posted data: {result.get('json', {})}")
else:
print(f"Request failed with status: {response.status_code}")

except FlareProxError as e:
print(f"FlareProx error: {e}")
except Exception as e:
print(f"Request error: {e}")
```
</details>

**Burp/Scanner integrasie**
- Wys jou tooling (byvoorbeeld Burp Suite) na die Worker-URL.
- Verskaf die werklike upstream met ?url= of X-Target-URL.
- HTTP semantics (methods/headers/body) word behou terwyl jou bron-IP agter Cloudflare gemasker word.

**Operationele notas en perke**
- Cloudflare Workers Free plan laat ongeveer 100,000 versoeke/dag per rekening toe; gebruik verskeie endpunte om verkeer te versprei indien nodig.
- Workers hardloop op Cloudflare se netwerk; baie teikens sal slegs Cloudflare IPs/ASN sien, wat eenvoudige IP allow/deny-lyste of geo-heuristieke kan omseil.
- Gebruik dit verantwoordelik en slegs met magtiging. Respekteer ToS en robots.txt.

## Verwysings
- [FlareProx (Cloudflare Workers pass-through/rotation)](https://github.com/MrTurvey/flareprox)
- [Cloudflare Workers fetch() API](https://developers.cloudflare.com/workers/runtime-apis/fetch/)
- [Cloudflare Workers pricing and free tier](https://developers.cloudflare.com/workers/platform/pricing/)
- [FireProx (AWS API Gateway)](https://github.com/ustayready/fireprox)

{{#include ../../banners/hacktricks-training.md}}
