VPN Banks
VPN Banks are pools of workers assigned to specific geographic regions. They provide load-balanced, geo-targeted proxy access for cbintel operations.
Concept
graph LR
subgraph "Bank: California"
W1[Worker 1<br/>us-ca-001.ovpn]
W2[Worker 2<br/>us-ca-042.ovpn]
W3[Worker 3<br/>us-ca-123.ovpn]
end
HAP[HAProxy :8890] --> W1 & W2 & W3
CLIENT[HTTP Request] --> HAP
W1 & W2 & W3 --> EXIT[CA Exit IPs]
A bank groups workers and:
1. Assigns VPN profiles matching a geographic filter
2. Configures HAProxy for load balancing
3. Provides a single endpoint for clients
Bank Lifecycle
stateDiagram-v2
[*] --> Created: create_bank()
Created --> Active: VPN tunnels up
Active --> Idle: idle_bank()
Idle --> Active: resume_bank()
Active --> [*]: delete_bank()
Idle --> [*]: delete_bank()
Creating Banks
Via API
curl -X POST http://localhost:9002/api/v1/banks/ \
-H "Content-Type: application/json" \
-d '{
"name": "California Research",
"workers": [1, 2, 3],
"filter": "us:ca"
}'
Via Python
from cbintel.cluster.services.bank_service import BankService
service = BankService()
# Create bank with workers and geographic filter
bank = await service.create_bank(
name="California Research",
workers=[1, 2, 3],
filter="us:ca"
)
print(f"Bank created: {bank.tag}")
print(f"Endpoint: {bank.endpoint}") # http://17.0.0.1:8890
print(f"Workers: {bank.workers}")
Bank Request Schema
{
"name": "California Research",
"workers": [1, 2, 3],
"filter": "us:ca"
}
| Field |
Type |
Description |
name |
string |
Display name for the bank |
workers |
int[] |
Worker numbers (1-16) to assign |
filter |
string |
Geographic filter (see below) |
Geographic Filters
{country}[:{state}][:{type}]
| Component |
Description |
Examples |
country |
ISO country code |
us, de, uk, fr |
state |
US state code (optional) |
ca, ny, tx |
type |
VPN type (optional) |
tor |
Filter Examples
| Filter |
Description |
Profile Match |
us |
Any US server |
us-*.ovpn |
us:ca |
California |
us-ca-*.ovpn |
us:ny |
New York |
us-ny-*.ovpn |
us:tx:tor |
Texas with Tor exit |
us-tx-*-tor.ovpn |
de |
Germany |
de-*.ovpn |
uk |
United Kingdom |
uk-*.ovpn |
ch |
Switzerland |
ch-*.ovpn |
Profile Inventory
| Country |
Profiles |
States/Regions |
| US |
~3,500 |
50 states |
| UK |
~800 |
- |
| Germany |
~600 |
Frankfurt, Berlin, Munich |
| Netherlands |
~400 |
Amsterdam |
| Switzerland |
~300 |
Zurich, Geneva |
| Total |
~12,909 |
127 countries |
Bank Response Schema
{
"name": "California Research",
"tag": "californiaresearch",
"workers": [1, 2, 3],
"worker_assignments": [
{
"worker_number": 1,
"worker_ip": "17.0.0.10",
"vpn_profile": "us-ca-324.protonvpn.udp.ovpn",
"vpn_status": "up",
"exit_ip": "146.70.195.107"
},
{
"worker_number": 2,
"worker_ip": "17.0.0.11",
"vpn_profile": "us-ca-042.protonvpn.udp.ovpn",
"vpn_status": "up",
"exit_ip": "146.70.195.108"
},
{
"worker_number": 3,
"worker_ip": "17.0.0.12",
"vpn_profile": "us-ca-123.protonvpn.udp.ovpn",
"vpn_status": "up",
"exit_ip": "146.70.195.109"
}
],
"filter": {"country": "us", "state": "ca", "type": null},
"port": 8890,
"status": "active",
"endpoint": "http://17.0.0.1:8890",
"health": {
"workers_total": 3,
"workers_up": 3,
"workers_down": 0,
"success_rate": 1.0
}
}
Bank Operations
List Banks
banks = await service.list_banks()
for bank in banks:
print(f"{bank.tag}: {bank.status} ({bank.health.workers_up}/{bank.health.workers_total})")
Get Bank Details
bank = await service.get_bank("californiaresearch")
print(f"Endpoint: {bank.endpoint}")
print(f"Health: {bank.health.success_rate * 100:.0f}%")
Idle/Resume Bank
# Pause bank (stops VPN tunnels, releases workers)
await service.idle_bank("californiaresearch")
# Resume bank (restarts VPN tunnels)
await service.resume_bank("californiaresearch")
Delete Bank
# Delete bank and release workers
await service.delete_bank("californiaresearch")
Using Banks
Direct HTTP Proxy
from cbintel.net import HTTPClient
async with HTTPClient() as client:
# Route through California bank
response = await client.get(
"https://example.com",
proxy="http://17.0.0.1:8890" # Bank endpoint
)
Via GeoRouter
from cbintel.geo import GeoRouter
router = GeoRouter()
# GeoRouter selects appropriate bank
proxy = await router.get_proxy("us:ca")
response = await client.get(url, proxy=proxy)
In Graph Operations
stages:
- name: fetch_california
parallel:
- op: fetch
params:
url: "https://example.com"
geo: "us:ca"
output: content
HAProxy Integration
Each bank creates a HAProxy frontend/backend pair.
Configuration Generated
# Frontend for bank "californiaresearch"
frontend californiaresearch_frontend
bind *:8890
default_backend californiaresearch_backend
# Backend with round-robin load balancing
backend californiaresearch_backend
balance roundrobin
option httpchk GET /
server worker1 17.0.0.10:3128 check inter 5000
server worker2 17.0.0.11:3128 check inter 5000
server worker3 17.0.0.12:3128 check inter 5000
Port Allocation
| Port Range |
Usage |
| 8890-8899 |
Bank frontends |
| 8900-8999 |
Reserved |
Health Monitoring
Bank Health Check
bank = await service.get_bank("californiaresearch")
print(f"Total workers: {bank.health.workers_total}")
print(f"Workers up: {bank.health.workers_up}")
print(f"Workers down: {bank.health.workers_down}")
print(f"Success rate: {bank.health.success_rate * 100:.0f}%")
Individual Worker Status
for assignment in bank.worker_assignments:
print(f"Worker {assignment.worker_number}:")
print(f" IP: {assignment.worker_ip}")
print(f" Profile: {assignment.vpn_profile}")
print(f" VPN Status: {assignment.vpn_status}")
print(f" Exit IP: {assignment.exit_ip}")
API Endpoints
| Method |
Endpoint |
Description |
GET |
/api/v1/banks/ |
List all banks |
POST |
/api/v1/banks/ |
Create new bank |
GET |
/api/v1/banks/{tag} |
Get bank details |
PUT |
/api/v1/banks/{tag} |
Update bank |
DELETE |
/api/v1/banks/{tag} |
Delete bank |
POST |
/api/v1/banks/{tag}/idle |
Pause bank |
POST |
/api/v1/banks/{tag}/resume |
Resume bank |
Best Practices
- Worker allocation: Don't share workers between banks
- Profile diversity: Banks get different profiles for IP diversity
- Monitoring: Check health regularly for VPN failures
- Cleanup: Delete unused banks to free workers
- Naming: Use descriptive names for easy identification
Troubleshooting
Bank Not Creating
- Check worker availability (not in other banks)
- Verify profile existence for filter
- Check HAProxy configuration permissions
Workers Not Connecting
- Check individual worker VPN status
- Verify profile credentials
- Review OpenVPN logs on worker
- Check worker load and memory
- Consider geographic proximity
- Try different VPN server (reprofile)