summaryrefslogtreecommitdiffhomepage
path: root/gui
diff options
context:
space:
mode:
authorJonathan <jonathan@mullvad.net>2024-01-03 14:39:12 +0100
committerJonathan <jonathan@mullvad.net>2024-01-03 14:39:12 +0100
commit711d4e439866ab12e03d33d5efae3c2355c0c229 (patch)
tree80d3a23c1a96bd3d80e05ac66b530e39c252d48a /gui
parentc510df96772b1e4ab7998e739ced42806c78e931 (diff)
parent4fdc34acbba60d5092e45ce3e513d30ec996c317 (diff)
downloadmullvadvpn-711d4e439866ab12e03d33d5efae3c2355c0c229.tar.xz
mullvadvpn-711d4e439866ab12e03d33d5efae3c2355c0c229.zip
Merge branch 'implement-custom-openvpn-socks5-bridge-client-in-daemon-des-430'
Diffstat (limited to 'gui')
-rw-r--r--gui/src/main/daemon-rpc.ts138
-rw-r--r--gui/src/main/default-settings.ts2
-rw-r--r--gui/src/renderer/app.tsx18
-rw-r--r--gui/src/renderer/components/select-location/select-location-hooks.ts14
-rw-r--r--gui/src/renderer/lib/utilityHooks.ts2
-rw-r--r--gui/src/renderer/redux/settings/reducers.ts15
-rw-r--r--gui/src/shared/bridge-settings-builder.ts2
-rw-r--r--gui/src/shared/daemon-rpc-types.ts24
8 files changed, 144 insertions, 71 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index ad7b60dec2..d5d29ad709 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -15,6 +15,7 @@ import {
AuthFailedError,
BridgeSettings,
BridgeState,
+ BridgeType,
ConnectionConfig,
Constraint,
CustomListError,
@@ -51,7 +52,6 @@ import {
ObfuscationSettings,
ObfuscationType,
Ownership,
- ProxySettings,
ProxyType,
RelayEndpointType,
RelayLocation,
@@ -341,13 +341,52 @@ export class DaemonRpc {
public async setBridgeSettings(bridgeSettings: BridgeSettings): Promise<void> {
const grpcBridgeSettings = new grpcTypes.BridgeSettings();
- if ('normal' in bridgeSettings) {
- const normalSettings = convertToNormalBridgeSettings(bridgeSettings.normal);
- grpcBridgeSettings.setNormal(normalSettings);
+ if (bridgeSettings.type === 'custom') {
+ throw configNotSupported;
}
- if ('custom' in bridgeSettings) {
- throw configNotSupported;
+ grpcBridgeSettings.setBridgeType(grpcTypes.BridgeSettings.BridgeType.NORMAL);
+
+ 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);
+ }
+
+ grpcBridgeSettings.setCustom(customProxy);
}
await this.call<grpcTypes.BridgeSettings, Empty>(
@@ -1140,49 +1179,64 @@ function convertFromRelaySettings(
function convertFromBridgeSettings(bridgeSettings: grpcTypes.BridgeSettings): BridgeSettings {
const bridgeSettingsObject = bridgeSettings.toObject();
+
+ const detailsMap: Record<grpcTypes.BridgeSettings.BridgeType, BridgeType> = {
+ [grpcTypes.BridgeSettings.BridgeType.NORMAL]: 'normal',
+ [grpcTypes.BridgeSettings.BridgeType.CUSTOM]: 'custom',
+ };
+ const type = detailsMap[bridgeSettingsObject.bridgeType];
+
const normalSettings = bridgeSettingsObject.normal;
- if (normalSettings) {
- const locationConstraint = convertFromLocationConstraint(
- bridgeSettings.getNormal()?.getLocation(),
- );
- const location = wrapConstraint(locationConstraint);
- const providers = normalSettings.providersList;
- const ownership = convertFromOwnership(normalSettings.ownership);
- return {
- normal: {
- location,
- providers,
- ownership,
- },
- };
- }
+ const locationConstraint = convertFromLocationConstraint(
+ bridgeSettings.getNormal()?.getLocation(),
+ );
+ const location = wrapConstraint(locationConstraint);
+ const providers = normalSettings!.providersList;
+ const ownership = convertFromOwnership(normalSettings!.ownership);
- const customSettings = (settings: ProxySettings): BridgeSettings => {
- return { custom: settings };
+ const normal = {
+ location,
+ providers,
+ ownership,
};
- const localSettings = bridgeSettingsObject.local;
- if (localSettings) {
- return customSettings({
- port: localSettings.port,
- peer: localSettings.peer,
- });
- }
+ let custom = undefined;
- const remoteSettings = bridgeSettingsObject.remote;
- if (remoteSettings) {
- return customSettings({
- address: remoteSettings.address,
- auth: remoteSettings.auth && { ...remoteSettings.auth },
- });
+ 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 shadowsocksSettings = bridgeSettingsObject.shadowsocks!;
- return customSettings({
- peer: shadowsocksSettings.peer!,
- password: shadowsocksSettings.password!,
- cipher: shadowsocksSettings.cipher!,
- });
+ return { type, normal, custom };
}
function convertFromConnectionConfig(
diff --git a/gui/src/main/default-settings.ts b/gui/src/main/default-settings.ts
index 55f420b659..fea88e4c27 100644
--- a/gui/src/main/default-settings.ts
+++ b/gui/src/main/default-settings.ts
@@ -29,11 +29,13 @@ export function getDefaultSettings(): ISettings {
},
},
bridgeSettings: {
+ type: 'normal',
normal: {
location: 'any',
providers: [],
ownership: Ownership.any,
},
+ custom: undefined,
},
bridgeState: 'auto',
tunnelOptions: {
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index b5eacf17b3..3806c12413 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -624,17 +624,13 @@ export default class AppRenderer {
private setBridgeSettings(bridgeSettings: BridgeSettings) {
const actions = this.reduxActions;
- if ('normal' in bridgeSettings) {
- actions.settings.updateBridgeSettings({
- normal: {
- location: liftConstraint(bridgeSettings.normal.location),
- },
- });
- } else if ('custom' in bridgeSettings) {
- actions.settings.updateBridgeSettings({
- custom: bridgeSettings.custom,
- });
- }
+ actions.settings.updateBridgeSettings({
+ type: bridgeSettings.type,
+ normal: {
+ location: liftConstraint(bridgeSettings.normal.location),
+ },
+ custom: bridgeSettings.custom,
+ });
}
private onDaemonConnected() {
diff --git a/gui/src/renderer/components/select-location/select-location-hooks.ts b/gui/src/renderer/components/select-location/select-location-hooks.ts
index 48d81e594c..b795f4a74f 100644
--- a/gui/src/renderer/components/select-location/select-location-hooks.ts
+++ b/gui/src/renderer/components/select-location/select-location-hooks.ts
@@ -11,6 +11,7 @@ import log from '../../../shared/logging';
import { useAppContext } from '../../context';
import { useRelaySettingsModifier } from '../../lib/constraint-updater';
import { useHistory } from '../../lib/history';
+import { useSelector } from '../../redux/store';
import { LocationType, SpecialBridgeLocationType } from './select-location-types';
import { useSelectLocationContext } from './SelectLocationContainer';
@@ -88,6 +89,7 @@ function useOnSelectLocation() {
export function useOnSelectBridgeLocation() {
const { updateBridgeSettings } = useAppContext();
const { setLocationType } = useSelectLocationContext();
+ const bridgeSettings = useSelector((state) => state.settings.bridgeSettings);
const setLocation = useCallback(async (bridgeUpdate: BridgeSettings) => {
if (bridgeUpdate) {
@@ -101,10 +103,14 @@ export function useOnSelectBridgeLocation() {
}
}, []);
- const onSelectRelay = useCallback((location: RelayLocation) => {
- const bridgeUpdate = new BridgeSettingsBuilder().location.fromRaw(location).build();
- return setLocation(bridgeUpdate);
- }, []);
+ const onSelectRelay = useCallback(
+ (location: RelayLocation) => {
+ const bridgeUpdate = new BridgeSettingsBuilder().location.fromRaw(location).build();
+ bridgeUpdate.custom = bridgeSettings.custom;
+ return setLocation(bridgeUpdate);
+ },
+ [bridgeSettings],
+ );
const onSelectSpecial = useCallback((location: SpecialBridgeLocationType) => {
switch (location) {
diff --git a/gui/src/renderer/lib/utilityHooks.ts b/gui/src/renderer/lib/utilityHooks.ts
index 49f508a883..8c3925762e 100644
--- a/gui/src/renderer/lib/utilityHooks.ts
+++ b/gui/src/renderer/lib/utilityHooks.ts
@@ -67,5 +67,5 @@ export function useNormalRelaySettings() {
export function useNormalBridgeSettings() {
const bridgeSettings = useSelector((state) => state.settings.bridgeSettings);
- return 'normal' in bridgeSettings ? bridgeSettings.normal : undefined;
+ return bridgeSettings.normal;
}
diff --git a/gui/src/renderer/redux/settings/reducers.ts b/gui/src/renderer/redux/settings/reducers.ts
index b400799095..3d03093e0a 100644
--- a/gui/src/renderer/redux/settings/reducers.ts
+++ b/gui/src/renderer/redux/settings/reducers.ts
@@ -1,6 +1,7 @@
import { IWindowsApplication } from '../../../shared/application-types';
import {
BridgeState,
+ BridgeType,
CustomLists,
IDnsOptions,
IpVersion,
@@ -51,13 +52,11 @@ export type RelaySettingsRedux =
};
};
-export type BridgeSettingsRedux =
- | {
- normal: NormalBridgeSettingsRedux;
- }
- | {
- custom: ProxySettings;
- };
+export type BridgeSettingsRedux = {
+ type: BridgeType;
+ normal: NormalBridgeSettingsRedux;
+ custom?: ProxySettings;
+};
export interface IRelayLocationRelayRedux {
hostname: string;
@@ -140,9 +139,11 @@ const initialState: ISettingsReduxState = {
allowLan: false,
enableIpv6: true,
bridgeSettings: {
+ type: 'normal',
normal: {
location: 'any',
},
+ custom: undefined,
},
bridgeState: 'auto',
blockWhenDisconnected: false,
diff --git a/gui/src/shared/bridge-settings-builder.ts b/gui/src/shared/bridge-settings-builder.ts
index 858bea055d..2ee5469707 100644
--- a/gui/src/shared/bridge-settings-builder.ts
+++ b/gui/src/shared/bridge-settings-builder.ts
@@ -7,11 +7,13 @@ export default class BridgeSettingsBuilder {
public build(): BridgeSettings {
if (this.payload.location) {
return {
+ type: 'normal',
normal: {
location: this.payload.location,
providers: this.payload.providers ?? [],
ownership: this.payload.ownership ?? Ownership.any,
},
+ custom: undefined,
};
} else {
throw new Error('Unsupported configuration');
diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts
index e83f9e5afc..48a4110e13 100644
--- a/gui/src/shared/daemon-rpc-types.ts
+++ b/gui/src/shared/daemon-rpc-types.ts
@@ -345,15 +345,20 @@ export interface IDnsOptions {
};
}
-export type ProxySettings = ILocalProxySettings | IRemoteProxySettings | IShadowsocksProxySettings;
+export type ProxySettings =
+ | { local: ILocalProxySettings }
+ | { remote: IRemoteProxySettings }
+ | { shadowsocks: IShadowsocksProxySettings };
export interface ILocalProxySettings {
- port: number;
- peer: string;
+ localPort: number;
+ remoteIp: string;
+ remotePort: number;
}
export interface IRemoteProxySettings {
- address: string;
+ ip: string;
+ port: number;
auth?: IRemoteProxyAuth;
}
@@ -363,7 +368,8 @@ export interface IRemoteProxyAuth {
}
export interface IShadowsocksProxySettings {
- peer: string;
+ ip: string;
+ port: number;
password: string;
cipher: string;
}
@@ -451,7 +457,13 @@ export interface IBridgeConstraints {
ownership: Ownership;
}
-export type BridgeSettings = { normal: IBridgeConstraints } | { custom: ProxySettings };
+export type BridgeType = 'normal' | 'custom';
+
+export interface BridgeSettings {
+ type: BridgeType;
+ normal: IBridgeConstraints;
+ custom?: ProxySettings;
+}
export interface ISocketAddress {
host: string;