vpnhood / VpnHood

Undetectable Fast Portable VPN
GNU Lesser General Public License v2.1
992 stars 149 forks source link

allow update from v3 token to v4 in new clients #451

Closed SSgumS closed 9 months ago

SSgumS commented 9 months ago

Without this update, token auto update for old users will be broken. This allows old users to update to new client versions without being forced to renew their access key manually.

trudyhood commented 9 months ago

Hi,

I have seen you changed UpdateTokenFromUrl to support TokenV3. However, it is not needed at all. There are two reasons:

1) The update from token V3 was almost useless as it worked for just one token, perhaps public tokens only, shared between many users. The URL in TokenV3 pointed to another access key token, while the URL in TokenV4 pointed to a server token, not a user access token. There are some shares but different concepts.

2) The old token will be automatically updated to the new format of the server, so after that, the server-token part can be updated from V4, and there is no need to support V3 in UpdateTokenFromUrl,

The good news is that the new server will upgrade all old tokens when you set ServerTokenUrl in your server configuration. As we decouple ServerToken from AccessToken. It means you have two ways to update the server-token part of client access tokens, one from the server and one from the URL, and the UpdateTokenFromUrl respects the created time.

Of course, updating from the server doesn't work when they can't connect to a server, so the URL comes to work; the user needs to update their client at this moment, and after that, we shouldn't worry about compatibility.

Thank you for trying to improve VpnHood. Your work is so respected, and we like your clean code; however, v3 support in UpdateTokenFromUrl suppressed the other method. I hope to see more contributions from your side.

SSgumS commented 9 months ago

Hi,

I have seen you changed UpdateTokenFromUrl to support TokenV3. However, it is not needed at all. There are two reasons:

  1. The update from token V3 was almost useless as it worked for just one token, perhaps public tokens only, shared between many users. The URL in TokenV3 pointed to another access key token, while the URL in TokenV4 pointed to a server token, not a user access token. There are some shares but different concepts.
  2. The old token will be automatically updated to the new format of the server, so after that, the server-token part can be updated from V4, and there is no need to support V3 in UpdateTokenFromUrl,

The good news is that the new server will upgrade all old tokens when you set ServerTokenUrl in your server configuration. As we decouple ServerToken from AccessToken. It means you have two ways to update the server-token part of client access tokens, one from the server and one from the URL, and the UpdateTokenFromUrl respects the created time.

Of course, updating from the server doesn't work when they can't connect to a server, so the URL comes to work; the user needs to update their client at this moment, and after that, we shouldn't worry about compatibility.

Thank you for trying to improve VpnHood. Your work is so respected, and we like your clean code; however, v3 support in UpdateTokenFromUrl suppressed the other method. I hope to see more contributions from your side.

When a user's client gets updated from v3.2.448 to v3.3.454, their v3 token is converted to a v4 token in the client application with the ServerToken.Secret property having null. This results in a situation which no one will be able to update their server token anymore! The modification I did, allows the token to be updated with a valid v4 token (this happens only for the first time which ServerToken.Secret is null). Then the next time, ServerToken.Secret is populated with a proper value and the update process for server token will be proceed as expected.

Note that the VPN service provider must put a valid v4 token in the old update URL. But in the new v4 token's ServerToken.Url, a URL for server token is provided.

I tried my best to describe the deadlock situation that the new client version has created. To summarize, for the reason that ServerToken.Secret is null, old users can't update their server token in new clients. As far as I could understand, your description doesn't address this issue. Please correct me if I'm wrong.

trudyhood commented 9 months ago

image

The case above happens only after the user upgrades, but after the user establishes a connection to the server, their token always gets updated from the server regardless of ServerTokenUrl and ServerToken.Secret. "This results in a situation which no one will be able to update their server token anymore!" That is not right, their token will updated by the server, and from then on they can update from the URL when the server is not available.

So, only one circumstance in your code may help: when the user cannot connect to the server even before the upgrade. Are you targeting this? It rarely happens. If your client is still able to connect to a server, their server token part will immediately be updated after the VPN connection, not the URL.

Are you trying to cover the users that have TokenUrl in their token and can not establish a connection at this moment?

SSgumS commented 9 months ago

image

The case above happens only after the user upgrades, but after the user establishes a connection to the server, their token always gets updated from the server regardless of ServerTokenUrl and ServerToken.Secret. "This results in a situation which no one will be able to update their server token anymore!" That is not right, their token will updated by the server, and from then on they can update from the URL when the server is not available.

So, only one circumstance in your code may help: when the user cannot connect to the server even before the upgrade. Are you targeting this? It rarely happens. If your client is still able to connect to a server, their server token part will immediately be updated after the VPN connection, not the URL.

Are you trying to cover the users that have TokenUrl in their token and can not establish a connection at this moment?

I couldn't find anything in the code of VpnHoodClient.cs and VpnHoodApp.cs, related to the update process you mentioned. Would you please show me where the server updates the token?

As a side note, I'm completely against the idea of updating the server token by server; it has no benefits. I will try to explain my reasoning. I hope that my understanding of the code is accurate.

  1. ServerToken.Url exists for this exact purpose. Why add another thing and complicating stuffs? All updates being based on a URL mentioned in the token is a more logical method.

  2. More importantly, it is meaningless if the server token can't be updated when the client can't connect; the update process exists only for these exact situations; situations in which a user has a list of outdated servers (or in the context of our conversation, an old v3 subscription link)!

  3. Overriding the server token by server is unwise as it prevents administrators from providing different server tokens for different purposes or users which could be a common situation. Having an entity named server token for storing some information about servers may be a good choice, but we could have multiple server configuration setups (with overlaps!) for different purposes; therefore, I personally do not like creating limitations when the previous setup is perfectly fine both now and in the past.

I recommend that each server token has an update URL (as is the case now) and that the URL be independent of anything else; it only depends on the update URL's content. The server token should be updated from the URL after a connection has been established inside the VPN session, or when an error occurs during the connection establishment process.

trudyhood commented 9 months ago

First thank you for presenting your concern

Here is the case: There are many VPM merchants who don't set the ServerTokenUrl at first. They distribute tokens, but after a month, they realize they need to set the ServerTokenUrl. This becomes problematic since there is no way to update all the tokens. Another issue arises when the domain that hosts the ServerTokenUrl gets blocked while many of the VPN servers are still functioning. This again leads to the inability to update all the tokens if we don't update the ServerToken by the server. Also, I couldn't understand why updating ServerToken can be problematic, sounds like you are using FileAccessServer for managing multiple servers!

  1. Overriding the server token by server is unwise as it prevents administrators from providing different server tokens for different purposes or users which could be a common situation ...

I couldn't understand this claim, what kind of limitation? Each server (server farm) has its own ServerTokenUrl.

By the way, we have found some issues in updating the token, and we will release a new version soon. Also, the VpnHood Enterprise Access Manager is still not updated with this feature; however, I think you are not using it. You must know the FileAccessManager (the build account control) has limited functionality and is not designed to support multiple servers, if you have a plan to support many servers you need to implement your own access manager or you can use the VpnHood Enterprise Access Manager

SSgumS commented 9 months ago

Here is the case: There are many VPM merchants who don't set the ServerTokenUrl at first. They distribute tokens, but after a month, they realize they need to set the ServerTokenUrl. This becomes problematic since there is no way to update all the tokens.

For this purpose, we should prioritize ServerToken.Url if exists, otherwise, it can be updated from the server itself.

Another issue arises when the domain that hosts the ServerTokenUrl gets blocked while many of the VPN servers are still functioning. This again leads to the inability to update all the tokens if we don't update the ServerToken by the server.

This problem can be mitigated by updating the token inside the VPN session after the VPN connection is established. If the connection fails, we update the token like now (in the finally code region).

I couldn't understand this claim, what kind of limitation? Each server (server farm) has its own ServerTokenUrl.

Think of a situation in which we have endpoints x, y, and z. All these endpoints are reverse proxy servers which forward traffic to a backend server A. Using x, y, and z is common because IP bans are very frequent in restricted areas, and we should change the edge servers frequently. In internet provider 1, x is available, in internet provider 2, y is available, and in internet provider 3, z is available. For a better experience, we should provide 3 different server tokens to users, each for an individual internet provider. Updating the server token without considering ServerToken.Url prevents us from supporting this common scenario.

This is just a simple example, we can imagine more complex setups where we want different server tokens, but they share backend servers. That's why prioritizing the server update process is a limitation that wasn't necessary and further adds inconsistancy in updating procedure of tokens; but as you mentioned, it is a suitable alternative way to support scenarios in which the merchant forgets to set ServerToken.Url.


If you consider my recommendation to be a good solution to all the problems both of us mentioned, I would be glad to help you implement it.

trudyhood commented 9 months ago

It's important to understand that typically only the ServerToken's URL and the ServerSecret are updated by the server. However, from what I gather, your setup involves multiple ServerTokenUrls pointing to a server farm. This farm consists of several servers situated behind proxies, and the ServerToken endpoints are directed to these proxies.

In such a scenario, a single token might correspond to different servers. However, VpnHood is designed to support only one TLS certificate across all servers. This means all servers in the farm must share the same certificate, as clients could connect to any server in the farm. This shared setup is what we refer to as a 'server farm'. I presume the ServerTokens are manually generated in your custom implementation.

From my perspective, this approach complicates the system. With a farm hosting numerous servers, secrets and endpoints become widely shared among clients, thereby we can not call it ServerSecret. It resembles a VPN server with a dynamic IP, seeking server IPs via URL rather than DNS. Our method is distinct, involving thousands of smaller farms, each distributed among a small group of people.

Nevertheless, we're open to supporting your configuration if it's already operational. We can introduce a toggle switch on servers which allows you to bypass updating the client's ServerTokenUrl.

