Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "smart routing" daita setting #6604

Merged
merged 16 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ internal fun ManagementInterface.FeatureIndicator.toDomain() =
FeatureIndicator.SERVER_IP_OVERRIDE
ManagementInterface.FeatureIndicator.CUSTOM_MTU -> FeatureIndicator.CUSTOM_MTU
ManagementInterface.FeatureIndicator.DAITA -> FeatureIndicator.DAITA
ManagementInterface.FeatureIndicator.DAITA_SMART_ROUTING,
ManagementInterface.FeatureIndicator.LOCKDOWN_MODE,
ManagementInterface.FeatureIndicator.SHADOWSOCKS,
ManagementInterface.FeatureIndicator.MULTIHOP,
Expand Down
38 changes: 32 additions & 6 deletions gui/locales/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ msgstr ""
msgid "%(amount)d more..."
msgstr ""

#. This refers to the Smart Routing setting in the VPN settings view.
#. This is displayed when both Smart Routing and DAITA features are on.
msgid "%(daita)s: Smart routing"
msgstr ""

msgid "%(duration)s was added, account paid until %(expiry)s."
msgstr ""

Expand Down Expand Up @@ -125,6 +130,9 @@ msgstr ""
msgid "Disable"
msgstr ""

msgid "Disable anyway"
msgstr ""

msgid "Disconnect"
msgstr ""

Expand Down Expand Up @@ -245,6 +253,9 @@ msgstr ""
msgid "Settings"
msgstr ""

msgid "Smart routing"
msgstr ""

msgid "System default"
msgstr ""

Expand Down Expand Up @@ -1934,6 +1945,10 @@ msgctxt "vpn-settings-view"
msgid "IPv4 is always enabled and the majority of websites and applications use this protocol. We do not recommend enabling IPv6 unless you know you need it."
msgstr ""

msgctxt "vpn-settings-view"
msgid "Is automatically enabled with %(daita)s, makes it possible to use %(daita)s with any server by using multihop. This might increase latency."
msgstr ""

msgctxt "vpn-settings-view"
msgid "It does this by allowing network communication outside the tunnel to local multicast and broadcast ranges as well as to and from these private IP ranges:"
msgstr ""
Expand Down Expand Up @@ -2065,7 +2080,7 @@ msgid "%(wireguard)s settings"
msgstr ""

msgctxt "wireguard-settings-view"
msgid "Attention: Since this increases your total network traffic, be cautious if you have a limited data plan. It can also negatively impact your network speed. Please consider this if you want to enable %(daita)s."
msgid "Hides patterns in your encrypted VPN traffic. Since this increases your total network traffic, be cautious if you have a limited data plan. It can also negatively impact your network speed and battery usage."
msgstr ""

msgctxt "wireguard-settings-view"
Expand All @@ -2080,6 +2095,15 @@ msgctxt "wireguard-settings-view"
msgid "MTU"
msgstr ""

#. Warning text in a dialog that is displayed after a setting is toggled.
msgctxt "wireguard-settings-view"
msgid "Not all our servers are %(daita)s-enabled. In order to use the internet, you might have to select a new location after disabling, or you can continue using %(daita)s with Smart routing."
msgstr ""

msgctxt "wireguard-settings-view"
msgid "Not all our servers are %(daita)s-enabled. Smart routing allows %(daita)s to be used at any location. It does this by using multihop in the background to route your traffic via the closest %(daita)s-enabled server first."
msgstr ""

msgctxt "wireguard-settings-view"
msgid "Obfuscation"
msgstr ""
Expand Down Expand Up @@ -2134,11 +2158,6 @@ msgctxt "wireguard-settings-view"
msgid "This allows access to %(wireguard)s for devices that only support IPv6."
msgstr ""

#. Warning text in a dialog that is displayed after a setting is toggled.
msgctxt "wireguard-settings-view"
msgid "This feature isn’t available on all servers. You might need to change location after enabling."
msgstr ""

msgctxt "wireguard-settings-view"
msgid "This feature makes the WireGuard tunnel resistant to potential attacks from quantum computers."
msgstr ""
Expand All @@ -2151,6 +2170,10 @@ msgctxt "wireguard-settings-view"
msgid "UDP-over-TCP port"
msgstr ""

msgctxt "wireguard-settings-view"
msgid "Use Smart routing"
msgstr ""

#. Text describing the valid port range for a port selector.
msgctxt "wireguard-settings-view"
msgid "Valid range: %(min)s - %(max)s"
Expand Down Expand Up @@ -2541,6 +2564,9 @@ msgstr ""
msgid "This address has already been entered."
msgstr ""

msgid "This feature isn’t available on all servers. You might need to change location after enabling."
msgstr ""

msgid "This field is required"
msgstr ""

Expand Down
16 changes: 8 additions & 8 deletions gui/src/main/daemon-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import {
IAppVersionInfo,
IBridgeConstraints,
ICustomList,
IDaitaSettings,
IDevice,
IDeviceRemoval,
IDnsOptions,
Expand Down Expand Up @@ -586,13 +585,12 @@ export class DaemonRpc {
await this.callBool(this.client.prepareRestartV2, quit);
}

public async setDaitaSettings(daitaSettings: IDaitaSettings): Promise<void> {
const grpcDaitaSettings = new grpcTypes.DaitaSettings();
grpcDaitaSettings.setEnabled(daitaSettings.enabled);
await this.call<grpcTypes.DaitaSettings, Empty>(
this.client.setDaitaSettings,
grpcDaitaSettings,
);
public async setEnableDaita(value: boolean): Promise<void> {
await this.callBool(this.client.setEnableDaita, value);
}

public async setDaitaSmartRouting(value: boolean): Promise<void> {
await this.callBool(this.client.setDaitaSmartRouting, value);
}

public async listDevices(accountToken: AccountToken): Promise<Array<IDevice>> {
Expand Down Expand Up @@ -1182,6 +1180,8 @@ function convertFromFeatureIndicator(
return FeatureIndicator.customMssFix;
case grpcTypes.FeatureIndicator.DAITA:
return FeatureIndicator.daita;
case grpcTypes.FeatureIndicator.DAITA_SMART_ROUTING:
return FeatureIndicator.daitaSmartRouting;
case grpcTypes.FeatureIndicator.SHADOWSOCKS:
return FeatureIndicator.shadowsocks;
}
Expand Down
7 changes: 5 additions & 2 deletions gui/src/main/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,11 @@ export default class Settings implements Readonly<ISettings> {
const settings = await fs.readFile(path);
return this.daemonRpc.applyJsonSettings(settings.toString());
});
IpcMainEventChannel.settings.handleSetDaitaSettings((daitaSettings) => {
return this.daemonRpc.setDaitaSettings(daitaSettings);
IpcMainEventChannel.settings.handleSetEnableDaita((value) => {
return this.daemonRpc.setEnableDaita(value);
});
IpcMainEventChannel.settings.handleSetDaitaSmartRouting((value) => {
return this.daemonRpc.setDaitaSmartRouting(value);
});

IpcMainEventChannel.guiSettings.handleSetEnableSystemNotifications((flag: boolean) => {
Expand Down
7 changes: 4 additions & 3 deletions gui/src/renderer/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
IAccountData,
IAppVersionInfo,
ICustomList,
IDaitaSettings,
IDevice,
IDeviceRemoval,
IDnsOptions,
Expand Down Expand Up @@ -345,8 +344,10 @@ export default class AppRenderer {
IpcRendererEventChannel.splitTunneling.forgetManuallyAddedApplication(application);
public setObfuscationSettings = (obfuscationSettings: ObfuscationSettings) =>
IpcRendererEventChannel.settings.setObfuscationSettings(obfuscationSettings);
public setDaitaSettings = (daitaSettings: IDaitaSettings) =>
IpcRendererEventChannel.settings.setDaitaSettings(daitaSettings);
public setEnableDaita = (value: boolean) =>
IpcRendererEventChannel.settings.setEnableDaita(value);
public setDaitaSmartRouting = (value: boolean) =>
IpcRendererEventChannel.settings.setDaitaSmartRouting(value);
public collectProblemReport = (toRedact: string | undefined) =>
IpcRendererEventChannel.problemReport.collectLogs(toRedact);
public viewLog = (path: string) => IpcRendererEventChannel.problemReport.viewLog(path);
Expand Down
2 changes: 2 additions & 0 deletions gui/src/renderer/components/AppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ITransitionSpecification, transitions, useHistory } from '../lib/histor
import { RoutePath } from '../lib/routes';
import Account from './Account';
import ApiAccessMethods from './ApiAccessMethods';
import DaitaSettings from './DaitaSettings';
import Debug from './Debug';
import { DeviceRevokedView } from './DeviceRevokedView';
import { EditApiAccessMethod } from './EditApiAccessMethod';
Expand Down Expand Up @@ -85,6 +86,7 @@ export default function AppRouter() {
<Route exact path={RoutePath.userInterfaceSettings} component={UserInterfaceSettings} />
<Route exact path={RoutePath.vpnSettings} component={VpnSettings} />
<Route exact path={RoutePath.wireguardSettings} component={WireguardSettings} />
<Route exact path={RoutePath.daitaSettings} component={DaitaSettings} />
<Route exact path={RoutePath.udpOverTcp} component={UdpOverTcp} />
<Route exact path={RoutePath.shadowsocks} component={Shadowsocks} />
<Route exact path={RoutePath.openVpnSettings} component={OpenVpnSettings} />
Expand Down
193 changes: 193 additions & 0 deletions gui/src/renderer/components/DaitaSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import { useCallback } from 'react';
import { sprintf } from 'sprintf-js';
import styled from 'styled-components';

import { strings } from '../../config.json';
import { messages } from '../../shared/gettext';
import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { useBoolean } from '../lib/utilityHooks';
import { useSelector } from '../redux/store';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import InfoButton from './InfoButton';
import { BackAction } from './KeyboardNavigation';
import { Layout, SettingsContainer } from './Layout';
import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
import {
NavigationBar,
NavigationContainer,
NavigationInfoButton,
NavigationItems,
NavigationScrollbars,
TitleBarItem,
} from './NavigationBar';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
import { SmallButton, SmallButtonColor } from './SmallButton';

const StyledContent = styled.div({
display: 'flex',
flexDirection: 'column',
flex: 1,
marginBottom: '2px',
});

export default function DaitaSettings() {
const { pop } = useHistory();

return (
<BackAction action={pop}>
<Layout>
<SettingsContainer>
<NavigationContainer>
<NavigationBar>
<NavigationItems>
<TitleBarItem>{strings.daita}</TitleBarItem>

<NavigationInfoButton>
<ModalMessage>
{sprintf(
messages.pgettext(
'wireguard-settings-view',
'%(daita)s (%(daitaFull)s) hides patterns in your encrypted VPN traffic. If anyone is monitoring your connection, this makes it significantly harder for them to identify what websites you are visiting. It does this by carefully adding network noise and making all network packets the same size.',
),
{ daita: strings.daita, daitaFull: strings.daitaFull },
)}
</ModalMessage>
</NavigationInfoButton>
</NavigationItems>
</NavigationBar>

<NavigationScrollbars>
<SettingsHeader>
<HeaderTitle>{strings.daita}</HeaderTitle>
<HeaderSubTitle>
{messages.pgettext(
'wireguard-settings-view',
'Hides patterns in your encrypted VPN traffic. Since this increases your total network traffic, be cautious if you have a limited data plan. It can also negatively impact your network speed and battery usage.',
)}
</HeaderSubTitle>
</SettingsHeader>

<StyledContent>
<Cell.Group>
<DaitaToggle />
</Cell.Group>
</StyledContent>
</NavigationScrollbars>
</NavigationContainer>
</SettingsContainer>
</Layout>
</BackAction>
);
}

function DaitaToggle() {
const { setEnableDaita, setDaitaSmartRouting } = useAppContext();
const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false);
const smartRouting = useSelector(
(state) => state.settings.wireguard.daita?.smartRouting ?? false,
);

const [confirmationDialogVisible, showConfirmationDialog, hideConfirmationDialog] = useBoolean();

const setDaita = useCallback((value: boolean) => {
void setEnableDaita(value);
}, []);

const setSmartRouting = useCallback((value: boolean) => {
if (value) {
void setDaitaSmartRouting(value);
} else {
showConfirmationDialog();
}
}, []);

const confirmDisableSmartRouting = useCallback(() => {
void setDaitaSmartRouting(false);
hideConfirmationDialog();
}, []);

return (
<>
<AriaInputGroup>
<Cell.Container>
<AriaLabel>
<Cell.InputLabel>{messages.gettext('Enable')}</Cell.InputLabel>
</AriaLabel>
<AriaInput>
<Cell.Switch isOn={daita} onChange={setDaita} />
</AriaInput>
</Cell.Container>
</AriaInputGroup>
<AriaInputGroup>
<Cell.Container disabled={!daita}>
<AriaLabel>
<Cell.InputLabel>{messages.gettext('Smart routing')}</Cell.InputLabel>
</AriaLabel>
<InfoButton>
<SmartRoutingModalMessage />
</InfoButton>
<AriaInput>
<Cell.Switch isOn={smartRouting} onChange={setSmartRouting} />
</AriaInput>
</Cell.Container>
<Cell.CellFooter>
<AriaDescription>
<Cell.CellFooterText>
{sprintf(
messages.pgettext(
'vpn-settings-view',
'Is automatically enabled with %(daita)s, makes it possible to use %(daita)s with any server by using multihop. This might increase latency.',
),
{ daita: strings.daita },
)}
</Cell.CellFooterText>
</AriaDescription>
</Cell.CellFooter>
</AriaInputGroup>
<ModalAlert
isOpen={confirmationDialogVisible}
type={ModalAlertType.caution}
gridButtons={[
<SmallButton
key="confirm"
onClick={confirmDisableSmartRouting}
color={SmallButtonColor.blue}>
{messages.gettext('Disable anyway')}
</SmallButton>,
<SmallButton key="cancel" onClick={hideConfirmationDialog} color={SmallButtonColor.blue}>
{messages.pgettext('wireguard-settings-view', 'Use Smart routing')}
</SmallButton>,
]}
close={hideConfirmationDialog}>
<ModalMessage>
{sprintf(
// TRANSLATORS: Warning text in a dialog that is displayed after a setting is toggled.
messages.pgettext(
'wireguard-settings-view',
'Not all our servers are %(daita)s-enabled. In order to use the internet, you might have to select a new location after disabling, or you can continue using %(daita)s with Smart routing.',
),
{ daita: strings.daita },
)}
</ModalMessage>
</ModalAlert>
</>
);
}

export function SmartRoutingModalMessage() {
return (
<ModalMessage>
{sprintf(
messages.pgettext(
'wireguard-settings-view',
'Not all our servers are %(daita)s-enabled. Smart routing allows %(daita)s to be used at any location. It does this by using multihop in the background to route your traffic via the closest %(daita)s-enabled server first.',
),
{
daita: strings.daita,
},
)}
</ModalMessage>
);
}
Loading
Loading