aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/app/src/main/java/com/wireguard/android/backend
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/wireguard/android/backend')
-rw-r--r--app/src/main/java/com/wireguard/android/backend/Backend.java79
-rw-r--r--app/src/main/java/com/wireguard/android/backend/GoBackend.java241
-rw-r--r--app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java133
3 files changed, 0 insertions, 453 deletions
diff --git a/app/src/main/java/com/wireguard/android/backend/Backend.java b/app/src/main/java/com/wireguard/android/backend/Backend.java
deleted file mode 100644
index a25bfd04..00000000
--- a/app/src/main/java/com/wireguard/android/backend/Backend.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.backend;
-
-import com.wireguard.android.model.Tunnel;
-import com.wireguard.android.model.Tunnel.State;
-import com.wireguard.android.model.Tunnel.Statistics;
-import com.wireguard.config.Config;
-
-import java.util.Set;
-
-/**
- * Interface for implementations of the WireGuard secure network tunnel.
- */
-
-public interface Backend {
- /**
- * Update the volatile configuration of a running tunnel and return the resulting configuration.
- * If the tunnel is not up, return the configuration that would result (if known), or else
- * simply return the given configuration.
- *
- * @param tunnel The tunnel to apply the configuration to.
- * @param config The new configuration for this tunnel.
- * @return The updated configuration of the tunnel.
- */
- Config applyConfig(Tunnel tunnel, Config config) throws Exception;
-
- /**
- * Enumerate the names of currently-running tunnels.
- *
- * @return The set of running tunnel names.
- */
- Set<String> enumerate();
-
- /**
- * Get the actual state of a tunnel.
- *
- * @param tunnel The tunnel to examine the state of.
- * @return The state of the tunnel.
- */
- State getState(Tunnel tunnel) throws Exception;
-
- /**
- * Get statistics about traffic and errors on this tunnel. If the tunnel is not running, the
- * statistics object will be filled with zero values.
- *
- * @param tunnel The tunnel to retrieve statistics for.
- * @return The statistics for the tunnel.
- */
- Statistics getStatistics(Tunnel tunnel) throws Exception;
-
- /**
- * Determine type name of underlying backend.
- *
- * @return Type name
- */
- String getTypePrettyName();
-
- /**
- * Determine version of underlying backend.
- *
- * @return The version of the backend.
- * @throws Exception
- */
- String getVersion() throws Exception;
-
- /**
- * Set the state of a tunnel.
- *
- * @param tunnel The tunnel to control the state of.
- * @param state The new state for this tunnel. Must be {@code UP}, {@code DOWN}, or
- * {@code TOGGLE}.
- * @return The updated state of the tunnel.
- */
- State setState(Tunnel tunnel, State state) throws Exception;
-}
diff --git a/app/src/main/java/com/wireguard/android/backend/GoBackend.java b/app/src/main/java/com/wireguard/android/backend/GoBackend.java
deleted file mode 100644
index e85f2b0d..00000000
--- a/app/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.backend;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.os.ParcelFileDescriptor;
-import androidx.annotation.Nullable;
-import androidx.collection.ArraySet;
-import android.util.Log;
-
-import com.wireguard.android.Application;
-import com.wireguard.android.R;
-import com.wireguard.android.activity.MainActivity;
-import com.wireguard.android.model.Tunnel;
-import com.wireguard.android.model.Tunnel.State;
-import com.wireguard.android.model.Tunnel.Statistics;
-import com.wireguard.android.util.ExceptionLoggers;
-import com.wireguard.android.util.SharedLibraryLoader;
-import com.wireguard.config.Config;
-import com.wireguard.config.InetNetwork;
-import com.wireguard.config.Peer;
-
-import java.net.InetAddress;
-import java.util.Collections;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import java9.util.concurrent.CompletableFuture;
-
-public final class GoBackend implements Backend {
- private static final String TAG = "WireGuard/" + GoBackend.class.getSimpleName();
- private static CompletableFuture<VpnService> vpnService = new CompletableFuture<>();
-
- private final Context context;
- @Nullable private Tunnel currentTunnel;
- private int currentTunnelHandle = -1;
-
- public GoBackend(final Context context) {
- SharedLibraryLoader.loadSharedLibrary(context, "wg-go");
- this.context = context;
- }
-
- private static native int wgGetSocketV4(int handle);
-
- private static native int wgGetSocketV6(int handle);
-
- private static native void wgTurnOff(int handle);
-
- private static native int wgTurnOn(String ifName, int tunFd, String settings);
-
- private static native String wgVersion();
-
- @Override
- public Config applyConfig(final Tunnel tunnel, final Config config) throws Exception {
- if (tunnel.getState() == State.UP) {
- // Restart the tunnel to apply the new config.
- setStateInternal(tunnel, tunnel.getConfig(), State.DOWN);
- try {
- setStateInternal(tunnel, config, State.UP);
- } catch (final Exception e) {
- // The new configuration didn't work, so try to go back to the old one.
- setStateInternal(tunnel, tunnel.getConfig(), State.UP);
- throw e;
- }
- }
- return config;
- }
-
- @Override
- public Set<String> enumerate() {
- if (currentTunnel != null) {
- final Set<String> runningTunnels = new ArraySet<>();
- runningTunnels.add(currentTunnel.getName());
- return runningTunnels;
- }
- return Collections.emptySet();
- }
-
- @Override
- public State getState(final Tunnel tunnel) {
- return currentTunnel == tunnel ? State.UP : State.DOWN;
- }
-
- @Override
- public Statistics getStatistics(final Tunnel tunnel) {
- return new Statistics();
- }
-
- @Override
- public String getTypePrettyName() {
- return context.getString(R.string.type_name_go_userspace);
- }
-
- @Override
- public String getVersion() {
- return wgVersion();
- }
-
- @Override
- public State setState(final Tunnel tunnel, State state) throws Exception {
- final State originalState = getState(tunnel);
- if (state == State.TOGGLE)
- state = originalState == State.UP ? State.DOWN : State.UP;
- if (state == originalState)
- return originalState;
- if (state == State.UP && currentTunnel != null)
- throw new IllegalStateException(context.getString(R.string.multiple_tunnels_error));
- Log.d(TAG, "Changing tunnel " + tunnel.getName() + " to state " + state);
- setStateInternal(tunnel, tunnel.getConfig(), state);
- return getState(tunnel);
- }
-
- private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state)
- throws Exception {
-
- if (state == State.UP) {
- Log.i(TAG, "Bringing tunnel up");
-
- Objects.requireNonNull(config, context.getString(R.string.no_config_error));
-
- if (VpnService.prepare(context) != null)
- throw new Exception(context.getString(R.string.vpn_not_authorized_error));
-
- final VpnService service;
- if (!vpnService.isDone())
- startVpnService();
-
- try {
- service = vpnService.get(2, TimeUnit.SECONDS);
- } catch (final TimeoutException e) {
- throw new Exception(context.getString(R.string.vpn_start_error), e);
- }
-
- if (currentTunnelHandle != -1) {
- Log.w(TAG, "Tunnel already up");
- return;
- }
-
- // Build config
- final String goConfig = config.toWgUserspaceString();
-
- // Create the vpn tunnel with android API
- final VpnService.Builder builder = service.getBuilder();
- builder.setSession(tunnel.getName());
-
- final Intent configureIntent = new Intent(context, MainActivity.class);
- configureIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- builder.setConfigureIntent(PendingIntent.getActivity(context, 0, configureIntent, 0));
-
- for (final String excludedApplication : config.getInterface().getExcludedApplications())
- builder.addDisallowedApplication(excludedApplication);
-
- for (final InetNetwork addr : config.getInterface().getAddresses())
- builder.addAddress(addr.getAddress(), addr.getMask());
-
- for (final InetAddress addr : config.getInterface().getDnsServers())
- builder.addDnsServer(addr.getHostAddress());
-
- for (final Peer peer : config.getPeers()) {
- for (final InetNetwork addr : peer.getAllowedIps())
- builder.addRoute(addr.getAddress(), addr.getMask());
- }
-
- builder.setMtu(config.getInterface().getMtu().orElse(1280));
-
- builder.setBlocking(true);
- try (final ParcelFileDescriptor tun = builder.establish()) {
- if (tun == null)
- throw new Exception(context.getString(R.string.tun_create_error));
- Log.d(TAG, "Go backend v" + wgVersion());
- currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig);
- }
- if (currentTunnelHandle < 0)
- throw new Exception(context.getString(R.string.tunnel_on_error, currentTunnelHandle));
-
- currentTunnel = tunnel;
-
- service.protect(wgGetSocketV4(currentTunnelHandle));
- service.protect(wgGetSocketV6(currentTunnelHandle));
- } else {
- Log.i(TAG, "Bringing tunnel down");
-
- if (currentTunnelHandle == -1) {
- Log.w(TAG, "Tunnel already down");
- return;
- }
-
- wgTurnOff(currentTunnelHandle);
- currentTunnel = null;
- currentTunnelHandle = -1;
- }
- }
-
- private void startVpnService() {
- Log.d(TAG, "Requesting to start VpnService");
- context.startService(new Intent(context, VpnService.class));
- }
-
- public static class VpnService extends android.net.VpnService {
- public Builder getBuilder() {
- return new Builder();
- }
-
- @Override
- public void onCreate() {
- vpnService.complete(this);
- super.onCreate();
- }
-
- @Override
- public void onDestroy() {
- Application.getTunnelManager().getTunnels().thenAccept(tunnels -> {
- for (final Tunnel tunnel : tunnels) {
- if (tunnel != null && tunnel.getState() != State.DOWN)
- tunnel.setState(State.DOWN);
- }
- });
-
- vpnService = vpnService.newIncompleteFuture();
- super.onDestroy();
- }
-
- @Override
- public int onStartCommand(@Nullable final Intent intent, final int flags, final int startId) {
- vpnService.complete(this);
- if (intent == null || intent.getComponent() == null || !intent.getComponent().getPackageName().equals(getPackageName())) {
- Log.d(TAG, "Service started by Always-on VPN feature");
- Application.getTunnelManager().restoreState(true).whenComplete(ExceptionLoggers.D);
- }
- return super.onStartCommand(intent, flags, startId);
- }
-
- }
-}
diff --git a/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java b/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java
deleted file mode 100644
index 71427d8a..00000000
--- a/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.backend;
-
-import android.content.Context;
-import androidx.annotation.Nullable;
-import android.util.Log;
-
-import com.wireguard.android.Application;
-import com.wireguard.android.R;
-import com.wireguard.android.model.Tunnel;
-import com.wireguard.android.model.Tunnel.State;
-import com.wireguard.android.model.Tunnel.Statistics;
-import com.wireguard.config.Config;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.Set;
-
-import java9.util.stream.Collectors;
-import java9.util.stream.Stream;
-
-/**
- * WireGuard backend that uses {@code wg-quick} to implement tunnel configuration.
- */
-
-public final class WgQuickBackend implements Backend {
- private static final String TAG = "WireGuard/" + WgQuickBackend.class.getSimpleName();
-
- private final File localTemporaryDir;
- private final Context context;
-
- public WgQuickBackend(final Context context) {
- localTemporaryDir = new File(context.getCacheDir(), "tmp");
- this.context = context;
- }
-
- @Override
- public Config applyConfig(final Tunnel tunnel, final Config config) throws Exception {
- if (tunnel.getState() == State.UP) {
- // Restart the tunnel to apply the new config.
- setStateInternal(tunnel, tunnel.getConfig(), State.DOWN);
- try {
- setStateInternal(tunnel, config, State.UP);
- } catch (final Exception e) {
- // The new configuration didn't work, so try to go back to the old one.
- setStateInternal(tunnel, tunnel.getConfig(), State.UP);
- throw e;
- }
- }
- return config;
- }
-
- @Override
- public Set<String> enumerate() {
- final List<String> output = new ArrayList<>();
- // Don't throw an exception here or nothing will show up in the UI.
- try {
- Application.getToolsInstaller().ensureToolsAvailable();
- if (Application.getRootShell().run(output, "wg show interfaces") != 0 || output.isEmpty())
- return Collections.emptySet();
- } catch (final Exception e) {
- Log.w(TAG, "Unable to enumerate running tunnels", e);
- return Collections.emptySet();
- }
- // wg puts all interface names on the same line. Split them into separate elements.
- return Stream.of(output.get(0).split(" ")).collect(Collectors.toUnmodifiableSet());
- }
-
- @Override
- public State getState(final Tunnel tunnel) {
- return enumerate().contains(tunnel.getName()) ? State.UP : State.DOWN;
- }
-
- @Override
- public Statistics getStatistics(final Tunnel tunnel) {
- return new Statistics();
- }
-
- @Override
- public String getTypePrettyName() {
- return context.getString(R.string.type_name_kernel_module);
- }
-
- @Override
- public String getVersion() throws Exception {
- final List<String> output = new ArrayList<>();
- if (Application.getRootShell()
- .run(output, "cat /sys/module/wireguard/version") != 0 || output.isEmpty())
- throw new Exception(context.getString(R.string.module_version_error));
- return output.get(0);
- }
-
- @Override
- public State setState(final Tunnel tunnel, State state) throws Exception {
- final State originalState = getState(tunnel);
- if (state == State.TOGGLE)
- state = originalState == State.UP ? State.DOWN : State.UP;
- if (state == originalState)
- return originalState;
- Log.d(TAG, "Changing tunnel " + tunnel.getName() + " to state " + state);
- Application.getToolsInstaller().ensureToolsAvailable();
- setStateInternal(tunnel, tunnel.getConfig(), state);
- return getState(tunnel);
- }
-
- private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state) throws Exception {
- Objects.requireNonNull(config, "Trying to set state with a null config");
-
- final File tempFile = new File(localTemporaryDir, tunnel.getName() + ".conf");
- try (final FileOutputStream stream = new FileOutputStream(tempFile, false)) {
- stream.write(config.toWgQuickString().getBytes(StandardCharsets.UTF_8));
- }
- String command = String.format("wg-quick %s '%s'",
- state.toString().toLowerCase(Locale.ENGLISH), tempFile.getAbsolutePath());
- if (state == State.UP)
- command = "cat /sys/module/wireguard/version && " + command;
- final int result = Application.getRootShell().run(null, command);
- // noinspection ResultOfMethodCallIgnored
- tempFile.delete();
- if (result != 0)
- throw new Exception(context.getString(R.string.tunnel_config_error, result));
- }
-}