As for the V3 token, if you have a V3 URL compatible with the provided code, we can temporarily integrate it into the client. Once your client token is updated, we'll phase out this temporary code after one month.

If you have any other changes in mind that may assist you, please let us know.

SSgumS commented 9 months ago

First of all, I appreciate your cooperation and openness to suggestions.

... your setup involves multiple ServerTokenUrls pointing to a server farm.

Exactly.

This means all servers in the farm must share the same certificate...

In my setup, they all use the same certificate and server secret.

It resembles a VPN server with a dynamic IP, seeking server IPs via URL rather than DNS.

Hmm. I think my setup is just a multi-token setup: not hard-linking server tokens to any physical server.

Nevertheless, we're open to supporting your configuration if it's already operational. We can introduce a toggle switch on servers which allows you to bypass updating the client's ServerTokenUrl.

Great. The toggle switch can be a viable solution.

Personally, I prefer this update procedure as it is much simpler, more consistent and more robust:

  1. At the start of a VPN session establishment, try to update the server token using the server token URL (this update happens inside the VPN session).

  2. If this fails, update the server token URL and server secret from the VPN server connected.

  3. If all failed, in the finally section of the code, try to update the server token using the server token URL if the 1st step failed.

BTW, the choice is yours. I will implement the method you prefer (or if you are more comfortable implementing it yourself, please let me know).

As for the V3 token, if you have a V3 URL compatible with the provided code, we can temporarily integrate it into the client. Once your client token is updated, we'll phase out this temporary code after one month.

Good enough. Thanks.

trudyhood commented 9 months ago

Hi,

We held a discussion about the process of updating tokens. Based on our conversation, we've decided on the following approach until further requirements emerge:

  1. Comprehensive Token Update: Post-establishment of the VPN, the server token will be updated from the server. This ensures that clients can refresh their server tokens

  2. Fallback Strategy: In cases where the first step fails, we will attempt to update the server token using a URL, followed by a reconnection attempt if there is a newer server token.

I recognize that this strategy might not align perfectly with your specific needs. To accommodate this, we plan to introduce an option on the server side. This switch will prevent the server from automatically updating the client with the new token, tailored specifically for your scenario.

Regarding further customization, it appears that your needs might be more deeply connected to the File Access Manager. In our system, clients transmit their tokens to the server, enabling the backend Access Manager to identify users and understand the initial generation and distribution of the access token. This insight allows the Enterprise Access Manager to make informed decisions.

Generally, we don't extensively customize the built-in File Access Manager; it is for a single server. However, we can consider tailoring our Enterprise Access Server to your requirements; it's important to note that this depends on the number of your users. If your strategy is highly specific, consider developing a custom Access Manager. This would be entirely independent of the VpnHood server, allowing for a solution that's precisely tailored to your needs.

trudyhood commented 9 months ago

1 At the start of a VPN session establishment, try to update the server token using the server token URL (this update happens inside the VPN session

We can also add this feature, in that case, your server does not return any token, and TokenUrl exists. I believe it is what you need.

SSgumS commented 9 months ago

Hello

Thanks for the heads up.

This switch will prevent the server from automatically updating the client with the new token, tailored specifically for your scenario.

Good. This option will solve my problem.

But what about the update of v3 tokens that this pull request opened for? Have you changed your mind regarding merging the pull request's update procedure temporarily in clients?

As for the V3 token, if you have a V3 URL compatible with the provided code, we can temporarily integrate it into the client. Once your client token is updated, we'll phase out this temporary code after one month.

trudyhood commented 9 months ago

Do you really need it at the moment? I think it is too late; perhaps most users have updated their clients by now, so unfortunately, the previous update dropped the TokenUrl port (As it was for an access token, not a server token). I am sorry for that, but very few people were using it. Unfortunately, the TokenUrl has been lost by now and the upgrade is too late 😞

SSgumS commented 9 months ago

the previous update dropped the TokenUrl port

If I'm not wrong, in the converted v4 token from v3 one, ServerToken.Url is populated by the old Token.Url. So, the users can still update their tokens if this change is merged.

SSgumS commented 9 months ago

https://github.com/vpnhood/VpnHood/blob/eb95dc8560110dcd1907d671a71e9a33b323424d/VpnHood.Common/TokenLegacy/TokenV3.cs#L50-L70

trudyhood commented 9 months ago

Oh, so lucky. I thought we had set it to null. So, I will copy your code manually as the development branch has changed a lot. then the recent main branch

trudyhood commented 9 months ago

Ok, check it out https://github.com/vpnhood/VpnHood/blob/development/VpnHood.Client.App/ClientProfileService.cs

trudyhood commented 9 months ago

I have also added ReplyAccessKey in FileAccessServerOptiosn. There is no integration test or document for it. Please check the development branch and make sure it is what you need.

SSgumS commented 9 months ago

Your work looks great. Thank you for your help and prompt response.