summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2019-07-26 13:59:15 +0100
committerEmīls Piņķis <emils@mullvad.net>2019-07-30 18:19:24 +0100
commit60f4c7d207a82a2ca192a92ce7e6bb539e1b955e (patch)
tree87f5b9af2795427deb3d6de7de6994b2cdd2c5e3 /gui/src
parent5eb694a0468d7bcf199c58cec4b0b17529558339 (diff)
downloadmullvadvpn-60f4c7d207a82a2ca192a92ce7e6bb539e1b955e.tar.xz
mullvadvpn-60f4c7d207a82a2ca192a92ce7e6bb539e1b955e.zip
Allow setting TunnelProtocol constraint from GUI
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/app.tsx28
-rw-r--r--gui/src/renderer/components/AdvancedSettings.tsx140
-rw-r--r--gui/src/renderer/components/AdvancedSettingsStyles.tsx3
-rw-r--r--gui/src/renderer/components/WireguardKeys.tsx2
-rw-r--r--gui/src/renderer/components/WireguardKeysStyles.tsx4
-rw-r--r--gui/src/renderer/containers/AdvancedSettingsPage.tsx60
-rw-r--r--gui/src/renderer/lib/relay-settings-builder.ts70
-rw-r--r--gui/src/renderer/redux/settings/reducers.ts16
8 files changed, 258 insertions, 65 deletions
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index d77cf65e89..f4a3e052dc 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -380,27 +380,19 @@ export default class AppRenderer {
const location = normal.location;
const relayLocation = location === 'any' ? 'any' : location.only;
- if (tunnelProtocol === 'any' || tunnelProtocol.only === 'openvpn') {
- const { port, protocol } = normal.openvpnConstraints;
- actions.settings.updateRelay({
- normal: {
- location: relayLocation,
+ const { port, protocol } = normal.openvpnConstraints;
+ const wireguardPort = normal.wireguardConstraints.port;
+ actions.settings.updateRelay({
+ normal: {
+ location: relayLocation,
+ openvpn: {
port: port === 'any' ? port : port.only,
protocol: protocol === 'any' ? protocol : protocol.only,
- tunnelProtocol: liftConstraint(tunnelProtocol),
- },
- });
- } else {
- const { port } = normal.wireguardConstraints;
- actions.settings.updateRelay({
- normal: {
- tunnelProtocol: liftConstraint(tunnelProtocol),
- location: relayLocation,
- port: port === 'any' ? port : port.only,
- protocol: 'udp',
},
- });
- }
+ wireguard: { port: wireguardPort === 'any' ? wireguardPort : wireguardPort.only },
+ tunnelProtocol: liftConstraint(tunnelProtocol),
+ },
+ });
} else if ('customTunnelEndpoint' in relaySettings) {
const customTunnelEndpoint = relaySettings.customTunnelEndpoint;
const config = customTunnelEndpoint.config;
diff --git a/gui/src/renderer/components/AdvancedSettings.tsx b/gui/src/renderer/components/AdvancedSettings.tsx
index 1805e07bae..f85ae547aa 100644
--- a/gui/src/renderer/components/AdvancedSettings.tsx
+++ b/gui/src/renderer/components/AdvancedSettings.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import { Component, View } from 'reactxp';
import { sprintf } from 'sprintf-js';
import { colors } from '../../config.json';
-import { BridgeState, RelayProtocol } from '../../shared/daemon-rpc-types';
+import { BridgeState, RelayProtocol, TunnelProtocol } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
import styles from './AdvancedSettingsStyles';
import * as Cell from './Cell';
@@ -20,10 +20,12 @@ const MIN_MSSFIX_VALUE = 1000;
const MAX_MSSFIX_VALUE = 1450;
const UDP_PORTS = [1194, 1195, 1196, 1197, 1300, 1301, 1302];
const TCP_PORTS = [80, 443];
+const WIREUGARD_UDP_PORTS = [53];
type OptionalPort = number | undefined;
type OptionalRelayProtocol = RelayProtocol | undefined;
+type OptionalTunnelProtocol = TunnelProtocol | undefined;
function mapPortToSelectorItem(value: number): ISelectorItem<number> {
return { label: value.toString(), value };
@@ -32,16 +34,22 @@ function mapPortToSelectorItem(value: number): ISelectorItem<number> {
interface IProps {
enableIpv6: boolean;
blockWhenDisconnected: boolean;
- protocol?: RelayProtocol;
+ tunnelProtocol?: TunnelProtocol;
+ openvpn: {
+ protocol?: RelayProtocol;
+ port?: number;
+ };
+ wireguard: { port?: number };
mssfix?: number;
- port?: number;
bridgeState: BridgeState;
enableWireguardKeysPage: boolean;
setBridgeState: (value: BridgeState) => void;
setEnableIpv6: (value: boolean) => void;
setBlockWhenDisconnected: (value: boolean) => void;
+ setTunnelProtocol: (value: OptionalTunnelProtocol) => void;
setOpenVpnMssfix: (value: number | undefined) => void;
- setRelayProtocolAndPort: (protocol?: RelayProtocol, port?: number) => void;
+ setOpenVpnRelayProtocolAndPort: (protocol?: RelayProtocol, port?: number) => void;
+ setWireguardRelayPort: (port?: number) => void;
onViewWireguardKeys: () => void;
onClose: () => void;
}
@@ -56,6 +64,8 @@ export default class AdvancedSettings extends Component<IProps, IState> {
private portItems: { [key in RelayProtocol]: Array<ISelectorItem<OptionalPort>> };
private protocolItems: Array<ISelectorItem<OptionalRelayProtocol>>;
private bridgeStateItems: Array<ISelectorItem<BridgeState>>;
+ private tunnelProtocolItems: Array<ISelectorItem<OptionalTunnelProtocol>>;
+ private wireguardPortItems: Array<ISelectorItem<OptionalPort>>;
constructor(props: IProps) {
super(props);
@@ -70,6 +80,10 @@ export default class AdvancedSettings extends Component<IProps, IState> {
tcp: [automaticPort].concat(TCP_PORTS.map(mapPortToSelectorItem)),
};
+ this.wireguardPortItems = [automaticPort].concat(
+ WIREUGARD_UDP_PORTS.map(mapPortToSelectorItem),
+ );
+
this.protocolItems = [
{
label: messages.pgettext('advanced-settings-view', 'Automatic'),
@@ -85,6 +99,25 @@ export default class AdvancedSettings extends Component<IProps, IState> {
},
];
+ this.tunnelProtocolItems = [
+ {
+ label: messages.pgettext('advanced-settings-view', 'Automatic'),
+ value: undefined,
+ },
+ {
+ label: messages.pgettext('advanced-settings-view', 'OpenVPN'),
+ value: 'openvpn',
+ },
+ {
+ label: messages.pgettext('advanced-settings-view', 'WireGuard'),
+ value: 'wireguard',
+ },
+ ];
+
+ this.wireguardPortItems = [automaticPort].concat(
+ WIREUGARD_UDP_PORTS.map(mapPortToSelectorItem),
+ );
+
this.bridgeStateItems = [
{
label: messages.pgettext('advanced-settings-view', 'Automatic'),
@@ -186,33 +219,68 @@ export default class AdvancedSettings extends Component<IProps, IState> {
undefined
)}
- <View style={styles.advanced_settings__content}>
- <Selector
- title={messages.pgettext('advanced-settings-view', 'Network protocols')}
- values={this.protocolItems}
- value={this.props.protocol}
- onSelect={this.onSelectProtocol}
- />
+ {process.platform !== 'win32' ? (
+ <View style={styles.advanced_settings__content}>
+ <Selector
+ title={messages.pgettext('advanced-settings-view', 'Tunnel protocols')}
+ values={this.tunnelProtocolItems}
+ value={this.props.tunnelProtocol}
+ onSelect={this.onSelectTunnelProtocol}
+ />
+ </View>
+ ) : (
+ undefined
+ )}
- {this.props.protocol ? (
+ {this.props.tunnelProtocol === 'openvpn' ||
+ this.props.tunnelProtocol === undefined ? (
+ <View style={styles.advanced_settings__content}>
<Selector
- title={sprintf(
- // TRANSLATORS: The title for the port selector section.
- // TRANSLATORS: Available placeholders:
- // TRANSLATORS: %(portType)s - a selected protocol (either TCP or UDP)
- messages.pgettext('advanced-settings-view', '%(portType)s port'),
- {
- portType: this.props.protocol.toUpperCase(),
- },
+ title={messages.pgettext(
+ 'advanced-settings-view',
+ 'OpenVPN transport protocols',
)}
- values={this.portItems[this.props.protocol]}
- value={this.props.port}
- onSelect={this.onSelectPort}
+ values={this.protocolItems}
+ value={this.props.openvpn.protocol}
+ onSelect={this.onSelectOpenvpnProtocol}
/>
- ) : (
- undefined
- )}
- </View>
+
+ {this.props.openvpn.protocol ? (
+ <Selector
+ title={sprintf(
+ // TRANSLATORS: The title for the port selector section.
+ // TRANSLATORS: Available placeholders:
+ // TRANSLATORS: %(portType)s - a selected protocol (either TCP or UDP)
+ messages.pgettext('advanced-settings-view', '%(portType)s port'),
+ {
+ portType: this.props.openvpn.protocol.toUpperCase(),
+ },
+ )}
+ values={this.portItems[this.props.openvpn.protocol]}
+ value={this.props.openvpn.port}
+ onSelect={this.onSelectOpenVpnPort}
+ />
+ ) : (
+ undefined
+ )}
+ </View>
+ ) : (
+ undefined
+ )}
+
+ {this.props.tunnelProtocol === 'wireguard' ? (
+ <View style={styles.advanced_settings__content}>
+ <Selector
+ // TRANSLATORS: The title for the shadowsocks bridge selector section.
+ title={messages.pgettext('advanced-settings-view', 'WireGuard port')}
+ values={this.wireguardPortItems}
+ value={this.props.wireguard.port}
+ onSelect={this.onSelectWireguardPort}
+ />
+ </View>
+ ) : (
+ undefined
+ )}
<Selector
title={
@@ -270,7 +338,7 @@ export default class AdvancedSettings extends Component<IProps, IState> {
private wireguardKeysButton() {
if (this.props.enableWireguardKeysPage) {
return (
- <View>
+ <View style={styles.advanced_settings__wgkeys_cell}>
<Cell.CellButton onPress={this.props.onViewWireguardKeys}>
<Cell.Label>{messages.pgettext('advanced-settings-view', 'WireGuard keys')}</Cell.Label>
<Cell.Icon height={12} width={7} source="icon-chevron" />
@@ -282,12 +350,20 @@ export default class AdvancedSettings extends Component<IProps, IState> {
}
}
- private onSelectProtocol = (protocol?: RelayProtocol) => {
- this.props.setRelayProtocolAndPort(protocol);
+ private onSelectTunnelProtocol = (protocol?: TunnelProtocol) => {
+ this.props.setTunnelProtocol(protocol);
+ };
+
+ private onSelectOpenvpnProtocol = (protocol?: RelayProtocol) => {
+ this.props.setOpenVpnRelayProtocolAndPort(protocol);
+ };
+
+ private onSelectOpenVpnPort = (port?: number) => {
+ this.props.setOpenVpnRelayProtocolAndPort(this.props.openvpn.protocol, port);
};
- private onSelectPort = (port?: number) => {
- this.props.setRelayProtocolAndPort(this.props.protocol, port);
+ private onSelectWireguardPort = (port?: number) => {
+ this.props.setWireguardRelayPort(port);
};
private onSelectBridgeState = (bridgeState: BridgeState) => {
diff --git a/gui/src/renderer/components/AdvancedSettingsStyles.tsx b/gui/src/renderer/components/AdvancedSettingsStyles.tsx
index c8eafe052f..b5fbf82c06 100644
--- a/gui/src/renderer/components/AdvancedSettingsStyles.tsx
+++ b/gui/src/renderer/components/AdvancedSettingsStyles.tsx
@@ -19,6 +19,9 @@ export default {
advanced_settings__selector_section: Styles.createViewStyle({
marginBottom: 24,
}),
+ advanced_settings__wgkeys_cell: Styles.createViewStyle({
+ marginBottom: 24,
+ }),
advanced_settings__cell_hover: Styles.createButtonStyle({
backgroundColor: colors.blue80,
}),
diff --git a/gui/src/renderer/components/WireguardKeys.tsx b/gui/src/renderer/components/WireguardKeys.tsx
index dadaca4b51..ce28c28454 100644
--- a/gui/src/renderer/components/WireguardKeys.tsx
+++ b/gui/src/renderer/components/WireguardKeys.tsx
@@ -24,7 +24,7 @@ export default class WireguardKeys extends Component<IProps> {
return (
<Layout>
<Container>
- <View>
+ <View style={styles.wgkeys}>
<NavigationContainer>
<NavigationBar>
<BackBarItem action={this.props.onClose}>
diff --git a/gui/src/renderer/components/WireguardKeysStyles.tsx b/gui/src/renderer/components/WireguardKeysStyles.tsx
index 8f94bdcca6..2172b79dae 100644
--- a/gui/src/renderer/components/WireguardKeysStyles.tsx
+++ b/gui/src/renderer/components/WireguardKeysStyles.tsx
@@ -2,6 +2,10 @@ import { Styles } from 'reactxp';
import { colors } from '../../config.json';
export default {
+ wgkeys: Styles.createViewStyle({
+ backgroundColor: colors.darkBlue,
+ flex: 1,
+ }),
wgkeys__container: Styles.createViewStyle({
flexDirection: 'column',
flex: 1,
diff --git a/gui/src/renderer/containers/AdvancedSettingsPage.tsx b/gui/src/renderer/containers/AdvancedSettingsPage.tsx
index 4dcb91b6b5..9440a0077b 100644
--- a/gui/src/renderer/containers/AdvancedSettingsPage.tsx
+++ b/gui/src/renderer/containers/AdvancedSettingsPage.tsx
@@ -2,7 +2,7 @@ import { goBack, push } from 'connected-react-router';
import log from 'electron-log';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
-import { BridgeState, RelayProtocol } from '../../shared/daemon-rpc-types';
+import { BridgeState, RelayProtocol, TunnelProtocol } from '../../shared/daemon-rpc-types';
import AdvancedSettings from '../components/AdvancedSettings';
import RelaySettingsBuilder from '../lib/relay-settings-builder';
@@ -26,14 +26,26 @@ const mapStateToProps = (state: IReduxState) => {
const mapRelaySettingsToProtocolAndPort = (relaySettings: RelaySettingsRedux) => {
if ('normal' in relaySettings) {
- const { protocol, port } = relaySettings.normal;
+ const { tunnelProtocol, openvpn, wireguard } = relaySettings.normal;
return {
- protocol: protocol === 'any' ? undefined : protocol,
- port: port === 'any' ? undefined : port,
+ openvpn: {
+ protocol: openvpn.protocol === 'any' ? undefined : openvpn.protocol,
+ port: openvpn.port === 'any' ? undefined : openvpn.port,
+ },
+ wireguard: { port: wireguard.port === 'any' ? undefined : wireguard.port },
+ tunnelProtocol: tunnelProtocol === 'any' ? undefined : tunnelProtocol,
};
+ // since the GUI doesn't display custom settings, just display the default ones.
+ // If the user sets any settings, then those will be applied.
} else if ('customTunnelEndpoint' in relaySettings) {
- const { protocol, port } = relaySettings.customTunnelEndpoint;
- return { protocol, port };
+ return {
+ openvpn: {
+ protocol: undefined,
+ port: undefined,
+ },
+ wireguard: { port: undefined },
+ tunnelProtocol: undefined,
+ };
} else {
throw new Error('Unknown type of relay settings.');
}
@@ -45,7 +57,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: ISharedRouteProps) =
onClose: () => {
history.goBack();
},
- setRelayProtocolAndPort: async (protocol?: RelayProtocol, port?: number) => {
+ setOpenVpnRelayProtocolAndPort: async (protocol?: RelayProtocol, port?: number) => {
const relayUpdate = RelaySettingsBuilder.normal()
.tunnel.openvpn((openvpn) => {
if (protocol) {
@@ -69,6 +81,40 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: ISharedRouteProps) =
}
},
+ setWireguardRelayPort: async (port?: number) => {
+ const relayUpdate = RelaySettingsBuilder.normal()
+ .tunnel.wireguard((wireguard) => {
+ if (port) {
+ wireguard.port.exact(port);
+ } else {
+ wireguard.port.any();
+ }
+ })
+ .build();
+ try {
+ await props.app.updateRelaySettings(relayUpdate);
+ } catch (e) {
+ log.error('Failed to update relay settings', e.message);
+ }
+ },
+
+ setTunnelProtocol: async (tunnelProtocol: TunnelProtocol | undefined) => {
+ const relayUpdate = RelaySettingsBuilder.normal()
+ .tunnel.tunnelProtocol((config) => {
+ if (tunnelProtocol) {
+ config.tunnelProtocol.exact(tunnelProtocol);
+ } else {
+ config.tunnelProtocol.any();
+ }
+ })
+ .build();
+ try {
+ await props.app.updateRelaySettings(relayUpdate);
+ } catch (e) {
+ log.error('Failed to update tunnel protocol constraints', e.message);
+ }
+ },
+
setEnableIpv6: async (enableIpv6: boolean) => {
try {
await props.app.setEnableIpv6(enableIpv6);
diff --git a/gui/src/renderer/lib/relay-settings-builder.ts b/gui/src/renderer/lib/relay-settings-builder.ts
index bbf85b1fed..08ecef720e 100644
--- a/gui/src/renderer/lib/relay-settings-builder.ts
+++ b/gui/src/renderer/lib/relay-settings-builder.ts
@@ -1,9 +1,11 @@
import {
IOpenVpnConstraints,
+ IWireguardConstraints,
RelayLocation,
RelayProtocol,
RelaySettingsNormalUpdate,
RelaySettingsUpdate,
+ TunnelProtocol,
} from '../../shared/daemon-rpc-types';
interface ILocationBuilder<Self> {
@@ -24,11 +26,24 @@ interface IOpenVPNConfigurator {
protocol: IExactOrAny<RelayProtocol, IOpenVPNConfigurator>;
}
+interface IWireguardConfigurator {
+ port: IExactOrAny<number, IWireguardConfigurator>;
+}
+
+interface ITunnelProtocolConfigurator {
+ tunnelProtocol: IExactOrAny<TunnelProtocol, ITunnelProtocolConfigurator>;
+}
+
interface ITunnelBuilder {
openvpn(
configurator: (openVpnConfigurator: IOpenVPNConfigurator) => void,
): NormalRelaySettingsBuilder;
- any(): NormalRelaySettingsBuilder;
+ wireguard(
+ configurator: (wireguardConfigurator: IWireguardConfigurator) => void,
+ ): NormalRelaySettingsBuilder;
+ tunnelProtocol(
+ configurator: (tunnelProtocolConfigurator: ITunnelProtocolConfigurator) => void,
+ ): NormalRelaySettingsBuilder;
}
class NormalRelaySettingsBuilder {
@@ -91,6 +106,22 @@ class NormalRelaySettingsBuilder {
}
};
+ const updateWireguard = (next: Partial<IWireguardConstraints>) => {
+ if (this.payload.wireguardConstraints === undefined) {
+ this.payload.wireguardConstraints = next;
+ } else {
+ const prev = this.payload.wireguardConstraints;
+ this.payload.wireguardConstraints = {
+ ...prev,
+ ...next,
+ };
+ }
+ };
+
+ const updateTunnelProtocol = (next: { only: TunnelProtocol } | 'any' | undefined) => {
+ this.payload.tunnelProtocol = next;
+ };
+
return {
openvpn: (configurator: (configurator: IOpenVPNConfigurator) => void) => {
const openvpnBuilder: IOpenVPNConfigurator = {
@@ -120,8 +151,41 @@ class NormalRelaySettingsBuilder {
return this;
},
- any: () => {
- this.payload.tunnelProtocol = 'any';
+
+ wireguard: (configurator: (configurator: IWireguardConfigurator) => void) => {
+ const wireguardBuilder: IWireguardConfigurator = {
+ get port() {
+ const apply = (port: 'any' | { only: number }) => {
+ updateWireguard({ port });
+ return this;
+ };
+ return {
+ exact: (value: number) => apply({ only: value }),
+ any: () => apply('any'),
+ };
+ },
+ };
+ configurator(wireguardBuilder);
+ return this;
+ },
+
+ tunnelProtocol: (configurator: (configurator: ITunnelProtocolConfigurator) => void) => {
+ const tunnelProtocolBuilder = {
+ get tunnelProtocol() {
+ return {
+ exact: (value: TunnelProtocol) => {
+ updateTunnelProtocol({ only: value });
+ return this;
+ },
+ any: () => {
+ updateTunnelProtocol('any');
+ return this;
+ },
+ };
+ },
+ };
+
+ configurator(tunnelProtocolBuilder);
return this;
},
};
diff --git a/gui/src/renderer/redux/settings/reducers.ts b/gui/src/renderer/redux/settings/reducers.ts
index e41750b496..e90022062c 100644
--- a/gui/src/renderer/redux/settings/reducers.ts
+++ b/gui/src/renderer/redux/settings/reducers.ts
@@ -14,8 +14,13 @@ export type RelaySettingsRedux =
normal: {
tunnelProtocol: 'any' | TunnelProtocol;
location: 'any' | RelayLocation;
- port: 'any' | number;
- protocol: 'any' | RelayProtocol;
+ openvpn: {
+ port: 'any' | number;
+ protocol: 'any' | RelayProtocol;
+ };
+ wireguard: {
+ port: 'any' | number;
+ };
};
}
| {
@@ -111,8 +116,11 @@ const initialState: ISettingsReduxState = {
normal: {
location: 'any',
tunnelProtocol: 'any',
- port: 'any',
- protocol: 'any',
+ wireguard: { port: 'any' },
+ openvpn: {
+ port: 'any',
+ protocol: 'any',
+ },
},
},
relayLocations: [],