WireGuard for MacOS (#248)

* WireGuard for MacOS
* Fix openvpn block-outside-dns
This commit is contained in:
pokamest 2023-07-15 14:19:48 -07:00 committed by GitHub
parent ed5dc7cdfd
commit 35ecb8499d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
118 changed files with 5150 additions and 3486 deletions

View file

@ -3,8 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "wireguardutilsmacos.h"
#include "leakdetector.h"
#include "logger.h"
#include <errno.h>
#include <QByteArray>
#include <QDir>
@ -12,19 +12,20 @@
#include <QLocalSocket>
#include <QTimer>
#include <errno.h>
#include "leakdetector.h"
#include "logger.h"
constexpr const int WG_TUN_PROC_TIMEOUT = 5000;
constexpr const char* WG_RUNTIME_DIR = "/var/run/wireguard";
namespace {
Logger logger(LOG_MACOS, "WireguardUtilsMacos");
Logger logwireguard(LOG_MACOS, "WireguardGo");
Logger logger("WireguardUtilsMacos");
Logger logwireguard("WireguardGo");
}; // namespace
WireguardUtilsMacos::WireguardUtilsMacos(QObject* parent)
: WireguardUtils(parent), m_tunnel(this) {
MVPN_COUNT_CTOR(WireguardUtilsMacos);
MZ_COUNT_CTOR(WireguardUtilsMacos);
logger.debug() << "WireguardUtilsMacos created.";
connect(&m_tunnel, SIGNAL(readyReadStandardOutput()), this,
@ -34,7 +35,7 @@ WireguardUtilsMacos::WireguardUtilsMacos(QObject* parent)
}
WireguardUtilsMacos::~WireguardUtilsMacos() {
MVPN_COUNT_DTOR(WireguardUtilsMacos);
MZ_COUNT_DTOR(WireguardUtilsMacos);
logger.debug() << "WireguardUtilsMacos destroyed.";
}
@ -68,15 +69,12 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
QProcessEnvironment pe = QProcessEnvironment::systemEnvironment();
QString wgNameFile = wgRuntimeDir.filePath(QString(WG_INTERFACE) + ".name");
pe.insert("WG_TUN_NAME_FILE", wgNameFile);
#ifdef QT_DEBUG
#ifdef MZ_DEBUG
pe.insert("LOG_LEVEL", "debug");
#endif
m_tunnel.setProcessEnvironment(pe);
QDir appPath(QCoreApplication::applicationDirPath());
appPath.cdUp();
appPath.cd("Resources");
appPath.cd("utils");
QStringList wgArgs = {"-f", "utun"};
m_tunnel.start(appPath.filePath("wireguard-go"), wgArgs);
if (!m_tunnel.waitForStarted(WG_TUN_PROC_TIMEOUT)) {
@ -99,6 +97,7 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
// Send a UAPI command to configure the interface
QString message("set=1\n");
QByteArray privateKey = QByteArray::fromBase64(config.m_privateKey.toUtf8());
QTextStream out(&message);
out << "private_key=" << QString(privateKey.toHex()) << "\n";
out << "replace_peers=true\n";
@ -134,14 +133,15 @@ bool WireguardUtilsMacos::deleteInterface() {
// dummy implementations for now
bool WireguardUtilsMacos::updatePeer(const InterfaceConfig& config) {
QByteArray publicKey =
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
QByteArray publicKey = QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
QByteArray pskKey = QByteArray::fromBase64(qPrintable(config.m_serverPskKey));
// Update/create the peer config
QString message;
QTextStream out(&message);
out << "set=1\n";
out << "public_key=" << QString(publicKey.toHex()) << "\n";
out << "preshared_key=" << QString(pskKey.toHex()) << "\n";
if (!config.m_serverIpv4AddrIn.isNull()) {
out << "endpoint=" << config.m_serverIpv4AddrIn << ":";
} else if (!config.m_serverIpv6AddrIn.isNull()) {
@ -153,10 +153,12 @@ bool WireguardUtilsMacos::updatePeer(const InterfaceConfig& config) {
out << config.m_serverPort << "\n";
out << "replace_allowed_ips=true\n";
for (const IPAddressRange& ip : config.m_allowedIPAddressRanges) {
out << "persistent_keepalive_interval=" << WG_KEEPALIVE_PERIOD << "\n";
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
out << "allowed_ip=" << ip.toString() << "\n";
}
logger.debug() << message;
int err = uapiErrno(uapiCommand(message));
if (err != 0) {
logger.error() << "Peer configuration failed:" << strerror(err);
@ -164,8 +166,9 @@ bool WireguardUtilsMacos::updatePeer(const InterfaceConfig& config) {
return (err == 0);
}
bool WireguardUtilsMacos::deletePeer(const QString& pubkey) {
QByteArray publicKey = QByteArray::fromBase64(qPrintable(pubkey));
bool WireguardUtilsMacos::deletePeer(const InterfaceConfig& config) {
QByteArray publicKey =
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
QString message;
QTextStream out(&message);
@ -180,13 +183,10 @@ bool WireguardUtilsMacos::deletePeer(const QString& pubkey) {
return (err == 0);
}
WireguardUtils::peerStatus WireguardUtilsMacos::getPeerStatus(
const QString& pubkey) {
peerStatus status = {0, 0};
QString hexkey = QByteArray::fromBase64(pubkey.toUtf8()).toHex();
QList<WireguardUtils::PeerStatus> WireguardUtilsMacos::getPeerStatus() {
QString reply = uapiCommand("get=1");
bool match = false;
PeerStatus status;
QList<PeerStatus> peerList;
for (const QString& line : reply.split('\n')) {
int eq = line.indexOf('=');
if (eq <= 0) {
@ -196,39 +196,90 @@ WireguardUtils::peerStatus WireguardUtilsMacos::getPeerStatus(
QString value = line.mid(eq + 1);
if (name == "public_key") {
match = (value == hexkey);
continue;
} else if (!match) {
continue;
if (!status.m_pubkey.isEmpty()) {
peerList.append(status);
}
QByteArray pubkey = QByteArray::fromHex(value.toUtf8());
status = PeerStatus(pubkey.toBase64());
}
if (name == "tx_bytes") {
status.txBytes = value.toDouble();
status.m_txBytes = value.toDouble();
}
if (name == "rx_bytes") {
status.rxBytes = value.toDouble();
status.m_rxBytes = value.toDouble();
}
if (name == "last_handshake_time_sec") {
status.m_handshake += value.toLongLong() * 1000;
}
if (name == "last_handshake_time_nsec") {
status.m_handshake += value.toLongLong() / 1000000;
}
}
if (!status.m_pubkey.isEmpty()) {
peerList.append(status);
}
return status;
return peerList;
}
bool WireguardUtilsMacos::updateRoutePrefix(const IPAddressRange& prefix,
bool WireguardUtilsMacos::updateRoutePrefix(const IPAddress& prefix,
int hopindex) {
Q_UNUSED(hopindex);
if (!m_rtmonitor) {
return false;
}
return m_rtmonitor->insertRoute(prefix);
if (prefix.prefixLength() > 0) {
return m_rtmonitor->insertRoute(prefix);
}
// Ensure that we do not replace the default route.
if (prefix.type() == QAbstractSocket::IPv4Protocol) {
return m_rtmonitor->insertRoute(IPAddress("0.0.0.0/1")) &&
m_rtmonitor->insertRoute(IPAddress("128.0.0.0/1"));
}
if (prefix.type() == QAbstractSocket::IPv6Protocol) {
return m_rtmonitor->insertRoute(IPAddress("::/1")) &&
m_rtmonitor->insertRoute(IPAddress("8000::/1"));
}
return false;
}
bool WireguardUtilsMacos::deleteRoutePrefix(const IPAddressRange& prefix,
bool WireguardUtilsMacos::deleteRoutePrefix(const IPAddress& prefix,
int hopindex) {
Q_UNUSED(hopindex);
if (!m_rtmonitor) {
return false;
}
return m_rtmonitor->deleteRoute(prefix);
if (prefix.prefixLength() > 0) {
return m_rtmonitor->insertRoute(prefix);
}
// Ensure that we do not replace the default route.
if (prefix.type() == QAbstractSocket::IPv4Protocol) {
return m_rtmonitor->deleteRoute(IPAddress("0.0.0.0/1")) &&
m_rtmonitor->deleteRoute(IPAddress("128.0.0.0/1"));
} else if (prefix.type() == QAbstractSocket::IPv6Protocol) {
return m_rtmonitor->deleteRoute(IPAddress("::/1")) &&
m_rtmonitor->deleteRoute(IPAddress("8000::/1"));
} else {
return false;
}
}
bool WireguardUtilsMacos::addExclusionRoute(const QHostAddress& address) {
if (!m_rtmonitor) {
return false;
}
return m_rtmonitor->addExclusionRoute(address);
}
bool WireguardUtilsMacos::deleteExclusionRoute(const QHostAddress& address) {
if (!m_rtmonitor) {
return false;
}
return m_rtmonitor->deleteExclusionRoute(address);
}
QString WireguardUtilsMacos::uapiCommand(const QString& command) {