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
|
|
@ -124,26 +124,23 @@ void MacosRouteMonitor::handleRtmDelete(const struct rt_msghdr* rtm,
|
|||
const struct sockaddr* dst =
|
||||
reinterpret_cast<const struct sockaddr*>(addrlist[0].constData());
|
||||
QAbstractSocket::NetworkLayerProtocol protocol;
|
||||
unsigned int plen;
|
||||
if (dst->sa_family == AF_INET) {
|
||||
m_defaultGatewayIpv4.clear();
|
||||
m_defaultIfindexIpv4 = 0;
|
||||
protocol = QAbstractSocket::IPv4Protocol;
|
||||
plen = 32;
|
||||
} else if (dst->sa_family == AF_INET6) {
|
||||
m_defaultGatewayIpv6.clear();
|
||||
m_defaultIfindexIpv6 = 0;
|
||||
protocol = QAbstractSocket::IPv6Protocol;
|
||||
plen = 128;
|
||||
}
|
||||
|
||||
logger.debug() << "Lost default route via" << ifname
|
||||
<< logger.sensitive(addrToString(addrlist[1]));
|
||||
for (const QHostAddress& addr : m_exclusionRoutes) {
|
||||
if (addr.protocol() == protocol) {
|
||||
for (const IPAddress& prefix : m_exclusionRoutes) {
|
||||
if (prefix.address().protocol() == protocol) {
|
||||
logger.debug() << "Removing exclusion route to"
|
||||
<< logger.sensitive(addr.toString());
|
||||
rtmSendRoute(RTM_DELETE, addr, plen, rtm->rtm_index, nullptr);
|
||||
<< logger.sensitive(prefix.toString());
|
||||
rtmSendRoute(RTM_DELETE, prefix, rtm->rtm_index, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -227,7 +224,6 @@ void MacosRouteMonitor::handleRtmUpdate(const struct rt_msghdr* rtm,
|
|||
const struct sockaddr* dst =
|
||||
reinterpret_cast<const struct sockaddr*>(addrlist[0].constData());
|
||||
QAbstractSocket::NetworkLayerProtocol protocol;
|
||||
unsigned int plen;
|
||||
int rtm_type = RTM_ADD;
|
||||
if (dst->sa_family == AF_INET) {
|
||||
if (m_defaultIfindexIpv4 != 0) {
|
||||
|
|
@ -236,7 +232,6 @@ void MacosRouteMonitor::handleRtmUpdate(const struct rt_msghdr* rtm,
|
|||
m_defaultGatewayIpv4 = addrlist[1];
|
||||
m_defaultIfindexIpv4 = ifindex;
|
||||
protocol = QAbstractSocket::IPv4Protocol;
|
||||
plen = 32;
|
||||
} else if (dst->sa_family == AF_INET6) {
|
||||
if (m_defaultIfindexIpv6 != 0) {
|
||||
rtm_type = RTM_CHANGE;
|
||||
|
|
@ -244,7 +239,6 @@ void MacosRouteMonitor::handleRtmUpdate(const struct rt_msghdr* rtm,
|
|||
m_defaultGatewayIpv6 = addrlist[1];
|
||||
m_defaultIfindexIpv6 = ifindex;
|
||||
protocol = QAbstractSocket::IPv6Protocol;
|
||||
plen = 128;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
|
@ -252,11 +246,11 @@ void MacosRouteMonitor::handleRtmUpdate(const struct rt_msghdr* rtm,
|
|||
// Update the exclusion routes with the new default route.
|
||||
logger.debug() << "Updating default route via" << ifname
|
||||
<< addrToString(addrlist[1]);
|
||||
for (const QHostAddress& addr : m_exclusionRoutes) {
|
||||
if (addr.protocol() == protocol) {
|
||||
for (const IPAddress& prefix : m_exclusionRoutes) {
|
||||
if (prefix.address().protocol() == protocol) {
|
||||
logger.debug() << "Updating exclusion route to"
|
||||
<< logger.sensitive(addr.toString());
|
||||
rtmSendRoute(rtm_type, addr, plen, ifindex, addrlist[1].constData());
|
||||
<< logger.sensitive(prefix.toString());
|
||||
rtmSendRoute(rtm_type, prefix, ifindex, addrlist[1].constData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -353,8 +347,8 @@ void MacosRouteMonitor::rtmAppendAddr(struct rt_msghdr* rtm, size_t maxlen,
|
|||
}
|
||||
}
|
||||
|
||||
bool MacosRouteMonitor::rtmSendRoute(int action, const QHostAddress& prefix,
|
||||
unsigned int plen, unsigned int ifindex,
|
||||
bool MacosRouteMonitor::rtmSendRoute(int action, const IPAddress& prefix,
|
||||
unsigned int ifindex,
|
||||
const void* gateway) {
|
||||
constexpr size_t rtm_max_size = sizeof(struct rt_msghdr) +
|
||||
sizeof(struct sockaddr_in6) * 2 +
|
||||
|
|
@ -375,9 +369,9 @@ bool MacosRouteMonitor::rtmSendRoute(int action, const QHostAddress& prefix,
|
|||
memset(&rtm->rtm_rmx, 0, sizeof(rtm->rtm_rmx));
|
||||
|
||||
// Append RTA_DST
|
||||
if (prefix.protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
if (prefix.address().protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
struct sockaddr_in6 sin6;
|
||||
Q_IPV6ADDR dst = prefix.toIPv6Address();
|
||||
Q_IPV6ADDR dst = prefix.address().toIPv6Address();
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
|
|
@ -385,7 +379,7 @@ bool MacosRouteMonitor::rtmSendRoute(int action, const QHostAddress& prefix,
|
|||
rtmAppendAddr(rtm, rtm_max_size, RTA_DST, &sin6);
|
||||
} else {
|
||||
struct sockaddr_in sin;
|
||||
quint32 dst = prefix.toIPv4Address();
|
||||
quint32 dst = prefix.address().toIPv4Address();
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(sin);
|
||||
|
|
@ -403,7 +397,8 @@ bool MacosRouteMonitor::rtmSendRoute(int action, const QHostAddress& prefix,
|
|||
}
|
||||
|
||||
// Append RTA_NETMASK
|
||||
if (prefix.protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
unsigned int plen = prefix.prefixLength();
|
||||
if (prefix.address().protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
struct sockaddr_in6 sin6;
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
|
|
@ -413,7 +408,7 @@ bool MacosRouteMonitor::rtmSendRoute(int action, const QHostAddress& prefix,
|
|||
sin6.sin6_addr.s6_addr[plen / 8] = 0xFF ^ (0xFF >> (plen % 8));
|
||||
}
|
||||
rtmAppendAddr(rtm, rtm_max_size, RTA_NETMASK, &sin6);
|
||||
} else if (prefix.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
} else if (prefix.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
struct sockaddr_in sin;
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
|
|
@ -497,34 +492,32 @@ bool MacosRouteMonitor::insertRoute(const IPAddress& prefix) {
|
|||
datalink.sdl_slen = 0;
|
||||
memcpy(&datalink.sdl_data, qPrintable(m_ifname), datalink.sdl_nlen);
|
||||
|
||||
return rtmSendRoute(RTM_ADD, prefix.address(), prefix.prefixLength(),
|
||||
m_ifindex, &datalink);
|
||||
return rtmSendRoute(RTM_ADD, prefix, m_ifindex, &datalink);
|
||||
}
|
||||
|
||||
bool MacosRouteMonitor::deleteRoute(const IPAddress& prefix) {
|
||||
return rtmSendRoute(RTM_DELETE, prefix.address(), prefix.prefixLength(),
|
||||
m_ifindex, nullptr);
|
||||
return rtmSendRoute(RTM_DELETE, prefix, m_ifindex, nullptr);
|
||||
}
|
||||
|
||||
bool MacosRouteMonitor::addExclusionRoute(const QHostAddress& address) {
|
||||
bool MacosRouteMonitor::addExclusionRoute(const IPAddress& prefix) {
|
||||
logger.debug() << "Adding exclusion route for"
|
||||
<< logger.sensitive(address.toString());
|
||||
<< logger.sensitive(prefix.toString());
|
||||
|
||||
if (m_exclusionRoutes.contains(address)) {
|
||||
if (m_exclusionRoutes.contains(prefix)) {
|
||||
logger.warning() << "Exclusion route already exists";
|
||||
return false;
|
||||
}
|
||||
m_exclusionRoutes.append(address);
|
||||
m_exclusionRoutes.append(prefix);
|
||||
|
||||
// If the default route is known, then updte the routing table immediately.
|
||||
if ((address.protocol() == QAbstractSocket::IPv4Protocol) &&
|
||||
if ((prefix.address().protocol() == QAbstractSocket::IPv4Protocol) &&
|
||||
(m_defaultIfindexIpv4 != 0) && !m_defaultGatewayIpv4.isEmpty()) {
|
||||
return rtmSendRoute(RTM_ADD, address, 32, m_defaultIfindexIpv4,
|
||||
return rtmSendRoute(RTM_ADD, prefix, m_defaultIfindexIpv4,
|
||||
m_defaultGatewayIpv4.constData());
|
||||
}
|
||||
if ((address.protocol() == QAbstractSocket::IPv6Protocol) &&
|
||||
if ((prefix.address().protocol() == QAbstractSocket::IPv6Protocol) &&
|
||||
(m_defaultIfindexIpv6 != 0) && !m_defaultGatewayIpv6.isEmpty()) {
|
||||
return rtmSendRoute(RTM_ADD, address, 128, m_defaultIfindexIpv6,
|
||||
return rtmSendRoute(RTM_ADD, prefix, m_defaultIfindexIpv6,
|
||||
m_defaultGatewayIpv6.constData());
|
||||
}
|
||||
|
||||
|
|
@ -532,16 +525,15 @@ bool MacosRouteMonitor::addExclusionRoute(const QHostAddress& address) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MacosRouteMonitor::deleteExclusionRoute(const QHostAddress& address) {
|
||||
bool MacosRouteMonitor::deleteExclusionRoute(const IPAddress& prefix) {
|
||||
logger.debug() << "Deleting exclusion route for"
|
||||
<< logger.sensitive(address.toString());
|
||||
<< logger.sensitive(prefix.toString());
|
||||
|
||||
m_exclusionRoutes.removeAll(address);
|
||||
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
return rtmSendRoute(RTM_DELETE, address, 32, m_defaultIfindexIpv4, nullptr);
|
||||
} else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
return rtmSendRoute(RTM_DELETE, address, 128, m_defaultIfindexIpv6,
|
||||
nullptr);
|
||||
m_exclusionRoutes.removeAll(prefix);
|
||||
if (prefix.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
return rtmSendRoute(RTM_DELETE, prefix, m_defaultIfindexIpv4, nullptr);
|
||||
} else if (prefix.address().protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
return rtmSendRoute(RTM_DELETE, prefix, m_defaultIfindexIpv6, nullptr);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -549,11 +541,11 @@ bool MacosRouteMonitor::deleteExclusionRoute(const QHostAddress& address) {
|
|||
|
||||
void MacosRouteMonitor::flushExclusionRoutes() {
|
||||
while (!m_exclusionRoutes.isEmpty()) {
|
||||
QHostAddress address = m_exclusionRoutes.takeFirst();
|
||||
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
rtmSendRoute(RTM_DELETE, address, 32, m_defaultIfindexIpv4, nullptr);
|
||||
} else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
rtmSendRoute(RTM_DELETE, address, 128, m_defaultIfindexIpv6, nullptr);
|
||||
IPAddress prefix = m_exclusionRoutes.takeFirst();
|
||||
if (prefix.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
rtmSendRoute(RTM_DELETE, prefix, m_defaultIfindexIpv4, nullptr);
|
||||
} else if (prefix.address().protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
rtmSendRoute(RTM_DELETE, prefix, m_defaultIfindexIpv6, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,16 +28,16 @@ class MacosRouteMonitor final : public QObject {
|
|||
bool deleteRoute(const IPAddress& prefix);
|
||||
int interfaceFlags() { return m_ifflags; }
|
||||
|
||||
bool addExclusionRoute(const QHostAddress& address);
|
||||
bool deleteExclusionRoute(const QHostAddress& address);
|
||||
bool addExclusionRoute(const IPAddress& prefix);
|
||||
bool deleteExclusionRoute(const IPAddress& prefix);
|
||||
void flushExclusionRoutes();
|
||||
|
||||
private:
|
||||
void handleRtmDelete(const struct rt_msghdr* msg, const QByteArray& payload);
|
||||
void handleRtmUpdate(const struct rt_msghdr* msg, const QByteArray& payload);
|
||||
void handleIfaceInfo(const struct if_msghdr* msg, const QByteArray& payload);
|
||||
bool rtmSendRoute(int action, const QHostAddress& prefix, unsigned int plen,
|
||||
unsigned int ifindex, const void* gateway);
|
||||
bool rtmSendRoute(int action, const IPAddress& prefix, unsigned int ifindex,
|
||||
const void* gateway);
|
||||
bool rtmFetchRoutes(int family);
|
||||
static void rtmAppendAddr(struct rt_msghdr* rtm, size_t maxlen, int rtaddr,
|
||||
const void* sa);
|
||||
|
|
@ -50,7 +50,7 @@ class MacosRouteMonitor final : public QObject {
|
|||
static QString addrToString(const struct sockaddr* sa);
|
||||
static QString addrToString(const QByteArray& data);
|
||||
|
||||
QList<QHostAddress> m_exclusionRoutes;
|
||||
QList<IPAddress> m_exclusionRoutes;
|
||||
QByteArray m_defaultGatewayIpv4;
|
||||
QByteArray m_defaultGatewayIpv6;
|
||||
unsigned int m_defaultIfindexIpv4 = 0;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ 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";
|
||||
|
|
@ -133,9 +132,14 @@ 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));
|
||||
|
||||
logger.debug() << "Configuring peer" << config.m_serverPublicKey
|
||||
<< "via" << config.m_serverIpv4AddrIn;
|
||||
|
||||
// Update/create the peer config
|
||||
QString message;
|
||||
QTextStream out(&message);
|
||||
|
|
@ -150,6 +154,7 @@ bool WireguardUtilsMacos::updatePeer(const InterfaceConfig& config) {
|
|||
logger.warning() << "Failed to create peer with no endpoints";
|
||||
return false;
|
||||
}
|
||||
|
||||
out << config.m_serverPort << "\n";
|
||||
|
||||
out << "replace_allowed_ips=true\n";
|
||||
|
|
@ -158,7 +163,13 @@ bool WireguardUtilsMacos::updatePeer(const InterfaceConfig& config) {
|
|||
out << "allowed_ip=" << ip.toString() << "\n";
|
||||
}
|
||||
|
||||
logger.debug() << message;
|
||||
// Exclude the server address, except for multihop exit servers.
|
||||
if ((config.m_hopType != InterfaceConfig::MultiHopExit) &&
|
||||
(m_rtmonitor != nullptr)) {
|
||||
m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
||||
m_rtmonitor->addExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
||||
}
|
||||
|
||||
int err = uapiErrno(uapiCommand(message));
|
||||
if (err != 0) {
|
||||
logger.error() << "Peer configuration failed:" << strerror(err);
|
||||
|
|
@ -170,6 +181,13 @@ bool WireguardUtilsMacos::deletePeer(const InterfaceConfig& config) {
|
|||
QByteArray publicKey =
|
||||
QByteArray::fromBase64(qPrintable(config.m_serverPublicKey));
|
||||
|
||||
// Clear exclustion routes for this peer.
|
||||
if ((config.m_hopType != InterfaceConfig::MultiHopExit) &&
|
||||
(m_rtmonitor != nullptr)) {
|
||||
m_rtmonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv4AddrIn));
|
||||
m_rtmonitor->deleteExclusionRoute(IPAddress(config.m_serverIpv6AddrIn));
|
||||
}
|
||||
|
||||
QString message;
|
||||
QTextStream out(&message);
|
||||
out << "set=1\n";
|
||||
|
|
@ -223,9 +241,7 @@ QList<WireguardUtils::PeerStatus> WireguardUtilsMacos::getPeerStatus() {
|
|||
return peerList;
|
||||
}
|
||||
|
||||
bool WireguardUtilsMacos::updateRoutePrefix(const IPAddress& prefix,
|
||||
int hopindex) {
|
||||
Q_UNUSED(hopindex);
|
||||
bool WireguardUtilsMacos::updateRoutePrefix(const IPAddress& prefix) {
|
||||
if (!m_rtmonitor) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -246,9 +262,7 @@ bool WireguardUtilsMacos::updateRoutePrefix(const IPAddress& prefix,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool WireguardUtilsMacos::deleteRoutePrefix(const IPAddress& prefix,
|
||||
int hopindex) {
|
||||
Q_UNUSED(hopindex);
|
||||
bool WireguardUtilsMacos::deleteRoutePrefix(const IPAddress& prefix) {
|
||||
if (!m_rtmonitor) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -268,18 +282,18 @@ bool WireguardUtilsMacos::deleteRoutePrefix(const IPAddress& prefix,
|
|||
}
|
||||
}
|
||||
|
||||
bool WireguardUtilsMacos::addExclusionRoute(const QHostAddress& address) {
|
||||
bool WireguardUtilsMacos::addExclusionRoute(const IPAddress& prefix) {
|
||||
if (!m_rtmonitor) {
|
||||
return false;
|
||||
}
|
||||
return m_rtmonitor->addExclusionRoute(address);
|
||||
return m_rtmonitor->addExclusionRoute(prefix);
|
||||
}
|
||||
|
||||
bool WireguardUtilsMacos::deleteExclusionRoute(const QHostAddress& address) {
|
||||
bool WireguardUtilsMacos::deleteExclusionRoute(const IPAddress& prefix) {
|
||||
if (!m_rtmonitor) {
|
||||
return false;
|
||||
}
|
||||
return m_rtmonitor->deleteExclusionRoute(address);
|
||||
return m_rtmonitor->deleteExclusionRoute(prefix);
|
||||
}
|
||||
|
||||
QString WireguardUtilsMacos::uapiCommand(const QString& command) {
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ class WireguardUtilsMacos final : public WireguardUtils {
|
|||
bool deletePeer(const InterfaceConfig& config) override;
|
||||
QList<PeerStatus> getPeerStatus() override;
|
||||
|
||||
bool updateRoutePrefix(const IPAddress& prefix, int hopindex) override;
|
||||
bool deleteRoutePrefix(const IPAddress& prefix, int hopindex) override;
|
||||
bool updateRoutePrefix(const IPAddress& prefix) override;
|
||||
bool deleteRoutePrefix(const IPAddress& prefix) override;
|
||||
|
||||
bool addExclusionRoute(const QHostAddress& address) override;
|
||||
bool deleteExclusionRoute(const QHostAddress& address) override;
|
||||
bool addExclusionRoute(const IPAddress& prefix) override;
|
||||
bool deleteExclusionRoute(const IPAddress& prefix) override;
|
||||
|
||||
signals:
|
||||
void backendFailure();
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ bool dockClickHandler(id self, SEL cmd, ...) {
|
|||
Q_UNUSED(cmd);
|
||||
|
||||
logger.debug() << "Dock icon clicked.";
|
||||
|
||||
//TODO IMPL FOR AMNEZIA
|
||||
//QmlEngineHolder::instance()->showWindow();
|
||||
return FALSE;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue