WireGuard rework for MacOS and Windows (#314)

WireGuard rework for MacOS and Windows
This commit is contained in:
Mykola Baibuz 2023-09-14 19:44:17 +03:00 committed by GitHub
parent 421a27ceae
commit 07c38e9b6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 4779 additions and 434 deletions

View file

@ -5,9 +5,9 @@
#ifndef CONTROLLERIMPL_H
#define CONTROLLERIMPL_H
#include <QDateTime>
#include <QObject>
#include <functional>
#include <QDateTime>
class Keys;
class Device;

View file

@ -52,18 +52,51 @@ DnsPingSender::DnsPingSender(const QHostAddress& source, QObject* parent)
: PingSender(parent) {
MZ_COUNT_CTOR(DnsPingSender);
if (source.isNull()) {
m_socket.bind();
} else {
m_socket.bind(source);
}
m_source = source;
connect(&m_socket, &QUdpSocket::readyRead, this, &DnsPingSender::readData);
}
DnsPingSender::~DnsPingSender() { MZ_COUNT_DTOR(DnsPingSender); }
void DnsPingSender::start() {
auto state = m_socket.state();
if (state != QAbstractSocket::UnconnectedState) {
logger.info()
<< "Attempted to start UDP socket, but it's in an invalid state:"
<< state;
return;
}
bool bindResult = false;
if (m_source.isNull()) {
bindResult = m_socket.bind();
} else {
bindResult = m_socket.bind(m_source);
}
if (!bindResult) {
logger.error() << "Unable to bind UDP socket. Socket state:" << state;
return;
}
logger.debug() << "UDP socket bound to:"
<< m_socket.localAddress().toString();
return;
}
void DnsPingSender::sendPing(const QHostAddress& dest, quint16 sequence) {
if (dest.isNull()) {
logger.error() << "Attempted to send DNS ping to invalid destination:"
<< dest.toString() << "Ignoring.";
return;
}
if (!m_socket.isValid()) {
logger.error() << "Attempted to send DNS ping, but socket is invalid.";
return;
}
QByteArray packet;
// Assemble a DNS query header.
@ -82,7 +115,14 @@ void DnsPingSender::sendPing(const QHostAddress& dest, quint16 sequence) {
packet.append(query, sizeof(query));
// Send the datagram.
m_socket.writeDatagram(packet, dest, DNS_PORT);
logger.debug() << "Sending" << packet.size() << "bytes to UDP socket.";
auto bytesWritten = m_socket.writeDatagram(packet, dest, DNS_PORT);
if (bytesWritten >= 0) {
logger.debug() << "Number of bytes written to UDP socket:" << bytesWritten;
} else {
logger.error() << "Error writing to UDP socket:" << m_socket.error();
}
}
void DnsPingSender::readData() {
@ -112,6 +152,7 @@ void DnsPingSender::readData() {
continue;
}
logger.debug() << "Received valid DNS reply";
emit recvPing(qFromBigEndian<quint16>(header.id));
}
}

View file

@ -19,11 +19,15 @@ class DnsPingSender final : public PingSender {
void sendPing(const QHostAddress& dest, quint16 sequence) override;
void start();
void stop() { m_socket.close(); }
private:
void readData();
private:
QUdpSocket m_socket;
QHostAddress m_source;
};
#endif // DNSPINGSENDER_H

View file

@ -1,7 +1,6 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "protocols/protocols_defs.h"
#include "localsocketcontroller.h"
@ -14,10 +13,14 @@
#include <QJsonValue>
#include <QStandardPaths>
//#include "errorhandler.h"
#include "ipaddress.h"
#include "leakdetector.h"
#include "logger.h"
//#include "models/device.h"
//#include "models/keys.h"
#include "models/server.h"
//#include "settingsholder.h"
// How many times do we try to reconnect.
constexpr int MAX_CONNECTION_RETRY = 10;
@ -112,23 +115,22 @@ void LocalSocketController::daemonConnected() {
}
void LocalSocketController::activate(const QJsonObject &rawConfig) {
QJsonObject wgConfig = rawConfig.value("wireguard_config_data").toObject();
QJsonObject json;
json.insert("type", "activate");
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
json.insert("privateKey", wgConfig.value(amnezia::config_key::client_priv_key));
json.insert("deviceIpv4Address", wgConfig.value(amnezia::config_key::client_ip));
json.insert("deviceIpv6Address", "dead::1");
json.insert("serverPublicKey", wgConfig.value(amnezia::config_key::server_pub_key));
json.insert("serverPskKey", wgConfig.value(amnezia::config_key::psk_key));
json.insert("serverIpv4AddrIn", wgConfig.value(amnezia::config_key::hostName));
// json.insert("serverIpv6AddrIn", QJsonValue(hop.m_server.ipv6AddrIn()));
// json.insert("serverIpv6AddrIn", QJsonValue(hop.m_server.ipv6AddrIn()));
json.insert("serverPort", wgConfig.value(amnezia::config_key::port).toInt());
json.insert("serverIpv4Gateway", wgConfig.value(amnezia::config_key::hostName));
// json.insert("serverIpv6Gateway", QJsonValue(hop.m_server.ipv6Gateway()));
// json.insert("serverIpv6Gateway", QJsonValue(hop.m_server.ipv6Gateway()));
json.insert("dnsServer", rawConfig.value(amnezia::config_key::dns1));
QJsonArray jsAllowedIPAddesses;
@ -148,17 +150,16 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
json.insert("allowedIPAddressRanges", jsAllowedIPAddesses);
QJsonArray jsExcludedAddresses;
jsExcludedAddresses.append(wgConfig.value(amnezia::config_key::hostName));
json.insert("excludedAddresses", jsExcludedAddresses);
QJsonArray jsExcludedAddresses;
jsExcludedAddresses.append(wgConfig.value(amnezia::config_key::hostName));
json.insert("excludedAddresses", jsExcludedAddresses);
// QJsonArray splitTunnelApps;
// for (const auto& uri : hop.m_vpnDisabledApps) {
// splitTunnelApps.append(QJsonValue(uri));
// }
// json.insert("vpnDisabledApps", splitTunnelApps);
// QJsonArray splitTunnelApps;
// for (const auto& uri : hop.m_vpnDisabledApps) {
// splitTunnelApps.append(QJsonValue(uri));
// }
// json.insert("vpnDisabledApps", splitTunnelApps);
write(json);
}

View file

@ -6,13 +6,16 @@
#include <QMetaEnum>
//#include "controller.h"
#include "leakdetector.h"
#include "logger.h"
//#include "mozillavpn.h"
#include "networkwatcherimpl.h"
#include "platforms/dummy/dummynetworkwatcher.h"
//#include "settingsholder.h"
#ifdef MZ_WINDOWS
//# include "platforms/windows/windowsnetworkwatcher.h"
# include "platforms/windows/windowsnetworkwatcher.h"
#endif
#ifdef MZ_LINUX
@ -51,9 +54,9 @@ void NetworkWatcher::initialize() {
logger.debug() << "Initialize";
#if defined(MZ_WINDOWS)
//m_impl = new WindowsNetworkWatcher(this);
m_impl = new WindowsNetworkWatcher(this);
#elif defined(MZ_LINUX)
//m_impl = new LinuxNetworkWatcher(this);
// m_impl = new LinuxNetworkWatcher(this);
#elif defined(MZ_MACOS)
m_impl = new MacOSNetworkWatcher(this);
#elif defined(MZ_WASM)
@ -73,11 +76,34 @@ void NetworkWatcher::initialize() {
m_impl->initialize();
//TODO IMPL FOR AMNEZIA
// TODO: IMPL FOR AMNEZIA
#if 0
SettingsHolder* settingsHolder = SettingsHolder::instance();
Q_ASSERT(settingsHolder);
m_active = settingsHolder->unsecuredNetworkAlert() ||
settingsHolder->captivePortalAlert();
m_reportUnsecuredNetwork = settingsHolder->unsecuredNetworkAlert();
if (m_active) {
m_impl->start();
}
connect(settingsHolder, &SettingsHolder::unsecuredNetworkAlertChanged, this,
&NetworkWatcher::settingsChanged);
connect(settingsHolder, &SettingsHolder::captivePortalAlertChanged, this,
&NetworkWatcher::settingsChanged);
#endif
}
void NetworkWatcher::settingsChanged() {
//TODO IMPL FOR AMNEZIA
// TODO: IMPL FOR AMNEZIA
#if 0
SettingsHolder* settingsHolder = SettingsHolder::instance();
m_active = settingsHolder->unsecuredNetworkAlert() ||
settingsHolder->captivePortalAlert();
m_reportUnsecuredNetwork = settingsHolder->unsecuredNetworkAlert();
if (m_active) {
logger.debug()
@ -88,6 +114,7 @@ void NetworkWatcher::settingsChanged() {
logger.debug() << "Stopping Network Watcher";
m_impl->stop();
}
#endif
}
void NetworkWatcher::unsecuredNetwork(const QString& networkName,
@ -95,9 +122,55 @@ void NetworkWatcher::unsecuredNetwork(const QString& networkName,
logger.debug() << "Unsecured network:" << logger.sensitive(networkName)
<< "id:" << logger.sensitive(networkId);
//TODO IMPL FOR AMNEZIA
#ifndef UNIT_TEST
if (!m_reportUnsecuredNetwork) {
logger.debug() << "Disabled. Ignoring unsecured network";
return;
}
// TODO: IMPL FOR AMNEZIA
#if 0
MozillaVPN* vpn = MozillaVPN::instance();
if (vpn->state() != App::StateMain) {
logger.debug() << "VPN not ready. Ignoring unsecured network";
return;
}
Controller::State state = vpn->controller()->state();
if (state == Controller::StateOn || state == Controller::StateConnecting ||
state == Controller::StateCheckSubscription ||
state == Controller::StateSwitching ||
state == Controller::StateSilentSwitching) {
logger.debug() << "VPN on. Ignoring unsecured network";
return;
}
if (!m_networks.contains(networkId)) {
m_networks.insert(networkId, QElapsedTimer());
} else if (!m_networks[networkId].hasExpired(NETWORK_WATCHER_TIMER_MSEC)) {
logger.debug() << "Notification already shown. Ignoring unsecured network";
return;
}
// Let's activate the QElapsedTimer to avoid notification loops.
m_networks[networkId].start();
// We don't connect the system tray handler in the CTOR because it can be too
// early. Maybe the NotificationHandler has not been created yet. We do it at
// the first detection of an unsecured network.
if (m_firstNotification) {
connect(NotificationHandler::instance(),
&NotificationHandler::notificationClicked, this,
&NetworkWatcher::notificationClicked);
m_firstNotification = false;
}
NotificationHandler::instance()->unsecuredNetworkNotification(networkName);
#endif
#endif
}
QString NetworkWatcher::getCurrentTransport() {
auto type = m_impl->getTransportType();
QMetaEnum metaEnum = QMetaEnum::fromType<NetworkWatcherImpl::TransportType>();

View file

@ -33,6 +33,8 @@ class NetworkWatcher final : public QObject {
private:
void settingsChanged();
// void notificationClicked(NotificationHandler::Message message);
private:
bool m_active = false;
bool m_reportUnsecuredNetwork = false;

View file

@ -59,6 +59,10 @@ class PingHelper final : public QObject {
QTimer m_pingTimer;
PingSender* m_pingSender = nullptr;
#ifdef UNIT_TEST
friend class TestConnectionHealth;
#endif
};
#endif // PINGHELPER_H

View file

@ -9,7 +9,7 @@
#elif defined(MZ_MACOS) || defined(MZ_IOS)
# include "platforms/macos/macospingsender.h"
#elif defined(MZ_WINDOWS)
// #include "platforms/windows/windowspingsender.h"
# include "platforms/windows/windowspingsender.h"
#elif defined(MZ_DUMMY) || defined(UNIT_TEST)
# include "platforms/dummy/dummypingsender.h"
#else
@ -19,13 +19,12 @@
PingSender* PingSenderFactory::create(const QHostAddress& source,
QObject* parent) {
#if defined(MZ_LINUX) || defined(MZ_ANDROID)
return nullptr;
//return new LinuxPingSender(source, parent);
return nullptr;
// return new LinuxPingSender(source, parent);
#elif defined(MZ_MACOS) || defined(MZ_IOS)
return new MacOSPingSender(source, parent);
#elif defined(MZ_WINDOWS)
return nullptr;
//return new WindowsPingSender(source, parent);
return new WindowsPingSender(source, parent);
#else
return new DummyPingSender(source, parent);
#endif

View file

@ -50,4 +50,9 @@ class IPAddress final {
int m_prefixLength;
};
inline size_t qHash(const IPAddress& key, size_t seed) {
const QHostAddress& address = key.address();
return qHash(address, seed) ^ key.prefixLength();
}
#endif // IPADDRESS_H