ProtonVPN_Privoxy_Docker

Image generated by StableDiffusionXL

TL;DR

Reverse split tunneling:

Bonus: A dedicated app like browser/terminal routing through VPN: vopono

Introduction

I use ProtonVPN when connecting to api.openai.com. For all other traffic, I don’t want need a VPN. Turned out it’s a feature called reverse split tunneling. This feature is only available on Windows and Android (ref), and not supported for the official Linux CLI (ref). I’ll introduction 3 ways to do this as mentioned above.

This guide is for the following target audience:

  • Only use VPN for a handful of traffic like openai.com for using GPT-4
  • Overkill for ProtonVPN Plus (their browser extension has the split-tunneling feature)

1. ProtonVPN with WireGuard

This is the method I use.

  1. Follow the official guide How to download WireGuard configuration files.

  2. Install WireGuard:

sudo pacman -S wireguard-tools
  1. Create a new WireGuard configuration file:
sudo vim /etc/wireguard/wg0.conf
  1. Paste the downloaded ProtonVPN WireGuard configuration file content
[Interface]
PrivateKey = ****
Address = 10.2.0.2/32
DNS = 10.2.0.1

[Peer]
PublicKey = ****
AllowedIPs = 104.18.6.192/32, 104.18.7.192/32, 104.16.154.36/32, 104.16.155.36/32
Endpoint = ***.***
Note

Modify the line AllowedIPs for the traffic to be routed through WireGuard.

  • 104.18.6.192/32 and 104.18.7.192/32 are api.openai.com
  • 104.16.154.36/32 and 104.16.155.36/32 are whatismyipaddress.com (for testing)
  1. Start the WireGuard interface:
sudo wg-quick up wg0

Verified the traffic is routed through WireGuard:

➜ ip route get 104.18.6.192
104.18.6.192 dev wg0 src 10.2.0.2 uid 1000

10.2.0.2 is the proof that the traffic is routed through ProtonVPN (ref).

Tip

Use systemd to automatically start the WireGuard interface on system boot:

systemctl enable wg-quick@wg0.service

2. proton-privoxy

2024-03-21 Update
The following was what I used until it broke one day. It works now after a merge but it doesn’t seem stable since it’s no longer supported.

docker-compose.yml:

version: "3"
services:
  proton-privoxy:
    image: walt3rl/proton-privoxy
    container_name: proton-privoxy
    environment:
      - PVPN_USERNAME=username
      - PVPN_PASSWORD=password
      - PVPN_TIER=0
      - PVPN_PROTOCOL=tcp
      - PVPN_DEBUG=1
      - PVPN_CMD_ARGS=connect US-FREE-52
    volumes:
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 8888:8080
    restart: unless-stopped
    devices:
      - /dev/net/tun
    cap_add:
      - NET_ADMIN

For the field PVPN_CMD_ARGS, it took me some time to figure out that you can’t put double quotes around the value (i.e., PVPN_CMD_ARGS="connect US-FREE-52" doesn’t work).

To run it:

docker-compose down && docker-compose up -d && docker-compose logs -f

To test, run curl --proxy http://127.0.0.1:8888 ifconfig.co/json and you should see your VPN info. Any traffic with curl --proxy http://127.0.0.1:8888 will route through the VPN.

If you want to add request logs to make sure requests are routed through proton-privoxy, see #42.

proton-privoxy with ChatGPT.nvim

If you’re using jackMort/ChatGPT.nvim, you can add the following line:

extra_curl_params = { "--proxy", "http://127.0.0.1:8888" },

This way, ChatGPT.nvim will route through protonvpn.

3. protonvpn-cli-community

The linux-cli-community doesn’t support reverse split tunneling: #230. Luckily, there is a fork that implements it (Thanks jonasjancarik!).

Installation

git clone https://github.com/jonasjancarik/protonvpn-cli-community.git
cd protonvpn-cli-community
pipx install -e .

Create ~/.pvpn-cli/pvpn-cli.cfg:

[USER]
username = your/username/here
tier = 0
default_protocol = tcp
initialized = 1
dns_leak_protection = 1
custom_dns = None
check_update_interval = 3
api_domain = https://api.protonvpn.ch
killswitch = 0
ignore_ping_restart = 0
ping = 0
ping_exit = 0
split_tunnel = 1
split_type = whitelist

The last 5 fields are specific to this fork.

split_type = whitelist is using the reverse split tunneling feature. For help, run sudo protonvpn --help

Create ~/.pvpn-cli/split_tunnel.txt and add the following:

104.18.6.192
104.18.7.192
104.16.154.36
104.16.155.36

The first 2 values are for api.openai.com. The last 2 are whatismyipaddress.com for testing (i.e., ensure that the traffic on this list are really routed through ProtonVPN).

Run sudo protonvpn refresh to update your config.

Let’s try connecting:

sudo protonvpn c JP-FREE-01 -p TCP

To test, go to whatismyipaddress.com and you should see you’re located in Japan. Go to whatismyip.com and you should see your real IP address.

Therefore, only the entries in ~/.pvpn-cli/split_tunnel.txt are routed through ProtonVPN.

You can create a systemd service to run the above command on startup.

4. Bonus: vopono

This is perfect if you use VPN only in an isolate browser, i.e., firefox without VPN and ungoogled-chromium with VPN. After following the installation and setup, run the following to use Chrome to establish a ProtonVPN connection to Japan:

vopono -v exec --firewall iptables --provider protonvpn --server japan "chromium"

I need the flag --firewall iptables or else it doesn’t work for me. ymmv.

Conclusion

Hopefully at least one of the above methods works for you:)