diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2024-04-11 18:11:33 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2024-04-11 18:11:33 +0200 |
| commit | 9aaebecc3c6d1838722a66875b5a330ca7967020 (patch) | |
| tree | c877bcc16c9eb3e325aecdd5f2861b9e6f5824a5 /gui/src/main | |
| parent | d2e198cd8ce15225d4329cbb61f4561e293ea239 (diff) | |
| parent | 36322705705857c549fa90616884bc64740cbbef (diff) | |
| download | mullvadvpn-9aaebecc3c6d1838722a66875b5a330ca7967020.tar.xz mullvadvpn-9aaebecc3c6d1838722a66875b5a330ca7967020.zip | |
Merge branch 'add-custom-bridge-to-gui-des-431'
Diffstat (limited to 'gui/src/main')
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 187 | ||||
| -rw-r--r-- | gui/src/main/settings.ts | 13 |
2 files changed, 73 insertions, 127 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 703ad027cc..531ec80ced 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -17,6 +17,7 @@ import { ApiAccessMethodSettings, AuthFailedError, BridgeSettings, + BridgesMethod, BridgeState, BridgeType, ConnectionConfig, @@ -27,6 +28,7 @@ import { DaemonEvent, DeviceEvent, DeviceState, + DirectMethod, EndpointObfuscationType, ErrorState, ErrorStateCause, @@ -82,7 +84,6 @@ const NETWORK_CALL_TIMEOUT = 10000; const CHANNEL_STATE_TIMEOUT = 1000 * 60 * 60; const noConnectionError = new Error('No connection established to daemon'); -const configNotSupported = new Error('Setting custom settings is not supported'); const invalidErrorStateCause = new Error( 'VPN_PERMISSION_DENIED is not a valid error state cause on desktop', ); @@ -347,51 +348,17 @@ export class DaemonRpc { public async setBridgeSettings(bridgeSettings: BridgeSettings): Promise<void> { const grpcBridgeSettings = new grpcTypes.BridgeSettings(); - if (bridgeSettings.type === 'custom') { - throw configNotSupported; - } - - grpcBridgeSettings.setBridgeType(grpcTypes.BridgeSettings.BridgeType.NORMAL); + grpcBridgeSettings.setBridgeType( + bridgeSettings.type === 'normal' + ? grpcTypes.BridgeSettings.BridgeType.NORMAL + : grpcTypes.BridgeSettings.BridgeType.CUSTOM, + ); const normalSettings = convertToNormalBridgeSettings(bridgeSettings.normal); grpcBridgeSettings.setNormal(normalSettings); if (bridgeSettings.custom) { - const customProxy = new grpcTypes.CustomProxy(); - - const customSettings = bridgeSettings.custom; - - if ('local' in customSettings) { - const local = customSettings.local; - const socks5Local = new grpcTypes.Socks5Local(); - socks5Local.setLocalPort(local.localPort); - socks5Local.setRemoteIp(local.remoteIp); - socks5Local.setRemotePort(local.remotePort); - customProxy.setSocks5local(socks5Local); - } - if ('remote' in customSettings) { - const remote = customSettings.remote; - const socks5Remote = new grpcTypes.Socks5Remote(); - if (remote.auth) { - const auth = new grpcTypes.SocksAuth(); - auth.setUsername(remote.auth.username); - auth.setPassword(remote.auth.password); - socks5Remote.setAuth(auth); - } - socks5Remote.setIp(remote.ip); - socks5Remote.setPort(remote.port); - customProxy.setSocks5remote(socks5Remote); - } - if ('shadowsocks' in customSettings) { - const shadowsocks = customSettings.shadowsocks; - const shadowOut = new grpcTypes.Shadowsocks(); - shadowOut.setCipher(shadowsocks.cipher); - shadowOut.setIp(shadowsocks.ip); - shadowOut.setPort(shadowsocks.port); - shadowOut.setPassword(shadowsocks.password); - customProxy.setShadowsocks(shadowOut); - } - + const customProxy = convertToCustomProxy(bridgeSettings.custom); grpcBridgeSettings.setCustom(customProxy); } @@ -1276,41 +1243,8 @@ function convertFromBridgeSettings(bridgeSettings: grpcTypes.BridgeSettings): Br ownership, }; - let custom = undefined; - - if (bridgeSettingsObject.custom) { - const localSettings = bridgeSettingsObject.custom.socks5local; - if (localSettings) { - custom = { - local: { - localPort: localSettings.localPort, - remoteIp: localSettings.remoteIp, - remotePort: localSettings.remotePort, - }, - }; - } - const remoteSettings = bridgeSettingsObject.custom.socks5remote; - if (remoteSettings) { - custom = { - remote: { - ip: remoteSettings.ip, - port: remoteSettings.port, - auth: remoteSettings.auth && { ...remoteSettings.auth }, - }, - }; - } - const shadowsocksSettings = bridgeSettingsObject.custom.shadowsocks; - if (shadowsocksSettings) { - custom = { - shadowsocks: { - ip: shadowsocksSettings.ip, - port: shadowsocksSettings.port, - password: shadowsocksSettings.password, - cipher: shadowsocksSettings.cipher, - }, - }; - } - } + const grpcCustom = bridgeSettings.getCustom(); + const custom = grpcCustom ? convertFromCustomProxy(grpcCustom) : undefined; return { type, normal, custom }; } @@ -1910,15 +1844,16 @@ function convertFromApiAccessMethodSettings( ): ApiAccessMethodSettings { const direct = convertFromApiAccessMethodSetting( ensureExists(accessMethods.getDirect(), "no 'Direct' access method was found"), - ); + ) as AccessMethodSetting<DirectMethod>; const bridges = convertFromApiAccessMethodSetting( ensureExists(accessMethods.getMullvadBridges(), "no 'Mullvad Bridges' access method was found"), - ); - const custom = - accessMethods - .getCustomList() - .filter((setting) => setting.hasId() && setting.hasAccessMethod()) - .map(convertFromApiAccessMethodSetting) ?? []; + ) as AccessMethodSetting<BridgesMethod>; + const custom = accessMethods + .getCustomList() + .filter((setting) => setting.hasId() && setting.hasAccessMethod()) + .map(convertFromApiAccessMethodSetting) + // The last filter helps TypeScript infer the custom proxy type. + .filter(isCustomProxy); return { direct, @@ -1927,6 +1862,12 @@ function convertFromApiAccessMethodSettings( }; } +function isCustomProxy( + accessMethod: AccessMethodSetting, +): accessMethod is AccessMethodSetting<CustomProxy> { + return accessMethod.type !== 'direct' && accessMethod.type !== 'bridges'; +} + function convertFromApiAccessMethodSetting( setting: grpcTypes.AccessMethodSetting, ): AccessMethodSetting { @@ -1948,52 +1889,52 @@ function convertFromAccessMethod(method: grpcTypes.AccessMethod): AccessMethod { case grpcTypes.AccessMethod.AccessMethodCase.BRIDGES: return { type: 'bridges' }; case grpcTypes.AccessMethod.AccessMethodCase.CUSTOM: { - const proxy = method.getCustom()!; - switch (proxy.getProxyMethodCase()) { - case grpcTypes.CustomProxy.ProxyMethodCase.SOCKS5LOCAL: { - const socks5Local = proxy.getSocks5local()!; - return { - type: 'socks5-local', - remoteIp: socks5Local.getRemoteIp(), - remotePort: socks5Local.getRemotePort(), - remoteTransportProtocol: convertFromTransportProtocol( - socks5Local.getRemoteTransportProtocol(), - ), - localPort: socks5Local.getLocalPort(), - }; - } - case grpcTypes.CustomProxy.ProxyMethodCase.SOCKS5REMOTE: { - const socks5Remote = proxy.getSocks5remote()!; - const auth = socks5Remote.getAuth(); - return { - type: 'socks5-remote', - ip: socks5Remote.getIp(), - port: socks5Remote.getPort(), - authentication: auth === undefined ? undefined : convertFromSocksAuth(auth), - }; - } - case grpcTypes.CustomProxy.ProxyMethodCase.SHADOWSOCKS: { - const shadowsocks = proxy.getShadowsocks()!; - return { - type: 'shadowsocks', - ip: shadowsocks.getIp(), - port: shadowsocks.getPort(), - password: shadowsocks.getPassword(), - cipher: shadowsocks.getCipher(), - }; - } - case grpcTypes.CustomProxy.ProxyMethodCase.PROXY_METHOD_NOT_SET: - throw new Error('Custom method not set, which should always be set'); - } - // This break is required to prevent eslint from complainting about fallthrough, even though - // all cases are covered above. - break; + return convertFromCustomProxy(method.getCustom()!); } case grpcTypes.AccessMethod.AccessMethodCase.ACCESS_METHOD_NOT_SET: throw new Error('Access method not set, which should always be set'); } } +function convertFromCustomProxy(proxy: grpcTypes.CustomProxy): CustomProxy { + switch (proxy.getProxyMethodCase()) { + case grpcTypes.CustomProxy.ProxyMethodCase.SOCKS5LOCAL: { + const socks5Local = proxy.getSocks5local()!; + return { + type: 'socks5-local', + remoteIp: socks5Local.getRemoteIp(), + remotePort: socks5Local.getRemotePort(), + remoteTransportProtocol: convertFromTransportProtocol( + socks5Local.getRemoteTransportProtocol(), + ), + localPort: socks5Local.getLocalPort(), + }; + } + case grpcTypes.CustomProxy.ProxyMethodCase.SOCKS5REMOTE: { + const socks5Remote = proxy.getSocks5remote()!; + const auth = socks5Remote.getAuth(); + return { + type: 'socks5-remote', + ip: socks5Remote.getIp(), + port: socks5Remote.getPort(), + authentication: auth === undefined ? undefined : convertFromSocksAuth(auth), + }; + } + case grpcTypes.CustomProxy.ProxyMethodCase.SHADOWSOCKS: { + const shadowsocks = proxy.getShadowsocks()!; + return { + type: 'shadowsocks', + ip: shadowsocks.getIp(), + port: shadowsocks.getPort(), + password: shadowsocks.getPassword(), + cipher: shadowsocks.getCipher(), + }; + } + case grpcTypes.CustomProxy.ProxyMethodCase.PROXY_METHOD_NOT_SET: + throw new Error('Custom method not set, which should always be set'); + } +} + function convertFromSocksAuth(auth: grpcTypes.SocksAuth): SocksAuth { return { username: auth.getUsername(), diff --git a/gui/src/main/settings.ts b/gui/src/main/settings.ts index 16996eebd9..8bf60d9108 100644 --- a/gui/src/main/settings.ts +++ b/gui/src/main/settings.ts @@ -1,6 +1,5 @@ import fs from 'fs/promises'; -import BridgeSettingsBuilder from '../shared/bridge-settings-builder'; import { ISettings } from '../shared/daemon-rpc-types'; import { ICurrentAppVersionInfo } from '../shared/ipc-types'; import log from '../shared/logging'; @@ -44,9 +43,15 @@ export default class Settings implements Readonly<ISettings> { IpcMainEventChannel.settings.handleSetBridgeState(async (bridgeState) => { await this.daemonRpc.setBridgeState(bridgeState); - // Reset bridge constraints to `any` when the state is set to auto or off - if (bridgeState === 'auto' || bridgeState === 'off') { - await this.daemonRpc.setBridgeSettings(new BridgeSettingsBuilder().location.any().build()); + // Reset bridge constraints to `any` when the state is set to auto or off if not custom + if ( + (bridgeState === 'auto' || bridgeState === 'off') && + this.bridgeSettings.type === 'normal' + ) { + await this.daemonRpc.setBridgeSettings({ + ...this.bridgeSettings, + normal: { ...this.bridgeSettings.normal, location: 'any' }, + }); } }); IpcMainEventChannel.settings.handleSetOpenVpnMssfix((mssfix?: number) => |
