Skip to content

Conversation

@qdm12
Copy link
Owner

@qdm12 qdm12 commented Aug 16, 2025

  • -proton-username flag for cli update
  • -proton-password flag for cli update
  • UPDATER_PROTONVPN_USERNAME option for periodic updates
  • UPDATER_PROTONVPN_PASSWORD option for periodic updates

Fix #2820

Clone of #2789 but with a branch within the repository, so other forks can target it (#2864)

@qdm12 qdm12 marked this pull request as draft August 16, 2025 20:31
@qdm12 qdm12 added the Status: 🔴 Blocked Blocked by another issue or pull request label Aug 18, 2025
@kubrickfr
Copy link

Does this require any new settings? It doesn't look like it but it doesn't seem to work, at least for me.

ERROR updating server information: getting servers: HTTP status code not OK: 403 403 Forbidden

@qdm12
Copy link
Owner Author

qdm12 commented Sep 10, 2025

This is unfinished and I'm waiting for an answer at: #2864 (comment)

Actually if you want to help, maybe you could try on your side (I don't have a protonvpn account), for example with curl, this is what's done currently in the Go code:

curl -X POST https://api.proton.me/auth/v4/sessions -H "Content-Type: application/json" -H "x-pm-appversion: Other" -H "x-pm-apiversion: 3" -H "User-Agent: test" -d '{"Scope": "vpn"}'

Now the json body can also contain a ClientSecret string and a Payload string and I have no idea what these are.

This returns you an AccessToken and a UID, which you can then use to access https://api.proton.me/vpn/v1/logicals:

curl -X GET https://api.proton.me/vpn/v1/logicals -H "Authorization: Bearer <AccessToken>" -H "x-pm-uid: <UID>" -H "x-pm-appversion: Other" -H "x-pm-apiversion: 3" -H "User-Agent: test"

Obviously something isn't right in one or the other or both of these commands. If you can crack this, I can near-immediately fix Gluetun.

@Drewsapple
Copy link

Drewsapple commented Sep 10, 2025

I tried to figure out the auth flow with curl for a bit and resorted to using their python packages instead. Annoyingly, I think they're only packaged for their debian releases, so I built a container that sets them up and runs a simple script to auth and then fetch the server list. I spent some time trying to inspect the requests made and copy them, but that's not something I've done before and felt I was at a dead end.

You can find the repo for the container here, it's worked to generate the server list files for me. If you want to try and inspect the requests, my work for that was in the instrumented branch, although it's all just stuff GPT5 wrote. I hope this is helpful for someone else who has more experience reversing apis.

@kubrickfr
Copy link

kubrickfr commented Sep 11, 2025

So far, the only way I have found if you want to get all the servers including premium is to go on https://account.proton.me/vpn, log-in, get the value of the REFRESH- cookie, which contains a URL-encoded value like

{"ResponseType":"token","ClientID":"WebAccount","GrantType":"refresh_token","RefreshToken":"xxxx","UID":"yyy"}

It's valid for a year.

Then you can query https://account.proton.me/api/auth/refresh like so

  curl 'https://account.proton.me/api/auth/refresh' \
  --compressed \
  -X POST \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0' \
  -H 'Accept: application/vnd.protonmail.v1+json' \
  -H 'Accept-Language: en-GB,en-US;q=0.7,en;q=0.3' \
  -H 'Accept-Encoding: gzip, deflate, br, zstd' \
  -H 'Referer: https://account.proton.me/u/1/vpn/WireGuard' \
  -H 'x-pm-appversion: [email protected]' \
  -H 'x-pm-uid: yyy' \
  -H 'Origin: https://account.proton.me' \
  -H 'Cookie: REFRESH-yyy=%7B%22ResponseType%22%3A%22token%22%2C%22ClientID%22%3A%22WebAccount%22%2C%22GrantType%22%3A%22refresh_token%22%2C%22RefreshToken%22%3A%xxxx%22%2C%22UID%22%3A%yyy%22%7D;' \

replacing xxxx and yyy with the appropriate value, with that you get a cookie named AUTH-yyy=zzzz and query

curl 'https://account.proton.me/api/vpn/logicals' \
  --compressed \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0' \
  -H 'Accept: application/vnd.protonmail.v1+json' \
  -H 'Accept-Language: en-GB,en-US;q=0.7,en;q=0.3' \
  -H 'Accept-Encoding: gzip, deflate, br, zstd' \
  -H 'Referer: https://account.proton.me/u/1/vpn/WireGuard' \
  -H 'x-pm-appversion: [email protected]' \
  -H 'x-pm-uid: yyy' \
  -H 'Connection: keep-alive' \
  -H 'Cookie: AUTH-yyy=zzzz;'

But I would really not like to have to do this because I'm pretty sure that if for any reason this token leaks, then whoever gets it can control my account.

@qdm12
Copy link
Owner Author

qdm12 commented Oct 23, 2025

I worked like 12 hours on it the last 2 days with just failures, I sent proton support an email at the end of the day, because their authentication system is just plain odd 🤷 The even have https://github.com/ProtonMail/go-proton-api which I twisted in all ways possible without succeeding once... 😢
What I'll do tomorrow though, is just use some token from my browser (thanks for the comment @kubrickfr !) to update the servers in Gluetun on the master branch. Updater will remain broken for a few more days/weeks until their authentication mechanism can finally be understood though.

@qdm12 qdm12 force-pushed the protonvpn-api-fix branch from 24cdfd6 to 557cc36 Compare October 29, 2025 02:36
@qdm12
Copy link
Owner Author

qdm12 commented Oct 29, 2025

Ok I finally figured it out @kubrickfr - your curl commands definitely helped me out a lot get started so thanks for that 💪 !
Proton has been unhelpful as hell and I'm mad at them.
But given I'm stubborn enough, username+password authentication finally works (a good 20 hours of work ugh) to update servers data. I didn't work on 2fa at this time, because I'm sure it's many more hours of reverse engineering which can be skipped, at least there is a way to update servers now.
It does import protonmail/go-srp but I really don't want to reinvent the wheel, especially since this is really specific code to proton, I think it's wise for this one time to just import that.

@qdm12 qdm12 changed the title Altered ProtonVPN API Updater to use auth tokens fix(protonvpn): authenticated servers data updating Oct 29, 2025
@kubrickfr
Copy link

Hi @qdm12,

Thanks for doing this, I'll try it out!

FYI I had also reached out to their support, as a paying customer. And they politely told me to F off.

Since this decision was purposefully made with the intention to stop such activities due to security concerns, I am afraid I would not be able to provide further support.

So yes, I also got mad at them.

I also abandoned this track because I think it's a security issue to have my unscoped credentials in gluetun configuration: this username / password can be used to access my emails, drive documents, etc.

So I actually made a fork that loads the logicals.json from a local file.

My last response to them was:

That's fine. I guess we'll just end up having someone maintain a mirror somewhere, and everybody loses.

To which they replied:

Thank you for your understanding and consideration.

So here we are.

@qdm12
Copy link
Owner Author

qdm12 commented Oct 29, 2025

I also abandoned this track because I think it's a security issue to have my unscoped credentials in gluetun configuration: this username / password can be used to access my emails, drive documents, etc.

I see your point, although code is open source so risk should be limited, but yes still possible. And not everyone has the time to check the code on every commit 😄 !
But at least I can update it (done here) on the master branch for the built-in servers.json.
Actually @shwoop floated the idea on #2919 to have CI update periodically all the servers data. In that case, I can set my credentials as CI secrets to update it as well. That would resolve this situation 👍 Coming soon ™️ I hope!
One last note: you could also create another "dummy" proton free account to access the servers data, if you want to do update servers locally without risk (what I've done for testing).

So here we are.

Laughing with you in support hell! 😈

@kubrickfr
Copy link

kubrickfr commented Oct 29, 2025

although code is open source so risk should be limited

@qdm12 I didn't mean it this way, I don't distrust gluetun, all I'm saying is, I'm not happy leaving my (unencrypted) credentials on my server.

create another "dummy" proton free account to access the servers data

good suggestion

@qdm12
Copy link
Owner Author

qdm12 commented Oct 30, 2025

Oh no worry, I get you as well! Definitely a risk either way (on the server, or in Gluetun or both) - plus right now otp support isn't implemented (and would be cumbersome to use in a container periodically anyway), so disabling otp temporarily does suck too.

@qdm12 qdm12 added Status: 🗯️ Waiting for feedback Status: 🟡 Nearly resolved This might be resolved or is about to be resolved and removed Status: 🔴 Blocked Blocked by another issue or pull request labels Oct 30, 2025
@qdm12 qdm12 force-pushed the protonvpn-api-fix branch from 1abbc1e to 5cef053 Compare October 30, 2025 02:47
@qdm12 qdm12 force-pushed the protonvpn-api-fix branch from fb72887 to d083367 Compare October 30, 2025 20:49
@qdm12 qdm12 marked this pull request as ready for review October 31, 2025 11:32
@qdm12 qdm12 force-pushed the protonvpn-api-fix branch from d1e7479 to 2447696 Compare November 7, 2025 14:50
@alanstrok
Copy link

alanstrok commented Nov 7, 2025

This should work (you forgot to specify the image tag I think)

docker run --rm -v /mnt/user/appdata/gluetun:/gluetun qmcgaw/gluetun:pr-2878 update -enduser -providers protonvpn -proton-username my-username -proton-password mypassword

Yeah silly me, the tag was incorrect. Now im facing a different issue, my proton username is my email, this leads to an auth error. « Username is respons does not match request username »

Edit: Actually the username is the part before the @ of my email

@qdm12
Copy link
Owner Author

qdm12 commented Nov 7, 2025

Yeah silly me

No problem, pushed a change to auto-trim the domain in case it's set, to make it silly-proof 👍 I love silly reports in a PR ❤️ rather than on the master branch 😅

@qdm12 qdm12 force-pushed the protonvpn-api-fix branch from d7d58d4 to 6d5ce23 Compare November 7, 2025 19:28
@qdm12 qdm12 added Status: 🔴 Blocked Blocked by another issue or pull request and removed Status: 🗯️ Waiting for feedback labels Nov 7, 2025
@SerhiyRomanov
Copy link

This should work (you forgot to specify the image tag I think)

docker run --rm -v /mnt/user/appdata/gluetun:/gluetun qmcgaw/gluetun:pr-2878 update -enduser -providers protonvpn -proton-username my-username -proton-password mypassword

Thanks for your work. I've tested and it's works for me

@qdm12 qdm12 merged commit 8a09217 into master Nov 13, 2025
6 checks passed
@qdm12 qdm12 deleted the protonvpn-api-fix branch November 13, 2025 19:05
qdm12 added a commit to qdm12/gluetun-wiki that referenced this pull request Nov 13, 2025
qdm12 added a commit that referenced this pull request Nov 15, 2025
- `-proton-username` flag for cli update
- `-proton-password` flag for cli update
- `UPDATER_PROTONVPN_USERNAME` option for periodic updates
- `UPDATER_PROTONVPN_PASSWORD` option for periodic updates
qdm12 added a commit that referenced this pull request Nov 15, 2025
- `-proton-username` flag for cli update
- `-proton-password` flag for cli update
- `UPDATER_PROTONVPN_USERNAME` option for periodic updates
- `UPDATER_PROTONVPN_PASSWORD` option for periodic updates
@Codelica
Copy link

Codelica commented Nov 17, 2025

I've been trying to update for an hour now with this command, and am about to take a hostage. (As they also toss captcha and rate limits in after a few requests) My "username" at Proton is my email address. Yet using that via the follwing from a clean host (not rate limted or catpcha'd yet):

docker run --rm -v /storage/docker/gluetun:/gluetun qmcgaw/gluetun:pr-2878 update -enduser -providers protonvpn -proton-username [email protected] -proton-password xxxxxxxxxxx

I get...

2025-11-17T02:34:20Z INFO creating /gluetun/servers.json with 20738 hardcoded servers
2025-11-17T02:34:20Z INFO updating Protonvpn servers...
2025-11-17T02:34:27Z ERROR updating server information: getting protonvpn servers: authentifying with Proton: getting auth information: username in response does not match request username: expected [email protected] got
2025-11-17T02:34:27Z INFO Shutdown successful

Any guesses? I've tried with my "display name" for username just for fun but get the expected "Incorrect login credentials."

I assume others are using their email usernames.

Edit: Just to be clear, my Proton username is my work email address. It is not a @protonmail.com or @proton.me address. (As I see some code related to stripping Proton domains from usernames). I just have a VPN Plus account.

@scraunt
Copy link

scraunt commented Nov 17, 2025

Linking here for visibility #2985

@Codelica

You could try enclosing your email with single quotes. Since you can create a Proton account any time (maybe not everyone knows this) I have just created an account only used for VPN - no 'external' email required (e.g. I could log into the Protonmail inbox for that account). Obviously this does not help you if you have an account with paid time on already. You might be best off posting in the discussions, or creating a new issue. You will get more visibility there. Best of luck!

@qdm12
Copy link
Owner Author

qdm12 commented Nov 17, 2025

@Codelica

Edit: Just to be clear, my Proton username is my work email address. It is not a @protonmail.com or @proton.me address. (As I see some code related to stripping Proton domains from usernames). I just have a VPN Plus account.

Ah! I wasn't aware of that. So both using username and [email protected] does not fix it I suppose? I have no idea how this could be fixed. On the other hand, the plan is to update protonvpn servers data regularly with CI so you might not have to do this updating that much. Ideally, you should be able to as a fallback though.

On a similar note, my free account does work but an older (~3 years old) paid account gives me:

updating server information: getting protonvpn servers: authentifying with Proton: authentifying: HTTP status code not OK: Unprocessable Entity: {"Code":9001,"Error":"For security reasons, please complete CAPTCHA. If you can't pass it, please try updating your app or contact us here: https://proton.me/support/appeal-abuse","Details":{"HumanVerificationToken":"xxxx","HumanVerificationMethods":["captcha"],"Direct":1,"Description":"","Title":"Human Verification","WebUrl":"https://verify.proton.me/?methods=captcha&token=xxxx","ExpiresAt":1763395346}}

Ugh I am hating Proton more almost every day....

Please create an issue if it doesn't work, since I'm not notified on this PR anymore so I likely won't see it.

@Codelica
Copy link

You could try enclosing your email with single quotes. Since you can create a Proton account any time (maybe not everyone knows this) I have just created an account only used for VPN - no 'external' email required (e.g. I could log into the Protonmail inbox for that account).

Yep, I've tried most everything. Quoting, removing special chars, etc. It really comes down to that username check on return. The free VPN account is confusing to me though, as it requests an email address to use for the account which becomes the username. That seems like the same situation to me (username = non Proton email address). I did try it anyway, but got the same results as my paid account.

Ah! I wasn't aware of that. So both using username and [email protected] does not fix it I suppose? I have no idea how this could be fixed. On the other hand, the plan is to update protonvpn servers data regularly with CI so you might not have to do this updating that much. Ideally, you should be able to as a fallback though.

That's correct. I've tried [email protected], username, and "display name" just for fun. It really feels like I may be getting authenticated, but the return value for username is empty/missing when using [email protected] (which is my username per their UI and being able to login :) )

On a similar note, my free account does work but an older (~3 years old) paid account gives me:

Lol.. yea, try it a couple more times and you'll feel their rate limits also with a taunting message about how limits are much higher when logged in 😅

qdm12 added a commit to qdm12/gluetun-wiki that referenced this pull request Nov 18, 2025
@FlorentLM
Copy link

Hey, has this become mandatory for any ProtonVPN based install, even with WireGuard? Having the password in clear or in a docker secret is a bit of a downgrade in security, isn't it?

Also what about accounts with 2FA enabled?

@flueflacks
Copy link

The free VPN account is confusing to me though, as it requests an email address to use for the account which becomes the username.

having created only a vpn acccount, My non proton email i signed up with was my username for login, until i added protonmail, then my proton email was [email protected] and my username for logging in and for the updater became myprotonaddy, and the updater worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: 🔴 Blocked Blocked by another issue or pull request Status: 🟡 Nearly resolved This might be resolved or is about to be resolved

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: protonvpn servers update broken? 400 Bad Request