refactor: route Windows WG killswitch through TrafficGuard

This commit is contained in:
cd-amn
2026-05-26 10:30:14 +00:00
parent 72147d3a67
commit eb42ce8fef
4 changed files with 56 additions and 37 deletions
+10
View File
@@ -181,6 +181,15 @@ void VpnTrafficGuard::applyFirewall(const QString &gateway, const QString &local
QJsonObject updatedConfig = m_config;
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
#ifdef Q_OS_WIN
const QString ifname = updatedConfig.value("ifname").toString();
if (!ifname.isEmpty()) {
updatedConfig.insert("vpnGateway", gateway);
updatedConfig.insert("vpnServer", NetworkUtilities::getIPAddress(updatedConfig.value(configKey::hostName).toString()));
if (QVariant(updatedConfig.value(configKey::killSwitchOption).toString()).toBool()) {
iface->enableKillSwitch(updatedConfig, 0);
}
iface->enablePeerTraffic(updatedConfig);
} else {
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j=0; j < netInterfaces.at(i).addressEntries().size(); j++)
@@ -196,6 +205,7 @@ void VpnTrafficGuard::applyFirewall(const QString &gateway, const QString &local
}
}
}
}
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
if (QVariant(updatedConfig.value(configKey::killSwitchOption).toString()).toBool()) {
@@ -12,7 +12,6 @@
#include <QFileInfo>
#include "killswitch.h"
#include "leakdetector.h"
#include "logger.h"
#include "windowsfirewall.h"
@@ -103,14 +102,19 @@ bool WireguardUtilsWindows::addInterface(const InterfaceConfig& config) {
return false;
}
// We don't want to pass a peer just yet, that will happen later with
// a UAPI command in WireguardUtilsWindows::updatePeer(), so truncate
// the config file to remove the [Peer] section.
qsizetype peerStart = configString.indexOf("[Peer]", 0, Qt::CaseSensitive);
if (peerStart >= 0) {
configString.truncate(peerStart);
}
qsizetype dnsStart = configString.indexOf("DNS = ");
if (dnsStart >= 0) {
qsizetype dnsEnd = configString.indexOf('\n', dnsStart);
if (dnsEnd >= 0) {
configString.remove(dnsStart, dnsEnd - dnsStart + 1);
}
}
m_ifname = config.m_ifname.isEmpty() ? s_defaultInterfaceName() : config.m_ifname;
if (!m_tunnel.start(configString, m_ifname)) {
logger.error() << "Failed to activate the tunnel service";
@@ -126,14 +130,6 @@ bool WireguardUtilsWindows::addInterface(const InterfaceConfig& config) {
m_luid = luid.Value;
m_routeMonitor = new WindowsRouteMonitor(luid.Value, this);
if (config.m_killSwitchEnabled) {
NET_IFINDEX ifindex;
ConvertInterfaceLuidToIndex(&luid, &ifindex);
m_firewall->allowAllTraffic();
m_firewall->enableInterface(ifindex);
KillSwitch::instance()->addAllowedRange({});
}
logger.debug() << "Registration completed";
return true;
}
@@ -143,7 +139,6 @@ bool WireguardUtilsWindows::deleteInterface() {
m_routeMonitor->deleteLater();
}
m_firewall->disableKillSwitch();
m_tunnel.stop();
return true;
}
@@ -154,10 +149,6 @@ bool WireguardUtilsWindows::updatePeer(const InterfaceConfig& config) {
QByteArray pskKey =
QByteArray::fromBase64(qPrintable(config.m_serverPskKey));
if (config.m_killSwitchEnabled) {
// Enable the windows firewall for this peer.
m_firewall->enablePeerTraffic(config);
}
logger.debug() << "Configuring peer" << publicKey.toHex()
<< "via" << config.m_serverIpv4AddrIn;
@@ -194,9 +185,6 @@ bool WireguardUtilsWindows::deletePeer(const InterfaceConfig& config) {
QByteArray publicKey =
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
// Disable the windows firewall for this peer.
m_firewall->disablePeerTraffic(config.m_serverPublicKey);
QString message;
QTextStream out(&message);
out << "set=1\n";
+1 -4
View File
@@ -146,8 +146,6 @@ void VpnConnection::wireTunnelSignals(Tunnel* tunnel, bool isActive)
if (isActive) {
connect(tunnel, &Tunnel::bytesChanged, this, &VpnConnection::onBytesChanged);
connect(tunnel, &Tunnel::addressesUpdated,
m_trafficGuard.data(), &VpnTrafficGuard::applyFirewall);
}
}
@@ -216,6 +214,7 @@ void VpnConnection::connectToVpn(const QString &serverId, DockerContainer contai
#ifdef AMNEZIA_DESKTOP
if (VpnProtocol::isWireGuardBased(container)) {
const QString ifname = allocateIfname();
config.insert("ifname", ifname);
m_active = new Tunnel(ifname, container, config, resolvedRemote, this);
wireTunnelSignals(m_active, /*isActive=*/true);
wireDaemonReconnectSignals();
@@ -561,8 +560,6 @@ void VpnConnection::onTunnelPrepared()
m_active = m_staging;
m_staging = nullptr;
connect(m_active, &Tunnel::bytesChanged, this, &VpnConnection::onBytesChanged);
connect(m_active, &Tunnel::addressesUpdated,
m_trafficGuard.data(), &VpnTrafficGuard::applyFirewall);
m_vpnConfiguration = m_active->config();
m_remoteAddress = m_active->remoteAddress();
m_trafficGuard->setConfig(m_vpnConfiguration);
+26 -2
View File
@@ -14,6 +14,28 @@
#ifdef Q_OS_WIN
#include "../client/platforms/windows/daemon/windowsfirewall.h"
#include "../client/platforms/windows/daemon/windowsdaemon.h"
namespace {
int resolveVpnAdapterIndex(const QJsonObject& configStr) {
int index = configStr.value("vpnAdapterIndex").toInt();
if (index != 0) {
return index;
}
const QString ifname = configStr.value("ifname").toString();
if (ifname.isEmpty()) {
return 0;
}
NET_LUID luid;
if (ConvertInterfaceAliasToLuid((wchar_t*)ifname.utf16(), &luid) != 0) {
return 0;
}
NET_IFINDEX ifindex = 0;
if (ConvertInterfaceLuidToIndex(&luid, &ifindex) != 0) {
return 0;
}
return static_cast<int>(ifindex);
}
}
#endif
#ifdef Q_OS_LINUX
@@ -223,7 +245,7 @@ bool KillSwitch::enablePeerTraffic(const QJsonObject &configStr) {
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 vpnAdapterIndex = resolveVpnAdapterIndex(configStr);
int inetAdapterIndex = configStr.value("inetAdapterIndex").toInt();
int splitTunnelType = configStr.value("splitTunnelType").toInt();
@@ -282,10 +304,12 @@ bool KillSwitch::enablePeerTraffic(const QJsonObject &configStr) {
bool KillSwitch::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterIndex) {
#ifdef Q_OS_WIN
Q_UNUSED(vpnAdapterIndex)
const int resolvedIndex = resolveVpnAdapterIndex(configStr);
if (configStr.value("splitTunnelType").toInt() != 0) {
WindowsFirewall::create(this)->allowAllTraffic();
}
return WindowsFirewall::create(this)->enableInterface(vpnAdapterIndex);
return WindowsFirewall::create(this)->enableInterface(resolvedIndex);
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)