Skip to content

thomaswitt/mullvad-socks-proxy-rotator

Repository files navigation

mullvad-socks-proxy-rotator

Generate a PAC (Proxy Auto-Configuration) file that routes each browser request through a randomly selected Mullvad SOCKS5 relay. The generator uses Mullvad's public relay API and can filter by location, ownership, relay type, and measured proxy probe latency.

Inspired by: https://k4yt3x.com/using-a-random-mullvad-socks5-proxy-for-each-browser-request/

Prerequisites

  • Ruby 3.4+ (tested on Ruby 3.4.8)
  • curl available on PATH for proxy latency probing (primary; Ruby socket fallback is used if unavailable)
  • Active Mullvad VPN tunnel (WireGuard) while using the generated SOCKS5 proxies

Installation

git clone https://github.com/thomaswitt/mullvad-socks-proxy-rotator.git
cd mullvad-socks-proxy-rotator
chmod +x generate_pac.rb

Usage

ruby generate_pac.rb [options]

Options:

  • -l, --location PREFIXES comma-separated country or country-city codes (e.g. us,ca,de-fra)
  • -m, --max-latency MS max proxy probe latency in ms (default: 80)
  • --no-latency-check disable proxy latency probing and the default 80ms ceiling
  • -n, --top N use only the N lowest-latency relays after active filters (implies latency probe)
  • -o, --output FILE output file path (default: proxy.pac for PAC mode, stdout for --list/--json, use - for stdout)
  • -t, --type TYPE server type: wireguard (default), all
  • --owned-only only Mullvad-owned servers
  • --include-unsafe include countries with questionable privacy laws (excluded by default)
  • --no-bypass don't add localhost/LAN bypass rules to PAC
  • --fallback MODE fallback mode: none (default), direct
  • --list list matching proxies and exit
  • -j, --json output JSON instead of PAC
  • -h, --help show help

Unexpected positional arguments are rejected. For example, ruby generate_pac.rb us fails fast instead of silently generating the default global PAC. Latency filtering is enabled by default with a strict 80ms ceiling. Relays slower than that from your machine, or unreachable from your machine, are excluded from the result. The probe measures proxy usability latency via curl --socks5-hostname, not raw TCP connect RTT to the SOCKS port. Use --no-latency-check to skip latency filtering entirely. --top N is applied after all active filters, so it can return fewer than N relays when the current latency ceiling excludes the rest.

Examples

# 1) PAC with all safe-country WireGuard SOCKS5 relays
ruby generate_pac.rb

# 2) European subset
ruby generate_pac.rb -l it,fr,ch,de

# 3) Include countries excluded by default safety policy
ruby generate_pac.rb --include-unsafe

# 4) Top 10 US relays by measured proxy probe latency
ruby generate_pac.rb -l us -n 10

# 5) List German relays
ruby generate_pac.rb --list -l de

# 6) JSON output
ruby generate_pac.rb -j

# 7) PAC to stdout
ruby generate_pac.rb -o -

# 8) PAC with direct fallback (availability > strict fail-closed)
ruby generate_pac.rb --fallback direct

# 9) Skip latency filtering entirely
ruby generate_pac.rb --no-latency-check

Browser Setup

ZeroOmega / SwitchyOmega

  1. Import the generated proxy.pac.
  2. Set mode to PAC.
  3. Confirm requests rotate across SOCKS5 relays.

Firefox

  1. Open Settings -> Network Settings.
  2. Select Automatic proxy configuration URL and point to your PAC file location.
  3. Keep DNS-over-proxy behavior consistent with your privacy requirements.

macOS system proxy

  1. System Settings -> Network -> active interface -> Details -> Proxies.
  2. Enable Automatic Proxy Configuration.
  3. Set file URL to the generated PAC file.

Privacy Notes

  • SOCKS5 proxies from Mullvad are reachable only when Mullvad VPN is connected.
  • Generated PAC includes localhost/LAN bypass rules by default so local development and RFC1918 traffic still works.
  • Default fallback is fail-closed (--fallback none). Use --fallback direct only if you accept potential IP leaks.
  • The default latency probe uses curl --socks5-hostname against a lightweight HTTPS endpoint, so it measures proxy usability latency rather than pure SOCKS port TCP connect RTT.
  • SOCKS5 via PAC typically leaves DNS outside the proxy path. Disable or control WebRTC/QUIC to reduce leak risk, and enable remote DNS explicitly in Firefox if you need it.
  • Countries excluded by default (--include-unsafe overrides):
    • hk cn ru tr ae sg th ph my id ng il vn by kz

Development Checks

# Run the check-only quality gate:
# syntax + rufo check + rubocop + gem audit
rake

# Auto-format Ruby files (rufo + rubocop autocorrect)
bundle exec rake app:formatter

# Run Rufo directly
bundle exec rake app:rufo

# Run Rufo check mode
bundle exec rake app:rufo:check

# Run RuboCop checks
bundle exec rake app:rubocop

# Run security checks individually
bundle exec rake security:bundle_audit

License

This project is licensed under the MIT License. See LICENSE.

About

Using a Random Mullvad SOCKS5 Proxy for Each Browser Request

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages