diff --git a/app/src/main/aidl/de/blinkt/openvpn/core/IOpenVPNServiceInternal.aidl b/app/src/main/aidl/de/blinkt/openvpn/core/IOpenVPNServiceInternal.aidl
index 3958bcf33746e04618fb34a3326ff2f4e634c5d0..b19cf99e22c274d4ecce871b18466313101a368d 100644
--- a/app/src/main/aidl/de/blinkt/openvpn/core/IOpenVPNServiceInternal.aidl
+++ b/app/src/main/aidl/de/blinkt/openvpn/core/IOpenVPNServiceInternal.aidl
@@ -20,4 +20,6 @@ interface IOpenVPNServiceInternal {
      * @return true if there was a process that has been send a stop signal
      */
     boolean stopVPN(boolean replaceConnection);
+
+    boolean isVpnRunning();
 }
diff --git a/app/src/main/java/de/blinkt/openvpn/core/ConnectionStatus.java b/app/src/main/java/de/blinkt/openvpn/core/ConnectionStatus.java
index 03d842e3f9832f2028009ec388f0bc6fc88c2ed3..3e6d23f7c29f91657ee588047c4851d9feb83ea8 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/ConnectionStatus.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/ConnectionStatus.java
@@ -21,6 +21,7 @@ public enum ConnectionStatus implements Parcelable {
     LEVEL_START,
     LEVEL_AUTH_FAILED,
     LEVEL_WAITING_FOR_USER_INPUT,
+    LEVEL_BLOCKING,                 // used for Bitmask's VoidVPN
     UNKNOWN_LEVEL;
 
     @Override
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index ded7490a8b186caabeb2d11305834c3fa684a03f..86e1bb02b0cbac9f217aa0f7b80b431478dd339b 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -115,6 +115,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
         public boolean stopVPN(boolean replaceConnection) throws RemoteException {
             return OpenVPNService.this.stopVPN(replaceConnection);
         }
+
+        @Override
+        public boolean isVpnRunning() throws RemoteException {
+            return OpenVPNService.this.isVpnRunning();
+        }
     };
 
     // From: http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
@@ -412,6 +417,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
 
     }
 
+    @Override
     public void userPause(boolean shouldBePaused) {
         if (mDeviceStateReceiver != null)
             mDeviceStateReceiver.userPause(shouldBePaused);
@@ -425,6 +431,20 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
             return false;
     }
 
+    /**
+     * used in Bitmask
+     */
+    @Override
+    public boolean isVpnRunning() {
+        boolean hasVPNProcessThread = false;
+        synchronized (mProcessLock) {
+            hasVPNProcessThread = mProcessThread != null && mProcessThread.isAlive();
+        }
+
+        return hasVPNProcessThread;
+
+    }
+
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
 
diff --git a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
index 3f1663d001a09b3569dc6c64d6a3dd999e1d1e1d..1a4adc1d993e071c0c298158f3326c9ac126c4e6 100644
--- a/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
+++ b/app/src/main/java/se/leap/bitmaskclient/Dashboard.java
@@ -63,6 +63,9 @@ import se.leap.bitmaskclient.userstatus.SessionDialog;
 import se.leap.bitmaskclient.userstatus.User;
 import se.leap.bitmaskclient.userstatus.UserStatusFragment;
 
+import static se.leap.bitmaskclient.eip.Constants.IS_ALWAYS_ON;
+import static se.leap.bitmaskclient.eip.Constants.RESTART_ON_BOOT;
+
 /**
  * The main user facing Activity of Bitmask Android, consisting of status, controls,
  * and access to preferences.
@@ -78,15 +81,23 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec
     public static final String TAG = Dashboard.class.getSimpleName();
     public static final String SHARED_PREFERENCES = "LEAPPreferences";
     public static final String ACTION_QUIT = "quit";
+
+    /**
+     * When "Disconnect" is clicked from the notification this extra gets added to the calling intent.
+     */
     public static final String ACTION_ASK_TO_CANCEL_VPN = "ask to cancel vpn";
+    /**
+     * if always-on feature is enabled, but there's no provider configured the EIP Service
+     * adds this intent extra. ACTION_CONFIGURE_ALWAYS_ON_PROFILE
+     * serves to start the Configuration Wizard on top of the Dashboard Activity.
+     */
+    public static final String ACTION_CONFIGURE_ALWAYS_ON_PROFILE = "configure always-on profile";
     public static final String REQUEST_CODE = "request_code";
     public static final String PARAMETERS = "dashboard parameters";
-    public static final String START_ON_BOOT = "dashboard start on boot";
-    //FIXME: remove OR FIX ON_BOOT
-    public static final String ON_BOOT = "dashboard on boot";
     public static final String APP_VERSION = "bitmask version";
 
-    private static Context app;
+    //FIXME: context classes in static fields lead to memory leaks!
+    private static Context dashboardContext;
     protected static SharedPreferences preferences;
     private FragmentManagerEnhanced fragment_manager;
 
@@ -108,31 +119,21 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec
         ProviderAPICommand.initialize(this);
         providerAPI_result_receiver = new ProviderAPIResultReceiver(new Handler(), this);
 
-        if (app == null) {
-            app = this;
+        if (dashboardContext == null) {
+            dashboardContext = this;
 
             VpnStatus.initLogCache(getApplicationContext().getCacheDir());
             handleVersion();
             User.init(getString(R.string.default_username));
         }
-        boolean provider_exists = previousProviderExists(savedInstanceState);
-        if (provider_exists) {
-            provider = getProvider(savedInstanceState);
-            if(!provider.isConfigured())
-                startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP);
-            else {
-                buildDashboard(getIntent().getBooleanExtra(ON_BOOT, false));
-                user_status_fragment.restoreSessionStatus(savedInstanceState);
-            }
-        } else {
-            startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP);
-        }
+
+        prepareEIP(savedInstanceState);
     }
 
     @Override
     protected void onResume() {
         super.onResume();
-        handleVPNCancellation(getIntent());
+        handleVpnCancellation(getIntent());
     }
 
     private boolean previousProviderExists(Bundle savedInstanceState) {
@@ -198,7 +199,19 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
         setIntent(intent);
-        handleVPNCancellation(intent);
+        handleIntentExtras(intent);
+    }
+
+    private void handleIntentExtras(Intent intent) {
+        if (intent.hasExtra(ACTION_ASK_TO_CANCEL_VPN)) {
+            handleVpnCancellation(intent);
+        } else if (intent.hasExtra(RESTART_ON_BOOT)) {
+            Log.d(TAG, "Dashboard: RESTART_ON_BOOT");
+            prepareEIP(null);
+        } else if (intent.hasExtra(ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) {
+            Log.d(TAG, "Dashboard: ACTION_CONFIGURE_ALWAYS_ON_PROFILE");
+            handleConfigureAlwaysOn(getIntent());
+        }
     }
 
     @Override
@@ -221,15 +234,44 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec
         }
     }
 
-    private void handleVPNCancellation(Intent intent) {
+    private void handleVpnCancellation(Intent intent) {
         if (intent.hasExtra(Dashboard.ACTION_ASK_TO_CANCEL_VPN)) {
             eip_fragment.askToStopEIP();
             intent.removeExtra(ACTION_ASK_TO_CANCEL_VPN);
         }
     }
 
+    private void handleConfigureAlwaysOn(Intent intent) {
+            intent.removeExtra(ACTION_CONFIGURE_ALWAYS_ON_PROFILE);
+            Log.d(TAG, "start Configuration wizard!");
+            startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP);
+    }
+
+    private void prepareEIP(Bundle savedInstanceState) {
+        boolean provider_exists = previousProviderExists(savedInstanceState);
+        if (provider_exists) {
+            provider = getProvider(savedInstanceState);
+            if(!provider.isConfigured()) {
+                configureLeapProvider();
+            } else {
+                Log.d(TAG, "vpn provider is configured");
+                buildDashboard(getIntent().getBooleanExtra(RESTART_ON_BOOT, false));
+                user_status_fragment.restoreSessionStatus(savedInstanceState);
+            }
+        } else {
+            configureLeapProvider();
+        }
+    }
+
+    private void configureLeapProvider() {
+        if (getIntent().hasExtra(ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) {
+            getIntent().removeExtra(ACTION_CONFIGURE_ALWAYS_ON_PROFILE);
+        }
+        startActivityForResult(new Intent(this, ConfigurationWizard.class), CONFIGURE_LEAP);
+    }
     @SuppressLint("CommitPrefEdits")
     private void providerToPreferences(Provider provider) {
+        //FIXME: figure out why .commit() is used and try refactor that cause, currently runs on UI thread
         preferences.edit().putBoolean(Constants.PROVIDER_CONFIGURED, true).commit();
         preferences.edit().putString(Provider.MAIN_URL, provider.mainUrl().toString()).apply();
         preferences.edit().putString(Provider.KEY, provider.definition().toString()).apply();
@@ -261,7 +303,10 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec
      * Inflates permanent UI elements of the View and contains logic for what
      * service dependent UI elements to include.
      */
-    private void buildDashboard(boolean hide_and_turn_on_eip) {
+    //TODO: REFACTOR ME! Consider implementing a manager that handles most of VpnFragment's logic about handling EIP commands.
+    //This way, we could avoid to create UI elements (like fragment_manager.replace(R.id.servicesCollection, eip_fragment, VpnFragment.TAG); )
+    // just to start services and destroy them afterwards
+    private void buildDashboard(boolean hideAndTurnOnEipOnBoot) {
         setContentView(R.layout.dashboard);
         ButterKnife.inject(this);
 
@@ -275,24 +320,43 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec
 
         if (provider.hasEIP()) {
             fragment_manager.removePreviousFragment(VpnFragment.TAG);
-            eip_fragment = new VpnFragment();
-
-            if (hide_and_turn_on_eip) {
-                //TODO: remove line below if not in use anymore...
-                preferences.edit().remove(Dashboard.START_ON_BOOT).apply();
-                //FIXME: always start on Boot? Why do we keep shared preferences then?
-                Bundle arguments = new Bundle();
-                arguments.putBoolean(VpnFragment.START_ON_BOOT, true);
-                if (eip_fragment != null) eip_fragment.setArguments(arguments);
-            }
-
+            eip_fragment = prepareEipFragment(hideAndTurnOnEipOnBoot);
             fragment_manager.replace(R.id.servicesCollection, eip_fragment, VpnFragment.TAG);
-            if (hide_and_turn_on_eip) {
+            if (hideAndTurnOnEipOnBoot) {
                 onBackPressed();
             }
         }
     }
 
+    /**
+     *
+     * @param hideAndTurnOnEipOnBoot Flag that indicates if system intent android.intent.action.BOOT_COMPLETED
+     *                               has caused to start Dashboard
+     * @return
+     */
+    private VpnFragment prepareEipFragment(boolean hideAndTurnOnEipOnBoot) {
+        VpnFragment eip_fragment = new VpnFragment();
+
+        if (hideAndTurnOnEipOnBoot && !isAlwaysOn()) {
+            preferences.edit().remove(Constants.RESTART_ON_BOOT).apply();
+            Bundle arguments = new Bundle();
+            arguments.putBoolean(VpnFragment.START_EIP_ON_BOOT, true);
+            Log.d(TAG, "set START_EIP_ON_BOOT argument for eip_fragment");
+            eip_fragment.setArguments(arguments);
+
+        }
+        return eip_fragment;
+    }
+
+    /**
+     * checks if Android's VPN feature 'always-on' is enabled for Bitmask
+     * @return
+     */
+    private boolean isAlwaysOn() {
+        return  preferences.getBoolean(IS_ALWAYS_ON, false);
+    }
+
+
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
         if (provider.allowsRegistration()) {
@@ -395,7 +459,7 @@ public class Dashboard extends Activity implements ProviderAPIResultReceiver.Rec
     }
 
     public static Context getContext() {
-        return app;
+        return dashboardContext;
     }
 
     public static Provider getProvider() { return provider; }
diff --git a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
index 9171e8165418aae2032cbcd38180d21ba657d1e9..943e877a230d402f2f3a34421d8dec8846514f5f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/OnBootReceiver.java
@@ -1,25 +1,46 @@
 package se.leap.bitmaskclient;
 
-import android.content.*;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.util.Log;
 
-import se.leap.bitmaskclient.eip.*;
+import static se.leap.bitmaskclient.eip.Constants.IS_ALWAYS_ON;
+import static se.leap.bitmaskclient.eip.Constants.RESTART_ON_BOOT;
+import static se.leap.bitmaskclient.eip.Constants.VPN_CERTIFICATE;
 
 public class OnBootReceiver extends BroadcastReceiver {
 
     SharedPreferences preferences;
 
-    // Debug: am broadcast -a android.intent.action.BOOT_COMPLETED
+
+    // Debug: su && am broadcast -a android.intent.action.BOOT_COMPLETED
     @Override
     public void onReceive(Context context, Intent intent) {
         preferences = context.getSharedPreferences(Dashboard.SHARED_PREFERENCES, Context.MODE_PRIVATE);
-        boolean provider_configured = !preferences.getString(Provider.KEY, "").isEmpty();
-        boolean start_on_boot = preferences.getBoolean(Dashboard.START_ON_BOOT, false);
-        if (provider_configured && start_on_boot) {
-            Intent dashboard_intent = new Intent(context, Dashboard.class);
-            dashboard_intent.setAction(Constants.ACTION_START_EIP);
-            dashboard_intent.putExtra(Dashboard.ON_BOOT, true);
-            dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            context.startActivity(dashboard_intent);
+        boolean provider_configured = !preferences.getString(VPN_CERTIFICATE, "").isEmpty();
+        boolean start_on_boot = preferences.getBoolean(RESTART_ON_BOOT, false);
+        boolean isAlwaysOnConfigured = preferences.getBoolean(IS_ALWAYS_ON, false);
+        Log.d("OpenVPN", "OpenVPN onBoot intent received. Provider configured? " + provider_configured + "  Start on boot? " + start_on_boot + "  isAlwaysOn feature configured: " + isAlwaysOnConfigured);
+        if (provider_configured) {
+            if (isAlwaysOnConfigured) {
+                //exit because the app is already setting up the vpn
+                return;
+            }
+            if (start_on_boot) {
+                Intent dashboard_intent = new Intent(context, Dashboard.class);
+                dashboard_intent.putExtra(RESTART_ON_BOOT, true);
+                dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                context.startActivity(dashboard_intent);
+            }
+        } else {
+            if (isAlwaysOnConfigured) {
+                Intent dashboard_intent = new Intent(context, Dashboard.class);
+                dashboard_intent.putExtra(Dashboard.ACTION_CONFIGURE_ALWAYS_ON_PROFILE, true);
+                dashboard_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                context.startActivity(dashboard_intent);
+            }
         }
     }
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java
index c85b01517eece6537a75e2fb7786189735eaffea..57c066aa367c96238539f890be2da9c3d9ce620d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/VpnFragment.java
@@ -16,24 +16,50 @@
  */
 package se.leap.bitmaskclient;
 
-import android.app.*;
-import android.content.*;
-import android.os.*;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.util.Log;
-import android.view.*;
-import android.widget.*;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
 
-import org.jetbrains.annotations.*;
+import org.jetbrains.annotations.NotNull;
 
-import java.util.*;
+import java.util.Observable;
+import java.util.Observer;
 
-import butterknife.*;
+import butterknife.ButterKnife;
+import butterknife.InjectView;
+import butterknife.OnClick;
+import de.blinkt.openvpn.core.ConnectionStatus;
 import de.blinkt.openvpn.core.IOpenVPNServiceInternal;
 import de.blinkt.openvpn.core.OpenVPNService;
 import de.blinkt.openvpn.core.ProfileManager;
 import de.blinkt.openvpn.core.VpnStatus;
-import mbanje.kurt.fabbutton.*;
-import se.leap.bitmaskclient.eip.*;
+import mbanje.kurt.fabbutton.FabButton;
+import se.leap.bitmaskclient.eip.Constants;
+import se.leap.bitmaskclient.eip.EIP;
+import se.leap.bitmaskclient.eip.EipStatus;
+import se.leap.bitmaskclient.eip.VoidVpnService;
+
+import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK;
+import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.BLOCKING;
+import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.CONNECTED;
+import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.CONNECTING;
+import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.DISCONNECTED;
+import static se.leap.bitmaskclient.eip.EipStatus.EipLevel.DISCONNECTING;
 
 public class VpnFragment extends Fragment implements Observer {
 
@@ -41,7 +67,7 @@ public class VpnFragment extends Fragment implements Observer {
 
     public static final String IS_PENDING = TAG + ".is_pending";
     protected static final String IS_CONNECTED = TAG + ".is_connected";
-    public static final String START_ON_BOOT = "start on boot";
+    public static final String START_EIP_ON_BOOT = "start on boot";
 
     @InjectView(R.id.vpn_status_image)
     FabButton vpn_status_image;
@@ -94,26 +120,19 @@ public class VpnFragment extends Fragment implements Observer {
         ButterKnife.inject(this, view);
 
         Bundle arguments = getArguments();
-        if (arguments != null && arguments.containsKey(START_ON_BOOT) && arguments.getBoolean(START_ON_BOOT))
+        if (arguments != null && arguments.containsKey(START_EIP_ON_BOOT) && arguments.getBoolean(START_EIP_ON_BOOT)) {
             startEipFromScratch();
-        if (savedInstanceState != null) restoreState(savedInstanceState);
+        }
 
         return view;
     }
 
-    private void restoreState(@NotNull Bundle savedInstanceState) {
-        if (savedInstanceState.getBoolean(IS_PENDING))
-            eip_status.setConnecting();
-        else if (savedInstanceState.getBoolean(IS_CONNECTED))
-            eip_status.setConnectedOrDisconnected();
-    }
-
     @Override
     public void onResume() {
         super.onResume();
         //FIXME: avoid race conditions while checking certificate an logging in at about the same time
         //eipCommand(Constants.ACTION_CHECK_CERT_VALIDITY);
-        handleNewState(eip_status);
+        handleNewState();
         bindOpenVpnService();
     }
 
@@ -130,9 +149,9 @@ public class VpnFragment extends Fragment implements Observer {
         super.onSaveInstanceState(outState);
     }
 
-    private void saveStatus() {
-        boolean is_on = eip_status.isConnected() || eip_status.isConnecting();
-        Dashboard.preferences.edit().putBoolean(Dashboard.START_ON_BOOT, is_on).commit();
+    private void saveStatus(boolean restartOnBoot) {
+        //boolean is_on = eip_status.isConnected() || eip_status.isConnecting() || eip_status.isBlocking();
+        Dashboard.preferences.edit().putBoolean(Constants.RESTART_ON_BOOT, restartOnBoot).commit();
     }
 
     @OnClick(R.id.vpn_main_button)
@@ -142,7 +161,7 @@ public class VpnFragment extends Fragment implements Observer {
         else
             handleSwitchOn();
 
-        saveStatus();
+        saveStatus(eip_status.isConnected() || eip_status.isConnecting());
     }
 
     private void handleSwitchOn() {
@@ -177,8 +196,11 @@ public class VpnFragment extends Fragment implements Observer {
             askPendingStartCancellation();
         } else if (eip_status.isConnected()) {
             askToStopEIP();
-        } else
+        } else if (eip_status.isBlocking()) {
+            stop();
+        } else {
             updateIcon();
+        }
     }
 
     private void askPendingStartCancellation() {
@@ -201,25 +223,26 @@ public class VpnFragment extends Fragment implements Observer {
 
     public void startEipFromScratch() {
         wants_to_connect = false;
-        eip_status.setConnecting();
+        //eip_status.setEipLevel(BLOCKING);
 
-        saveStatus();
+        saveStatus(true);
         eipCommand(Constants.ACTION_START_EIP);
     }
 
     private void stop() {
-        if (eip_status.isConnecting())
+
+        if (eip_status.isBlockingVpnEstablished()) {
+            Log.d(TAG, "stop VoidVpn!");
             VoidVpnService.stop();
+        }
         disconnect();
     }
 
     private void disconnect() {
-        eip_status.setDisconnecting();
         ProfileManager.setConntectedVpnProfileDisconnected(dashboard);
         if (mService != null) {
             try {
                 mService.stopVPN(false);
-                eip_status.setConnectedOrDisconnected();
             } catch (RemoteException e) {
                 VpnStatus.logException(e);
             }
@@ -227,6 +250,7 @@ public class VpnFragment extends Fragment implements Observer {
     }
 
     protected void stopEipIfPossible() {
+        //FIXME: no need to start a service here!
         eipCommand(Constants.ACTION_STOP_EIP);
     }
 
@@ -276,36 +300,33 @@ public class VpnFragment extends Fragment implements Observer {
     public void update(Observable observable, Object data) {
         if (observable instanceof EipStatus) {
             eip_status = (EipStatus) observable;
-            final EipStatus eip_status = (EipStatus) observable;
             dashboard.runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
-                    handleNewState(eip_status);
+                    handleNewState();
                 }
             });
         }
     }
 
-    private void handleNewState(EipStatus eip_status) {
-        Context context = dashboard.getApplicationContext();
-        String error = eip_status.lastError(5, context);
-
-        if (!error.isEmpty()) VoidVpnService.stop();
+    private void handleNewState() {
         updateIcon();
         updateButton();
     }
 
     private void updateIcon() {
-        if (eip_status.isConnected() || eip_status.isConnecting()) {
-            if(eip_status.isConnecting()) {
-                vpn_status_image.showProgress(true);
-                vpn_status_image.setIcon(R.drawable.ic_stat_vpn_empty_halo, R.drawable.ic_stat_vpn_empty_halo);
-                vpn_status_image.setTag(R.drawable.ic_stat_vpn_empty_halo);
-            } else {
-                vpn_status_image.showProgress(false);
-                vpn_status_image.setIcon(R.drawable.ic_stat_vpn, R.drawable.ic_stat_vpn);
-                vpn_status_image.setTag(R.drawable.ic_stat_vpn);
-            }
+        if (eip_status.isBlocking()) {
+            vpn_status_image.showProgress(false);
+            vpn_status_image.setIcon(R.drawable.ic_stat_vpn_blocking, R.drawable.ic_stat_vpn_blocking);
+            vpn_status_image.setTag(R.drawable.ic_stat_vpn_blocking);
+        } else if (eip_status.isConnecting()) {
+            vpn_status_image.showProgress(true);
+            vpn_status_image.setIcon(R.drawable.ic_stat_vpn_empty_halo, R.drawable.ic_stat_vpn_empty_halo);
+            vpn_status_image.setTag(R.drawable.ic_stat_vpn_empty_halo);
+        } else  if (eip_status.isConnected()){
+            vpn_status_image.showProgress(false);
+            vpn_status_image.setIcon(R.drawable.ic_stat_vpn, R.drawable.ic_stat_vpn);
+            vpn_status_image.setTag(R.drawable.ic_stat_vpn);
         } else {
             vpn_status_image.setIcon(R.drawable.ic_stat_vpn_offline, R.drawable.ic_stat_vpn_offline);
             vpn_status_image.setTag(R.drawable.ic_stat_vpn_offline);
@@ -314,17 +335,28 @@ public class VpnFragment extends Fragment implements Observer {
     }
 
     private void updateButton() {
-        if (eip_status.isConnected() || eip_status.isConnecting()) {
-            if(eip_status.isConnecting()) {
-                main_button.setText(dashboard.getString(android.R.string.cancel));
-            } else {
-                main_button.setText(dashboard.getString(R.string.vpn_button_turn_off));
-            }
+        if (eip_status.isConnecting()) {
+            main_button.setText(dashboard.getString(android.R.string.cancel));
+        } else if (eip_status.isConnected() || isOpenVpnRunningWithoutNetwork()) {
+            main_button.setText(dashboard.getString(R.string.vpn_button_turn_off));
         } else {
             main_button.setText(dashboard.getString(R.string.vpn_button_turn_on));
         }
     }
 
+    private boolean isOpenVpnRunningWithoutNetwork() {
+        boolean isRunning = false;
+        try {
+            isRunning = eip_status.getLevel() == LEVEL_NONETWORK &&
+                    mService.isVpnRunning();
+        } catch (Exception e) {
+            //eat me
+            e.printStackTrace();
+        }
+
+        return isRunning;
+    }
+
     private void bindOpenVpnService() {
         Intent intent = new Intent(dashboard, OpenVPNService.class);
         intent.setAction(OpenVPNService.START_SERVICE);
@@ -381,7 +413,7 @@ public class VpnFragment extends Fragment implements Observer {
                             startEipFromScratch();
                         break;
                     case Activity.RESULT_CANCELED:
-                        handleNewState(eip_status);
+                        handleNewState();
                         break;
                 }
             }
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
index db1cb4a11b3765bdd2d54eb7870825da3e84603b..ed4ebcbcdc4271e6678b647387cb559acab0279d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/Constants.java
@@ -27,6 +27,7 @@ public interface Constants {
 
     public final static String ACTION_CHECK_CERT_VALIDITY = TAG + ".CHECK_CERT_VALIDITY";
     public final static String ACTION_START_EIP = TAG + ".START_EIP";
+    public final static String ACTION_START_ALWAYS_ON_EIP = TAG + ".START_ALWAYS_ON_EIP";
     public final static String ACTION_STOP_EIP = TAG + ".STOP_EIP";
     public final static String ACTION_UPDATE_EIP_SERVICE = TAG + ".UPDATE_EIP_SERVICE";
     public final static String ACTION_IS_EIP_RUNNING = TAG + ".IS_RUNNING";
@@ -40,5 +41,7 @@ public interface Constants {
     public final static String REQUEST_TAG = TAG + ".REQUEST_TAG";
     public final static String START_BLOCKING_VPN_PROFILE = TAG + ".START_BLOCKING_VPN_PROFILE";
     public final static String PROVIDER_CONFIGURED = TAG + ".PROVIDER_CONFIGURED";
+    public final static String IS_ALWAYS_ON = TAG + ".IS_ALWAYS_ON";
+    public final static String RESTART_ON_BOOT = TAG + ".RESTART_ON_BOOT";
 
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
index 28a9bb5082d1110247b37d2f71084a7bb05c1cab..39dd133ffb79525edf9c838a9084d79c8193a92e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -19,6 +19,7 @@ package se.leap.bitmaskclient.eip;
 import android.app.*;
 import android.content.*;
 import android.os.*;
+import android.util.Log;
 
 import org.json.*;
 
@@ -57,7 +58,6 @@ public final class EIP extends IntentService {
     @Override
     public void onCreate() {
         super.onCreate();
-
         context = getApplicationContext();
         preferences = getSharedPreferences(Dashboard.SHARED_PREFERENCES, MODE_PRIVATE);
         eip_definition = eipDefinitionFromPreferences();
@@ -72,6 +72,8 @@ public final class EIP extends IntentService {
 
         if (action.equals(ACTION_START_EIP))
             startEIP();
+        else if (action.equals(ACTION_START_ALWAYS_ON_EIP))
+            startAlwaysOnEIP();
         else if (action.equals(ACTION_STOP_EIP))
             stopEIP();
         else if (action.equals(ACTION_IS_EIP_RUNNING))
@@ -88,9 +90,12 @@ public final class EIP extends IntentService {
      * It also sets up early routes.
      */
     private void startEIP() {
+        Log.d(TAG, "startEIP vpn");
         if (gateways_manager.isEmpty())
             updateEIPService();
-        earlyRoutes();
+        if (!EipStatus.getInstance().isBlockingVpnEstablished())  {
+            earlyRoutes();
+        }
 
         gateway = gateways_manager.select();
         if (gateway != null && gateway.getProfile() != null) {
@@ -101,6 +106,27 @@ public final class EIP extends IntentService {
             tellToReceiver(ACTION_START_EIP, Activity.RESULT_CANCELED);
     }
 
+    /**
+     * Tries to start the last used vpn profile when the OS was rebooted and always-on-VPN is enabled.
+     * The {@link OnBootReceiver} will care if there is no profile.
+     */
+    private void startAlwaysOnEIP() {
+        Log.d(TAG, "startAlwaysOnEIP vpn");
+
+        if (gateways_manager.isEmpty())
+            updateEIPService();
+
+        gateway = gateways_manager.select();
+
+        if (gateway != null && gateway.getProfile() != null) {
+            //mReceiver = VpnFragment.getReceiver();
+            Log.d(TAG, "startAlwaysOnEIP eip launch avtive gateway vpn");
+            launchActiveGateway();
+        } else {
+            Log.d(TAG, "startAlwaysOnEIP no active profile available!");
+        }
+    }
+
     /**
      * Early routes are routes that block traffic until a new
      * VpnService is started properly.
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
index 501543b8a0b7edd4257cdc417bb1fd00510f71e5..dc2e81f5c8a1439ab6bd41b3ddd3208579fc1faa 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -17,19 +17,37 @@
 package se.leap.bitmaskclient.eip;
 
 import android.content.*;
+import android.os.AsyncTask;
+import android.support.annotation.VisibleForTesting;
 
 import java.util.*;
 
 import de.blinkt.openvpn.core.*;
 
+/**
+ * EipStatus is a Singleton that represents a reduced set of a vpn's ConnectionStatus.
+ * EipStatus changes it's state (EipLevel) when ConnectionStatus gets updated by OpenVpnService or
+ * by VoidVpnService.
+ */
 public class EipStatus extends Observable implements VpnStatus.StateListener {
     public static String TAG = EipStatus.class.getSimpleName();
     private static EipStatus current_status;
+    public enum EipLevel {
+        CONNECTING,
+        DISCONNECTING,
+        CONNECTED,
+        DISCONNECTED,
+        BLOCKING,
+        UNKNOWN
+    }
 
-    private static ConnectionStatus level = ConnectionStatus.LEVEL_NOTCONNECTED;
-    private static boolean
-            wants_to_disconnect = false,
-            is_connecting = false;
+    /**
+     * vpn_level holds the connection status of the openvpn vpn and the traffic blocking
+     * void vpn. LEVEL_BLOCKING is set when the latter vpn is up. All other states are set by
+     * openvpn.
+     */
+    private ConnectionStatus vpn_level = ConnectionStatus.LEVEL_NOTCONNECTED;
+    private EipLevel current_eip_level = EipLevel.DISCONNECTED;
 
     int last_error_line = 0;
     private String state, log_message;
@@ -48,64 +66,137 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
 
     @Override
     public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
-        updateStatus(state, logmessage, localizedResId, level);
-        if (isConnected() || isDisconnected() || wantsToDisconnect()) {
-            setConnectedOrDisconnected();
-        } else
-            setConnecting();
+        current_status = getInstance();
+        current_status.setState(state);
+        current_status.setLogMessage(logmessage);
+        current_status.setLocalizedResId(localizedResId);
+        current_status.setLevel(level);
+        current_status.setEipLevel(level);
     }
 
     @Override
     public void setConnectedVPN(String uuid) {
     }
 
-    private void updateStatus(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
-        current_status = getInstance();
-        current_status.setState(state);
-        current_status.setLogMessage(logmessage);
-        current_status.setLocalizedResId(localizedResId);
-        current_status.setLevel(level);
-        current_status.setChanged();
+
+    private void setEipLevel(ConnectionStatus level) {
+        EipLevel tmp = current_eip_level;
+        switch (level) {
+            case LEVEL_CONNECTED:
+                current_eip_level = EipLevel.CONNECTED;
+                break;
+            case LEVEL_VPNPAUSED:
+                throw new IllegalStateException("Ics-Openvpn's VPNPAUSED state is not supported by Bitmask");
+            case LEVEL_CONNECTING_SERVER_REPLIED:
+            case LEVEL_CONNECTING_NO_SERVER_REPLY_YET:
+            case LEVEL_WAITING_FOR_USER_INPUT:
+            case LEVEL_START:
+                current_eip_level = EipLevel.CONNECTING;
+                break;
+            case LEVEL_AUTH_FAILED:
+            case LEVEL_NOTCONNECTED:
+                current_eip_level = EipLevel.DISCONNECTED;
+                break;
+            case LEVEL_NONETWORK:
+            case LEVEL_BLOCKING:
+                setEipLevelWithDelay(level);
+                break;
+            case UNKNOWN_LEVEL:
+                current_eip_level = EipLevel.UNKNOWN; //??
+                break;
+        }
+        if (tmp != current_eip_level) {
+            current_status.setChanged();
+            current_status.notifyObservers();
+        }
     }
 
-    public boolean wantsToDisconnect() {
-        return wants_to_disconnect;
+    @VisibleForTesting
+    EipLevel getEipLevel() {
+        return current_eip_level;
     }
 
-    public boolean isConnecting() {
-        return is_connecting;
+    /**
+     * This method intends to ignore states that are valid for less than a second.
+     * This way flickering UI changes can be avoided
+     *
+     * @param futureLevel
+     */
+    private void setEipLevelWithDelay(ConnectionStatus futureLevel) {
+        new DelayTask(current_status.getLevel(), futureLevel).execute();
     }
 
-    public boolean isConnected() {
-        return level == ConnectionStatus.LEVEL_CONNECTED;
+    private class DelayTask extends AsyncTask<Void, Void, Void> {
+
+        private final ConnectionStatus currentLevel;
+        private final ConnectionStatus futureLevel;
+
+        public DelayTask(ConnectionStatus currentLevel, ConnectionStatus futureLevel) {
+            this.currentLevel = currentLevel;
+            this.futureLevel = futureLevel;
+        }
+        protected Void doInBackground(Void... levels) {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                Thread.interrupted();
+            }
+            return null;
+        }
+
+        protected void onPostExecute(Void result) {;
+            if (currentLevel == current_status.getLevel()) {
+                switch (futureLevel) {
+                    case LEVEL_NONETWORK:
+                        current_eip_level = EipLevel.DISCONNECTED;
+                        break;
+                    case LEVEL_BLOCKING:
+                        current_eip_level = EipLevel.BLOCKING;
+                        break;
+                    default:
+                        break;
+                }
+                current_status.setChanged();
+                current_status.notifyObservers();
+            }
+        }
     }
 
-    public boolean isDisconnected() {
-        return level == ConnectionStatus.LEVEL_NOTCONNECTED;
+    public boolean isConnecting() {
+        return current_eip_level == EipLevel.CONNECTING;
     }
 
-    public boolean isPaused() {
-        return level == ConnectionStatus.LEVEL_VPNPAUSED;
+    public boolean isConnected() {
+        return current_eip_level == EipLevel.CONNECTED;
     }
 
-    public void setConnecting() {
-        is_connecting = true;
+    /**
+     * @return true if current_eip_level is for at least a second {@link EipLevel#BLOCKING}.
+     * See {@link #setEipLevelWithDelay(ConnectionStatus)}.
+     */
+    public boolean isBlocking() {
+        return current_eip_level == EipLevel.BLOCKING;
+    }
 
-        wants_to_disconnect = false;
-        current_status.setChanged();
-        current_status.notifyObservers();
+    /**
+     *
+     * @return true immediately after traffic blocking VoidVpn was established.
+     */
+    public boolean isBlockingVpnEstablished() {
+        return vpn_level == ConnectionStatus.LEVEL_BLOCKING;
     }
 
-    public void setConnectedOrDisconnected() {
-        is_connecting = false;
-        wants_to_disconnect = false;
-        current_status.setChanged();
-        current_status.notifyObservers();
+    public boolean isDisconnected() {
+        return current_eip_level == EipLevel.DISCONNECTED;
     }
 
-    public void setDisconnecting() {
-        wants_to_disconnect = true;
-        is_connecting = false;
+    /**
+     * ics-openvpn's paused state is not implemented yet
+     * @return
+     */
+    @Deprecated
+    public boolean isPaused() {
+        return vpn_level == ConnectionStatus.LEVEL_VPNPAUSED;
     }
 
     public String getState() {
@@ -121,7 +212,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
     }
 
     public ConnectionStatus getLevel() {
-        return level;
+        return vpn_level;
     }
 
     private void setState(String state) {
@@ -137,7 +228,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
     }
 
     private void setLevel(ConnectionStatus level) {
-        EipStatus.level = level;
+        this.vpn_level = level;
     }
 
     public boolean errorInLast(int lines, Context context) {
@@ -169,7 +260,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
 
     @Override
     public String toString() {
-        return "State: " + state + " Level: " + level.toString();
+        return "State: " + state + " Level: " + vpn_level.toString();
     }
 
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
index cbf0fed2928fda34a281724ea3305816f7b92a0c..46c010ca2f4c772a0b2cacc6d82ab5ed94d414db 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
@@ -1,41 +1,58 @@
 package se.leap.bitmaskclient.eip;
 
-import android.content.*;
-import android.net.*;
-import android.os.*;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.VpnService;
+import android.os.Build;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.IOException;
+
+import de.blinkt.openvpn.core.ConnectionStatus;
+import de.blinkt.openvpn.core.VpnStatus;
+import se.leap.bitmaskclient.R;
+
+import static se.leap.bitmaskclient.Dashboard.SHARED_PREFERENCES;
+import static se.leap.bitmaskclient.eip.Constants.ACTION_START_ALWAYS_ON_EIP;
 
-import java.io.*;
 
 public class VoidVpnService extends VpnService {
 
     static final String TAG = VoidVpnService.class.getSimpleName();
     static ParcelFileDescriptor fd;
-
     static Thread thread;
+    private final int ALWAYS_ON_MIN_API_LEVEL = Build.VERSION_CODES.N;
+    private static final String STATE_ESTABLISH = "ESTABLISHVOIDVPN";
+    private static final String STATE_STOP = "STOPVOIDVPN";
 
     @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
+    public int onStartCommand(final Intent intent, int flags, int startId) {
         String action = intent != null ? intent.getAction() : "";
-        if (action == Constants.START_BLOCKING_VPN_PROFILE) {
+        if (action.equals(Constants.START_BLOCKING_VPN_PROFILE)) {
             thread = new Thread(new Runnable() {
                 public void run() {
-                    Builder builder = new Builder();
-                    builder.setSession("Blocking until running");
-                    builder.addAddress("10.42.0.8", 16);
-                    builder.addRoute("0.0.0.0", 1);
-                    builder.addRoute("192.168.1.0", 24);
-                    builder.addDnsServer("10.42.0.1");
-                    try {
-                        fd = builder.establish();
-
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
+                    establishBlockingVpn();
+                    SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+                    preferences.edit().putBoolean(Constants.IS_ALWAYS_ON, false).commit();
+                    Log.d(TAG, "start blocking vpn profile - always on = false");
+                }
+            });
+            thread.run();
+        } else if (action.equals("android.net.VpnService") && Build.VERSION.SDK_INT >= ALWAYS_ON_MIN_API_LEVEL) {
+            //only always-on feature triggers this
+            thread = new Thread(new Runnable() {
+                public void run() {
+                    establishBlockingVpn();
+                    SharedPreferences preferences = getSharedPreferences(SHARED_PREFERENCES, MODE_PRIVATE);
+                    preferences.edit().putBoolean(Constants.IS_ALWAYS_ON, true).commit();
+                    requestVpnWithLastSelectedProfile();
+                    Log.d(TAG, "start blocking vpn profile - always on = true");
                 }
             });
             thread.run();
         }
-        return 0;
+        return START_STICKY;
     }
 
     @Override
@@ -48,6 +65,8 @@ public class VoidVpnService extends VpnService {
         if (thread != null)
             thread.interrupt();
         closeFd();
+        VpnStatus.updateStateString(STATE_STOP, "",
+                R.string.void_vpn_stopped, ConnectionStatus.LEVEL_NOTCONNECTED);
     }
 
     public static boolean isRunning() throws NullPointerException {
@@ -62,4 +81,45 @@ public class VoidVpnService extends VpnService {
             e.printStackTrace();
         }
     }
+
+    private Builder prepareBlockingVpnProfile() {
+        Builder builder = new Builder();
+        builder.setSession("Blocking until running");
+        builder.addRoute("0.0.0.0", 1);
+        builder.addRoute("192.168.1.0", 24);
+        builder.addDnsServer("10.42.0.1");
+        builder.addAddress("10.42.0.8", 16);
+        return builder;
+
+    }
+
+    private void establishBlockingVpn() {
+        try {
+            VpnStatus.logInfo(getString(R.string.void_vpn_establish));
+            VpnStatus.updateStateString(STATE_ESTABLISH, "",
+                    R.string.void_vpn_establish, ConnectionStatus.LEVEL_BLOCKING);
+            Builder builder = prepareBlockingVpnProfile();
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)  {
+                builder.addDisallowedApplication(getPackageName());
+            }
+
+            fd = builder.establish();
+        } catch (Exception e) {
+            // Catch any exception
+            e.printStackTrace();
+            VpnStatus.logError(R.string.void_vpn_error_establish);
+        }
+    }
+
+    private void requestVpnWithLastSelectedProfile() {
+        Intent startEIP = new Intent(getApplicationContext(), EIP.class);
+        startEIP.setAction(ACTION_START_ALWAYS_ON_EIP);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            //noinspection NewApi
+            getApplicationContext().startForegroundService(startEIP);
+        } else {
+            getApplicationContext().startService(startEIP);
+        }
+    }
+
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
index d124c395657d62a3a0dc662d2feb25d275e80d83..37744927547025cdb220fb82d659df4bc375a7da 100644
--- a/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/SessionDialog.java
@@ -159,7 +159,7 @@ public class SessionDialog extends DialogFragment {
         public void logIn(String username, String password);
 
         public void signUp(String username, String password);
-
+        //FIXME: can we remove this method?
         public void cancelLoginOrSignup();
     }
 
diff --git a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
index 2018990427655c3d55aed2213757db1e15118744..14323f8e8c75e200d17a768cf55267f80433798d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/userstatus/UserStatusFragment.java
@@ -24,7 +24,6 @@ import se.leap.bitmaskclient.ProviderAPI;
 import se.leap.bitmaskclient.ProviderAPICommand;
 import se.leap.bitmaskclient.ProviderAPIResultReceiver;
 import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.eip.EipStatus;
 
 public class UserStatusFragment extends Fragment implements Observer, SessionDialog.SessionDialogInterface {
 
@@ -169,7 +168,7 @@ public class UserStatusFragment extends Fragment implements Observer, SessionDia
     }
 
     public void cancelLoginOrSignup() {
-        EipStatus.getInstance().setConnectedOrDisconnected();
+        //EipStatus.getInstance().setConnectedOrDisconnected();
     }
 
     private Bundle bundlePassword(String password) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 04e83a1850e7fad1c3244fbf6ffb3f2392a156b2..70f6f4ab2835328866d8e18ef426c1e1f0309753 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -76,5 +76,10 @@
     <string name="signingup_message">is being registered.</string>
     <string name="vpn.button.turn.on">Turn on</string>
     <string name="vpn.button.turn.off">Turn off</string>
+    <string name="vpn_button_turn_off_blocking">Stop blocking</string>
     <string name="bitmask_log">Bitmask Log</string>
+    <string name="void_vpn_establish">Bitmask blocks all outgoing internet traffic.</string>
+    <string name="void_vpn_error_establish">Failed to establish blocking VPN.</string>
+    <string name="void_vpn_stopped">Stopped blocking all outgoing internet traffic.</string>
+    <string name="void_vpn_title">Blocking traffic</string>
 </resources>