Azure

Provision on-demand HTTP(S) proxy servers on Azure Virtual Machines with a single Python call. Each proxy runs Squid on an Ubuntu 24.04 LTS VM and is fully managed — creation, authentication, firewall rules, and cleanup are handled automatically.

Table of Contents


Requirements

Dependency

Purpose

azure-identity

Azure authentication (DefaultAzureCredential)

azure-mgmt-subscription

List available regions

azure-mgmt-resource

Manage resource groups

azure-mgmt-network

NSG, VNet, public IP, NIC management

azure-mgmt-compute

Virtual machine lifecycle

Installation

pip install auto_proxy_vpn[azure]

Azure Credentials Setup

You need an Azure subscription. Authentication is handled by the Azure SDK’s DefaultAzureCredential, which tries multiple credential sources automatically. Choose the option that best fits your workflow:

Option A: Azure CLI Login (simplest)

If you already have the Azure CLI installed, just log in and set your subscription ID:

az login

Then provide only the subscription ID. The recommended way is to create a .env file in your project root:

# .env
AZURE_SUBSCRIPTION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Load it at the start of your script:

from dotenv import load_dotenv
load_dotenv()  # reads .env into environment variables

manager = ProxyManagerAzure(ssh_key="ssh-rsa AAAAB3...")

Alternatively, pass the subscription ID directly in code:

manager = ProxyManagerAzure(
    credentials="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",   # subscription ID
    ssh_key="ssh-rsa AAAAB3..."
)

Note: This option is ideal for local development and interactive use. DefaultAzureCredential will pick up the session from az login automatically.


Quick Start

Import

from auto_proxy_vpn.providers.azure import ProxyManagerAzure, AzureProxy

Passing Credentials Explicitly

manager = ProxyManagerAzure(
    credentials={
        "AZURE_SUBSCRIPTION_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "AZURE_CLIENT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "AZURE_CLIENT_SECRET": "your-client-secret",
        "AZURE_TENANT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    },
    ssh_key="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC2..."
)

Manual Lifecycle

proxy = manager.get_proxy()

try:
    r = requests.get("https://httpbin.org/ip", proxies=proxy.get_proxy())
    print(r.json())
finally:
    proxy.close()           # destroys Azure resources

API Reference

ProxyManagerAzure

Factory class that provisions and manages Azure proxy VMs.

VM sizes:

Size

Azure SKU

small

Standard_B1s

medium

Standard_B1ms

large

Standard_B2s

ProxyManagerAzure(
    ssh_key,                # str | dict | list — SSH public key(s) or path to key file
    credentials="",         # str | dict — subscription ID, credential dict, or "" for env vars
    log=True,               # bool — enable logging
    log_file=None,          # str | None — log file path (None = stdout)
    log_format="...",       # str — Python logging format string
    logger=None,            # Logger | None — custom logger instance
)

manager.get_proxy()

Create and start a new proxy VM.

proxy = manager.get_proxy(
    port=0,                 # int — proxy port (0 = random 10000–65000)
    size="medium",          # "small" | "medium" | "large"
    region="",              # str — Azure region (empty = random)
    auth={},                # {"user": ..., "password": ...} — basic auth
    allowed_ips=[],         # str | list[str] — allowed source IPs (your IP is auto-added)
    is_async=False,         # bool — return immediately without waiting for full startup
    retry=True,             # bool — retry in a different region on failure
    proxy_name="",          # str — explicit name (empty = auto-generated)
    on_exit="destroy",      # "destroy" | "keep" — cleanup behavior on close
)

manager.get_proxies()

Create multiple proxies in one call and return a ProxyBatch.

batch = manager.get_proxies(
    number=3,
    sizes=["small", "medium", "large"],
    is_async=True,
)

for proxy in batch:
    print(proxy.get_proxy_str())

batch.close()

manager.get_proxy_by_name()

Reload a previously created (and still running) proxy by name.

proxy = manager.get_proxy_by_name(
    name="proxy1",          # str — existing proxy resource group name
    is_async=False,         # bool
    on_exit="destroy",      # "destroy" | "keep"
)

manager.get_running_proxy_names()

List names of all running proxy resource groups.

names = manager.get_running_proxy_names()
# ["proxy1", "proxy2"]

AzureProxy

Represents a single proxy VM instance. You typically get this from manager.get_proxy() rather than constructing it directly.

Properties

Property

Type

Description

ip

str

Public IPv4 address

port

int

Proxy TCP port

region

str

Azure region

user

str

Basic-auth username (empty if none)

password

str

Basic-auth password (empty if none)

active

bool

Whether the proxy is confirmed reachable

name

str

Resource group / VM name

Methods

Method

Returns

Description

get_proxy_str()

str

Proxy URL, e.g. http://user:pass@1.2.3.4:8080

get_proxy()

dict

{"http": url, "https": url} for use with requests

is_active(wait=False)

bool

Check (or wait for) proxy readiness

close(wait=True)

None

Stop proxy; destroys resources if on_exit="destroy"

Context Manager

with manager.get_proxy() as proxy:
    # proxy is guaranteed active here
    r = requests.get("https://example.com", proxies=proxy.get_proxy())
# proxy resources are automatically cleaned up

Advanced Usage

Proxy with Basic Authentication

proxy = manager.get_proxy(
    auth={"user": "myuser", "password": "s3cret"},
)
# Proxy URL: http://myuser:s3cret@<ip>:<port>

Restrict Access by IP

proxy = manager.get_proxy(
    allowed_ips=["203.0.113.10", "198.51.100.0/24"],
)
# Your current public IP is always added automatically

Keep Proxy Alive After Close

proxy = manager.get_proxy(on_exit="keep")
proxy.close()  # resources are NOT deleted

# Later, reconnect to it:
proxy = manager.get_proxy_by_name("proxy1", on_exit="destroy")

Asynchronous Creation

proxy = manager.get_proxy(is_async=True)

# Do other work while the VM provisions...

# Block until ready when you need it:
if proxy.is_active(wait=True):
    r = requests.get("https://example.com", proxies=proxy.get_proxy())

SSH Key from File

manager = ProxyManagerAzure(
    ssh_key="/path/to/authorized_keys",  # one public key per line
)