Killswitch strict mode for Linux and MacOS
This commit is contained in:
parent
d65273e43e
commit
08e5ff2eef
9 changed files with 97 additions and 14 deletions
|
|
@ -17,6 +17,8 @@
|
||||||
#include "leakdetector.h"
|
#include "leakdetector.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
|
#include "killswitch.h"
|
||||||
|
|
||||||
constexpr const int WG_TUN_PROC_TIMEOUT = 5000;
|
constexpr const int WG_TUN_PROC_TIMEOUT = 5000;
|
||||||
constexpr const char* WG_RUNTIME_DIR = "/var/run/amneziawg";
|
constexpr const char* WG_RUNTIME_DIR = "/var/run/amneziawg";
|
||||||
|
|
||||||
|
|
@ -182,7 +184,7 @@ bool WireguardUtilsLinux::deleteInterface() {
|
||||||
QFile::remove(wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".name"));
|
QFile::remove(wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".name"));
|
||||||
|
|
||||||
// double-check + ensure our firewall is installed and enabled
|
// double-check + ensure our firewall is installed and enabled
|
||||||
LinuxFirewall::uninstall();
|
KillSwitch::instance()->disableKillSwitch();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
#include "leakdetector.h"
|
#include "leakdetector.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
|
#include "killswitch.h"
|
||||||
|
|
||||||
constexpr const int WG_TUN_PROC_TIMEOUT = 5000;
|
constexpr const int WG_TUN_PROC_TIMEOUT = 5000;
|
||||||
constexpr const char* WG_RUNTIME_DIR = "/var/run/amneziawg";
|
constexpr const char* WG_RUNTIME_DIR = "/var/run/amneziawg";
|
||||||
|
|
||||||
|
|
@ -180,7 +182,7 @@ bool WireguardUtilsMacos::deleteInterface() {
|
||||||
QFile::remove(wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".name"));
|
QFile::remove(wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".name"));
|
||||||
|
|
||||||
// double-check + ensure our firewall is installed and enabled
|
// double-check + ensure our firewall is installed and enabled
|
||||||
MacOSFirewall::uninstall();
|
KillSwitch::instance()->disableKillSwitch();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,11 @@ ErrorCode OpenVpnProtocol::start()
|
||||||
return lastError();
|
return lastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||||
|
IpcClient::Interface()->allowTrafficTo(QStringList(NetworkUtilities::getIPAddress(
|
||||||
|
m_configData.value(amnezia::config_key::hostName).toString())));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Detect default gateway
|
// Detect default gateway
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
QProcess p;
|
QProcess p;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ class IpcInterface
|
||||||
|
|
||||||
SLOT( bool disableKillSwitch() );
|
SLOT( bool disableKillSwitch() );
|
||||||
SLOT( bool disableAllTraffic() );
|
SLOT( bool disableAllTraffic() );
|
||||||
|
SLOT( bool allowTrafficTo( const QStringList ranges ) );
|
||||||
SLOT( bool enablePeerTraffic( const QJsonObject &configStr) );
|
SLOT( bool enablePeerTraffic( const QJsonObject &configStr) );
|
||||||
SLOT( bool enableKillSwitch( const QJsonObject &excludeAddr, int vpnAdapterIndex) );
|
SLOT( bool enableKillSwitch( const QJsonObject &excludeAddr, int vpnAdapterIndex) );
|
||||||
SLOT( bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) );
|
SLOT( bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) );
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,11 @@ void IpcServer::setLogsEnabled(bool enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IpcServer::allowTrafficTo(QStringList ranges)
|
||||||
|
{
|
||||||
|
return KillSwitch::instance()->allowTrafficTo(ranges);
|
||||||
|
}
|
||||||
|
|
||||||
bool IpcServer::disableAllTraffic()
|
bool IpcServer::disableAllTraffic()
|
||||||
{
|
{
|
||||||
return KillSwitch::instance()->disableAllTraffic();
|
return KillSwitch::instance()->disableAllTraffic();
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ public:
|
||||||
virtual void StartRoutingIpv6() override;
|
virtual void StartRoutingIpv6() override;
|
||||||
virtual void StopRoutingIpv6() override;
|
virtual void StopRoutingIpv6() override;
|
||||||
virtual bool disableAllTraffic() override;
|
virtual bool disableAllTraffic() override;
|
||||||
|
virtual bool allowTrafficTo(QStringList ranges) override;
|
||||||
virtual bool enablePeerTraffic(const QJsonObject &configStr) override;
|
virtual bool enablePeerTraffic(const QJsonObject &configStr) override;
|
||||||
virtual bool enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapterIndex) override;
|
virtual bool enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapterIndex) override;
|
||||||
virtual bool disableKillSwitch() override;
|
virtual bool disableKillSwitch() override;
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,9 @@ if(APPLE)
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/macos/daemon/wireguardutilsmacos.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/macos/daemon/wireguardutilsmacos.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/macos/daemon/macosfirewall.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/macos/daemon/macosfirewall.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(LIBS ${OPENSSL_LIB_CRYPTO_PATH} qt6keychain)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(LINUX)
|
if(LINUX)
|
||||||
|
|
@ -288,6 +291,9 @@ if(LINUX)
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/linux/daemon/linuxroutemonitor.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/linux/daemon/linuxroutemonitor.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/linux/daemon/linuxfirewall.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/linux/daemon/linuxfirewall.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(LIBS ${OPENSSL_LIB_CRYPTO_PATH} qt6keychain -static-libstdc++ -static-libgcc -ldl)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../src/qtservice.cmake)
|
include(${CMAKE_CURRENT_LIST_DIR}/../src/qtservice.cmake)
|
||||||
|
|
@ -300,6 +306,7 @@ include_directories(
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
add_executable(${PROJECT} ${SOURCES} ${HEADERS})
|
add_executable(${PROJECT} ${SOURCES} ${HEADERS})
|
||||||
target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Widgets Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat Qt6::DBus ${LIBS})
|
target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Widgets Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat Qt6::DBus ${LIBS})
|
||||||
target_compile_definitions(${PROJECT} PRIVATE "MZ_$<UPPER_CASE:${MZ_PLATFORM_NAME}>")
|
target_compile_definitions(${PROJECT} PRIVATE "MZ_$<UPPER_CASE:${MZ_PLATFORM_NAME}>")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
#include "killswitch.h"
|
#include "killswitch.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QHostAddress>
|
||||||
|
|
||||||
#include "../client/protocols/protocols_defs.h"
|
#include "../client/protocols/protocols_defs.h"
|
||||||
#include "qjsonarray.h"
|
#include "qjsonarray.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
@ -29,11 +33,24 @@ KillSwitch* KillSwitch::instance()
|
||||||
|
|
||||||
bool KillSwitch::init()
|
bool KillSwitch::init()
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
WindowsFirewall::instance()->init();
|
WindowsFirewall::instance()->init();
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
if (!LinuxFirewall::isInstalled()) {
|
||||||
|
LinuxFirewall::install();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
if (!MacOSFirewall::isInstalled()) {
|
||||||
|
MacOSFirewall::install();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
m_appSettigns = QSharedPointer<SecureQSettings>(new SecureQSettings(ORGANIZATION_NAME, APPLICATION_NAME, nullptr));
|
m_appSettigns = QSharedPointer<SecureQSettings>(new SecureQSettings(ORGANIZATION_NAME, APPLICATION_NAME, nullptr));
|
||||||
if (isStrictKillSwitchEnabled()) {
|
if (isStrictKillSwitchEnabled()) {
|
||||||
return disableAllTraffic();
|
return disableAllTraffic();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KillSwitch::isStrictKillSwitchEnabled()
|
bool KillSwitch::isStrictKillSwitchEnabled()
|
||||||
|
|
@ -42,21 +59,46 @@ bool KillSwitch::isStrictKillSwitchEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KillSwitch::disableKillSwitch() {
|
bool KillSwitch::disableKillSwitch() {
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
if (isStrictKillSwitchEnabled()) {
|
if (isStrictKillSwitchEnabled()) {
|
||||||
return disableAllTraffic();
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), true);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("110.allowNets"), false);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("120.blockNets"), false);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("200.allowVPN"), false);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("290.allowDHCP"), false);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("300.allowLAN"), false);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("310.blockDNS"), false);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("320.allowDNS"), false);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("400.allowPIA"), false);
|
||||||
|
} else {
|
||||||
|
LinuxFirewall::uninstall();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
if (isStrictKillSwitchEnabled()) {
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("000.allowLoopback"), true);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("100.blockAll"), true);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("110.allowNets"), false);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("120.blockNets"), false);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("200.allowVPN"), false);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("250.blockIPv6"), true);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("290.allowDHCP"), false);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("300.allowLAN"), false);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("310.blockDNS"), false);
|
||||||
|
} else {
|
||||||
|
MacOSFirewall::uninstall();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return WindowsFirewall::instance()->allowAllTraffic();
|
return WindowsFirewall::instance()->allowAllTraffic();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
return true;
|
||||||
LinuxFirewall::uninstall();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
|
||||||
MacOSFirewall::uninstall();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KillSwitch::disableAllTraffic() {
|
bool KillSwitch::disableAllTraffic() {
|
||||||
|
|
@ -69,6 +111,7 @@ bool KillSwitch::disableAllTraffic() {
|
||||||
}
|
}
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), true);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), true);
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv6, QStringLiteral("250.blockIPv6"), true);
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
// double-check + ensure our firewall is installed and enabled. This is necessary as
|
// double-check + ensure our firewall is installed and enabled. This is necessary as
|
||||||
|
|
@ -78,10 +121,26 @@ bool KillSwitch::disableAllTraffic() {
|
||||||
MacOSFirewall::ensureRootAnchorPriority();
|
MacOSFirewall::ensureRootAnchorPriority();
|
||||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("100.blockAll"), true);
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("100.blockAll"), true);
|
||||||
MacOSFirewall::setAnchorEnabled(QStringLiteral("000.allowLoopback"), true);
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("000.allowLoopback"), true);
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("250.blockIPv6"), true);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KillSwitch::allowTrafficTo(const QStringList &ranges) {
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::IPv4, QStringLiteral("110.allowNets"), true);
|
||||||
|
LinuxFirewall::updateAllowNets(ranges);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
MacOSFirewall::setAnchorEnabled(QStringLiteral("110.allowNets"), true);
|
||||||
|
MacOSFirewall::setAnchorTable(QStringLiteral("110.allowNets"), true, QStringLiteral("allownets"), ranges);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool KillSwitch::enablePeerTraffic(const QJsonObject &configStr) {
|
bool KillSwitch::enablePeerTraffic(const QJsonObject &configStr) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
InterfaceConfig config;
|
InterfaceConfig config;
|
||||||
|
|
@ -139,8 +198,7 @@ bool KillSwitch::enablePeerTraffic(const QJsonObject &configStr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KillSwitch::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterIndex) {
|
||||||
bool KillSwitch::enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapterIndex) {
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return WindowsFirewall::instance()->enableKillSwitch(vpnAdapterIndex);
|
return WindowsFirewall::instance()->enableKillSwitch(vpnAdapterIndex);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -154,7 +212,6 @@ bool KillSwitch::enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapter
|
||||||
QStringList allownets;
|
QStringList allownets;
|
||||||
QStringList blocknets;
|
QStringList blocknets;
|
||||||
|
|
||||||
|
|
||||||
if (splitTunnelType == 0) {
|
if (splitTunnelType == 0) {
|
||||||
blockAll = true;
|
blockAll = true;
|
||||||
allowNets = true;
|
allowNets = true;
|
||||||
|
|
@ -177,6 +234,8 @@ bool KillSwitch::enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapter
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
if (!LinuxFirewall::isInstalled()) {
|
if (!LinuxFirewall::isInstalled()) {
|
||||||
LinuxFirewall::install();
|
LinuxFirewall::install();
|
||||||
|
}
|
||||||
|
|
||||||
// double-check + ensure our firewall is installed and enabled
|
// double-check + ensure our firewall is installed and enabled
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("000.allowLoopback"), true);
|
||||||
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), blockAll);
|
LinuxFirewall::setAnchorEnabled(LinuxFirewall::Both, QStringLiteral("100.blockAll"), blockAll);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ public:
|
||||||
bool disableKillSwitch();
|
bool disableKillSwitch();
|
||||||
bool disableAllTraffic();
|
bool disableAllTraffic();
|
||||||
bool enablePeerTraffic( const QJsonObject &configStr);
|
bool enablePeerTraffic( const QJsonObject &configStr);
|
||||||
bool enableKillSwitch( const QJsonObject &excludeAddr, int vpnAdapterIndex);
|
bool enableKillSwitch( const QJsonObject &configStr, int vpnAdapterIndex);
|
||||||
|
bool allowTrafficTo(const QStringList &ranges);
|
||||||
bool isStrictKillSwitchEnabled();
|
bool isStrictKillSwitchEnabled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue