WireGuard rework for MacOS and Windows (#314)
WireGuard rework for MacOS and Windows
This commit is contained in:
parent
421a27ceae
commit
07c38e9b6c
60 changed files with 4779 additions and 434 deletions
|
@ -5,9 +5,9 @@
|
|||
#ifndef CONTROLLERIMPL_H
|
||||
#define CONTROLLERIMPL_H
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <functional>
|
||||
#include <QDateTime>
|
||||
|
||||
class Keys;
|
||||
class Device;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue