Kaynağa Gözat

GoBackend: Use the android VpnService to encapsulate the go backend

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
master
Aurélien Chabot 6 yıl önce
committed by Jason A. Donenfeld
ebeveyn
işleme
9dfab4d60f
3 değiştirilmiş dosya ile 98 ekleme ve 6 silme
  1. +8
    -0
      app/src/main/AndroidManifest.xml
  2. +10
    -0
      app/src/main/java/com/wireguard/android/activity/BaseActivity.java
  3. +80
    -6
      app/src/main/java/com/wireguard/android/backend/GoBackend.java

+ 8
- 0
app/src/main/AndroidManifest.xml Dosyayı Görüntüle

@@ -50,6 +50,14 @@
</intent-filter>
</receiver>

<service
android:name=".backend.GoBackend$VpnService"
android:permission="android.permission.BIND_VPN_SERVICE" >
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
</service>

<service
android:name=".QuickTileService"
android:icon="@drawable/ic_tile"


+ 10
- 0
app/src/main/java/com/wireguard/android/activity/BaseActivity.java Dosyayı Görüntüle

@@ -1,11 +1,13 @@
package com.wireguard.android.activity;

import android.app.Activity;
import android.content.Intent;
import android.databinding.CallbackRegistry;
import android.databinding.CallbackRegistry.NotifierCallback;
import android.os.Bundle;

import com.wireguard.android.Application;
import com.wireguard.android.backend.GoBackend;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.model.TunnelManager;

@@ -42,8 +44,16 @@ public abstract class BaseActivity extends Activity {
final TunnelManager tunnelManager = Application.getComponent().getTunnelManager();
selectedTunnel = tunnelManager.getTunnels().get(savedTunnelName);
}

// The selected tunnel must be set before the superclass method recreates fragments.
super.onCreate(savedInstanceState);

if (Application.getComponent().getBackendType() == GoBackend.class) {
Intent intent = GoBackend.VpnService.prepare(this);
if (intent != null) {
startActivityForResult(intent, 0);
}
}
}

@Override


+ 80
- 6
app/src/main/java/com/wireguard/android/backend/GoBackend.java Dosyayı Görüntüle

@@ -1,6 +1,8 @@
package com.wireguard.android.backend;

import android.content.Context;
import android.content.Intent;
import android.os.ParcelFileDescriptor;
import android.support.v4.util.ArraySet;
import android.util.Log;

@@ -23,13 +25,36 @@ public final class GoBackend implements Backend {
System.loadLibrary("wg-go");
}

private final Context context;
private Tunnel currentTunnel;
private int currentTunnelHandle = -1;

public GoBackend(final Context context) {
private Context context;

public GoBackend(Context context) {
this.context = context;
context.startService(new Intent(context, VpnService.class));
}

public static class VpnService extends android.net.VpnService {
@Override
public void onCreate() {
super.onCreate();
vpnService = this;
}

@Override
public void onDestroy() {
super.onDestroy();
vpnService = null;
}

public Builder getBuilder() {
return new Builder();
}
}

private static VpnService vpnService = null;

private static native int wgGetSocketV4(int handle);

private static native int wgGetSocketV6(int handle);
@@ -90,10 +115,22 @@ public final class GoBackend implements Backend {

private void setStateInternal(final Tunnel tunnel, final Config config, final State state)
throws Exception {

if (state == State.UP) {
// Do something (context.startService()...).
currentTunnel = tunnel;
Log.i(TAG, "Bringing tunnel up");

if (VpnService.prepare(context) != null)
throw new Exception("VPN service not authorized by user");

if (vpnService == null)
throw new Exception("Android VPN service is not running");

if (currentTunnelHandle != -1) {
Log.w(TAG, "Tunnel already up");
return;
}

// Build config
Formatter fmt = new Formatter(new StringBuilder());
final Interface iface = config.getInterface();
fmt.format("replace_peers=true\n");
@@ -116,10 +153,47 @@ public final class GoBackend implements Backend {
}
}
}
wgTurnOn(tunnel.getName(), -1, fmt.toString());

// Create the vpn tunnel with android API
VpnService.Builder builder = vpnService.getBuilder();
builder.setSession(tunnel.getName());
builder.addAddress(config.getInterface().getAddress(), 32);
if (config.getInterface().getDns() != null)
builder.addDnsServer(config.getInterface().getDns());

for (final Peer peer : config.getPeers()) {
if (peer.getAllowedIPs() != null) {
for (final String allowedIp : peer.getAllowedIPs().split(" *, *")) {
String[] part = allowedIp.split("/", 2);
builder.addRoute(part[0], Integer.parseInt(part[1]));
}
}
}

builder.setBlocking(true);
ParcelFileDescriptor tun = builder.establish();
if (tun == null)
throw new Exception("Unable to create tun device");

currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), fmt.toString());
if (currentTunnelHandle < 0)
throw new Exception("Unable to turn tunnel on (wgTurnOn return " + currentTunnelHandle + ")");

currentTunnel = tunnel;

vpnService.protect(wgGetSocketV4(currentTunnelHandle));
vpnService.protect(wgGetSocketV6(currentTunnelHandle));
} else {
// Do something else.
Log.i(TAG, "Bringing tunnel down");

if (currentTunnelHandle == -1) {
Log.w(TAG, "Tunnel already down");
return;
}

wgTurnOff(currentTunnelHandle);
currentTunnel = null;
currentTunnelHandle = -1;
}
}
}

Yükleniyor…
İptal
Kaydet