Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
Nethius committed Sep 17, 2023
2 parents 32dda9b + f62076d commit 9b32411
Show file tree
Hide file tree
Showing 67 changed files with 4,821 additions and 434 deletions.
42 changes: 42 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Log files**
Attach log files to help explain your problem.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. Windows 10]
- Version [e.g. 2.1.2]

**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Version [e.g. 2.1.2]

**Server (please complete the following information):**
- OS: [e.g. Ubuntu 22.04]

**Additional context**
Add any other context about the problem here.
2 changes: 1 addition & 1 deletion client/3rd-prebuilt
Submodule 3rd-prebuilt updated 28 files
+ 3rd-prebuilt/libssh/android/arm64-v8a/libssh.so
+1 −1 3rd-prebuilt/libssh/android/arm64-v8a/libssh.so.sha256
+ 3rd-prebuilt/libssh/android/armeabi-v7a/libssh.so
+1 −1 3rd-prebuilt/libssh/android/armeabi-v7a/libssh.so.sha256
+ 3rd-prebuilt/libssh/android/x86/libssh.so
+1 −1 3rd-prebuilt/libssh/android/x86/libssh.so.sha256
+ 3rd-prebuilt/libssh/android/x86_64/libssh.so
+1 −1 3rd-prebuilt/libssh/android/x86_64/libssh.so.sha256
+ deploy-prebuilt/windows/x32/WdfCoinstaller01011.dll
+ deploy-prebuilt/windows/x32/mullvad-split-tunnel.cat
+87 −0 deploy-prebuilt/windows/x32/mullvad-split-tunnel.inf
+ deploy-prebuilt/windows/x32/mullvad-split-tunnel.sys
+ deploy-prebuilt/windows/x32/tunnel.dll
+ deploy-prebuilt/windows/x32/wintun.dll
+ deploy-prebuilt/windows/x32/wireguard/tunnel.dll
+0 −1 deploy-prebuilt/windows/x32/wireguard/tunnel.dll.sha256
+ deploy-prebuilt/windows/x32/wireguard/wireguard.dll
+0 −1 deploy-prebuilt/windows/x32/wireguard/wireguard.dll.sha256
+ deploy-prebuilt/windows/x64/WdfCoinstaller01011.dll
+ deploy-prebuilt/windows/x64/mullvad-split-tunnel.cat
+87 −0 deploy-prebuilt/windows/x64/mullvad-split-tunnel.inf
+ deploy-prebuilt/windows/x64/mullvad-split-tunnel.sys
+ deploy-prebuilt/windows/x64/tunnel.dll
+ deploy-prebuilt/windows/x64/wintun.dll
+ deploy-prebuilt/windows/x64/wireguard/tunnel.dll
+0 −1 deploy-prebuilt/windows/x64/wireguard/tunnel.dll.sha256
+ deploy-prebuilt/windows/x64/wireguard/wireguard.dll
+0 −1 deploy-prebuilt/windows/x64/wireguard/wireguard.dll.sha256
Binary file modified client/android/res/drawable-hdpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified client/android/res/drawable-ldpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified client/android/res/drawable-mdpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified client/android/res/drawable-xhdpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified client/android/res/drawable-xxhdpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified client/android/res/drawable-xxxhdpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
137 changes: 83 additions & 54 deletions client/daemon/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QMetaEnum>
#include <QTimer>

