Skip to content

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

Filter Format

{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

  1. Worker allocation: Don't share workers between banks
  2. Profile diversity: Banks get different profiles for IP diversity
  3. Monitoring: Check health regularly for VPN failures
  4. Cleanup: Delete unused banks to free workers
  5. Naming: Use descriptive names for easy identification

Troubleshooting

Bank Not Creating

  1. Check worker availability (not in other banks)
  2. Verify profile existence for filter
  3. Check HAProxy configuration permissions

Workers Not Connecting

  1. Check individual worker VPN status
  2. Verify profile credentials
  3. Review OpenVPN logs on worker

Poor Performance

  1. Check worker load and memory
  2. Consider geographic proximity
  3. Try different VPN server (reprofile)