How to Use Proxies for Penetration Testing
Penetration testing evaluates security by simulating real-world attacks. Proxy infrastructure enables testers to simulate attacks from diverse geographic locations and IP ranges, test geo-based security controls, and manage source attribution during authorized assessments.
Critical: Always obtain written authorization before any penetration testing. Unauthorized testing is illegal in virtually all jurisdictions.
Why Pentesters Use Proxies
- Geographic testing: Test geo-based security controls (geo-blocking, region-specific WAF rules)
- Source diversification: Test how security systems respond to distributed attack patterns
- WAF testing: Evaluate rate limiting and IP-based blocking across multiple source IPs
- Traffic attribution: Manage source IPs for responsible testing that does not contaminate production logs
Proxy Configuration for Security Tools
import httpx
from dataclasses import dataclass
@dataclass(frozen=True)
class PentestProxyConfig:
proxy_url: str
target: str
scope: list[str]
authorization_ref: str # Reference to written authorization
def create_pentest_client(config: PentestProxyConfig) -> httpx.Client:
"""Create an HTTP client configured for authorized pentest through proxy."""
return httpx.Client(
proxy=config.proxy_url,
timeout=30,
verify=True,
follow_redirects=False,
headers={
"User-Agent": "SecurityAudit/1.0 (Authorized Test)",
},
)Geographic Security Control Testing
def test_geo_blocking(
target_url: str,
username: str,
password: str,
countries: list[str],
) -> dict[str, dict]:
"""Test geographic access controls from multiple countries."""
results: dict[str, dict] = {}
for country in countries:
proxy = f"http://{username}-country-{country}:{password}@gate.hexproxies.com:8080"
try:
with httpx.Client(proxy=proxy, timeout=15) as client:
resp = client.get(target_url)
results = {**results, country: {
"status": resp.status_code,
"blocked": resp.status_code in (403, 451),
"headers": dict(resp.headers),
}}
except Exception as e:
results = {**results, country: {"error": str(e)}}
return resultsRate Limit Testing
import asyncio
import aiohttp
import time
async def test_rate_limiting(
target_url: str,
proxy: str,
requests_per_second: int,
duration_seconds: int,
) -> dict:
"""Test rate limiting behavior by sending controlled request volumes."""
results: list[dict] = []
delay = 1.0 / requests_per_second
async with aiohttp.ClientSession() as session:
for i in range(requests_per_second * duration_seconds):
start = time.monotonic()
try:
async with session.get(target_url, proxy=proxy, timeout=aiohttp.ClientTimeout(total=10)) as resp:
elapsed = (time.monotonic() - start) * 1000
results.append({"request": i, "status": resp.status, "latency_ms": round(elapsed, 1)})
except Exception as e:
results.append({"request": i, "status": 0, "error": str(e)})
await asyncio.sleep(delay)
total = len(results)
blocked = sum(1 for r in results if r.get("status") in (429, 403))
return {
"total_requests": total,
"blocked": blocked,
"block_rate": round(blocked / max(total, 1), 3),
"first_block_at": next((r["request"] for r in results if r.get("status") in (429, 403)), None),
}Multi-IP Attack Simulation
Test how your security infrastructure handles distributed attack patterns:
async def distributed_probe(
target_url: str,
username: str,
password: str,
num_ips: int = 10,
) -> dict:
"""Simulate a distributed probe from multiple IPs."""
tasks = []
for i in range(num_ips):
session_id = f"pentest-{i}"
proxy = f"http://{username}-session-{session_id}:{password}@gate.hexproxies.com:8080"
tasks.append(single_probe(target_url, proxy, session_id))
results = await asyncio.gather(*tasks, return_exceptions=True)
valid = [r for r in results if isinstance(r, dict)]
return {
"total_probes": num_ips,
"successful": sum(1 for r in valid if r.get("status") == 200),
"blocked": sum(1 for r in valid if r.get("status") in (403, 429)),
}
async def single_probe(url: str, proxy: str, session_id: str) -> dict:
async with aiohttp.ClientSession() as session:
async with session.get(url, proxy=proxy, timeout=aiohttp.ClientTimeout(total=10)) as resp:
return {"session": session_id, "status": resp.status}Responsible Testing Practices
- Written authorization is mandatory — no exceptions
- Stay within defined scope — test only authorized targets
- Document all activities — log every request with timestamps and proxy sessions
- Report findings responsibly — follow agreed disclosure timeline
- Clean up after testing — ensure no persistent effects on target systems
Hex Proxies provides the IP diversity and geographic targeting needed for comprehensive security assessments, with ISP proxies for speed-sensitive tests and residential for geographic coverage across 195+ countries.