Skip to content

hatemosphere/protonvpn-wg-confgen

Repository files navigation

ProtonVPN WireGuard Config Generate

CI Release Go Report Card License: GPL-3.0

A Go program that generates WireGuard configuration files for ProtonVPN servers with automatic selection of the best servers from specified countries with support of generic filters.

Motivation

I wanted to automatically rotate VPN servers on my private HTPC Linux host running WireGuard, and since I'm already paying for a Proton bundle subscription, why not just use theirs? Unfortunately, as of the time of writing, they didn't have a good programmatic headless way to generate WireGuard profiles, so I did my research and reverse-engineered their APIs (which was a pain in the butt) and created this. The idea is to run this code as a daemon and restart the WireGuard client on profile file change.

Features

  • Authenticates with ProtonVPN using username/password
  • Optionally persists and refreshes login session, to function in headless mode after entering password once
  • Supports 2FA authentication (TOTP only, no FIDO2/security keys)
  • Creates persistent WireGuard configurations (visible in ProtonVPN dashboard)
  • Automatically selects the best server from the specified countries using the Proton Quick Connect metric (lowest Score, with Load as tiebreaker — lower is better per the official API)
  • Supports Free tier or paid tier servers (Plus/Visionary)
  • Filters servers by features (P2P support, Secure Core)
  • Generates WireGuard configuration files
  • Supports VPN accelerator feature
  • IPv6 support
  • Lists persistent configurations registered on your account

Installation

  1. Clone the repository:
git clone https://github.com/hatemosphere/protonvpn-wg-confgen
cd protonvpn-wg-confgen
  1. Build the program:
make build

Or manually with Go:

go build -o build/protonvpn-wg-confgen cmd/protonvpn-wg/main.go

Usage

./build/protonvpn-wg-confgen -username <username> -countries <country-codes> [options]