#include "leakdetector.h"
Expand Down Expand Up @@ -64,9 +65,12 @@ bool Daemon::activate(const InterfaceConfig& config) {
// method calls switchServer().
//
// At the end, if the activation succeds, the `connected` signal is emitted.
// If the activation abort's for any reason `the `activationFailure` signal is
// emitted.
logger.debug() << "Activating interface";
auto emit_failure_guard = qScopeGuard([this] { emit activationFailure(); });

if (m_connections.contains(config.m_hopindex)) {
if (m_connections.contains(config.m_hopType)) {
if (supportServerSwitching(config)) {
logger.debug() << "Already connected. Server switching supported.";

Expand All @@ -85,19 +89,25 @@ bool Daemon::activate(const InterfaceConfig& config) {
bool status = run(Switch, config);
logger.debug() << "Connection status:" << status;
if (status) {
m_connections[config.m_hopindex] = ConnectionState(config);
m_connections[config.m_hopType] = ConnectionState(config);
m_handshakeTimer.start(HANDSHAKE_POLL_MSEC);
emit_failure_guard.dismiss();
return true;
}
return status;
return false;
}

logger.warning() << "Already connected. Server switching not supported.";
if (!deactivate(false)) {
return false;
}

Q_ASSERT(!m_connections.contains(config.m_hopindex));
return activate(config);
Q_ASSERT(!m_connections.contains(config.m_hopType));
if (activate(config)) {
emit_failure_guard.dismiss();
return true;
}
return false;
}

prepareActivation(config);
Expand All @@ -112,13 +122,7 @@ bool Daemon::activate(const InterfaceConfig& config) {

// Configure routing for excluded addresses.
for (const QString& i : config.m_excludedAddresses) {
QHostAddress address(i);
if (m_excludedAddrSet.contains(address)) {
m_excludedAddrSet[address]++;
continue;
}
wgutils()->addExclusionRoute(address);
m_excludedAddrSet[address] = 1;
addExclusionRoute(IPAddress(i));
}

// Add the peer to this interface.
Expand All @@ -142,7 +146,7 @@ bool Daemon::activate(const InterfaceConfig& config) {

// set routing
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
if (!wgutils()->updateRoutePrefix(ip, config.m_hopindex)) {
if (!wgutils()->updateRoutePrefix(ip)) {
logger.debug() << "Routing configuration failed for"
<< logger.sensitive(ip.toString());
return false;
Expand All @@ -152,15 +156,21 @@ bool Daemon::activate(const InterfaceConfig& config) {
bool status = run(Up, config);
logger.debug() << "Connection status:" << status;
if (status) {
m_connections[config.m_hopindex] = ConnectionState(config);
m_connections[config.m_hopType] = ConnectionState(config);
m_handshakeTimer.start(HANDSHAKE_POLL_MSEC);
emit_failure_guard.dismiss();
return true;
}

return status;
return false;
}

bool Daemon::maybeUpdateResolvers(const InterfaceConfig& config) {
if ((config.m_hopindex == 0) && supportDnsUtils()) {
if (!supportDnsUtils()) {
return true;
}

if ((config.m_hopType == InterfaceConfig::MultiHopExit) ||
(config.m_hopType == InterfaceConfig::SingleHop)) {
QList<QHostAddress> resolvers;
resolvers.append(QHostAddress(config.m_dnsServer));

Expand Down Expand Up @@ -199,6 +209,28 @@ bool Daemon::parseStringList(const QJsonObject& obj, const QString& name,
return true;
}

bool Daemon::addExclusionRoute(const IPAddress& prefix) {
if (m_excludedAddrSet.contains(prefix)) {
m_excludedAddrSet[prefix]++;
return true;
}
if (!wgutils()->addExclusionRoute(prefix)) {
return false;
}
m_excludedAddrSet[prefix] = 1;
return true;
}

bool Daemon::delExclusionRoute(const IPAddress& prefix) {
Q_ASSERT(m_excludedAddrSet.contains(prefix));
if (m_excludedAddrSet[prefix] > 1) {
m_excludedAddrSet[prefix]--;
return true;
}
m_excludedAddrSet.remove(prefix);
return wgutils()->deleteExclusionRoute(prefix);
}

// static
bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
#define GETVALUE(name, where, jsontype) \
Expand All @@ -216,8 +248,8 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {

GETVALUE("privateKey", config.m_privateKey, String);
GETVALUE("serverPublicKey", config.m_serverPublicKey, String);
GETVALUE("serverPort", config.m_serverPort, Double);
GETVALUE("serverPskKey", config.m_serverPskKey, String);
GETVALUE("serverPort", config.m_serverPort, Double);

config.m_deviceIpv4Address = obj.value("deviceIpv4Address").toString();
config.m_deviceIpv6Address = obj.value("deviceIpv6Address").toString();
Expand Down Expand Up @@ -247,15 +279,24 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
config.m_dnsServer = value.toString();
}

if (!obj.contains("hopindex")) {
config.m_hopindex = 0;
if (!obj.contains("hopType")) {
config.m_hopType = InterfaceConfig::SingleHop;
} else {
QJsonValue value = obj.value("hopindex");
if (!value.isDouble()) {
logger.error() << "hopindex is not a number";
QJsonValue value = obj.value("hopType");
if (!value.isString()) {
logger.error() << "hopType is not a string";
return false;
}

bool okay;
QByteArray vdata = value.toString().toUtf8();
QMetaEnum meta = QMetaEnum::fromType<InterfaceConfig::HopType>();
config.m_hopType =
InterfaceConfig::HopType(meta.keyToValue(vdata.constData(), &okay));
if (!okay) {
logger.error() << "hopType" << value.toString() << "is not valid";
return false;
}
config.m_hopindex = value.toInt();
}

if (!obj.contains(JSON_ALLOWEDIPADDRESSRANGES)) {
Expand Down Expand Up @@ -325,8 +366,8 @@ bool Daemon::deactivate(bool emitSignals) {
Q_ASSERT(wgutils() != nullptr);

// Deactivate the main interface.
if (m_connections.contains(0)) {
const ConnectionState& state = m_connections.value(0);
if (!m_connections.isEmpty()) {
const ConnectionState& state = m_connections.first();
if (!run(Down, state.m_config)) {
return false;
}
Expand All @@ -349,9 +390,9 @@ bool Daemon::deactivate(bool emitSignals) {
// Cleanup peers and routing
for (const ConnectionState& state : m_connections) {
const InterfaceConfig& config = state.m_config;
logger.debug() << "Deleting routes for hop" << config.m_hopindex;
logger.debug() << "Deleting routes for" << config.m_hopType;
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
wgutils()->deleteRoutePrefix(ip, config.m_hopindex);
wgutils()->deleteRoutePrefix(ip);
}
wgutils()->deletePeer(config);
}
Expand All @@ -376,14 +417,14 @@ QString Daemon::logs() {
return {};
}

void Daemon::cleanLogs() { }
void Daemon::cleanLogs() { }

bool Daemon::supportServerSwitching(const InterfaceConfig& config) const {
if (!m_connections.contains(config.m_hopindex)) {
if (!m_connections.contains(config.m_hopType)) {
return false;
}
const InterfaceConfig& current =
m_connections.value(config.m_hopindex).m_config;
m_connections.value(config.m_hopType).m_config;

return current.m_privateKey == config.m_privateKey &&
current.m_deviceIpv4Address == config.m_deviceIpv4Address &&
Expand All @@ -395,21 +436,15 @@ bool Daemon::supportServerSwitching(const InterfaceConfig& config) const {
bool Daemon::switchServer(const InterfaceConfig& config) {
Q_ASSERT(wgutils() != nullptr);

logger.debug() << "Switching server for hop" << config.m_hopindex;
logger.debug() << "Switching server for" << config.m_hopType;

Q_ASSERT(m_connections.contains(config.m_hopindex));
Q_ASSERT(m_connections.contains(config.m_hopType));
const InterfaceConfig& lastConfig =
m_connections.value(config.m_hopindex).m_config;
m_connections.value(config.m_hopType).m_config;

// Configure routing for new excluded addresses.
for (const QString& i : config.m_excludedAddresses) {
QHostAddress address(i);
if (m_excludedAddrSet.contains(address)) {
m_excludedAddrSet[address]++;
continue;
}
wgutils()->addExclusionRoute(address);
m_excludedAddrSet[address] = 1;
addExclusionRoute(IPAddress(i));
}

// Activate the new peer and its routes.
Expand All @@ -418,26 +453,19 @@ bool Daemon::switchServer(const InterfaceConfig& config) {
return false;
}
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
if (!wgutils()->updateRoutePrefix(ip, config.m_hopindex)) {
if (!wgutils()->updateRoutePrefix(ip)) {
logger.error() << "Server switch failed to update the routing table";
break;
}
}

// Remove routing entries for the old peer.
for (const QString& i : lastConfig.m_excludedAddresses) {
QHostAddress address(i);
Q_ASSERT(m_excludedAddrSet.contains(address));
if (m_excludedAddrSet[address] > 1) {
m_excludedAddrSet[address]--;
continue;
}
wgutils()->deleteExclusionRoute(address);
m_excludedAddrSet.remove(address);
delExclusionRoute(QHostAddress(i));
}
for (const IPAddress& ip : lastConfig.m_allowedIPAddressRanges) {
if (!config.m_allowedIPAddressRanges.contains(ip)) {
wgutils()->deleteRoutePrefix(ip, config.m_hopindex);
wgutils()->deleteRoutePrefix(ip);
}
}

Expand All @@ -448,7 +476,7 @@ bool Daemon::switchServer(const InterfaceConfig& config) {
}
}

m_connections[config.m_hopindex] = ConnectionState(config);
m_connections[config.m_hopType] = ConnectionState(config);
return true;
}

Expand All @@ -457,12 +485,12 @@ QJsonObject Daemon::getStatus() {
QJsonObject json;
logger.debug() << "Status request";

if (!m_connections.contains(0) || !wgutils()->interfaceExists()) {
if (!wgutils()->interfaceExists() || m_connections.isEmpty()) {
json.insert("connected", QJsonValue(false));
return json;
}

const ConnectionState& connection = m_connections.value(0);
const ConnectionState& connection = m_connections.first();
QList<WireguardUtils::PeerStatus> peers = wgutils()->getPeerStatus();
for (const WireguardUtils::PeerStatus& status : peers) {
if (status.m_pubkey != connection.m_config.m_serverPublicKey) {
Expand Down Expand Up @@ -495,6 +523,7 @@ void Daemon::checkHandshake() {
if (connection.m_date.isValid()) {
continue;
}
logger.debug() << "awaiting" << config.m_serverPublicKey;

// Check if the handshake has completed.
for (const WireguardUtils::PeerStatus& status : peers) {
Expand Down
11 changes: 9 additions & 2 deletions client/daemon/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,18 @@ class Daemon : public QObject {

signals:
void connected(const QString& pubkey);
/**
* Can be fired if a call to activate() was unsucessfull
* and connected systems should rollback
*/
void activationFailure();
void disconnected();
void backendFailure();

private:
bool maybeUpdateResolvers(const InterfaceConfig& config);
bool addExclusionRoute(const IPAddress& address);
bool delExclusionRoute(const IPAddress& address);

protected:
virtual bool run(Op op, const InterfaceConfig& config) {
Expand Down Expand Up @@ -75,8 +82,8 @@ class Daemon : public QObject {
QDateTime m_date;
InterfaceConfig m_config;
};
QMap<int, ConnectionState> m_connections;
QHash<QHostAddress, int> m_excludedAddrSet;
QMap<InterfaceConfig::HopType, ConnectionState> m_connections;
QHash<IPAddress, int> m_excludedAddrSet;
QTimer m_handshakeTimer;
};

Expand Down
Loading

0 comments on commit 9b32411

Please sign in to comment.