Merge pull request #27507 from brave/set_vpn_proxy_windows_ikev2

Set VPN proxy url in Windows ikev2 connection
This commit is contained in:
Brian Clifton
2025-03-05 12:16:22 -07:00
committed by GitHub
11 changed files with 127 additions and 16 deletions
@@ -36,8 +36,9 @@ std::unique_ptr<Hostname> PickBestHostname(
return a.capacity_score > b.capacity_score;
});
if (filtered_hostnames.empty())
if (filtered_hostnames.empty()) {
return std::make_unique<Hostname>();
}
// Pick highest capacity score.
return std::make_unique<Hostname>(filtered_hostnames[0]);
@@ -47,24 +48,30 @@ std::vector<Hostname> ParseHostnames(const base::Value::List& hostnames_value) {
std::vector<Hostname> hostnames;
for (const auto& value : hostnames_value) {
DCHECK(value.is_dict());
if (!value.is_dict())
if (!value.is_dict()) {
continue;
}
const auto& dict = value.GetDict();
constexpr char kHostnameKey[] = "hostname";
constexpr char kDisplayNameKey[] = "display-name";
constexpr char kOfflineKey[] = "offline";
constexpr char kCapacityScoreKey[] = "capacity-score";
constexpr char kSmartRoutingEnabled[] = "smart-routing-enabled";
const std::string* hostname_str = dict.FindString(kHostnameKey);
const std::string* display_name_str = dict.FindString(kDisplayNameKey);
std::optional<bool> offline = dict.FindBool(kOfflineKey);
std::optional<int> capacity_score = dict.FindInt(kCapacityScoreKey);
std::optional<bool> smart_routing_enabled =
dict.FindBool(kSmartRoutingEnabled);
if (!hostname_str || !display_name_str || !offline || !capacity_score)
if (!hostname_str || !display_name_str || !offline || !capacity_score) {
continue;
}
hostnames.push_back(
Hostname{*hostname_str, *display_name_str, *offline, *capacity_score});
hostnames.push_back(Hostname{*hostname_str, *display_name_str, *offline,
*capacity_score,
smart_routing_enabled.value_or(false)});
}
return hostnames;
@@ -20,6 +20,8 @@ void BraveVPNConnectionInfo::Reset() {
hostname_.clear();
username_.clear();
password_.clear();
smart_routing_enabled_ = false;
proxy_.clear();
}
bool BraveVPNConnectionInfo::IsValid() const {
@@ -31,11 +33,15 @@ void BraveVPNConnectionInfo::SetConnectionInfo(
const std::string& connection_name,
const std::string& hostname,
const std::string& username,
const std::string& password) {
const std::string& password,
const bool smart_routing_enabled,
const std::string& proxy) {
connection_name_ = connection_name;
hostname_ = hostname;
username_ = username;
password_ = password;
smart_routing_enabled_ = smart_routing_enabled;
proxy_ = proxy;
}
} // namespace brave_vpn
@@ -22,18 +22,24 @@ class BraveVPNConnectionInfo {
void SetConnectionInfo(const std::string& connection_name,
const std::string& hostname,
const std::string& username,
const std::string& password);
const std::string& password,
bool smart_routing_enabled,
const std::string& proxy);
std::string connection_name() const { return connection_name_; }
std::string hostname() const { return hostname_; }
std::string username() const { return username_; }
std::string password() const { return password_; }
bool smart_routing_enabled() const { return smart_routing_enabled_; }
std::string proxy() const { return proxy_; }
private:
std::string connection_name_;
std::string hostname_;
std::string username_;
std::string password_;
bool smart_routing_enabled_;
std::string proxy_;
};
} // namespace brave_vpn
@@ -15,6 +15,8 @@
#include "brave/components/brave_vpn/browser/api/brave_vpn_api_request.h"
#include "brave/components/brave_vpn/browser/connection/brave_vpn_connection_manager.h"
#include "brave/components/brave_vpn/common/brave_vpn_data_types.h"
#include "brave/components/brave_vpn/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace brave_vpn {
@@ -171,6 +173,23 @@ void ConnectionAPIImpl::ResetHostname() {
hostname_.reset();
}
bool ConnectionAPIImpl::SmartRoutingEnabled() const {
if (hostname_ && hostname_->smart_routing_enabled) {
bool smart_routing_user_supported = manager_->local_prefs()->GetBoolean(
prefs::kBraveVPNSmartProxyRoutingEnabled);
VLOG(2) << __func__ << " Host \"" << hostname_->hostname
<< "\" supports smart proxy routing. "
<< (smart_routing_user_supported
? "Smart proxy routing will be used."
: "However, user has disabled smart proxy routing.");
return smart_routing_user_supported;
} else if (hostname_) {
VLOG(2) << __func__ << " Host \"" << hostname_->hostname
<< "\" does not support smart proxy routing. ";
}
return false;
}
void ConnectionAPIImpl::UpdateAndNotifyConnectionStateChange(
mojom::ConnectionState state) {
// this is a simple state machine for handling connection state
@@ -46,6 +46,7 @@ class ConnectionAPIImpl
void ResetConnectionState();
std::string GetLastConnectionError() const;
std::string GetHostname() const;
bool SmartRoutingEnabled() const;
virtual void Connect() = 0;
virtual void Disconnect() = 0;
@@ -14,6 +14,7 @@
#include "brave/components/brave_vpn/browser/api/brave_vpn_api_request.h"
#include "brave/components/brave_vpn/browser/connection/brave_vpn_connection_manager.h"
#include "brave/components/brave_vpn/browser/connection/brave_vpn_region_data_manager.h"
#include "brave/components/brave_vpn/common/brave_vpn_constants.h"
#include "brave/components/brave_vpn/common/brave_vpn_data_types.h"
#include "brave/components/brave_vpn/common/brave_vpn_utils.h"
@@ -325,7 +326,8 @@ void SystemVPNConnectionAPIImplBase::OnGetProfileCredentials(
}
connection_info_.SetConnectionInfo(manager_->target_vpn_entry_name(),
GetHostname(), *username, *password);
GetHostname(), *username, *password,
SmartRoutingEnabled(), kProxyUrl);
// Let's create os vpn entry with |connection_info_|.
CreateVPNConnection();
return;
@@ -12,6 +12,7 @@
#include "brave/components/brave_vpn/browser/connection/ikev2/win/ras_utils.h"
#include <windows.h>
#include <ras.h>
#include <raserror.h>
#include <stdio.h>
@@ -31,6 +32,7 @@
#include "brave/base/process/process_launcher.h"
#include "brave/components/brave_vpn/browser/connection/brave_vpn_connection_info.h"
#include "brave/components/brave_vpn/common/brave_vpn_constants.h"
#include "url/gurl.h"
namespace brave_vpn {
@@ -422,6 +424,50 @@ RasOperationResult SetConnectionParamsUsingPowerShell(
return GetRasSuccessResult();
}
// `Set-VpnConnectionProxy` cmdlet:
// https://learn.microsoft.com/en-us/powershell/module/vpnclient/set-vpnconnectionproxy?view=windowsserver2022-ps
RasOperationResult SetConnectionProxyParamsUsingPowerShell(
const std::wstring& entry_name,
const std::wstring& pac_file_url) {
// Validate the entry name
DWORD nRet = RasValidateEntryName(NULL, entry_name.c_str());
switch (nRet) {
case ERROR_INVALID_NAME:
return GetRasErrorResult("`entry_name` is not a valid format");
case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY:
return GetRasErrorResult("`entry_name` is not in phone book");
default:
// ERROR_SUCCESS
// ERROR_ALREADY_EXISTS
break;
}
// Validate the URL of the provided PAC file
VLOG(2) << __func__ << " validating `pac_file_url`: \"" << pac_file_url
<< "\"";
GURL pac_file = GURL(base::WideToUTF8(pac_file_url));
if (!pac_file.is_valid()) {
return GetRasErrorResult("`pac_file_url` is not a valid URL");
}
if (!pac_file.SchemeIs(url::kHttpsScheme)) {
return GetRasErrorResult("`pac_file_url` is not using HTTPS");
}
base::CommandLine power_shell(base::FilePath(L"PowerShell"));
power_shell.AppendArg("Set-VpnConnectionProxy");
power_shell.AppendArg("-ConnectionName");
power_shell.AppendArg(base::WideToUTF8(entry_name));
power_shell.AppendArg("-AutoConfigurationScript");
power_shell.AppendArg(base::WideToUTF8(pac_file_url));
base::LaunchOptions options;
options.start_hidden = true;
auto result = brave::ProcessLauncher::ReadAppOutput(power_shell, options, 10);
if (!result.has_value()) {
return GetRasErrorResult(logging::SystemErrorCodeToString(GetLastError()));
}
return GetRasSuccessResult();
}
RasOperationResult SetConnectionParamsWin32(
const std::wstring& entry_name,
const std::wstring& phone_book_path) {
@@ -466,6 +512,7 @@ RasOperationResult CreateEntry(const BraveVPNConnectionInfo& info) {
const auto hostname = base::UTF8ToWide(info.hostname());
const auto username = base::UTF8ToWide(info.username());
const auto password = base::UTF8ToWide(info.password());
const auto proxy = base::UTF8ToWide(info.proxy());
// `RasSetEntryProperties` can have problems if fields are empty.
// Specifically, it will crash if `hostname` is NULL. Entry name
@@ -542,6 +589,13 @@ RasOperationResult CreateEntry(const BraveVPNConnectionInfo& info) {
if (!SetConnectionParamsUsingPowerShell(entry_name).success) {
return SetConnectionParamsWin32(entry_name, phone_book_path);
}
// Only provide proxy params if the host supports smart routing.
if (info.smart_routing_enabled()) {
// Can ignore proxy setting failure. VPN works w/o it.
SetConnectionProxyParamsUsingPowerShell(entry_name, proxy);
}
return GetRasSuccessResult();
}
@@ -57,6 +57,8 @@ inline constexpr char kSubscriberCredentialKey[] = "credential";
inline constexpr char kSkusCredentialKey[] = "skus_credential";
inline constexpr char kRetriedSkusCredentialKey[] = "retried_skus_credential";
inline constexpr char kSubscriberCredentialExpirationKey[] = "expiration";
inline constexpr char kProxyUrl[] =
"https://connect-api.guardianapp.com/api/v1/smart-proxy-routing/static-pac";
#if !BUILDFLAG(IS_ANDROID)
inline constexpr char kTokenNoLongerValid[] = "Token No Longer Valid";
@@ -15,6 +15,7 @@ struct Hostname {
std::string display_name;
bool is_offline;
int capacity_score;
bool smart_routing_enabled;
};
} // namespace brave_vpn
+18 -8
View File
@@ -53,6 +53,8 @@ void RegisterVPNLocalStatePrefs(PrefRegistrySimple* registry) {
#if BUILDFLAG(IS_MAC)
registry->RegisterBooleanPref(prefs::kBraveVPNOnDemandEnabled, false);
#endif
registry->RegisterBooleanPref(prefs::kBraveVPNSmartProxyRoutingEnabled,
false);
registry->RegisterListPref(prefs::kBraveVPNWidgetUsageWeeklyStorage);
}
@@ -244,12 +246,15 @@ std::string GetBraveVPNEntryName(version_info::Channel channel) {
}
std::string GetManageUrl(const std::string& env) {
if (env == skus::kEnvProduction)
if (env == skus::kEnvProduction) {
return brave_vpn::kManageUrlProd;
if (env == skus::kEnvStaging)
}
if (env == skus::kEnvStaging) {
return brave_vpn::kManageUrlStaging;
if (env == skus::kEnvDevelopment)
}
if (env == skus::kEnvDevelopment) {
return brave_vpn::kManageUrlDev;
}
NOTREACHED() << "All env handled above.";
}
@@ -300,29 +305,34 @@ void MigrateLocalStatePrefs(PrefService* local_prefs) {
bool HasValidSubscriberCredential(PrefService* local_prefs) {
const base::Value::Dict& sub_cred_dict =
local_prefs->GetDict(prefs::kBraveVPNSubscriberCredential);
if (sub_cred_dict.empty())
if (sub_cred_dict.empty()) {
return false;
}
const std::string* cred = sub_cred_dict.FindString(kSubscriberCredentialKey);
const base::Value* expiration_time_value =
sub_cred_dict.Find(kSubscriberCredentialExpirationKey);
if (!cred || !expiration_time_value)
if (!cred || !expiration_time_value) {
return false;
}
if (cred->empty())
if (cred->empty()) {
return false;
}
auto expiration_time = base::ValueToTime(expiration_time_value);
if (!expiration_time || expiration_time < base::Time::Now())
if (!expiration_time || expiration_time < base::Time::Now()) {
return false;
}
return true;
}
std::string GetSubscriberCredential(PrefService* local_prefs) {
if (!HasValidSubscriberCredential(local_prefs))
if (!HasValidSubscriberCredential(local_prefs)) {
return "";
}
const base::Value::Dict& sub_cred_dict =
local_prefs->GetDict(prefs::kBraveVPNSubscriberCredential);
const std::string* cred = sub_cred_dict.FindString(kSubscriberCredentialKey);
+3
View File
@@ -54,6 +54,9 @@ inline constexpr char kBraveVPNOnDemandEnabled[] =
"brave.brave_vpn.on_demand_enabled";
#endif
inline constexpr char kBraveVPNSmartProxyRoutingEnabled[] =
"brave.brave_vpn.smart_proxy_routing_enabled";
inline constexpr char kBraveVPNWireguardProfileCredentials[] =
"brave.brave_vpn.wireguard.profile_credentials";
inline constexpr char kBraveVPNEnvironment[] = "brave.brave_vpn.env";