Options

  • -username: ProtonVPN username (optional, will prompt if not provided)
  • -countries: Comma-separated list of country codes (e.g., US,NL,CH) [Required]
  • -output: Output WireGuard configuration file (default: protonvpn.conf)
  • -ipv6: Enable IPv6 support (default: false)
  • -dns: Comma-separated list of DNS servers (defaults based on IPv6 setting)
  • -allowed-ips: Comma-separated list of allowed IPs (defaults based on IPv6 setting)
  • -accelerator: Enable VPN accelerator (default: true)
  • -api-url: ProtonVPN API URL (default: https://vpn-api.proton.me)
  • -p2p-only: Use only P2P-enabled servers (default: true)
  • -secure-core: Use only Secure Core servers for multi-hop VPN (default: false)
  • -free-only: Use only Free tier servers (tier 0) (default: false)
  • -device-name: Device name for WireGuard config (auto-generated if empty)
  • -debug: Enable debug output showing all filtered servers (default: false)
  • -duration: Certificate duration (default: 365d). Examples: 30m, 24h, 7d, 1h30m. Maximum: 365d
  • -clear-session: Clear saved session and force re-authentication
  • -no-session: Don't save or use session persistence
  • -force-refresh: Force session refresh even if not close to expiration (requires re-authentication)
  • -session-duration: Session cache duration (default: 0 = use API expiration). Examples: 12h, 24h, 7d. Max: 30d

Listing existing configurations

  • -list-configs: List every persistent configuration on the account (SerialNumber, DeviceName, expiry, key fingerprint) and exit. -countries is not required in this mode.

Revoking a configuration is only possible via the ProtonVPN web dashboard (https://account.proton.me/u/0/vpn/WireGuard): the Proton API gates DELETE /vpn/v1/certificate behind the full session scope, which is granted only to account.proton.me web/desktop logins, not to VPN API clients.

Examples

  1. Generate config for best P2P server in US or Netherlands:
./build/protonvpn-wg-confgen -username myusername -countries US,NL
  1. Generate config with custom DNS and output file:
./build/protonvpn-wg-confgen -username myusername -countries CH,DE -dns 1.1.1.1,8.8.8.8 -output switzerland.conf
  1. Disable VPN accelerator:
./build/protonvpn-wg-confgen -username myusername -countries US -accelerator=false
  1. Generate config with 30-day duration:
./build/protonvpn-wg-confgen -username myusername -countries US -duration 30d
  1. Generate config without saving session (always prompt for password):
./build/protonvpn-wg-confgen -username myusername -countries US -no-session
  1. Use session with 24-hour expiration:
./build/protonvpn-wg-confgen -username myusername -countries US -session-duration 24h
  1. Enable IPv6 support:
./build/protonvpn-wg-confgen -username myusername -countries US -ipv6
  1. Use Secure Core servers for enhanced privacy:
./build/protonvpn-wg-confgen -username myusername -countries NL,US -secure-core
  1. Debug mode to see all available servers:
./build/protonvpn-wg-confgen -username myusername -countries US -debug
  1. Use Free tier servers only:
./build/protonvpn-wg-confgen -username myusername -countries US,NL -free-only
  1. List all persistent configurations on the account:
./build/protonvpn-wg-confgen -username myusername -list-configs

IPv6 Support

By default, the tool generates IPv4-only configurations. When you enable IPv6 with the -ipv6 flag:

  • Interface Address: Both IPv4 (10.2.0.2/32) and IPv6 (2a07:b944::2:2/128) addresses are assigned
  • DNS Servers: IPv4 DNS (10.2.0.1) and IPv6 DNS (2a07:b944::2:1) - both ProtonVPN's internal DNS servers
  • Allowed IPs: Both IPv4 (0.0.0.0/0) and IPv6 (::/0) routes are included

You can override the defaults by explicitly specifying -dns and -allowed-ips flags.

Secure Core

Secure Core is ProtonVPN's premium feature that routes your traffic through multiple servers before leaving the VPN network:

  • First hop: Through secure servers in privacy-friendly countries (Switzerland, Iceland, Sweden)
  • Second hop: To your chosen destination country
  • Provides additional protection against network-based attacks
  • Use the -secure-core flag to enable this feature
  • Note: Secure Core servers may have higher latency due to the multi-hop routing

Important Notes:

  • Secure Core servers don't support P2P, so P2P filtering is automatically disabled when using -secure-core
  • The country filter always applies to exit countries - where your traffic appears to come from
  • Server names show both entry and exit countries (e.g., "IS-NL#1" = Iceland → Netherlands)
  • Entry countries for Secure Core are always privacy-friendly: Switzerland (CH), Iceland (IS), Sweden (SE)

Authentication

Important: This tool only works with Proton accounts configured in Single Password Mode. This is the default for all new Proton accounts. If your account uses the legacy 2-password mode (separate login and mailbox passwords), you'll need to switch to single password mode first.

The program supports the following authentication methods:

  1. Username/Password: Enter your ProtonVPN credentials
  2. 2FA (TOTP only): If enabled, you'll be prompted for your 6-digit authenticator code

Important 2FA Limitation: This tool only supports TOTP-based 2FA (authenticator apps like Google Authenticator, Authy, 1Password, etc.). FIDO2/WebAuthn security keys are NOT supported because they require browser/platform APIs for the challenge-response protocol.

If you use a security key as your only 2FA method, you have two options:

  • Add TOTP as an additional 2FA method in your Proton account security settings
  • Use a security key that also supports TOTP (like YubiKey with Yubico Authenticator)

Session Persistence

The program saves your authentication session to avoid re-entering credentials:

  • Sessions are stored in ~/.protonvpn-session.json with secure permissions (0600)
  • ProtonVPN sessions expire after 30 days (from API ExpiresIn field)
  • Session duration is configurable with -session-duration (default: 0 = use API's 30 days)
  • Custom durations are capped at the API's expiration time
  • Sessions show time until expiration when reused
  • Sessions are automatically verified before use
  • Sessions automatically refresh when less than 7 days remain
  • Use -clear-session flag to force re-authentication
  • Use -force-refresh flag to force refresh even if not expiring soon
  • Use -no-session flag to disable session persistence entirely
  • Sessions are user-specific and won't be used for different usernames

Using the Generated Configuration

Once you have the WireGuard configuration file, you can use it with any WireGuard client:

Linux

sudo wg-quick up ./protonvpn.conf

macOS (with WireGuard installed)

sudo wg-quick up ./protonvpn.conf

Windows/GUI clients

Import the configuration file into your WireGuard client.

Server Tier Support

By default, the tool excludes Free tier servers and only uses paid tier servers:

  • Free tier (tier 0): Only selected when -free-only is set. Limited server selection, no P2P support
  • Plus tier (tier 2): Default. Full feature support including P2P and Secure Core
  • Visionary tier (tier 3): Default. Returned by the API for accounts on historical/bundle plans

Important Notes:

  • When using -free-only, P2P filtering is automatically disabled since Free servers don't support P2P
  • Free tier servers have limited availability and may have higher load
  • Secure Core requires Plus or higher subscription

Requirements

  • Go 1.26 or higher
  • ProtonVPN account (Free tier or paid subscription)

Security Notes

  • The program generates a new WireGuard private/public keypair on every generation run
  • Configuration files contain sensitive information and are saved with 0600 permissions
  • Never share your WireGuard configuration files
  • Persistent configurations appear in your ProtonVPN dashboard and can be revoked there
  • Certificates are valid for the specified duration (default: 365 days, max: 365 days)

Project Structure

.
├── cmd/
│   └── protonvpn-wg/
│       └── main.go         # CLI entry point + command dispatch
├── internal/
│   ├── api/
│   │   └── types.go        # ProtonVPN API request/response types
│   ├── auth/
│   │   ├── auth.go         # SRP authentication
│   │   ├── errors.go       # API error codes and types
│   │   └── session.go      # Session persistence, refresh, verify
│   ├── config/
│   │   ├── flags.go        # Command-line flag parsing
│   │   └── types.go        # Config struct
│   ├── constants/
│   │   ├── api.go          # API endpoints and version headers
│   │   ├── defaults.go     # Certificate/selection defaults
│   │   ├── session.go      # Session persistence constants
│   │   └── wireguard.go    # WireGuard network defaults
│   └── vpn/
│       ├── client.go       # Certificate create + list + server fetch
│       └── servers.go      # Server selection
├── pkg/
│   ├── timeutil/
│   │   ├── duration.go     # Human-readable duration formatting
│   │   └── parser.go       # Duration parsing
│   ├── validation/
│   │   └── username.go     # Username and country-code validation
│   └── wireguard/
│       ├── config.go       # .conf file generation
│       └── config_test.go
├── Makefile
├── go.mod
├── go.sum
└── README.md

Development

# Format code
make fmt

# Run tests
make test

# Run linter (requires golangci-lint)
make lint

# Build for multiple platforms
make build-all

# Clean build artifacts
make clean

Troubleshooting

CAPTCHA Verification Required (Error 9001)

If you encounter "CAPTCHA verification required" error:

  1. Login via ProtonVPN website first: This can help establish your account as legitimate
  2. Try from a different IP: VPN or residential IPs may work better than datacenter IPs
  3. Wait and retry: Sometimes waiting a few hours helps
  4. Use saved sessions: Once authenticated, sessions are saved to avoid repeated CAPTCHA challenges

App Version Errors (Error 5003)

If you see "This version of the app is no longer supported":

  • The app version is automatically fetched from ProtonVPN's GitHub at build time
  • Rebuild with make build to get the latest version
  • Override manually if needed: make build PROTON_VERSION=X.Y.Z
  • Check current version: make show-version

Two-Password Mode Error (Code 10013)

If you see "unexpected mailbox password request - account might still be in 2-password mode":

  • Your Proton account is using the legacy 2-password mode (separate login and mailbox passwords)
  • This tool only supports Single Password Mode
  • To switch: Go to Proton account settings → Security → Password mode → Switch to single password
  • Note: Single password mode is the default for all new Proton accounts since ~2020

Insufficient Scope (Error 9100)

Proton returns code 9100 when an endpoint needs a higher session scope than the current session has. In this tool it only shows up when fetching the VPN certificate during generate: the session needs the vpn scope, which is granted via 2FA. If your account has 2FA but the initial login didn't prompt for it (e.g. device trust reused a prior session), run with -clear-session to force a fresh 2FA-authenticated login.

API Reference

For detailed API documentation including endpoints, request formats, response codes, and reference implementations, see API_REFERENCE.md.

License

This project is licensed under the GNU General Public License v3.0.

This is required because the project uses ProtonVPN/go-vpn-lib which is licensed under GPL-3.0.

About

CLI tool to generate ProtonVPN WireGuard configs

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors