On Debian 13 how to make Python `requests` use different ProtonVPN servers at the same time?
Jul 26, 1:06am

To make Python's requests library use different ProtonVPN servers simultaneously on Debian 13, you need to route requests through different network interfaces or proxies, each connected to a distinct ProtonVPN server. Here's how you can achieve this:


Key Concepts

  1. ProtonVPN Configuration: ProtonVPN provides OpenVPN and WireGuard configurations for its servers. Each server has a unique endpoint (e.g., fr.protonvpn.com, us.protonvpn.com).
  2. Multiple VPN Connections: You cannot directly bind a single process (like a Python script) to multiple VPN connections. Instead, you need to:
    • Use multiple network interfaces (e.g., tun0, tun1), each connected to a different ProtonVPN server.
    • Route traffic for specific requests through these interfaces.
  3. Proxy Support: Alternatively, you can use SOCKS5 or HTTP proxies (e.g., ssh -D or redsocks) to forward requests through different VPN endpoints.

Step-by-Step Guide

Option 1: Use Multiple Network Interfaces (Advanced)

This method requires setting up multiple VPN connections and routing traffic manually.

1. Connect to Multiple ProtonVPN Servers

Use the openvpn or wg-quick command to connect to different ProtonVPN servers. Each connection will create a new network interface (e.g., tun0, tun1).

Example for OpenVPN:

bash
sudo openvpn --config fr.protonvpn.com.udp
sudo openvpn --config us.protonvpn.com.udp

2. Assign Routes to Interfaces

Use the ip route command to route traffic for specific IPs or subnets through each interface.

Example:

bash
# Route traffic for IP 1.1.1.1 through tun0
sudo ip route add 1.1.1.1 dev tun0

# Route traffic for IP 2.2.2.2 through tun1
sudo ip route add 2.2.2.2 dev tun1

3. Bind Python Requests to Interfaces

In Python, use the requests library with the socket module to bind requests to specific interfaces.

python
import requests
import socket

# Bind to tun0 (replace with the actual interface IP)
def get_interface_ip(interface):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', interface[:15].encode('utf-8'))
    )[20:24])

# Example: Bind request to tun0
interface_ip = get_interface_ip('tun0')
response = requests.get(
    "https://example.com",
    headers={"Host": "example.com"},
    params={"ip": interface_ip}
)

Note: Binding to interfaces is complex and may require root privileges. This method is not recommended for most users.


Option 2: Use Proxies (Recommended)

A simpler approach is to use SOCKS5 or HTTP proxies for each ProtonVPN server.

1. Set Up Proxies

Use ssh -D or redsocks to create SOCKS5 proxies for each VPN connection.

Example with ssh -D:

bash
# Create a SOCKS5 proxy on port 1080 for fr.protonvpn.com
ssh -D 1080 user@fr.protonvpn.com

# Create another SOCKS5 proxy on port 1081 for us.protonvpn.com
ssh -D 1081 user@us.protonvpn.com

2. Configure Python Requests

Use the requests library with the proxies parameter to route requests through different proxies.

python
import requests

# Define proxies
proxies = {
    "http": "socks5://127.0.0.1:1080",
    "https": "socks5://127.0.0.1:1080"
}

proxies_2 = {
    "http": "socks5://127.0.0.1:1081",
    "https": "socks5://127.0.0.1:1081"
}

# Send requests through different proxies
response1 = requests.get("https://example.com", proxies=proxies)
response2 = requests.get("https://example.com", proxies=proxies_2)

print(response1.text)
print(response2.text)

3. Install Required Dependencies

Ensure you have the requests and pysocks libraries installed:

bash
pip install requests pysocks

Option 3: Use ProtonVPN's API (Alternative)

ProtonVPN provides an API to fetch server information. You can dynamically switch servers by updating the proxy configuration.

Example:

python
import requests

# Fetch ProtonVPN server list
response = requests.get("https://api.protonvpn.ch/v1/servers")
servers = response.json()["Servers"]

# Select servers
server1 = servers[0]["EntryIP"]
server2 = servers[1]["EntryIP"]

# Configure proxies
proxies1 = {"http": f"http://{server1}", "https": f"http://{server1}"}
proxies2 = {"http": f"http://{server2}", "https": f"http://{server2}"}

# Send requests
response1 = requests.get("https://example.com", proxies=proxies1)
response2 = requests.get("https://example.com", proxies=proxies2)

Note: ProtonVPN's API may require authentication. Check their official documentation for details.


Summary Table

Comparison of Methods
Multiple Interfaces
High
Yes
No
No
Proxies (SOCKS5/HTTP)
Medium
No
Yes
Yes
ProtonVPN API
Low
No
Yes
Yes

Recommendation

  • For simplicity: Use Option 2 (Proxies). It’s easier to implement and doesn’t require root access.
  • For advanced users: Use Option 1 (Multiple Interfaces) if you need fine-grained control over routing.
  • For dynamic switching: Use Option 3 (ProtonVPN API) to fetch and switch servers programmatically.

Jul 26, 1:06am

This is a shared conversation and may include unverified content that doesn't reflect Mistral AI's views. Login to resume chatting.

Vibe can make mistakes. Check answers. Learn more