Improve killswitch behavior on Win32. Now there exists a button for it.

This commit is contained in:
Ludvig Strigeus 2018-10-21 21:53:02 +02:00
parent 6dd3dcd8d5
commit 358c79a918
13 changed files with 190 additions and 125 deletions

View file

@ -60,10 +60,11 @@ BEGIN
PUSHBUTTON "&Connect",ID_START,247,3,50,14
PUSHBUTTON "&Disconnect",ID_STOP,247,19,50,14
PUSHBUTTON "&Edit Config",ID_EDITCONF,247,35,50,14
PUSHBUTTON "Turn Off &Kill Switch",ID_BTN_KILLSWITCH,154,19,90,14,WS_CLIPSIBLINGS
CONTROL "",IDC_RICHEDIT21,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,167,180,40,16
CONTROL "",IDC_ADVANCEDBOX,"AdvancedBox",0x0,105,181,35,15
CONTROL "",IDC_GRAPHBOX,"GraphBox",0x0,239,181,35,15
CONTROL "",IDC_PAINTBOX,"PaintBox",0x0,4,0,240,44
CONTROL "",IDC_PAINTBOX,"PaintBox",0x0,4,0,240,44,0x4000000L
CONTROL "",IDC_TAB,"SysTabControl32",WS_TABSTOP,4,49,293,122
END
@ -166,6 +167,7 @@ BEGIN
MENUITEM "Yes, &Both Methods", IDSETT_BLOCKINTERNET_BOTH
MENUITEM SEPARATOR
MENUITEM "Block While &Disconnected", IDSETT_BLOCKINTERNET_DISCONN
MENUITEM "Allow Traffic to &Local Networks", IDSETT_BLOCKINTERNET_ALLOWLOCAL
END
POPUP "&Service Mode"
BEGIN

View file

@ -36,12 +36,11 @@ enum {
static uint8 internet_route_blocking_state;
static SLIST_HEADER freelist_head;
static HKEY g_hklm_reg_key;
static uint8 g_killswitch_curr = 255, g_killswitch_want;
static uint8 g_killswitch_curr, g_killswitch_want, g_killswitch_currconn;
bool g_allow_pre_post;
static InternetBlockState GetInternetBlockState(bool *is_activated);
static void DeactivateKillSwitch(InternetBlockState want);
static void DeactivateKillSwitch(uint32 want);
Packet *AllocPacket() {
Packet *packet = (Packet*)InterlockedPopEntrySList(&freelist_head);
@ -1280,15 +1279,9 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
dns_blocker_->RestoreDns();
}
// Cache the state of internet blocking
GetInternetBlockState(NULL);
uint8 ibs = config.internet_blocking;
if (ibs == kBlockInternet_Default || ibs == kBlockInternet_DefaultOn) {
uint8 new_ibs = (g_killswitch_want & (kBlockInternet_Firewall | kBlockInternet_Route));
ibs = (new_ibs == kBlockInternet_Off && ibs == kBlockInternet_DefaultOn) ? kBlockInternet_Firewall : new_ibs;
}
g_killswitch_currconn = config.internet_blocking;
uint8 ibs = (g_killswitch_currconn == kBlockInternet_Default) ? g_killswitch_want : g_killswitch_currconn;
bool block_all_traffic_route = (ibs & kBlockInternet_Route) != 0;
RouteInfo ri, ri6;
@ -1318,24 +1311,36 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
if (ConvertInterfaceIndexToLuid(1, &localhost_luid) || localhost_luid.Info.IfType != 24) {
RERROR("Unable to get localhost luid - while adding route based blocking.");
} else {
uint32 dst[4] = {0};
if (!AddMultipleCatchallRoutes(AF_INET, 1, (uint8*)&dst, localhost_luid, NULL))
RERROR("Unable to add routes for route based blocking.");
if (config.ipv6_cidr) {
if (!AddMultipleCatchallRoutes(AF_INET6, 1, (uint8*)&dst, localhost_luid, NULL))
RERROR("Unable to add IPv6 routes for route based blocking.");
}
g_killswitch_curr |= kBlockInternet_Route;
uint32 dst[4] = {0};
if (!AddMultipleCatchallRoutes(AF_INET, 1, (uint8*)&dst, localhost_luid, NULL)) {
RERROR("Unable to add routes for route based blocking.");
DeactivateKillSwitch(0);
return false;
}
if (config.ipv6_cidr) {
if (!AddMultipleCatchallRoutes(AF_INET6, 1, (uint8*)&dst, localhost_luid, NULL)) {
RERROR("Unable to add IPv6 routes for route based blocking.");
DeactivateKillSwitch(0);
return false;
}
}
}
}
if (ibs & kBlockInternet_Firewall) {
RINFO("Blocking all regular Internet traffic using firewall rules");
if (AddKillSwitchFirewall(ri.found_default_adapter ? &ri.default_adapter : NULL, interface_luid_, config.ipv6_cidr != 0))
g_killswitch_curr |= kBlockInternet_Firewall;
g_killswitch_curr |= kBlockInternet_Firewall;
if (!AddKillSwitchFirewall(interface_luid_, config.ipv6_cidr != 0, (ibs & kBlockInternet_AllowLocalNetworks) != 0)) {
RERROR("Unable to activate firewall based kill switch");
DeactivateKillSwitch(0);
return false;
}
}
DeactivateKillSwitch((InternetBlockState)ibs);
DeactivateKillSwitch(ibs);
// Configure default route?
if (config.use_ipv4_default_route) {
@ -2018,6 +2023,17 @@ TunsafeBackend::~TunsafeBackend() {
}
static bool GetKillSwitchRouteActive() {
RouteInfo ri;
return (GetDefaultRouteAndDeleteOldRoutes(AF_INET, NULL, TRUE, NULL, &ri) && ri.found_null_routes == 2);
}
static void RemoveKillSwitchRoute() {
RouteInfo ri;
GetDefaultRouteAndDeleteOldRoutes(AF_INET, NULL, FALSE, NULL, &ri);
GetDefaultRouteAndDeleteOldRoutes(AF_INET6, NULL, FALSE, NULL, &ri);
}
TunsafeBackendWin32::TunsafeBackendWin32(Delegate *delegate) : delegate_(delegate), dns_resolver_(&dns_blocker_) {
memset(&stats_, 0, sizeof(stats_));
wg_processor_ = NULL;
@ -2029,6 +2045,8 @@ TunsafeBackendWin32::TunsafeBackendWin32(Delegate *delegate) : delegate_(delegat
if (g_hklm_reg_key == NULL) {
RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\TunSafe", NULL, NULL, 0, KEY_ALL_ACCESS, NULL, &g_hklm_reg_key, NULL);
g_killswitch_want = RegReadInt(g_hklm_reg_key, "KillSwitch", 0);
g_killswitch_curr = GetKillSwitchRouteActive() * kBlockInternet_Route +
GetKillSwitchFirewallActive() * kBlockInternet_Firewall;
}
delegate_->OnStateChanged();
}
@ -2089,6 +2107,7 @@ void TunsafeBackendWin32::Stop() {
void TunsafeBackendWin32::Start(const char *config_file) {
StopInner(true);
dns_resolver_.ResetCancel();
g_killswitch_currconn = kBlockInternet_Default;
is_started_ = true;
memset(public_key_, 0, sizeof(public_key_));
SetStatus(kStatusInitializing);
@ -2118,7 +2137,8 @@ void TunsafeBackendWin32::StopInner(bool is_restart) {
status_ = kStatusStopped;
packet_processor_.Reset();
if (!is_restart && !(g_killswitch_want & kBlockInternet_BlockOnDisconnect))
uint8 wanted_ibs = (g_killswitch_currconn == kBlockInternet_Default) ? g_killswitch_want : g_killswitch_currconn;
if (!is_restart && !(wanted_ibs & kBlockInternet_BlockOnDisconnect))
DeactivateKillSwitch(kBlockInternet_Off);
}
}
@ -2154,35 +2174,13 @@ LinearizedGraph *TunsafeBackendWin32::GetGraph(int type) {
return graph;
}
static bool GetKillSwitchRouteActive() {
RouteInfo ri;
return (GetDefaultRouteAndDeleteOldRoutes(AF_INET, NULL, TRUE, NULL, &ri) && ri.found_null_routes == 2);
InternetBlockState TunsafeBackendWin32::GetInternetBlockState() {
return (InternetBlockState)(g_killswitch_want | (g_killswitch_curr ? kBlockInternet_Active : 0));
}
static void RemoveKillSwitchRoute() {
RouteInfo ri;
GetDefaultRouteAndDeleteOldRoutes(AF_INET, NULL, FALSE, NULL, &ri);
GetDefaultRouteAndDeleteOldRoutes(AF_INET6, NULL, FALSE, NULL, &ri);
}
static InternetBlockState GetInternetBlockState(bool *is_activated) {
// Read the value only once.
if (g_killswitch_curr == 255) {
g_killswitch_curr = GetKillSwitchRouteActive() * kBlockInternet_Route +
GetKillSwitchFirewallActive() * kBlockInternet_Firewall;
}
if (is_activated)
*is_activated = g_killswitch_curr != 0;
return (InternetBlockState)g_killswitch_want;
}
InternetBlockState TunsafeBackendWin32::GetInternetBlockState(bool *is_activated) {
return ::GetInternetBlockState(is_activated);
}
static void DeactivateKillSwitch(InternetBlockState want) {
static void DeactivateKillSwitch(uint32 want) {
// Disable blocking without reconnecting
int maybeon = g_killswitch_curr | g_killswitch_want;
uint32 maybeon = g_killswitch_curr;
if ((maybeon & kBlockInternet_Route) > (want & kBlockInternet_Route)) {
if (g_killswitch_curr & kBlockInternet_Route) {
g_killswitch_curr &= ~kBlockInternet_Route;
@ -2200,14 +2198,16 @@ static void DeactivateKillSwitch(InternetBlockState want) {
}
void TunsafeBackendWin32::SetInternetBlockState(InternetBlockState want) {
GetInternetBlockState(NULL); // ensure cache is read
if (worker_thread_ == NULL && !(want & kBlockInternet_BlockOnDisconnect))
if (worker_thread_ == NULL && !(want & kBlockInternet_BlockOnDisconnect) || !(want & kBlockInternet_Active))
DeactivateKillSwitch(kBlockInternet_Off);
else
DeactivateKillSwitch(want);
g_killswitch_want = want;
RegWriteInt(g_hklm_reg_key, "KillSwitch", (int)want);
int value = want & 0xff;
g_killswitch_want = value;
RegWriteInt(g_hklm_reg_key, "KillSwitch", (int)value);
delegate_->OnStateChanged();
}
void TunsafeBackendWin32::SetServiceStartupFlags(uint32 flags) {

View file

@ -218,7 +218,7 @@ public:
virtual void Stop() override;
virtual void RequestStats(bool enable) override;
virtual void ResetStats() override;
virtual InternetBlockState GetInternetBlockState(bool *is_activated) override;
virtual InternetBlockState GetInternetBlockState() override;
virtual void SetInternetBlockState(InternetBlockState s) override;
virtual void SetServiceStartupFlags(uint32 flags) override;
virtual LinearizedGraph *GetGraph(int type) override;
@ -248,7 +248,7 @@ private:
HANDLE worker_thread_;
bool want_periodic_stats_;
Delegate *delegate_;
char *config_file_;

View file

@ -97,8 +97,9 @@ public:
virtual void RequestStats(bool enable) = 0;
virtual void ResetStats() = 0;
virtual InternetBlockState GetInternetBlockState(bool *is_activated) = 0;
virtual InternetBlockState GetInternetBlockState() = 0;
virtual void SetInternetBlockState(InternetBlockState s) = 0;
virtual void SetServiceStartupFlags(uint32 flags) = 0;
virtual std::string GetConfigFileName() = 0;
virtual LinearizedGraph *GetGraph(int type) = 0;

View file

@ -159,7 +159,7 @@ void DnsBlocker::RestoreDns() {
}
}
static bool RemovePersistentInternetBlockingInner(HANDLE handle) {
static bool RemovePersistentInternetBlockingInner(HANDLE handle, bool destroy_sublayer) {
FWPM_FILTER_ENUM_TEMPLATE0 enum_template = {0};
HANDLE enum_handle = NULL;
DWORD err;
@ -184,7 +184,7 @@ static bool RemovePersistentInternetBlockingInner(HANDLE handle) {
}
for (UINT32 i = 0; i < num_returned; i++) {
FWPM_FILTER0 *cur_filter = filter[i];
if (memcmp(&cur_filter->subLayerKey, &TUNSAFE_GLOBAL_BLOCK_SUBLAYER, sizeof(GUID)) == 0) {
if (memcmp(&cur_filter->subLayerKey, &TUNSAFE_GLOBAL_BLOCK_SUBLAYER, sizeof(GUID)) == 0 && (destroy_sublayer || cur_filter->numFilterConditions != 0)) {
err = FwpmFilterDeleteById0(handle, cur_filter->filterId);
if (err != 0)
RERROR("FwpmFilterDeleteById0 failed: %d", err);
@ -197,10 +197,12 @@ static bool RemovePersistentInternetBlockingInner(HANDLE handle) {
enum_handle = NULL;
}
err = FwpmSubLayerDeleteByKey0(handle, &TUNSAFE_GLOBAL_BLOCK_SUBLAYER);
if (err != 0 && err != FWP_E_SUBLAYER_NOT_FOUND) {
RERROR("FwpmSubLayerDeleteByKey0 failed: %d", err);
goto getout;
if (destroy_sublayer) {
err = FwpmSubLayerDeleteByKey0(handle, &TUNSAFE_GLOBAL_BLOCK_SUBLAYER);
if (err != 0 && err != FWP_E_SUBLAYER_NOT_FOUND) {
RERROR("FwpmSubLayerDeleteByKey0 failed: %d", err);
goto getout;
}
}
getout:
@ -210,7 +212,16 @@ getout:
return false;
}
bool AddKillSwitchFirewall(const NET_LUID *default_interface, const NET_LUID &luid_to_allow, bool also_ipv6) {
struct LastKillswitchSettings {
NET_LUID luid_to_allow;
bool also_ipv6;
bool allow_local_networks;
};
static LastKillswitchSettings last_killswitch_settings;
bool AddKillSwitchFirewall(const NET_LUID &luid_to_allow, bool also_ipv6, bool allow_local_networks) {
FWPM_SUBLAYER0 *sublayer_p = NULL;
FWP_BYTE_BLOB *fwp_appid = NULL;
FWPM_FILTER0 filter;
@ -219,6 +230,11 @@ bool AddKillSwitchFirewall(const NET_LUID *default_interface, const NET_LUID &lu
HANDLE handle = NULL;
bool success = false;
LastKillswitchSettings new_settings;
new_settings.luid_to_allow = luid_to_allow;
new_settings.also_ipv6 = also_ipv6;
new_settings.allow_local_networks = allow_local_networks;
{
FWPM_SESSION0 session = {0};
err = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &handle);
@ -231,6 +247,9 @@ bool AddKillSwitchFirewall(const NET_LUID *default_interface, const NET_LUID &lu
if (FwpmSubLayerGetByKey0(handle, &TUNSAFE_GLOBAL_BLOCK_SUBLAYER, &sublayer_p) == 0) {
// The sublayer already exists
FwpmFreeMemory0((void **)&sublayer_p);
if (memcmp(&last_killswitch_settings, &new_settings, sizeof(new_settings)) != 0)
RemovePersistentInternetBlockingInner(handle, false);
} else {
// Add new sublayer
FWPM_SUBLAYER0 sublayer = {0};
@ -273,49 +292,72 @@ bool AddKillSwitchFirewall(const NET_LUID *default_interface, const NET_LUID &lu
filter.weight.uint8 = 14;
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, also_ipv6, 2))
goto getout;
// Permit everything that's loopback
filter_condition[0].fieldKey = FWPM_CONDITION_INTERFACE_TYPE;
filter_condition[0].conditionValue.type = FWP_UINT32;
filter_condition[0].conditionValue.uint32 = 24;
filter_condition[0].matchType = FWP_MATCH_EQUAL;
filter.weight.uint8 = 13;
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, also_ipv6, 2))
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, also_ipv6, 3))
goto getout;
// Permit all queries on the DHCP port (It uses 68 on the local side and 67 on the remote side)
if (default_interface) {
filter_condition[2].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
filter_condition[2].matchType = FWP_MATCH_EQUAL;
filter_condition[2].conditionValue.type = FWP_UINT16;
filter_condition[2].conditionValue.uint16 = 68;
filter_condition[1].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
filter_condition[1].matchType = FWP_MATCH_EQUAL;
filter_condition[1].conditionValue.type = FWP_UINT16;
filter_condition[1].conditionValue.uint16 = 67;
filter.numFilterConditions = 3;
filter_condition[0].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE;
filter_condition[0].conditionValue.type = FWP_UINT64;
filter_condition[0].conditionValue.uint64 = (uint64*)&default_interface->Value;
filter_condition[0].matchType = FWP_MATCH_EQUAL;
filter.weight.uint8 = 12;
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, also_ipv6, 2))
goto getout;
// Permit everything going out to local networks
// '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'
if (allow_local_networks) {
static const FWP_V4_ADDR_AND_MASK kLocalNetworkAddrMask[3] = {
{0x0A000000, 0xff000000}, // 10.0.0.0/8
{0xAC100000, 0xfff00000}, // 172.16.0.0/12
{0xC0A80000, 0xffff0000}, // 192.168.0.0/16
};
for (int i = 0; i < 3; i++) {
FWP_V4_ADDR_AND_MASK addr_mask = kLocalNetworkAddrMask[i];
filter.numFilterConditions = 1;
filter_condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS;
filter_condition[0].conditionValue.type = FWP_V4_ADDR_MASK;
filter_condition[0].conditionValue.v4AddrMask = &addr_mask;
filter_condition[0].matchType = FWP_MATCH_EQUAL;
filter.weight.uint8 = 12;
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, false, 4))
goto getout;
}
}
// Permit all queries on the DHCP port (It uses 68 on the local side and 67 on the remote side)
filter_condition[2].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;
filter_condition[2].matchType = FWP_MATCH_EQUAL;
filter_condition[2].conditionValue.type = FWP_UINT16;
filter_condition[2].conditionValue.uint16 = 68;
filter_condition[1].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
filter_condition[1].matchType = FWP_MATCH_EQUAL;
filter_condition[1].conditionValue.type = FWP_UINT16;
filter_condition[1].conditionValue.uint16 = 67;
filter.numFilterConditions = 3;
filter_condition[0].fieldKey = FWPM_CONDITION_IP_PROTOCOL;
filter_condition[0].conditionValue.type = FWP_UINT8;
filter_condition[0].conditionValue.uint8 = 17; // UDP
filter_condition[0].matchType = FWP_MATCH_EQUAL;
filter.weight.uint8 = 12;
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, also_ipv6, 5))
goto getout;
// Block the rest
filter.numFilterConditions = 0;
filter.weight.type = FWP_EMPTY;
filter.action.type = FWP_ACTION_BLOCK;
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, also_ipv6, 3))
if (!FwpmFilterAddCheckedAleConnect(handle, &filter, also_ipv6, 6))
goto getout;
success = true;
last_killswitch_settings = new_settings;
getout:
if (!success)
memset(&last_killswitch_settings, 0, sizeof(last_killswitch_settings));
if (handle != NULL) {
// delete the layer on failure
if (!success)
RemovePersistentInternetBlockingInner(handle);
RemovePersistentInternetBlockingInner(handle, true);
FwpmEngineClose0(handle);
handle = NULL;
}
@ -345,7 +387,7 @@ void RemoveKillSwitchFirewall() {
goto getout;
}
RemovePersistentInternetBlockingInner(handle);
RemovePersistentInternetBlockingInner(handle, true);
getout:
if (handle != NULL) {

View file

@ -18,6 +18,6 @@ public:
bool also_ipv6_;
};
bool AddKillSwitchFirewall(const NET_LUID *default_interface, const NET_LUID &luid_to_allow, bool also_ipv6);
bool AddKillSwitchFirewall(const NET_LUID &luid_to_allow, bool also_ipv6, bool allow_local_networks);
void RemoveKillSwitchFirewall();
bool GetKillSwitchFirewallActive();

View file

@ -28,6 +28,8 @@
#define IDSETT_SERVICE_CONNECT_AUTO 24
#define IDSETT_SERVICE_MINIMIZE_AUTO 25
#define IDSETT_BLOCKINTERNET_DISCONN 26
#define IDSETT_BLOCKINTERNET_ALLOWLOCAL 27
#define ID_BTN_KILLSWITCH 28
#define IDC_PAINTBOX 30
#define IDC_GRAPHBOX 31
#define IDC_ADVANCEDBOX 32
@ -41,13 +43,12 @@
#define IDC_PUBLIC_KEY 109
#define IDC_TAB 110
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 113
#define _APS_NEXT_COMMAND_VALUE 40026
#define _APS_NEXT_COMMAND_VALUE 40030
#define _APS_NEXT_CONTROL_VALUE 1016
#define _APS_NEXT_SYMED_VALUE 101
#endif

View file

@ -589,13 +589,11 @@ void TunsafeServiceBackend::SendStateUpdate(TunsafeServiceServer *filter) {
return;
uint8 *temp = new uint8[current_filename_.size() + 1 + sizeof(ServiceState)];
bool is_activated;
memset(temp, 0, sizeof(ServiceState));
ServiceState *ss = (ServiceState *)temp;
ss->is_started = backend_->is_started();
ss->internet_block_state = backend_->GetInternetBlockState(&is_activated);
ss->internet_block_state_active = is_activated;
ss->internet_block_state = backend_->GetInternetBlockState();
ss->ipv4_ip = backend_->GetIP();
memcpy(ss->public_key, backend_->public_key(), 32);
memcpy(temp + sizeof(ServiceState), current_filename_.c_str(), current_filename_.size() + 1);
@ -763,10 +761,9 @@ bool TunsafeServiceServer::HandleMessage(int type, uint8 *data, size_t size) {
break;
case TS_SERVICE_REQ_SET_INTERNET_BLOCKSTATE:
if (size < 1)
if (size < 2)
return false;
service_backend_->backend_->SetInternetBlockState((InternetBlockState)data[0]);
service_backend_->OnStateChanged();
service_backend_->backend_->SetInternetBlockState((InternetBlockState)Read16(data));
break;
case TS_SERVICE_REQ_RESETSTATS:
@ -934,15 +931,13 @@ void TunsafeServiceClient::ResetStats() {
connection_->WritePacket(TS_SERVICE_REQ_RESETSTATS, NULL, 0);
}
InternetBlockState TunsafeServiceClient::GetInternetBlockState(bool *is_activated) {
if (is_activated)
*is_activated = service_state_.internet_block_state_active;
InternetBlockState TunsafeServiceClient::GetInternetBlockState() {
return (InternetBlockState)service_state_.internet_block_state;
}
void TunsafeServiceClient::SetInternetBlockState(InternetBlockState s) {
uint8 v = (uint8)s;
connection_->WritePacket(TS_SERVICE_REQ_SET_INTERNET_BLOCKSTATE, &v, 1);
uint16 v = (uint16)s;
connection_->WritePacket(TS_SERVICE_REQ_SET_INTERNET_BLOCKSTATE, (uint8*)&v, sizeof(v));
}
void TunsafeServiceClient::SetServiceStartupFlags(uint32 flags) {

View file

@ -162,9 +162,9 @@ private:
struct ServiceState {
uint8 is_started : 1;
uint8 internet_block_state_active : 1;
uint8 internet_block_state;
uint8 reserved[26 + 64];
uint8 reserved1;
uint16 internet_block_state;
uint8 reserved[24 + 64];
uint32 ipv4_ip;
uint8 public_key[32];
};
@ -184,7 +184,7 @@ public:
virtual void Stop();
virtual void RequestStats(bool enable);
virtual void ResetStats();
virtual InternetBlockState GetInternetBlockState(bool *is_activated);
virtual InternetBlockState GetInternetBlockState();
virtual void SetInternetBlockState(InternetBlockState s);
virtual std::string GetConfigFileName();
virtual void SetServiceStartupFlags(uint32 flags);

View file

@ -1,7 +1,7 @@
#pragma once
#define TUNSAFE_PIPE_NAME "\\\\.\\pipe\\TunSafe\\ServiceControl"
#define TUNSAFE_SERVICE_PROTOCOL_VERSION 20180916001
#define TUNSAFE_SERVICE_PROTOCOL_VERSION 20181021001
enum {
TS_SERVICE_REQ_LOGIN = 0,

View file

@ -220,7 +220,11 @@ public:
}
}
uint32 state = g_backend->GetInternetBlockState();
bool running = g_backend->is_started();
ShowWindow(GetDlgItem(g_ui_window, ID_BTN_KILLSWITCH), (!running || (state & kBlockInternet_Both) == 0) && (state & kBlockInternet_Active) ? SW_SHOW : SW_HIDE);
SetDlgItemText(g_ui_window, ID_START, running ? "Re&connect" : "&Connect");
InvalidatePaintbox();
EnableWindow(GetDlgItem(g_ui_window, ID_STOP), running);
@ -813,6 +817,7 @@ enum {
static const WindowSizingItem kWindowSizing[] = {
{ID_START,WSI_LEFT | WSI_RIGHT},
{ID_BTN_KILLSWITCH, WSI_LEFT | WSI_RIGHT},
{ID_STOP,WSI_LEFT | WSI_RIGHT},
{ID_EDITCONF,WSI_LEFT | WSI_RIGHT},
{IDC_PAINTBOX,WSI_RIGHT},
@ -909,22 +914,33 @@ static void HandleClickedItem(HWND hWnd, int wParam) {
case IDSETT_BLOCKINTERNET_FIREWALL:
case IDSETT_BLOCKINTERNET_BOTH:
{
uint32 old_state = g_backend->GetInternetBlockState(NULL);
uint32 old_state = g_backend->GetInternetBlockState();
uint32 new_state = wParam - IDSETT_BLOCKINTERNET_OFF;
if ((old_state & kBlockInternet_Both) == kBlockInternet_Off && new_state != kBlockInternet_Off) {
if ((old_state & kBlockInternet_TypeMask) == kBlockInternet_Off && new_state != kBlockInternet_Off) {
if (MessageBoxA(g_ui_window, "Warning! All Internet traffic will be blocked while TunSafe is active. Only traffic through TunSafe will be allowed.\r\n\r\nThe blocking is activated the next time TunSafe connects.\r\n\r\nDo you want to continue?", "TunSafe", MB_ICONWARNING | MB_OKCANCEL) == IDCANCEL)
return;
}
g_backend->SetInternetBlockState((InternetBlockState)(new_state | (old_state & kBlockInternet_BlockOnDisconnect)));
g_backend->SetInternetBlockState((InternetBlockState)(new_state | (old_state & ~kBlockInternet_TypeMask)));
if ((~old_state & new_state) && g_backend->is_started())
StartTunsafeBackend(UIW_START);
return;
}
case IDSETT_BLOCKINTERNET_DISCONN: {
uint32 old_state = g_backend->GetInternetBlockState(NULL);
g_backend->SetInternetBlockState((InternetBlockState)(old_state ^ kBlockInternet_BlockOnDisconnect));
g_backend->SetInternetBlockState((InternetBlockState)(g_backend->GetInternetBlockState() ^ kBlockInternet_BlockOnDisconnect));
return;
}
case IDSETT_BLOCKINTERNET_ALLOWLOCAL: {
g_backend->SetInternetBlockState((InternetBlockState)(g_backend->GetInternetBlockState() ^ kBlockInternet_AllowLocalNetworks));
if (g_backend->is_started())
StartTunsafeBackend(UIW_START);
return;
}
case ID_BTN_KILLSWITCH: {
g_backend->SetInternetBlockState((InternetBlockState)(g_backend->GetInternetBlockState() & ~kBlockInternet_Active));
return;
}
@ -1030,11 +1046,11 @@ static INT_PTR WINAPI DlgProc(HWND hWnd, UINT message, WPARAM wParam,
CheckMenuItem(menu, IDSETT_SERVICE_MINIMIZE_AUTO, MF_CHECKED * !!(g_startup_flags & kStartupFlag_MinimizeToTrayWhenWindowsStarts));
CheckMenuItem(menu, IDSETT_PREPOST, g_allow_pre_post ? MF_CHECKED : 0);
bool is_activated = false;
int value = g_backend->GetInternetBlockState(&is_activated);
int value = g_backend->GetInternetBlockState();
CheckMenuRadioItem(menu, IDSETT_BLOCKINTERNET_OFF, IDSETT_BLOCKINTERNET_BOTH, IDSETT_BLOCKINTERNET_OFF + (value & kBlockInternet_Both), MF_BYCOMMAND);
CheckMenuRadioItem(menu, IDSETT_SERVICE_OFF, IDSETT_SERVICE_BACKGROUND, IDSETT_SERVICE_OFF + (g_startup_flags & 3), MF_BYCOMMAND);
CheckMenuItem(menu, IDSETT_BLOCKINTERNET_DISCONN, (value & kBlockInternet_BlockOnDisconnect) ? MF_CHECKED : 0);
CheckMenuItem(menu, IDSETT_BLOCKINTERNET_ALLOWLOCAL, (value & kBlockInternet_AllowLocalNetworks) ? MF_CHECKED : 0);
break;
}
@ -1691,6 +1707,8 @@ static bool CreateMainWindow() {
hwndGraphBox = GetDlgItem(g_ui_window, IDC_GRAPHBOX);
hwndAdvancedBox = GetDlgItem(g_ui_window, IDC_ADVANCEDBOX);
SetWindowLong(hwndPaintBox, GWL_STYLE, GetWindowLong(hwndPaintBox, GWL_STYLE) | WS_CLIPSIBLINGS);
SetWindowLong(hwndEdit, GWL_EXSTYLE, GetWindowLong(hwndEdit, GWL_EXSTYLE) &~ WS_EX_CLIENTEDGE);
// Create the status bar.

View file

@ -56,13 +56,14 @@ enum InternetBlockState {
kBlockInternet_Route = 1,
kBlockInternet_Firewall = 2,
kBlockInternet_Both = 3,
kBlockInternet_TypeMask = 0xf,
kBlockInternet_BlockOnDisconnect = 16,
// An unspecified value that uses either route or firewall
kBlockInternet_DefaultOn = 254,
kBlockInternet_AllowLocalNetworks = 32,
kBlockInternet_Default = 255,
kBlockInternet_Active = 256,
};
class WireguardProcessor {

View file

@ -140,23 +140,28 @@ bool WgFileParser::ParseFlag(const char *group, const char *key, char *value) {
wg_->SetDnsBlocking(v);
} else if (strcmp(key, "BlockInternet") == 0) {
uint8 v = kBlockInternet_Default;
SplitString(value, ',', &ss);
for (size_t i = 0; i < ss.size(); i++) {
if (strcmp(ss[i], "route") == 0) {
const char *s = ss[i];
if (strcmp(s, "route") == 0) {
if (v & 128) v = 0;
v |= kBlockInternet_Route;
} else if (strcmp(ss[i], "firewall") == 0) {
} else if (strcmp(s, "firewall") == 0 || strcmp(s, "on") == 0) {
if (v & 128) v = 0;
v |= kBlockInternet_Firewall;
} else if (strcmp(ss[i], "off") == 0)
} else if (strcmp(s, "off") == 0) {
v = 0;
else if (strcmp(ss[i], "on") == 0)
v = kBlockInternet_DefaultOn;
else if (strcmp(ss[i], "default") == 0)
} else if (strcmp(s, "default") == 0) {
v = kBlockInternet_Default;
else
} else if (strcmp(s, "persist") == 0) {
if (v & 128) v = 0;
v |= kBlockInternet_BlockOnDisconnect;
} else if (strcmp(s, "allow_local") == 0) {
if (v & 128) v = 0;
v |= kBlockInternet_AllowLocalNetworks;
} else {
RERROR("Unknown mode in BlockInternet: %s", ss[i]);
}
}
wg_->SetInternetBlocking((InternetBlockState)v);