mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
fix: xray stability and split-tunneling (#2187)
* fix: xray heap corruption * fix: use proper configuration for split-tunneled apps * chore: enable killswitch * chore: xray windows split-tunneling cleanup * chore: proper xray killswitch log * feat: add wait for the tun device * chore: update amnezia_xray deps for macos * fix: add nullptr check for split-tunnel on win * fix: modernize vpnAdapter grabbing function * fix: remove network watcher due to its fragileness * chore: xrayprotocol cleanup * fix: correct wrong iface index on win * chore: move tun2socks implementation to the client from the service * chore: xrayprotocol cleanup * chore: more xrayprotocol cleanup * fix: consistent tun device with GUID specified * chore: tun2socks logs * chore: PrivilegedProcess cleanup * better error handling in establishment phase * terminate&kill ops for remote process * fix: straighforward killing the process on windows * fix: finally remove GUID setting from tun2socks due to instability * fix: add sanitizer to ipc process * chore: do not collect sensitive info from tun2socks
This commit is contained in:
@@ -7,7 +7,6 @@ IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_node.connectToNode(QUrl("local:" + amnezia::getIpcServiceUrl()));
|
||||
m_interface.reset(m_node.acquire<IpcInterfaceReplica>());
|
||||
m_tun2socks.reset(m_node.acquire<IpcProcessTun2SocksReplica>());
|
||||
}
|
||||
|
||||
IpcClient& IpcClient::Instance()
|
||||
@@ -33,68 +32,43 @@ QSharedPointer<IpcInterfaceReplica> IpcClient::Interface()
|
||||
return rep;
|
||||
}
|
||||
|
||||
QSharedPointer<IpcProcessTun2SocksReplica> IpcClient::InterfaceTun2Socks()
|
||||
QSharedPointer<IpcProcessInterfaceReplica> IpcClient::CreatePrivilegedProcess()
|
||||
{
|
||||
QSharedPointer<IpcProcessTun2SocksReplica> rep = Instance().m_tun2socks;
|
||||
if (rep.isNull()) {
|
||||
qCritical() << "IpcClient::InterfaceTun2Socks: Replica is undefined";
|
||||
return nullptr;
|
||||
}
|
||||
if (!rep->waitForSource(1000)) {
|
||||
qCritical() << "IpcClient::InterfaceTun2Socks: Failed to initialize replica";
|
||||
return nullptr;
|
||||
}
|
||||
if (!rep->isReplicaValid()) {
|
||||
qWarning() << "IpcClient::InterfaceTun2Socks(): Replica is invalid";
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
||||
QSharedPointer<PrivilegedProcess> IpcClient::CreatePrivilegedProcess()
|
||||
{
|
||||
QSharedPointer<IpcInterfaceReplica> rep = Interface();
|
||||
if (!rep) {
|
||||
qCritical() << "IpcClient::createPrivilegedProcess: Replica is invalid";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QRemoteObjectPendingReply<int> pidReply = rep->createPrivilegedProcess();
|
||||
if (!pidReply.waitForFinished(5000)){
|
||||
qCritical() << "IpcClient::createPrivilegedProcess: Failed to execute RO createPrivilegedProcess call";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int pid = pidReply.returnValue();
|
||||
QSharedPointer<ProcessDescriptor> pd(new ProcessDescriptor());
|
||||
|
||||
pd->localSocket.reset(new QLocalSocket(pd->replicaNode.data()));
|
||||
|
||||
connect(pd->localSocket.data(), &QLocalSocket::connected, pd->replicaNode.data(), [pd]() {
|
||||
pd->replicaNode->addClientSideConnection(pd->localSocket.data());
|
||||
|
||||
IpcProcessInterfaceReplica *repl = pd->replicaNode->acquire<IpcProcessInterfaceReplica>();
|
||||
// TODO: rework the unsafe cast below
|
||||
PrivilegedProcess *priv = static_cast<PrivilegedProcess *>(repl);
|
||||
pd->ipcProcess.reset(priv);
|
||||
if (!pd->ipcProcess) {
|
||||
qWarning() << "Acquire PrivilegedProcess failed";
|
||||
} else {
|
||||
pd->ipcProcess->waitForSource(1000);
|
||||
if (!pd->ipcProcess->isReplicaValid()) {
|
||||
qWarning() << "PrivilegedProcess replica is not connected!";
|
||||
}
|
||||
|
||||
QObject::connect(pd->ipcProcess.data(), &PrivilegedProcess::destroyed, pd->ipcProcess.data(),
|
||||
[pd]() { pd->replicaNode->deleteLater(); });
|
||||
return withInterface([](QSharedPointer<IpcInterfaceReplica> &iface) -> QSharedPointer<IpcProcessInterfaceReplica> {
|
||||
auto createPrivilegedProcess = iface->createPrivilegedProcess();
|
||||
if (!createPrivilegedProcess.waitForFinished()) {
|
||||
qCritical() << "Failed to create privileged process";
|
||||
return nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
pd->localSocket->connectToServer(amnezia::getIpcProcessUrl(pid));
|
||||
if (!pd->localSocket->waitForConnected()) {
|
||||
qCritical() << "IpcClient::createPrivilegedProcess: Failed to connect to process' socket";
|
||||
const int pid = createPrivilegedProcess.returnValue();
|
||||
|
||||
auto* node = new QRemoteObjectNode();
|
||||
node->connectToNode(QUrl(QString("local:%1").arg(amnezia::getIpcProcessUrl(pid))));
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> rep(
|
||||
node->acquire<IpcProcessInterfaceReplica>(),
|
||||
[node] (IpcProcessInterfaceReplica *ptr) {
|
||||
delete ptr;
|
||||
node->deleteLater();
|
||||
}
|
||||
);
|
||||
if (rep.isNull()) {
|
||||
qCritical() << "IpcClient::CreatePrivilegedProcess(): Failed to acquire replica";
|
||||
return nullptr;
|
||||
}
|
||||
if (!rep->waitForSource()) {
|
||||
qCritical() << "IpcClient::CreatePrivilegedProcess(): Failed to initialize replica";
|
||||
return nullptr;
|
||||
}
|
||||
if (!rep->isReplicaValid()) {
|
||||
qCritical() << "IpcClient::CreatePrivilegedProcess(): Replica is invalid";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return rep;
|
||||
},
|
||||
[]() -> QSharedPointer<IpcProcessInterfaceReplica> {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto processReplica = QSharedPointer<PrivilegedProcess>(pd->ipcProcess);
|
||||
return processReplica;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "rep_ipc_interface_replica.h"
|
||||
#include "rep_ipc_process_tun2socks_replica.h"
|
||||
|
||||
#include "privileged_process.h"
|
||||
#include "rep_ipc_process_interface_replica.h"
|
||||
|
||||
class IpcClient : public QObject
|
||||
{
|
||||
@@ -18,8 +16,7 @@ public:
|
||||
static IpcClient& Instance();
|
||||
|
||||
static QSharedPointer<IpcInterfaceReplica> Interface();
|
||||
static QSharedPointer<IpcProcessTun2SocksReplica> InterfaceTun2Socks();
|
||||
static QSharedPointer<PrivilegedProcess> CreatePrivilegedProcess();
|
||||
static QSharedPointer<IpcProcessInterfaceReplica> CreatePrivilegedProcess();
|
||||
|
||||
template <typename Func>
|
||||
static auto withInterface(Func func)
|
||||
@@ -54,18 +51,6 @@ signals:
|
||||
private:
|
||||
QRemoteObjectNode m_node;
|
||||
QSharedPointer<IpcInterfaceReplica> m_interface;
|
||||
QSharedPointer<IpcProcessTun2SocksReplica> m_tun2socks;
|
||||
|
||||
struct ProcessDescriptor {
|
||||
ProcessDescriptor () {
|
||||
replicaNode = QSharedPointer<QRemoteObjectNode>(new QRemoteObjectNode());
|
||||
ipcProcess = QSharedPointer<PrivilegedProcess>();
|
||||
localSocket = QSharedPointer<QLocalSocket>();
|
||||
}
|
||||
QSharedPointer<PrivilegedProcess> ipcProcess;
|
||||
QSharedPointer<QRemoteObjectNode> replicaNode;
|
||||
QSharedPointer<QLocalSocket> localSocket;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // IPCCLIENT_H
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#include "privileged_process.h"
|
||||
|
||||
PrivilegedProcess::PrivilegedProcess() :
|
||||
IpcProcessInterfaceReplica()
|
||||
{
|
||||
}
|
||||
|
||||
PrivilegedProcess::~PrivilegedProcess()
|
||||
{
|
||||
qDebug() << "PrivilegedProcess::~PrivilegedProcess()";
|
||||
}
|
||||
|
||||
void PrivilegedProcess::waitForFinished(int msecs)
|
||||
{
|
||||
QSharedPointer<QEventLoop> loop(new QEventLoop);
|
||||
connect(this, &PrivilegedProcess::finished, this, [this, loop](int exitCode, QProcess::ExitStatus exitStatus) mutable{
|
||||
loop->quit();
|
||||
loop.clear();
|
||||
});
|
||||
|
||||
QTimer::singleShot(msecs, this, [this, loop]() mutable {
|
||||
loop->quit();
|
||||
loop.clear();
|
||||
});
|
||||
|
||||
loop->exec();
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#ifndef PRIVILEGED_PROCESS_H
|
||||
#define PRIVILEGED_PROCESS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "rep_ipc_process_interface_replica.h"
|
||||
// This class is dangerous - instance of this class casted from base class,
|
||||
// so it support only functions
|
||||
// Do not add any members into it
|
||||
//
|
||||
class PrivilegedProcess : public IpcProcessInterfaceReplica
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PrivilegedProcess();
|
||||
~PrivilegedProcess() override;
|
||||
|
||||
void waitForFinished(int msecs);
|
||||
|
||||
};
|
||||
|
||||
#endif // PRIVILEGED_PROCESS_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user