Windows killswitch strict mode backend part
This commit is contained in:
parent
212e9b3a91
commit
4d91245376
11 changed files with 378 additions and 201 deletions
|
|
@ -29,6 +29,8 @@
|
|||
#include "platforms/windows/windowsutils.h"
|
||||
#include "winsock.h"
|
||||
|
||||
#include "killswitch.h"
|
||||
|
||||
#define IPV6_ADDRESS_SIZE 16
|
||||
|
||||
// ID for the Firewall Sublayer
|
||||
|
|
@ -185,10 +187,23 @@ bool WindowsFirewall::enableKillSwitch(int vpnAdapterIndex) {
|
|||
}
|
||||
|
||||
logger.info() << "Enabling Killswitch Using Adapter:" << vpnAdapterIndex;
|
||||
if (vpnAdapterIndex < 0)
|
||||
{
|
||||
IPAddress allv4("0.0.0.0/0");
|
||||
if (!blockTrafficTo(allv4, MED_WEIGHT,
|
||||
"Block Internet", "killswitch")) {
|
||||
return false;
|
||||
}
|
||||
IPAddress allv6("::/0");
|
||||
if (!blockTrafficTo(allv6, MED_WEIGHT,
|
||||
"Block Internet", "killswitch")) {
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
FW_OK(allowTrafficOfAdapter(vpnAdapterIndex, MED_WEIGHT,
|
||||
"Allow usage of VPN Adapter"));
|
||||
"Allow usage of VPN Adapter"));
|
||||
FW_OK(allowDHCPTraffic(MED_WEIGHT, "Allow DHCP Traffic"));
|
||||
FW_OK(allowHyperVTraffic(MED_WEIGHT, "Allow Hyper-V Traffic"));
|
||||
FW_OK(allowHyperVTraffic(MAX_WEIGHT, "Allow Hyper-V Traffic"));
|
||||
FW_OK(allowTrafficForAppOnAll(getCurrentPath(), MAX_WEIGHT,
|
||||
"Allow all for AmneziaVPN.exe"));
|
||||
FW_OK(blockTrafficOnPort(53, MED_WEIGHT, "Block all DNS"));
|
||||
|
|
@ -287,37 +302,41 @@ bool WindowsFirewall::disablePeerTraffic(const QString& pubkey) {
|
|||
}
|
||||
|
||||
bool WindowsFirewall::disableKillSwitch() {
|
||||
auto result = FwpmTransactionBegin(m_sessionHandle, NULL);
|
||||
auto cleanup = qScopeGuard([&] {
|
||||
return KillSwitch::instance()->disableKillSwitch();
|
||||
}
|
||||
|
||||
bool WindowsFirewall::allowAllTraffic() {
|
||||
auto result = FwpmTransactionBegin(m_sessionHandle, NULL);
|
||||
auto cleanup = qScopeGuard([&] {
|
||||
if (result != ERROR_SUCCESS) {
|
||||
FwpmTransactionAbort0(m_sessionHandle);
|
||||
}
|
||||
});
|
||||
if (result != ERROR_SUCCESS) {
|
||||
FwpmTransactionAbort0(m_sessionHandle);
|
||||
logger.error() << "FwpmTransactionBegin0 failed. Return value:.\n"
|
||||
<< result;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (result != ERROR_SUCCESS) {
|
||||
logger.error() << "FwpmTransactionBegin0 failed. Return value:.\n"
|
||||
<< result;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& filterID : m_peerRules.values()) {
|
||||
FwpmFilterDeleteById0(m_sessionHandle, filterID);
|
||||
}
|
||||
for (const auto& filterID : m_peerRules.values()) {
|
||||
FwpmFilterDeleteById0(m_sessionHandle, filterID);
|
||||
}
|
||||
|
||||
for (const auto& filterID : qAsConst(m_activeRules)) {
|
||||
FwpmFilterDeleteById0(m_sessionHandle, filterID);
|
||||
}
|
||||
for (const auto& filterID : qAsConst(m_activeRules)) {
|
||||
FwpmFilterDeleteById0(m_sessionHandle, filterID);
|
||||
}
|
||||
|
||||
// Commit!
|
||||
result = FwpmTransactionCommit0(m_sessionHandle);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
logger.error() << "FwpmTransactionCommit0 failed. Return value:.\n"
|
||||
<< result;
|
||||
return false;
|
||||
}
|
||||
m_peerRules.clear();
|
||||
m_activeRules.clear();
|
||||
logger.debug() << "Firewall Disabled!";
|
||||
return true;
|
||||
// Commit!
|
||||
result = FwpmTransactionCommit0(m_sessionHandle);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
logger.error() << "FwpmTransactionCommit0 failed. Return value:.\n"
|
||||
<< result;
|
||||
return false;
|
||||
}
|
||||
m_peerRules.clear();
|
||||
m_activeRules.clear();
|
||||
logger.debug() << "Firewall Disabled!";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WindowsFirewall::allowTrafficForAppOnAll(const QString& exePath,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class WindowsFirewall final : public QObject {
|
|||
bool enablePeerTraffic(const InterfaceConfig& config);
|
||||
bool disablePeerTraffic(const QString& pubkey);
|
||||
bool disableKillSwitch();
|
||||
bool allowAllTraffic();
|
||||
|
||||
private:
|
||||
WindowsFirewall(QObject* parent);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "secure_qsettings.h"
|
||||
|
||||
#include "QAead.h"
|
||||
#include "QBlockCipher.h"
|
||||
#include "../client/3rd/QSimpleCrypto/src/include/QAead.h"
|
||||
#include "../client/3rd/QSimpleCrypto/src/include/QBlockCipher.h"
|
||||
#include "utilities.h"
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <QObject>
|
||||
#include <QSettings>
|
||||
|
||||
#include "keychain.h"
|
||||
#include "../client/3rd/qtkeychain/qtkeychain/keychain.h"
|
||||
|
||||
constexpr const char *settingsKeyTag = "settingsKeyTag";
|
||||
constexpr const char *settingsIvTag = "settingsIvTag";
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class IpcInterface
|
|||
SLOT( void StopRoutingIpv6() );
|
||||
|
||||
SLOT( bool disableKillSwitch() );
|
||||
SLOT( bool disableAllTraffic() );
|
||||
SLOT( bool enablePeerTraffic( const QJsonObject &configStr) );
|
||||
SLOT( bool enableKillSwitch( const QJsonObject &excludeAddr, int vpnAdapterIndex) );
|
||||
SLOT( bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) );
|
||||
|
|
|
|||
|
|
@ -8,21 +8,12 @@
|
|||
#include "logger.h"
|
||||
#include "router.h"
|
||||
|
||||
#include "../core/networkUtilities.h"
|
||||
#include "../client/protocols/protocols_defs.h"
|
||||
#include "killswitch.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "../client/platforms/windows/daemon/windowsdaemon.h"
|
||||
#include "../client/platforms/windows/daemon/windowsfirewall.h"
|
||||
#include "tapcontroller_win.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "../client/platforms/linux/daemon/linuxfirewall.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
#include "../client/platforms/macos/daemon/macosfirewall.h"
|
||||
#endif
|
||||
|
||||
IpcServer::IpcServer(QObject *parent) : IpcInterfaceSource(parent)
|
||||
|
||||
|
|
@ -35,10 +26,6 @@ int IpcServer::createPrivilegedProcess()
|
|||
qDebug() << "IpcServer::createPrivilegedProcess";
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
WindowsFirewall::instance()->init();
|
||||
#endif
|
||||
|
||||
m_localpid++;
|
||||
|
||||
ProcessDescriptor pd(this);
|
||||
|
|
@ -192,166 +179,22 @@ void IpcServer::setLogsEnabled(bool enabled)
|
|||
}
|
||||
}
|
||||
|
||||
bool IpcServer::disableAllTraffic()
|
||||
{
|
||||
return KillSwitch::instance()->disableAllTraffic();
|
||||
}
|
||||
|
||||
bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterIndex)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return WindowsFirewall::instance()->enableKillSwitch(vpnAdapterIndex);
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||
int splitTunnelType = configStr.value("splitTunnelType").toInt();
|
||||
QJsonArray splitTunnelSites = configStr.value("splitTunnelSites").toArray();
|
||||
bool blockAll = 0;
|
||||
bool allowNets = 0;
|
||||
bool blockNets = 0;
|
||||
QStringList allownets;
|
||||
QStringList blocknets;
|
||||
|
||||
if (splitTunnelType == 0) {
|
||||
blockAll = true;
|
||||
allowNets = true;
|
||||
allownets.append(configStr.value("vpnServer").toString());
|
||||
} else if (splitTunnelType == 1) {
|
||||
blockNets = true;
|
||||
for (auto v : splitTunnelSites) {
|
||||
blocknets.append(v.toString());
|
||||
}
|
||||
} else if (splitTunnelType == 2) {
|
||||
blockAll = true;
|
||||
allowNets = true;
|
||||
allownets.append(configStr.value("vpnServer").toString());
|
||||
for (auto v : splitTunnelSites) {
|
||||
allownets.append(v.toString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// double-check + ensure our firewall is installed and enabled
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), blockAll);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("110.allowNets"), allowNets);
|
||||
LinuxFirewall::updateAllowNets(allownets);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("120.blockNets"), blockAll);
|
||||
LinuxFirewall::updateBlockNets(blocknets);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("200.allowVPN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("300.allowLAN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("310.blockDNS"), true);
|
||||
QStringList dnsServers;
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns1).toString());
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns2).toString());
|
||||
dnsServers.append("127.0.0.1");
|
||||
dnsServers.append("127.0.0.53");
|
||||
LinuxFirewall::updateDNSServers(dnsServers);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("400.allowPIA"), true);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
|
||||
// double-check + ensure our firewall is installed and enabled. This is necessary as
|
||||
// other software may disable pfctl before re-enabling with their own rules (e.g other VPNs)
|
||||
if (!MacOSFirewall::isInstalled())
|
||||
MacOSFirewall::install();
|
||||
|
||||
MacOSFirewall::ensureRootAnchorPriority();
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("000.allowLoopback"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("100.blockAll"), blockAll);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("110.allowNets"), allowNets);
|
||||
MacOSFirewall::setAnchorTable(QStringLiteral("110.allowNets"), allowNets, QStringLiteral("allownets"), allownets);
|
||||
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("120.blockNets"), blockNets);
|
||||
MacOSFirewall::setAnchorTable(QStringLiteral("120.blockNets"), blockNets, QStringLiteral("blocknets"), blocknets);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("200.allowVPN"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("250.blockIPv6"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("290.allowDHCP"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("300.allowLAN"), true);
|
||||
|
||||
QStringList dnsServers;
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns1).toString());
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns2).toString());
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("310.blockDNS"), true);
|
||||
MacOSFirewall::setAnchorTable(QStringLiteral("310.blockDNS"), true, QStringLiteral("dnsaddr"), dnsServers);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return KillSwitch::instance()->enableKillSwitch(configStr, vpnAdapterIndex);
|
||||
}
|
||||
|
||||
bool IpcServer::disableKillSwitch()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return WindowsFirewall::instance()->disableKillSwitch();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
LinuxFirewall::uninstall();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
MacOSFirewall::uninstall();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return KillSwitch::instance()->disableKillSwitch();
|
||||
}
|
||||
|
||||
bool IpcServer::enablePeerTraffic(const QJsonObject &configStr)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
InterfaceConfig config;
|
||||
config.m_dnsServer = configStr.value(amnezia::config_key::dns1).toString();
|
||||
config.m_serverPublicKey = "openvpn";
|
||||
config.m_serverIpv4Gateway = configStr.value("vpnGateway").toString();
|
||||
config.m_serverIpv4AddrIn = configStr.value("vpnServer").toString();
|
||||
int vpnAdapterIndex = configStr.value("vpnAdapterIndex").toInt();
|
||||
int inetAdapterIndex = configStr.value("inetAdapterIndex").toInt();
|
||||
|
||||
int splitTunnelType = configStr.value("splitTunnelType").toInt();
|
||||
QJsonArray splitTunnelSites = configStr.value("splitTunnelSites").toArray();
|
||||
|
||||
QStringList AllowedIPAddesses;
|
||||
|
||||
// Use APP split tunnel
|
||||
if (splitTunnelType == 0 || splitTunnelType == 2) {
|
||||
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress("0.0.0.0"), 0));
|
||||
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress("::"), 0));
|
||||
}
|
||||
|
||||
if (splitTunnelType == 1) {
|
||||
for (auto v : splitTunnelSites) {
|
||||
QString ipRange = v.toString();
|
||||
if (ipRange.split('/').size() > 1) {
|
||||
config.m_allowedIPAddressRanges.append(
|
||||
IPAddress(QHostAddress(ipRange.split('/')[0]), atoi(ipRange.split('/')[1].toLocal8Bit())));
|
||||
} else {
|
||||
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress(ipRange), 32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.m_excludedAddresses.append(configStr.value("vpnServer").toString());
|
||||
if (splitTunnelType == 2) {
|
||||
for (auto v : splitTunnelSites) {
|
||||
QString ipRange = v.toString();
|
||||
config.m_excludedAddresses.append(ipRange);
|
||||
}
|
||||
}
|
||||
|
||||
for (const QJsonValue &i : configStr.value(amnezia::config_key::splitTunnelApps).toArray()) {
|
||||
if (!i.isString()) {
|
||||
break;
|
||||
}
|
||||
config.m_vpnDisabledApps.append(i.toString());
|
||||
}
|
||||
|
||||
// killSwitch toggle
|
||||
if (QVariant(configStr.value(amnezia::config_key::killSwitchOption).toString()).toBool()) {
|
||||
WindowsFirewall::instance()->enablePeerTraffic(config);
|
||||
}
|
||||
|
||||
WindowsDaemon::instance()->prepareActivation(config, inetAdapterIndex);
|
||||
WindowsDaemon::instance()->activateSplitTunnel(config, vpnAdapterIndex);
|
||||
#endif
|
||||
return true;
|
||||
return KillSwitch::instance()->enablePeerTraffic(configStr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public:
|
|||
virtual bool deleteTun(const QString &dev) override;
|
||||
virtual void StartRoutingIpv6() override;
|
||||
virtual void StopRoutingIpv6() override;
|
||||
virtual bool disableAllTraffic() override;
|
||||
virtual bool enablePeerTraffic(const QJsonObject &configStr) override;
|
||||
virtual bool enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapterIndex) override;
|
||||
virtual bool disableKillSwitch() override;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,47 @@ qt_standard_project_setup()
|
|||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
||||
|
||||
set(QSIMPLECRYPTO_DIR ${CMAKE_CURRENT_LIST_DIR}/../../client/3rd/QSimpleCrypto/src)
|
||||
|
||||
|
||||
set(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../../client/3rd-prebuilt/3rd-prebuilt/openssl/")
|
||||
set(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
|
||||
|
||||
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/windows/include")
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_ROOT_DIR}/windows/win64/libssl.lib")
|
||||
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/windows/win64/libcrypto.lib")
|
||||
else()
|
||||
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_ROOT_DIR}/windows/win32/libssl.lib")
|
||||
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/windows/win32/libcrypto.lib")
|
||||
endif()
|
||||
|
||||
|
||||
if(WIN32)
|
||||
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/windows/include")
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/windows/win64/libcrypto.lib")
|
||||
else()
|
||||
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/windows/win32/libcrypto.lib")
|
||||
endif()
|
||||
elseif(APPLE AND NOT IOS)
|
||||
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/macos/include")
|
||||
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/macos/lib/libcrypto.a")
|
||||
elseif(LINUX)
|
||||
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/linux/include")
|
||||
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/linux/x86_64/libcrypto.a")
|
||||
endif()
|
||||
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
||||
|
||||
include_directories(
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${QSIMPLECRYPTO_DIR}
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../client/utilities.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../client/secure_qsettings.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../client/core/networkUtilities.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipc.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserver.h
|
||||
|
|
@ -22,12 +61,20 @@ set(HEADERS
|
|||
${CMAKE_CURRENT_LIST_DIR}/localserver.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../common/logger/logger.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/router.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/killswitch.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/systemservice.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.h
|
||||
${QSIMPLECRYPTO_DIR}/include/QAead.h
|
||||
${QSIMPLECRYPTO_DIR}/include/QBlockCipher.h
|
||||
${QSIMPLECRYPTO_DIR}/include/QRsa.h
|
||||
${QSIMPLECRYPTO_DIR}/include/QSimpleCrypto_global.h
|
||||
${QSIMPLECRYPTO_DIR}/include/QX509.h
|
||||
${QSIMPLECRYPTO_DIR}/include/QX509Store.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../client/utilities.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../client/secure_qsettings.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../client/core/networkUtilities.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserver.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserverprocess.cpp
|
||||
|
|
@ -36,7 +83,13 @@ set(SOURCES
|
|||
${CMAKE_CURRENT_LIST_DIR}/../../common/logger/logger.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/main.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/router.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/killswitch.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/systemservice.cpp
|
||||
${QSIMPLECRYPTO_DIR}/sources/QAead.cpp
|
||||
${QSIMPLECRYPTO_DIR}/sources/QBlockCipher.cpp
|
||||
${QSIMPLECRYPTO_DIR}/sources/QRsa.cpp
|
||||
${QSIMPLECRYPTO_DIR}/sources/QX509.cpp
|
||||
${QSIMPLECRYPTO_DIR}/sources/QX509Store.cpp
|
||||
)
|
||||
|
||||
# Mozilla headres
|
||||
|
|
@ -132,6 +185,7 @@ if(WIN32)
|
|||
set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/tapcontroller_win.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/router_win.cpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/windows/daemon/windowsdaemon.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/windows/daemon/windowsdaemontunnel.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/windows/daemon/windowsfirewall.cpp
|
||||
|
|
@ -158,6 +212,8 @@ if(WIN32)
|
|||
gdi32
|
||||
Advapi32
|
||||
Kernel32
|
||||
${OPENSSL_LIB_CRYPTO_PATH}
|
||||
qt6keychain
|
||||
)
|
||||
|
||||
add_compile_definitions(_WINSOCKAPI_)
|
||||
|
|
|
|||
228
service/server/killswitch.cpp
Normal file
228
service/server/killswitch.cpp
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
#include "killswitch.h"
|
||||
|
||||
#include "../client/protocols/protocols_defs.h"
|
||||
#include "qjsonarray.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "../client/platforms/windows/daemon/windowsfirewall.h"
|
||||
#include "../client/platforms/windows/daemon/windowsdaemon.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "../client/platforms/linux/daemon/linuxfirewall.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
#include "../client/platforms/macos/daemon/macosfirewall.h"
|
||||
#endif
|
||||
|
||||
KillSwitch* s_instance = nullptr;
|
||||
|
||||
KillSwitch* KillSwitch::instance()
|
||||
{
|
||||
if (s_instance == nullptr) {
|
||||
s_instance = new KillSwitch(qApp);
|
||||
}
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
bool KillSwitch::init()
|
||||
{
|
||||
WindowsFirewall::instance()->init();
|
||||
m_appSettigns = QSharedPointer<SecureQSettings>(new SecureQSettings(ORGANIZATION_NAME, APPLICATION_NAME, nullptr));
|
||||
if (isStrictKillSwitchEnabled()) {
|
||||
return disableAllTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
bool KillSwitch::isStrictKillSwitchEnabled()
|
||||
{
|
||||
return m_appSettigns->value("Conf/strictKillSwitchEnabled", false).toBool();
|
||||
}
|
||||
|
||||
bool KillSwitch::disableKillSwitch() {
|
||||
if (isStrictKillSwitchEnabled()) {
|
||||
return disableAllTraffic();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
return WindowsFirewall::instance()->allowAllTraffic();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
LinuxFirewall::uninstall();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
MacOSFirewall::uninstall();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool KillSwitch::disableAllTraffic() {
|
||||
#ifdef Q_OS_WIN
|
||||
WindowsFirewall::instance()->enableKillSwitch(-1);
|
||||
#endif
|
||||
#ifdef Q_OS_LINUX
|
||||
if (!LinuxFirewall::isInstalled()) {
|
||||
LinuxFirewall::install();
|
||||
}
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||
#endif
|
||||
#ifdef Q_OS_MACOS
|
||||
// double-check + ensure our firewall is installed and enabled. This is necessary as
|
||||
// other software may disable pfctl before re-enabling with their own rules (e.g other VPNs)
|
||||
if (!MacOSFirewall::isInstalled())
|
||||
MacOSFirewall::install();
|
||||
MacOSFirewall::ensureRootAnchorPriority();
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("100.blockAll"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("000.allowLoopback"), true);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KillSwitch::enablePeerTraffic(const QJsonObject &configStr) {
|
||||
#ifdef Q_OS_WIN
|
||||
InterfaceConfig config;
|
||||
config.m_dnsServer = configStr.value(amnezia::config_key::dns1).toString();
|
||||
config.m_serverPublicKey = "openvpn";
|
||||
config.m_serverIpv4Gateway = configStr.value("vpnGateway").toString();
|
||||
config.m_serverIpv4AddrIn = configStr.value("vpnServer").toString();
|
||||
int vpnAdapterIndex = configStr.value("vpnAdapterIndex").toInt();
|
||||
int inetAdapterIndex = configStr.value("inetAdapterIndex").toInt();
|
||||
|
||||
int splitTunnelType = configStr.value("splitTunnelType").toInt();
|
||||
QJsonArray splitTunnelSites = configStr.value("splitTunnelSites").toArray();
|
||||
|
||||
// Use APP split tunnel
|
||||
if (splitTunnelType == 0 || splitTunnelType == 2) {
|
||||
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress("0.0.0.0"), 0));
|
||||
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress("::"), 0));
|
||||
}
|
||||
|
||||
if (splitTunnelType == 1) {
|
||||
for (auto v : splitTunnelSites) {
|
||||
QString ipRange = v.toString();
|
||||
if (ipRange.split('/').size() > 1) {
|
||||
config.m_allowedIPAddressRanges.append(
|
||||
IPAddress(QHostAddress(ipRange.split('/')[0]), atoi(ipRange.split('/')[1].toLocal8Bit())));
|
||||
} else {
|
||||
config.m_allowedIPAddressRanges.append(IPAddress(QHostAddress(ipRange), 32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.m_excludedAddresses.append(configStr.value("vpnServer").toString());
|
||||
if (splitTunnelType == 2) {
|
||||
for (auto v : splitTunnelSites) {
|
||||
QString ipRange = v.toString();
|
||||
config.m_excludedAddresses.append(ipRange);
|
||||
}
|
||||
}
|
||||
|
||||
for (const QJsonValue &i : configStr.value(amnezia::config_key::splitTunnelApps).toArray()) {
|
||||
if (!i.isString()) {
|
||||
break;
|
||||
}
|
||||
config.m_vpnDisabledApps.append(i.toString());
|
||||
}
|
||||
|
||||
// killSwitch toggle
|
||||
if (QVariant(configStr.value(amnezia::config_key::killSwitchOption).toString()).toBool()) {
|
||||
WindowsFirewall::instance()->enablePeerTraffic(config);
|
||||
}
|
||||
|
||||
WindowsDaemon::instance()->prepareActivation(config, inetAdapterIndex);
|
||||
WindowsDaemon::instance()->activateSplitTunnel(config, vpnAdapterIndex);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool KillSwitch::enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapterIndex) {
|
||||
#ifdef Q_OS_WIN
|
||||
return WindowsFirewall::instance()->enableKillSwitch(vpnAdapterIndex);
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||
int splitTunnelType = configStr.value("splitTunnelType").toInt();
|
||||
QJsonArray splitTunnelSites = configStr.value("splitTunnelSites").toArray();
|
||||
bool blockAll = 0;
|
||||
bool allowNets = 0;
|
||||
bool blockNets = 0;
|
||||
QStringList allownets;
|
||||
QStringList blocknets;
|
||||
|
||||
|
||||
if (splitTunnelType == 0) {
|
||||
blockAll = true;
|
||||
allowNets = true;
|
||||
allownets.append(configStr.value("vpnServer").toString());
|
||||
} else if (splitTunnelType == 1) {
|
||||
blockNets = true;
|
||||
for (auto v : splitTunnelSites) {
|
||||
blocknets.append(v.toString());
|
||||
}
|
||||
} else if (splitTunnelType == 2) {
|
||||
blockAll = true;
|
||||
allowNets = true;
|
||||
allownets.append(configStr.value("vpnServer").toString());
|
||||
for (auto v : splitTunnelSites) {
|
||||
allownets.append(v.toString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
if (!LinuxFirewall::isInstalled()) {
|
||||
LinuxFirewall::install();
|
||||
// double-check + ensure our firewall is installed and enabled
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), blockAll);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("110.allowNets"), allowNets);
|
||||
LinuxFirewall::updateAllowNets(allownets);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("120.blockNets"), blockAll);
|
||||
LinuxFirewall::updateBlockNets(blocknets);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("200.allowVPN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("300.allowLAN"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("310.blockDNS"), true);
|
||||
QStringList dnsServers;
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns1).toString());
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns2).toString());
|
||||
dnsServers.append("127.0.0.1");
|
||||
dnsServers.append("127.0.0.53");
|
||||
LinuxFirewall::updateDNSServers(dnsServers);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), true);
|
||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("400.allowPIA"), true);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
// double-check + ensure our firewall is installed and enabled. This is necessary as
|
||||
// other software may disable pfctl before re-enabling with their own rules (e.g other VPNs)
|
||||
if (!MacOSFirewall::isInstalled())
|
||||
MacOSFirewall::install();
|
||||
|
||||
MacOSFirewall::ensureRootAnchorPriority();
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("000.allowLoopback"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("100.blockAll"), blockAll);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("110.allowNets"), allowNets);
|
||||
MacOSFirewall::setAnchorTable(QStringLiteral("110.allowNets"), allowNets, QStringLiteral("allownets"), allownets);
|
||||
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("120.blockNets"), blockNets);
|
||||
MacOSFirewall::setAnchorTable(QStringLiteral("120.blockNets"), blockNets, QStringLiteral("blocknets"), blocknets);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("200.allowVPN"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("250.blockIPv6"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("290.allowDHCP"), true);
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("300.allowLAN"), true);
|
||||
|
||||
QStringList dnsServers;
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns1).toString());
|
||||
dnsServers.append(configStr.value(amnezia::config_key::dns2).toString());
|
||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("310.blockDNS"), true);
|
||||
MacOSFirewall::setAnchorTable(QStringLiteral("310.blockDNS"), true, QStringLiteral("dnsaddr"), dnsServers);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
27
service/server/killswitch.h
Normal file
27
service/server/killswitch.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef KILLSWITCH_H
|
||||
#define KILLSWITCH_H
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "secure_qsettings.h"
|
||||
|
||||
class KillSwitch : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static KillSwitch *instance();
|
||||
bool init();
|
||||
bool disableKillSwitch();
|
||||
bool disableAllTraffic();
|
||||
bool enablePeerTraffic( const QJsonObject &configStr);
|
||||
bool enableKillSwitch( const QJsonObject &excludeAddr, int vpnAdapterIndex);
|
||||
bool isStrictKillSwitchEnabled();
|
||||
|
||||
private:
|
||||
KillSwitch(QObject* parent) {};
|
||||
QSharedPointer<SecureQSettings> m_appSettigns;
|
||||
|
||||
};
|
||||
|
||||
#endif // KILLSWITCH_H
|
||||
|
|
@ -5,13 +5,12 @@
|
|||
|
||||
#include "ipc.h"
|
||||
#include "localserver.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "router.h"
|
||||
#include "killswitch.h"
|
||||
#include "logger.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "tapcontroller_win.h"
|
||||
#include "tapcontroller_win.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
|
@ -47,6 +46,8 @@ LocalServer::LocalServer(QObject *parent) : QObject(parent),
|
|||
return;
|
||||
}
|
||||
|
||||
KillSwitch::instance()->init();
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// Signal handling for a proper shutdown.
|
||||
QObject::connect(qApp, &QCoreApplication::aboutToQuit,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue