2023-10-23 21:43:25 +05:00
|
|
|
#include "serverController.h"
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2021-03-13 14:16:24 +03:00
|
|
|
#include <QCryptographicHash>
|
2021-11-26 17:43:02 +03:00
|
|
|
#include <QDir>
|
2020-12-18 14:57:22 +03:00
|
|
|
#include <QEventLoop>
|
2023-07-14 22:59:49 +09:00
|
|
|
#include <QFile>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QJsonDocument>
|
|
|
|
|
#include <QJsonObject>
|
2020-12-18 14:57:22 +03:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
#include <QPointer>
|
2021-04-04 23:12:36 +03:00
|
|
|
#include <QTemporaryFile>
|
2023-01-01 21:48:20 +03:00
|
|
|
#include <QThread>
|
2023-07-14 22:59:49 +09:00
|
|
|
#include <QTimer>
|
2023-01-01 21:48:20 +03:00
|
|
|
#include <QtConcurrent>
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2022-10-23 17:38:48 +03:00
|
|
|
#include <filesystem>
|
|
|
|
|
#include <fstream>
|
2023-07-14 22:59:49 +09:00
|
|
|
#include <iostream>
|
2022-10-23 17:38:48 +03:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <thread>
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2021-09-09 20:15:44 +03:00
|
|
|
#include "containers/containers_defs.h"
|
2024-04-12 20:00:21 +05:00
|
|
|
#include "core/networkUtilities.h"
|
2023-10-12 20:48:03 +05:00
|
|
|
#include "core/scripts_registry.h"
|
|
|
|
|
#include "core/server_defs.h"
|
2024-04-12 20:00:21 +05:00
|
|
|
#include "logger.h"
|
2022-08-25 17:35:28 +03:00
|
|
|
#include "settings.h"
|
2022-08-29 12:21:09 +04:30
|
|
|
#include "utilities.h"
|
2024-04-01 20:20:02 +07:00
|
|
|
#include "vpnConfigurationController.h"
|
2021-09-24 13:14:35 +03:00
|
|
|
|
2023-12-14 18:50:09 +07:00
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
Logger logger("ServerController");
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
ServerController::ServerController(std::shared_ptr<Settings> settings, QObject *parent) : m_settings(settings)
|
2021-11-18 01:40:28 +03:00
|
|
|
{
|
2022-12-14 21:50:52 +01:00
|
|
|
}
|
2022-08-25 17:35:28 +03:00
|
|
|
|
2022-12-14 21:50:52 +01:00
|
|
|
ServerController::~ServerController()
|
|
|
|
|
{
|
2023-04-04 10:22:25 +03:00
|
|
|
m_sshClient.disconnectFromHost();
|
2021-11-18 01:40:28 +03:00
|
|
|
}
|
|
|
|
|
|
2021-10-04 19:07:49 +03:00
|
|
|
ErrorCode ServerController::runScript(const ServerCredentials &credentials, QString script,
|
2023-07-14 22:59:49 +09:00
|
|
|
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut,
|
|
|
|
|
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
|
|
|
|
|
{
|
2022-10-23 17:38:48 +03:00
|
|
|
|
2022-12-26 12:43:51 +03:00
|
|
|
auto error = m_sshClient.connectToHost(credentials);
|
2022-12-20 13:43:46 +03:00
|
|
|
if (error != ErrorCode::NoError) {
|
|
|
|
|
return error;
|
2021-01-06 17:12:24 +03:00
|
|
|
}
|
2020-12-18 14:57:22 +03:00
|
|
|
|
|
|
|
|
script.replace("\r", "");
|
|
|
|
|
|
2023-07-15 14:19:48 -07:00
|
|
|
qDebug() << "ServerController::Run script";
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2021-04-04 23:12:36 +03:00
|
|
|
QString totalLine;
|
2022-08-29 12:21:09 +04:30
|
|
|
const QStringList &lines = script.split("\n", Qt::SkipEmptyParts);
|
2020-12-18 14:57:22 +03:00
|
|
|
for (int i = 0; i < lines.count(); i++) {
|
2021-04-04 23:12:36 +03:00
|
|
|
QString currentLine = lines.at(i);
|
2021-03-18 18:45:08 +03:00
|
|
|
|
2021-04-04 23:12:36 +03:00
|
|
|
if (totalLine.isEmpty()) {
|
|
|
|
|
totalLine = currentLine;
|
2022-12-20 13:43:46 +03:00
|
|
|
} else {
|
2021-04-04 23:12:36 +03:00
|
|
|
totalLine = totalLine + "\n" + currentLine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString lineToExec;
|
|
|
|
|
if (currentLine.endsWith("\\")) {
|
|
|
|
|
continue;
|
2022-12-20 13:43:46 +03:00
|
|
|
} else {
|
2021-04-04 23:12:36 +03:00
|
|
|
lineToExec = totalLine;
|
|
|
|
|
totalLine.clear();
|
2021-03-18 18:45:08 +03:00
|
|
|
}
|
2021-01-15 23:36:35 +03:00
|
|
|
|
2022-10-23 17:38:48 +03:00
|
|
|
if (lineToExec.startsWith("#")) {
|
2020-12-18 14:57:22 +03:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-15 14:19:48 -07:00
|
|
|
qDebug().noquote() << lineToExec;
|
2022-02-04 17:49:48 +03:00
|
|
|
|
2022-12-26 12:43:51 +03:00
|
|
|
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
|
2022-12-20 13:43:46 +03:00
|
|
|
if (error != ErrorCode::NoError) {
|
|
|
|
|
return error;
|
2021-01-06 17:12:24 +03:00
|
|
|
}
|
2020-12-18 14:57:22 +03:00
|
|
|
}
|
|
|
|
|
|
2023-07-15 14:19:48 -07:00
|
|
|
qDebug().noquote() << "ServerController::runScript finished\n";
|
2021-01-06 17:12:24 +03:00
|
|
|
return ErrorCode::NoError;
|
2020-12-18 14:57:22 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::runContainerScript(const ServerCredentials &credentials, DockerContainer container, QString script,
|
|
|
|
|
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdOut,
|
|
|
|
|
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
|
2021-10-04 19:07:49 +03:00
|
|
|
{
|
|
|
|
|
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
2021-11-17 23:42:17 +03:00
|
|
|
|
2021-11-26 17:43:02 +03:00
|
|
|
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2024-09-17 01:14:13 +04:00
|
|
|
QString runner =
|
|
|
|
|
QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
|
2023-07-14 22:59:49 +09:00
|
|
|
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2021-11-15 18:17:28 +03:00
|
|
|
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
2023-07-14 22:59:49 +09:00
|
|
|
runScript(credentials, replaceVars(remover, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
2021-10-04 19:07:49 +03:00
|
|
|
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container, const ServerCredentials &credentials, const QString &file,
|
|
|
|
|
const QString &path, libssh::ScpOverwriteMode overwriteMode)
|
2020-12-18 14:57:22 +03:00
|
|
|
{
|
2021-05-10 02:33:31 +03:00
|
|
|
ErrorCode e = ErrorCode::NoError;
|
2021-04-04 23:12:36 +03:00
|
|
|
QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16));
|
2021-05-07 23:28:37 +03:00
|
|
|
e = uploadFileToHost(credentials, file.toUtf8(), tmpFileName);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-05-07 23:28:37 +03:00
|
|
|
|
|
|
|
|
QString stdOut;
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStd = [&](const QString &data, libssh::Client &) {
|
2021-05-07 23:28:37 +03:00
|
|
|
stdOut += data + "\n";
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-05-07 23:28:37 +03:00
|
|
|
};
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2021-11-26 17:43:02 +03:00
|
|
|
// mkdir
|
2023-07-14 22:59:49 +09:00
|
|
|
QString mkdir = QString("sudo docker exec -i $CONTAINER_NAME mkdir -p \"$(dirname %1)\"").arg(path);
|
2021-11-26 17:43:02 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
e = runScript(credentials, replaceVars(mkdir, genVarsForScript(credentials, container)));
|
|
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-11-26 17:43:02 +03:00
|
|
|
|
2024-03-06 02:24:28 +01:00
|
|
|
if (overwriteMode == libssh::ScpOverwriteMode::ScpOverwriteExisting) {
|
2021-10-04 19:07:49 +03:00
|
|
|
e = runScript(credentials,
|
2025-05-12 18:14:59 +04:00
|
|
|
replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, path),
|
2023-07-14 22:59:49 +09:00
|
|
|
genVarsForScript(credentials, container)),
|
|
|
|
|
cbReadStd, cbReadStd);
|
2021-06-12 11:59:36 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2024-03-06 02:24:28 +01:00
|
|
|
} else if (overwriteMode == libssh::ScpOverwriteMode::ScpAppendToExisting) {
|
2021-10-04 19:07:49 +03:00
|
|
|
e = runScript(credentials,
|
2025-05-12 18:14:59 +04:00
|
|
|
replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, tmpFileName),
|
2023-07-14 22:59:49 +09:00
|
|
|
genVarsForScript(credentials, container)),
|
|
|
|
|
cbReadStd, cbReadStd);
|
2021-06-12 11:59:36 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-06-12 11:59:36 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
e = runScript(credentials,
|
2025-05-12 18:14:59 +04:00
|
|
|
replaceVars(QStringLiteral("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName, path),
|
2024-04-12 20:00:21 +05:00
|
|
|
genVarsForScript(credentials, container)),
|
|
|
|
|
cbReadStd, cbReadStd);
|
2021-06-12 11:59:36 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
|
|
|
|
} else
|
|
|
|
|
return ErrorCode::NotImplementedError;
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2024-01-06 20:41:06 +04:00
|
|
|
if (stdOut.contains("Error") && stdOut.contains("No such container")) {
|
2021-05-07 23:28:37 +03:00
|
|
|
return ErrorCode::ServerContainerMissingError;
|
|
|
|
|
}
|
2021-01-06 17:12:24 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
runScript(credentials, replaceVars(QString("sudo shred -u %1").arg(tmpFileName), genVarsForScript(credentials, container)));
|
2021-04-04 23:12:36 +03:00
|
|
|
return e;
|
2020-12-18 14:57:22 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
QByteArray ServerController::getTextFileFromContainer(DockerContainer container, const ServerCredentials &credentials, const QString &path,
|
2024-05-09 20:56:52 +03:00
|
|
|
ErrorCode &errorCode)
|
2020-12-18 14:57:22 +03:00
|
|
|
{
|
2022-10-23 17:38:48 +03:00
|
|
|
|
2024-04-01 20:20:02 +07:00
|
|
|
errorCode = ErrorCode::NoError;
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2025-05-12 18:14:59 +04:00
|
|
|
QString script = QStringLiteral("sudo docker exec -i %1 sh -c \"xxd -p '%2'\"").arg(ContainerProps::containerToString(container), path);
|
2021-01-06 17:12:24 +03:00
|
|
|
|
2022-10-23 17:38:48 +03:00
|
|
|
QString stdOut;
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2022-10-23 17:38:48 +03:00
|
|
|
stdOut += data;
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2022-10-23 17:38:48 +03:00
|
|
|
};
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2024-04-01 20:20:02 +07:00
|
|
|
errorCode = runScript(credentials, script, cbReadStdOut);
|
2022-12-26 10:12:42 +03:00
|
|
|
return QByteArray::fromHex(stdOut.toUtf8());
|
2021-01-06 17:12:24 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath,
|
|
|
|
|
libssh::ScpOverwriteMode overwriteMode)
|
2021-04-04 23:12:36 +03:00
|
|
|
{
|
2022-12-26 12:43:51 +03:00
|
|
|
auto error = m_sshClient.connectToHost(credentials);
|
2022-12-22 19:55:30 +03:00
|
|
|
if (error != ErrorCode::NoError) {
|
|
|
|
|
return error;
|
2021-04-04 23:12:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QTemporaryFile localFile;
|
|
|
|
|
localFile.open();
|
|
|
|
|
localFile.write(data);
|
|
|
|
|
localFile.close();
|
|
|
|
|
|
2024-03-06 02:24:28 +01:00
|
|
|
error = m_sshClient.scpFileCopy(overwriteMode, localFile.fileName(), remotePath, "non_desc");
|
2023-12-04 18:13:19 +03:00
|
|
|
|
2022-12-22 19:55:30 +03:00
|
|
|
if (error != ErrorCode::NoError) {
|
|
|
|
|
return error;
|
2021-03-14 21:19:11 +03:00
|
|
|
}
|
2022-10-23 17:38:48 +03:00
|
|
|
return ErrorCode::NoError;
|
2020-12-18 14:57:22 +03:00
|
|
|
}
|
|
|
|
|
|
2024-02-04 18:52:03 +02:00
|
|
|
ErrorCode ServerController::rebootServer(const ServerCredentials &credentials)
|
|
|
|
|
{
|
|
|
|
|
QString script = QString("sudo reboot");
|
|
|
|
|
|
|
|
|
|
QString stdOut;
|
|
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
|
|
|
|
stdOut += data;
|
|
|
|
|
return ErrorCode::NoError;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
|
|
|
|
stdOut += data + "\n";
|
|
|
|
|
return ErrorCode::NoError;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return runScript(credentials, script, cbReadStdOut, cbReadStdErr);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-26 22:54:31 +03:00
|
|
|
ErrorCode ServerController::removeAllContainers(const ServerCredentials &credentials)
|
2020-12-18 14:57:22 +03:00
|
|
|
{
|
2023-07-14 22:59:49 +09:00
|
|
|
return runScript(credentials, amnezia::scriptData(SharedScriptType::remove_all_containers));
|
2021-04-26 22:54:31 +03:00
|
|
|
}
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2021-04-26 22:54:31 +03:00
|
|
|
ErrorCode ServerController::removeContainer(const ServerCredentials &credentials, DockerContainer container)
|
|
|
|
|
{
|
2021-10-04 19:07:49 +03:00
|
|
|
return runScript(credentials,
|
2024-04-12 20:00:21 +05:00
|
|
|
replaceVars(amnezia::scriptData(SharedScriptType::remove_container), genVarsForScript(credentials, container)));
|
2020-12-18 14:57:22 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config, bool isUpdate)
|
2020-12-18 14:57:22 +03:00
|
|
|
{
|
2021-09-20 21:51:28 +03:00
|
|
|
qDebug().noquote() << "ServerController::setupContainer" << ContainerProps::containerToString(container);
|
2021-05-07 23:28:37 +03:00
|
|
|
ErrorCode e = ErrorCode::NoError;
|
|
|
|
|
|
2023-03-19 17:26:43 +03:00
|
|
|
e = isUserInSudo(credentials, container);
|
2023-08-16 23:47:21 +05:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2023-02-14 18:02:51 +03:00
|
|
|
|
2023-03-19 17:26:43 +03:00
|
|
|
e = isServerDpkgBusy(credentials, container);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2023-03-19 17:26:43 +03:00
|
|
|
|
2021-05-11 17:04:04 +03:00
|
|
|
e = installDockerWorker(credentials, container);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-06-14 22:15:11 +03:00
|
|
|
qDebug().noquote() << "ServerController::setupContainer installDockerWorker finished";
|
2021-04-26 22:54:31 +03:00
|
|
|
|
2023-08-13 03:10:41 -07:00
|
|
|
if (!isUpdate) {
|
|
|
|
|
e = isServerPortBusy(credentials, container, config);
|
2023-08-16 23:47:21 +05:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2023-08-13 03:10:41 -07:00
|
|
|
}
|
|
|
|
|
|
2023-08-16 13:26:41 +05:00
|
|
|
if (!isUpdate) {
|
|
|
|
|
e = isServerPortBusy(credentials, container, config);
|
2023-08-16 23:47:21 +05:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2023-08-16 13:26:41 +05:00
|
|
|
}
|
|
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
e = prepareHostWorker(credentials, container, config);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-06-14 22:15:11 +03:00
|
|
|
qDebug().noquote() << "ServerController::setupContainer prepareHostWorker finished";
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
removeContainer(credentials, container);
|
2021-06-14 22:15:11 +03:00
|
|
|
qDebug().noquote() << "ServerController::setupContainer removeContainer finished";
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2022-10-23 17:38:48 +03:00
|
|
|
qDebug().noquote() << "buildContainerWorker start";
|
2021-05-07 23:28:37 +03:00
|
|
|
e = buildContainerWorker(credentials, container, config);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-06-14 22:15:11 +03:00
|
|
|
qDebug().noquote() << "ServerController::setupContainer buildContainerWorker finished";
|
2021-05-07 23:28:37 +03:00
|
|
|
|
|
|
|
|
e = runContainerWorker(credentials, container, config);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-06-14 22:15:11 +03:00
|
|
|
qDebug().noquote() << "ServerController::setupContainer runContainerWorker finished";
|
2021-05-07 23:28:37 +03:00
|
|
|
|
|
|
|
|
e = configureContainerWorker(credentials, container, config);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-06-14 22:15:11 +03:00
|
|
|
qDebug().noquote() << "ServerController::setupContainer configureContainerWorker finished";
|
2021-05-07 23:28:37 +03:00
|
|
|
|
2021-06-19 16:38:35 +03:00
|
|
|
setupServerFirewall(credentials);
|
|
|
|
|
qDebug().noquote() << "ServerController::setupContainer setupServerFirewall finished";
|
|
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
return startupContainerWorker(credentials, container, config);
|
2021-01-06 17:12:24 +03:00
|
|
|
}
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &oldConfig,
|
|
|
|
|
QJsonObject &newConfig)
|
2021-01-06 17:12:24 +03:00
|
|
|
{
|
2023-04-11 09:50:44 -04:00
|
|
|
bool reinstallRequired = isReinstallContainerRequired(container, oldConfig, newConfig);
|
2024-04-12 20:00:21 +05:00
|
|
|
qDebug() << "ServerController::updateContainer for container" << container << "reinstall required is" << reinstallRequired;
|
2021-05-10 02:33:31 +03:00
|
|
|
|
2023-04-11 09:50:44 -04:00
|
|
|
if (reinstallRequired) {
|
2023-02-14 18:02:51 +03:00
|
|
|
return setupContainer(credentials, container, newConfig, true);
|
2023-07-14 22:59:49 +09:00
|
|
|
} else {
|
2021-05-07 23:28:37 +03:00
|
|
|
ErrorCode e = configureContainerWorker(credentials, container, newConfig);
|
2023-07-14 22:59:49 +09:00
|
|
|
if (e)
|
|
|
|
|
return e;
|
2020-12-18 14:57:22 +03:00
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
return startupContainerWorker(credentials, container, newConfig);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-06 17:12:24 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
bool ServerController::isReinstallContainerRequired(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig)
|
2021-05-07 23:28:37 +03:00
|
|
|
{
|
2021-12-25 23:01:53 +03:00
|
|
|
Proto mainProto = ContainerProps::defaultProtocol(container);
|
|
|
|
|
|
|
|
|
|
const QJsonObject &oldProtoConfig = oldConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
|
|
|
|
|
const QJsonObject &newProtoConfig = newConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
|
2021-02-25 18:05:42 +03:00
|
|
|
|
2021-09-20 21:51:28 +03:00
|
|
|
if (container == DockerContainer::OpenVpn) {
|
2023-07-14 22:59:49 +09:00
|
|
|
if (oldProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto)
|
|
|
|
|
!= newProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto))
|
|
|
|
|
return true;
|
2021-02-18 15:00:41 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
if (oldProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort)
|
|
|
|
|
!= newProtoConfig.value(config_key::port).toString(protocols::openvpn::defaultPort))
|
|
|
|
|
return true;
|
2021-05-07 23:28:37 +03:00
|
|
|
}
|
2021-02-18 15:00:41 +03:00
|
|
|
|
2021-09-20 21:51:28 +03:00
|
|
|
if (container == DockerContainer::Cloak) {
|
2023-07-14 22:59:49 +09:00
|
|
|
if (oldProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort)
|
|
|
|
|
!= newProtoConfig.value(config_key::port).toString(protocols::cloak::defaultPort))
|
|
|
|
|
return true;
|
2021-05-07 23:28:37 +03:00
|
|
|
}
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2021-09-20 21:51:28 +03:00
|
|
|
if (container == DockerContainer::ShadowSocks) {
|
2023-07-14 22:59:49 +09:00
|
|
|
if (oldProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort)
|
|
|
|
|
!= newProtoConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort))
|
|
|
|
|
return true;
|
2021-05-10 02:33:31 +03:00
|
|
|
}
|
2023-10-19 01:14:09 +05:00
|
|
|
|
2025-12-11 15:18:36 +08:00
|
|
|
if (ContainerProps::isAwgContainer(container)) {
|
2025-01-02 08:07:12 +01:00
|
|
|
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
|
|
|
|
!= newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)
|
2025-07-07 12:03:25 +08:00
|
|
|
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
|
2024-03-18 12:41:53 +02:00
|
|
|
|| (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)
|
|
|
|
|
!= newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize)
|
|
|
|
|
!= newProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize)
|
|
|
|
|
!= newProtoConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize)
|
|
|
|
|
!= newProtoConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize)
|
|
|
|
|
!= newProtoConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader)
|
|
|
|
|
!= newProtoConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader)
|
|
|
|
|
!= newProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader)
|
|
|
|
|
!= newProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader))
|
2025-07-07 12:03:25 +08:00
|
|
|
|| (oldProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader))
|
2025-12-11 15:18:36 +08:00
|
|
|
!= newProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader)
|
|
|
|
|
|| (oldProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize)
|
|
|
|
|
!= newProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize)
|
|
|
|
|
!= newProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize)))
|
2025-07-07 12:03:25 +08:00
|
|
|
|
2024-03-18 12:41:53 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
if (container == DockerContainer::WireGuard) {
|
2025-01-02 08:07:12 +01:00
|
|
|
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
|
|
|
|
!= newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress))
|
|
|
|
|
|| (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)
|
2025-07-07 12:03:25 +08:00
|
|
|
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)))
|
2024-03-18 12:41:53 +02:00
|
|
|
return true;
|
2023-10-06 16:43:52 +05:00
|
|
|
}
|
|
|
|
|
|
2024-06-10 18:35:24 +07:00
|
|
|
if (container == DockerContainer::Socks5Proxy) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-12 18:14:59 +04:00
|
|
|
if (container == DockerContainer::Xray) {
|
|
|
|
|
if (oldProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)
|
|
|
|
|
!= newProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
return false;
|
2021-01-06 17:12:24 +03:00
|
|
|
}
|
|
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
|
|
|
|
{
|
|
|
|
|
QString stdOut;
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &client) {
|
2021-05-07 23:28:37 +03:00
|
|
|
stdOut += data + "\n";
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
if (data.contains("Automatically restart Docker daemon?")) {
|
2022-12-26 12:43:51 +03:00
|
|
|
return client.writeResponse("yes");
|
2021-05-07 23:28:37 +03:00
|
|
|
}
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-05-07 23:28:37 +03:00
|
|
|
};
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
2021-05-07 23:28:37 +03:00
|
|
|
stdOut += data + "\n";
|
2023-01-02 17:32:27 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-05-07 23:28:37 +03:00
|
|
|
};
|
2023-01-02 17:32:27 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
ErrorCode error =
|
2024-04-12 20:00:21 +05:00
|
|
|
runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials)),
|
2023-07-14 22:59:49 +09:00
|
|
|
cbReadStdOut, cbReadStdErr);
|
2021-06-19 16:38:35 +03:00
|
|
|
|
2023-08-13 03:10:41 -07:00
|
|
|
qDebug().noquote() << "ServerController::installDockerWorker" << stdOut;
|
2026-01-30 08:04:27 +04:00
|
|
|
if (container == DockerContainer::Awg2) {
|
|
|
|
|
QRegularExpression regex(R"(Linux\s+(\d+)\.(\d+)[^\d]*)");
|
|
|
|
|
QRegularExpressionMatch match = regex.match(stdOut);
|
|
|
|
|
if (match.hasMatch()) {
|
|
|
|
|
int majorVersion = match.captured(1).toInt();
|
|
|
|
|
int minorVersion = match.captured(2).toInt();
|
|
|
|
|
|
|
|
|
|
if (majorVersion < 4 || (majorVersion == 4 && minorVersion < 14)) {
|
|
|
|
|
return ErrorCode::ServerLinuxKernelTooOld;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-16 23:47:21 +05:00
|
|
|
if (stdOut.contains("lock"))
|
|
|
|
|
return ErrorCode::ServerPacketManagerError;
|
|
|
|
|
if (stdOut.contains("command not found"))
|
|
|
|
|
return ErrorCode::ServerDockerFailedError;
|
2021-06-19 16:38:35 +03:00
|
|
|
|
2023-01-01 21:48:20 +03:00
|
|
|
return error;
|
2021-05-07 23:28:37 +03:00
|
|
|
}
|
2021-01-15 23:36:35 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
2021-05-07 23:28:37 +03:00
|
|
|
{
|
|
|
|
|
// create folder on host
|
2024-04-12 20:00:21 +05:00
|
|
|
return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::prepare_host), genVarsForScript(credentials, container)));
|
2020-12-18 14:57:22 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
2021-04-04 23:12:36 +03:00
|
|
|
{
|
2024-05-20 12:34:24 +02:00
|
|
|
QString dockerFilePath = amnezia::server::getDockerfileFolder(container) + "/Dockerfile";
|
|
|
|
|
QString scriptString = QString("sudo rm %1").arg(dockerFilePath);
|
|
|
|
|
ErrorCode errorCode = runScript(credentials, replaceVars(scriptString, genVarsForScript(credentials, container)));
|
|
|
|
|
if (errorCode)
|
|
|
|
|
return errorCode;
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2024-09-17 01:14:13 +04:00
|
|
|
errorCode = uploadFileToHost(credentials, amnezia::scriptData(ProtocolScriptType::dockerfile, container).toUtf8(), dockerFilePath);
|
2024-05-20 12:34:24 +02:00
|
|
|
|
|
|
|
|
if (errorCode)
|
|
|
|
|
return errorCode;
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2022-10-23 17:38:48 +03:00
|
|
|
QString stdOut;
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2022-10-23 17:38:48 +03:00
|
|
|
stdOut += data + "\n";
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2022-10-23 17:38:48 +03:00
|
|
|
};
|
2025-04-23 09:12:23 +04:00
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
|
|
|
|
stdOut += data + "\n";
|
|
|
|
|
return ErrorCode::NoError;
|
|
|
|
|
};
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2025-04-23 09:12:23 +04:00
|
|
|
ErrorCode error =
|
2024-09-17 01:14:13 +04:00
|
|
|
runScript(credentials,
|
|
|
|
|
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
|
2025-04-23 09:12:23 +04:00
|
|
|
cbReadStdOut, cbReadStdErr);
|
2025-07-07 12:03:25 +08:00
|
|
|
|
2025-04-23 09:12:23 +04:00
|
|
|
if (stdOut.contains("doesn't work on cgroups v2"))
|
|
|
|
|
return ErrorCode::ServerDockerOnCgroupsV2;
|
|
|
|
|
if (stdOut.contains("cgroup mountpoint does not exist"))
|
|
|
|
|
return ErrorCode::ServerCgroupMountpoint;
|
2025-06-23 06:32:56 +04:00
|
|
|
if (stdOut.contains("have reached") && stdOut.contains("pull rate limit"))
|
|
|
|
|
return ErrorCode::DockerPullRateLimit;
|
2022-10-23 17:38:48 +03:00
|
|
|
|
2025-04-23 09:12:23 +04:00
|
|
|
return error;
|
2021-05-07 23:28:37 +03:00
|
|
|
}
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
2021-05-07 23:28:37 +03:00
|
|
|
{
|
2021-05-11 17:04:04 +03:00
|
|
|
QString stdOut;
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2021-05-11 17:04:04 +03:00
|
|
|
stdOut += data + "\n";
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-05-11 17:04:04 +03:00
|
|
|
};
|
|
|
|
|
|
2021-10-04 19:07:49 +03:00
|
|
|
ErrorCode e = runScript(credentials,
|
2023-07-14 22:59:49 +09:00
|
|
|
replaceVars(amnezia::scriptData(ProtocolScriptType::run_container, container),
|
|
|
|
|
genVarsForScript(credentials, container, config)),
|
|
|
|
|
cbReadStdOut);
|
2022-10-23 17:38:48 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
if (stdOut.contains("address already in use"))
|
|
|
|
|
return ErrorCode::ServerPortAlreadyAllocatedError;
|
|
|
|
|
if (stdOut.contains("is already in use by container"))
|
|
|
|
|
return ErrorCode::ServerPortAlreadyAllocatedError;
|
|
|
|
|
if (stdOut.contains("invalid publish"))
|
|
|
|
|
return ErrorCode::ServerDockerFailedError;
|
2021-05-11 17:04:04 +03:00
|
|
|
|
|
|
|
|
return e;
|
2021-05-07 23:28:37 +03:00
|
|
|
}
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config)
|
2021-05-07 23:28:37 +03:00
|
|
|
{
|
2021-09-24 13:14:35 +03:00
|
|
|
QString stdOut;
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2021-09-24 13:14:35 +03:00
|
|
|
stdOut += data + "\n";
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-09-24 13:14:35 +03:00
|
|
|
};
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
2021-09-24 13:14:35 +03:00
|
|
|
stdOut += data + "\n";
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-09-24 13:14:35 +03:00
|
|
|
};
|
|
|
|
|
|
2021-10-04 19:07:49 +03:00
|
|
|
ErrorCode e = runContainerScript(credentials, container,
|
2023-07-14 22:59:49 +09:00
|
|
|
replaceVars(amnezia::scriptData(ProtocolScriptType::configure_container, container),
|
|
|
|
|
genVarsForScript(credentials, container, config)),
|
|
|
|
|
cbReadStdOut, cbReadStdErr);
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2024-04-01 20:20:02 +07:00
|
|
|
VpnConfigurationsController::updateContainerConfigAfterInstallation(container, config, stdOut);
|
2021-09-24 13:14:35 +03:00
|
|
|
|
|
|
|
|
return e;
|
2021-05-07 23:28:37 +03:00
|
|
|
}
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
2021-05-07 23:28:37 +03:00
|
|
|
{
|
2021-09-22 14:49:08 +03:00
|
|
|
QString script = amnezia::scriptData(ProtocolScriptType::container_startup, container);
|
|
|
|
|
|
|
|
|
|
if (script.isEmpty()) {
|
|
|
|
|
return ErrorCode::NoError;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode e = uploadTextFileToContainer(container, credentials, replaceVars(script, genVarsForScript(credentials, container, config)),
|
2023-07-14 22:59:49 +09:00
|
|
|
"/opt/amnezia/start.sh");
|
|
|
|
|
if (e)
|
|
|
|
|
return e;
|
2021-04-04 23:12:36 +03:00
|
|
|
|
2021-10-04 19:07:49 +03:00
|
|
|
return runScript(credentials,
|
2023-07-14 22:59:49 +09:00
|
|
|
replaceVars("sudo docker exec -d $CONTAINER_NAME sh -c \"chmod a+x /opt/amnezia/start.sh && "
|
|
|
|
|
"/opt/amnezia/start.sh\"",
|
|
|
|
|
genVarsForScript(credentials, container, config)));
|
2021-04-04 23:12:36 +03:00
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container,
|
|
|
|
|
const QJsonObject &config)
|
2021-03-18 18:45:08 +03:00
|
|
|
{
|
2021-11-30 16:56:24 +04:00
|
|
|
const QJsonObject &openvpnConfig = config.value(ProtocolProps::protoToString(Proto::OpenVpn)).toObject();
|
|
|
|
|
const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Proto::Cloak)).toObject();
|
|
|
|
|
const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Proto::ShadowSocks)).toObject();
|
|
|
|
|
const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject();
|
2023-10-19 01:14:09 +05:00
|
|
|
const QJsonObject &amneziaWireguarConfig = config.value(ProtocolProps::protoToString(Proto::Awg)).toObject();
|
2024-03-27 11:02:34 +00:00
|
|
|
const QJsonObject &xrayConfig = config.value(ProtocolProps::protoToString(Proto::Xray)).toObject();
|
2021-11-30 16:56:24 +04:00
|
|
|
const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject();
|
2024-06-10 18:35:24 +07:00
|
|
|
const QJsonObject &socks5ProxyConfig = config.value(ProtocolProps::protoToString(Proto::Socks5Proxy)).toObject();
|
2021-05-07 23:28:37 +03:00
|
|
|
|
2021-04-04 23:12:36 +03:00
|
|
|
Vars vars;
|
|
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$REMOTE_HOST", credentials.hostName } });
|
2021-05-10 02:33:31 +03:00
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
// OpenVPN vars
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$OPENVPN_SUBNET_IP",
|
|
|
|
|
openvpnConfig.value(config_key::subnet_address).toString(protocols::openvpn::defaultSubnetAddress) } });
|
|
|
|
|
vars.append({ { "$OPENVPN_SUBNET_CIDR", openvpnConfig.value(config_key::subnet_cidr).toString(protocols::openvpn::defaultSubnetCidr) } });
|
|
|
|
|
vars.append({ { "$OPENVPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(protocols::openvpn::defaultSubnetMask) } });
|
2023-07-14 22:59:49 +09:00
|
|
|
|
|
|
|
|
vars.append({ { "$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(protocols::openvpn::defaultPort) } });
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$OPENVPN_TRANSPORT_PROTO",
|
|
|
|
|
openvpnConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) } });
|
2021-05-07 23:28:37 +03:00
|
|
|
|
2021-06-12 11:59:36 +03:00
|
|
|
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable);
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$OPENVPN_NCP_DISABLE", isNcpDisabled ? protocols::openvpn::ncpDisableString : "" } });
|
2021-05-18 15:50:52 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher) } });
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash) } });
|
2021-05-07 23:28:37 +03:00
|
|
|
|
2021-06-12 11:59:36 +03:00
|
|
|
bool isTlsAuth = openvpnConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth);
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$OPENVPN_TLS_AUTH", isTlsAuth ? protocols::openvpn::tlsAuthString : "" } });
|
2021-05-18 15:50:52 +03:00
|
|
|
if (!isTlsAuth) {
|
|
|
|
|
// erase $OPENVPN_TA_KEY, so it will not set in OpenVpnConfigurator::genOpenVpnConfig
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$OPENVPN_TA_KEY", "" } });
|
2021-05-18 15:50:52 +03:00
|
|
|
}
|
|
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$OPENVPN_ADDITIONAL_CLIENT_CONFIG",
|
2024-04-12 20:00:21 +05:00
|
|
|
openvpnConfig.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig) } });
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$OPENVPN_ADDITIONAL_SERVER_CONFIG",
|
2024-04-12 20:00:21 +05:00
|
|
|
openvpnConfig.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig) } });
|
2022-10-26 09:36:58 +03:00
|
|
|
|
2021-05-07 23:28:37 +03:00
|
|
|
// ShadowSocks vars
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) } });
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$SHADOWSOCKS_LOCAL_PORT",
|
|
|
|
|
ssConfig.value(config_key::local_port).toString(protocols::shadowsocks::defaultLocalProxyPort) } });
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher) } });
|
2021-03-18 18:45:08 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$CONTAINER_NAME", ContainerProps::containerToString(container) } });
|
|
|
|
|
vars.append({ { "$DOCKERFILE_FOLDER", "/opt/amnezia/" + ContainerProps::containerToString(container) } });
|
2021-03-18 18:45:08 +03:00
|
|
|
|
2021-05-10 02:33:31 +03:00
|
|
|
// Cloak vars
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$CLOAK_SERVER_PORT", cloakConfig.value(config_key::port).toString(protocols::cloak::defaultPort) } });
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) } });
|
2021-05-10 02:33:31 +03:00
|
|
|
|
2024-03-27 11:02:34 +00:00
|
|
|
// Xray vars
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$XRAY_SITE_NAME", xrayConfig.value(config_key::site).toString(protocols::xray::defaultSite) } });
|
2024-08-12 09:27:52 +02:00
|
|
|
vars.append({ { "$XRAY_SERVER_PORT", xrayConfig.value(config_key::port).toString(protocols::xray::defaultPort) } });
|
2024-03-27 11:02:34 +00:00
|
|
|
|
2021-06-12 11:59:36 +03:00
|
|
|
// Wireguard vars
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$WIREGUARD_SUBNET_IP",
|
|
|
|
|
wireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) } });
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$WIREGUARD_SUBNET_CIDR",
|
|
|
|
|
wireguarConfig.value(config_key::subnet_cidr).toString(protocols::wireguard::defaultSubnetCidr) } });
|
|
|
|
|
vars.append({ { "$WIREGUARD_SUBNET_MASK",
|
|
|
|
|
wireguarConfig.value(config_key::subnet_mask).toString(protocols::wireguard::defaultSubnetMask) } });
|
2021-06-12 11:59:36 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$WIREGUARD_SERVER_PORT", wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) } });
|
2021-06-12 11:59:36 +03:00
|
|
|
|
2021-10-04 19:07:49 +03:00
|
|
|
// IPsec vars
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$IPSEC_VPN_L2TP_NET", "192.168.42.0/24" } });
|
|
|
|
|
vars.append({ { "$IPSEC_VPN_L2TP_POOL", "192.168.42.10-192.168.42.250" } });
|
|
|
|
|
vars.append({ { "$IPSEC_VPN_L2TP_LOCAL", "192.168.42.1" } });
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$IPSEC_VPN_XAUTH_NET", "192.168.43.0/24" } });
|
|
|
|
|
vars.append({ { "$IPSEC_VPN_XAUTH_POOL", "192.168.43.10-192.168.43.250" } });
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$IPSEC_VPN_SHA2_TRUNCBUG", "yes" } });
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$IPSEC_VPN_VPN_ANDROID_MTU_FIX", "yes" } });
|
|
|
|
|
vars.append({ { "$IPSEC_VPN_DISABLE_IKEV2", "no" } });
|
|
|
|
|
vars.append({ { "$IPSEC_VPN_DISABLE_L2TP", "no" } });
|
|
|
|
|
vars.append({ { "$IPSEC_VPN_DISABLE_XAUTH", "no" } });
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$IPSEC_VPN_C2C_TRAFFIC", "no" } });
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$PRIMARY_SERVER_DNS", m_settings->primaryDns() } });
|
|
|
|
|
vars.append({ { "$SECONDARY_SERVER_DNS", m_settings->secondaryDns() } });
|
2021-10-04 19:07:49 +03:00
|
|
|
|
2021-09-22 14:49:08 +03:00
|
|
|
// Sftp vars
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$SFTP_PORT", sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Proto::Sftp))) } });
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$SFTP_USER", sftpConfig.value(config_key::userName).toString() } });
|
|
|
|
|
vars.append({ { "$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() } });
|
2021-06-12 11:59:36 +03:00
|
|
|
|
2023-09-27 00:40:01 +05:00
|
|
|
// Amnezia wireguard vars
|
2025-01-02 08:07:12 +01:00
|
|
|
vars.append({ { "$AWG_SUBNET_IP",
|
|
|
|
|
amneziaWireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) } });
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$AWG_SERVER_PORT", amneziaWireguarConfig.value(config_key::port).toString(protocols::awg::defaultPort) } });
|
2023-10-19 01:14:09 +05:00
|
|
|
|
|
|
|
|
vars.append({ { "$JUNK_PACKET_COUNT", amneziaWireguarConfig.value(config_key::junkPacketCount).toString() } });
|
|
|
|
|
vars.append({ { "$JUNK_PACKET_MIN_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMinSize).toString() } });
|
|
|
|
|
vars.append({ { "$JUNK_PACKET_MAX_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMaxSize).toString() } });
|
|
|
|
|
vars.append({ { "$INIT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::initPacketJunkSize).toString() } });
|
2024-04-12 20:00:21 +05:00
|
|
|
vars.append({ { "$RESPONSE_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::responsePacketJunkSize).toString() } });
|
|
|
|
|
vars.append({ { "$INIT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::initPacketMagicHeader).toString() } });
|
|
|
|
|
vars.append({ { "$RESPONSE_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::responsePacketMagicHeader).toString() } });
|
|
|
|
|
vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::underloadPacketMagicHeader).toString() } });
|
|
|
|
|
vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::transportPacketMagicHeader).toString() } });
|
2023-09-27 00:40:01 +05:00
|
|
|
|
2025-07-07 12:03:25 +08:00
|
|
|
vars.append({ { "$COOKIE_REPLY_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::cookieReplyPacketJunkSize).toString() } });
|
|
|
|
|
vars.append({ { "$TRANSPORT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::transportPacketJunkSize).toString() } });
|
2025-12-11 15:18:36 +08:00
|
|
|
vars.append({ { "$SPECIAL_JUNK_1", amneziaWireguarConfig.value(config_key::specialJunk1).toString() } });
|
|
|
|
|
vars.append({ { "$SPECIAL_JUNK_2", amneziaWireguarConfig.value(config_key::specialJunk2).toString() } });
|
|
|
|
|
vars.append({ { "$SPECIAL_JUNK_3", amneziaWireguarConfig.value(config_key::specialJunk3).toString() } });
|
|
|
|
|
vars.append({ { "$SPECIAL_JUNK_4", amneziaWireguarConfig.value(config_key::specialJunk4).toString() } });
|
|
|
|
|
vars.append({ { "$SPECIAL_JUNK_5", amneziaWireguarConfig.value(config_key::specialJunk5).toString() } });
|
2025-07-07 12:03:25 +08:00
|
|
|
|
2024-06-10 18:35:24 +07:00
|
|
|
// Socks5 proxy vars
|
|
|
|
|
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
|
2024-09-17 01:14:13 +04:00
|
|
|
auto username = socks5ProxyConfig.value(config_key::userName).toString();
|
2024-06-10 18:35:24 +07:00
|
|
|
auto password = socks5ProxyConfig.value(config_key::password).toString();
|
|
|
|
|
QString socks5user = (!username.isEmpty() && !password.isEmpty()) ? QString("users %1:CL:%2").arg(username, password) : "";
|
2024-09-17 01:14:13 +04:00
|
|
|
vars.append({ { "$SOCKS5_USER", socks5user } });
|
|
|
|
|
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
|
2024-06-10 18:35:24 +07:00
|
|
|
|
2025-12-11 15:18:36 +08:00
|
|
|
QString serverIp = (!ContainerProps::isAwgContainer(container) &&
|
|
|
|
|
container != DockerContainer::WireGuard && container != DockerContainer::Xray)
|
2024-09-17 01:14:13 +04:00
|
|
|
? NetworkUtilities::getIPAddress(credentials.hostName)
|
|
|
|
|
: credentials.hostName;
|
2021-03-18 18:45:08 +03:00
|
|
|
if (!serverIp.isEmpty()) {
|
2023-07-14 22:59:49 +09:00
|
|
|
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
|
|
|
|
|
} else {
|
2021-03-18 18:45:08 +03:00
|
|
|
qWarning() << "ServerController::genVarsForScript unable to resolve address for credentials.hostName";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vars;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 20:56:52 +03:00
|
|
|
QString ServerController::checkSshConnection(const ServerCredentials &credentials, ErrorCode &errorCode)
|
2021-04-26 22:54:31 +03:00
|
|
|
{
|
|
|
|
|
QString stdOut;
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2021-04-26 22:54:31 +03:00
|
|
|
stdOut += data + "\n";
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-04-26 22:54:31 +03:00
|
|
|
};
|
2022-12-26 12:43:51 +03:00
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
2021-04-26 22:54:31 +03:00
|
|
|
stdOut += data + "\n";
|
2022-12-26 12:43:51 +03:00
|
|
|
return ErrorCode::NoError;
|
2021-04-26 22:54:31 +03:00
|
|
|
};
|
|
|
|
|
|
2024-04-01 20:20:02 +07:00
|
|
|
errorCode = runScript(credentials, amnezia::scriptData(SharedScriptType::check_connection), cbReadStdOut, cbReadStdErr);
|
2021-04-26 22:54:31 +03:00
|
|
|
|
|
|
|
|
return stdOut;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:21:57 +07:00
|
|
|
void ServerController::cancelInstallation()
|
2023-01-02 17:32:27 +03:00
|
|
|
{
|
2023-11-30 19:21:57 +07:00
|
|
|
m_cancelInstallation = true;
|
2023-01-02 17:32:27 +03:00
|
|
|
}
|
|
|
|
|
|
2021-01-21 19:14:07 +03:00
|
|
|
ErrorCode ServerController::setupServerFirewall(const ServerCredentials &credentials)
|
|
|
|
|
{
|
2024-04-12 20:00:21 +05:00
|
|
|
return runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::setup_host_firewall), genVarsForScript(credentials)));
|
2021-04-04 23:12:36 +03:00
|
|
|
}
|
2021-01-21 19:14:07 +03:00
|
|
|
|
2021-04-04 23:12:36 +03:00
|
|
|
QString ServerController::replaceVars(const QString &script, const Vars &vars)
|
|
|
|
|
{
|
|
|
|
|
QString s = script;
|
|
|
|
|
for (const QPair<QString, QString> &var : vars) {
|
|
|
|
|
s.replace(var.first, var.second);
|
|
|
|
|
}
|
|
|
|
|
return s;
|
2021-01-21 19:14:07 +03:00
|
|
|
}
|
2023-02-06 19:19:49 +03:00
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
2023-02-14 18:02:51 +03:00
|
|
|
{
|
2023-03-20 17:29:23 +03:00
|
|
|
if (container == DockerContainer::Dns) {
|
|
|
|
|
return ErrorCode::NoError;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-14 18:02:51 +03:00
|
|
|
QString stdOut;
|
2023-02-28 06:15:01 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2023-02-14 18:02:51 +03:00
|
|
|
stdOut += data + "\n";
|
2023-02-28 06:15:01 +03:00
|
|
|
return ErrorCode::NoError;
|
2023-02-14 18:02:51 +03:00
|
|
|
};
|
2023-02-28 06:15:01 +03:00
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
2023-02-14 18:02:51 +03:00
|
|
|
stdOut += data + "\n";
|
2023-02-28 06:15:01 +03:00
|
|
|
return ErrorCode::NoError;
|
2023-02-14 18:02:51 +03:00
|
|
|
};
|
|
|
|
|
|
2023-04-04 18:20:19 +03:00
|
|
|
const Proto protocol = ContainerProps::defaultProtocol(container);
|
|
|
|
|
const QString containerString = ProtocolProps::protoToString(protocol);
|
2023-02-25 18:17:25 +03:00
|
|
|
const QJsonObject containerConfig = config.value(containerString).toObject();
|
2023-02-14 18:02:51 +03:00
|
|
|
|
|
|
|
|
QStringList fixedPorts = ContainerProps::fixedPortsForContainer(container);
|
|
|
|
|
|
2023-04-04 18:20:19 +03:00
|
|
|
QString defaultPort("%1");
|
2024-04-12 20:00:21 +05:00
|
|
|
QString port = containerConfig.value(config_key::port).toString(defaultPort.arg(ProtocolProps::defaultPort(protocol)));
|
|
|
|
|
QString defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(protocol), protocol);
|
2023-04-04 18:20:19 +03:00
|
|
|
QString transportProto = containerConfig.value(config_key::transport_proto).toString(defaultTransportProto);
|
2023-02-14 18:02:51 +03:00
|
|
|
|
2023-08-30 20:39:14 +01:00
|
|
|
// TODO reimplement with netstat
|
2025-03-19 18:51:49 +04:00
|
|
|
QString script = QString("which lsof > /dev/null 2>&1 || true && sudo lsof -i -P -n 2>/dev/null | grep -E ':%1 ").arg(port);
|
2023-02-14 18:02:51 +03:00
|
|
|
for (auto &port : fixedPorts) {
|
|
|
|
|
script = script.append("|:%1").arg(port);
|
|
|
|
|
}
|
2024-05-27 16:15:55 +01:00
|
|
|
|
|
|
|
|
if (transportProto == "tcpandudp") {
|
|
|
|
|
QString tcpProtoScript = script;
|
|
|
|
|
QString udpProtoScript = script;
|
|
|
|
|
tcpProtoScript.append("' | grep -i tcp");
|
|
|
|
|
udpProtoScript.append("' | grep -i udp");
|
|
|
|
|
tcpProtoScript.append(" | grep LISTEN");
|
|
|
|
|
|
2024-09-17 01:14:13 +04:00
|
|
|
ErrorCode errorCode =
|
|
|
|
|
runScript(credentials, replaceVars(tcpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
2024-05-27 16:15:55 +01:00
|
|
|
if (errorCode != ErrorCode::NoError) {
|
|
|
|
|
return errorCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errorCode = runScript(credentials, replaceVars(udpProtoScript, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
|
|
|
|
if (errorCode != ErrorCode::NoError) {
|
|
|
|
|
return errorCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!stdOut.isEmpty()) {
|
|
|
|
|
return ErrorCode::ServerPortAlreadyAllocatedError;
|
|
|
|
|
}
|
|
|
|
|
return ErrorCode::NoError;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-14 18:02:51 +03:00
|
|
|
script = script.append("' | grep -i %1").arg(transportProto);
|
2023-04-19 06:39:50 +03:00
|
|
|
|
|
|
|
|
if (transportProto == "tcp") {
|
|
|
|
|
script = script.append(" | grep LISTEN");
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode errorCode = runScript(credentials, replaceVars(script, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
2023-03-20 17:29:23 +03:00
|
|
|
if (errorCode != ErrorCode::NoError) {
|
|
|
|
|
return errorCode;
|
|
|
|
|
}
|
2023-02-14 18:02:51 +03:00
|
|
|
|
|
|
|
|
if (!stdOut.isEmpty()) {
|
|
|
|
|
return ErrorCode::ServerPortAlreadyAllocatedError;
|
|
|
|
|
}
|
|
|
|
|
return ErrorCode::NoError;
|
|
|
|
|
}
|
2023-02-27 19:42:47 +03:00
|
|
|
|
2023-03-19 17:26:43 +03:00
|
|
|
ErrorCode ServerController::isUserInSudo(const ServerCredentials &credentials, DockerContainer container)
|
|
|
|
|
{
|
|
|
|
|
QString stdOut;
|
2023-03-19 17:29:48 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2023-03-19 17:26:43 +03:00
|
|
|
stdOut += data + "\n";
|
2023-03-19 17:29:48 +03:00
|
|
|
return ErrorCode::NoError;
|
2023-03-19 17:26:43 +03:00
|
|
|
};
|
2023-03-19 17:29:48 +03:00
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
2023-03-19 17:26:43 +03:00
|
|
|
stdOut += data + "\n";
|
2023-03-19 17:29:48 +03:00
|
|
|
return ErrorCode::NoError;
|
2023-03-19 17:26:43 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const QString scriptData = amnezia::scriptData(SharedScriptType::check_user_in_sudo);
|
2024-04-12 20:00:21 +05:00
|
|
|
ErrorCode error = runScript(credentials, replaceVars(scriptData, genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr);
|
2023-03-19 17:26:43 +03:00
|
|
|
|
2025-03-14 17:39:58 +04:00
|
|
|
if (credentials.userName != "root" && stdOut.contains("sudo:") && !stdOut.contains("uname:") && stdOut.contains("not found"))
|
2025-03-20 07:24:37 +04:00
|
|
|
return ErrorCode::ServerSudoPackageIsNotPreinstalled;
|
2025-03-14 17:39:58 +04:00
|
|
|
if (credentials.userName != "root" && !stdOut.contains("sudo") && !stdOut.contains("wheel"))
|
2023-07-14 22:59:49 +09:00
|
|
|
return ErrorCode::ServerUserNotInSudo;
|
2025-03-14 17:39:58 +04:00
|
|
|
if (stdOut.contains("can't cd to") || stdOut.contains("Permission denied") || stdOut.contains("No such file or directory"))
|
|
|
|
|
return ErrorCode::ServerUserDirectoryNotAccessible;
|
|
|
|
|
if (stdOut.contains("sudoers") || stdOut.contains("is not allowed to run sudo on"))
|
|
|
|
|
return ErrorCode::ServerUserNotAllowedInSudoers;
|
|
|
|
|
if (stdOut.contains("password is required"))
|
|
|
|
|
return ErrorCode::ServerUserPasswordRequired;
|
2023-03-19 17:26:43 +03:00
|
|
|
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ErrorCode ServerController::isServerDpkgBusy(const ServerCredentials &credentials, DockerContainer container)
|
|
|
|
|
{
|
2023-11-30 19:21:57 +07:00
|
|
|
m_cancelInstallation = false;
|
2023-03-19 17:26:43 +03:00
|
|
|
QString stdOut;
|
2023-03-19 17:29:48 +03:00
|
|
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
2023-03-19 17:26:43 +03:00
|
|
|
stdOut += data + "\n";
|
2023-03-19 17:29:48 +03:00
|
|
|
return ErrorCode::NoError;
|
2023-03-19 17:26:43 +03:00
|
|
|
};
|
2023-03-19 17:29:48 +03:00
|
|
|
auto cbReadStdErr = [&](const QString &data, libssh::Client &) {
|
2023-03-19 17:26:43 +03:00
|
|
|
stdOut += data + "\n";
|
2023-03-19 17:29:48 +03:00
|
|
|
return ErrorCode::NoError;
|
2023-03-19 17:26:43 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QFutureWatcher<ErrorCode> watcher;
|
|
|
|
|
|
|
|
|
|
QFuture<ErrorCode> future = QtConcurrent::run([this, &stdOut, &cbReadStdOut, &cbReadStdErr, &credentials]() {
|
2023-08-16 08:08:08 -07:00
|
|
|
// max 100 attempts
|
2023-08-30 20:39:14 +01:00
|
|
|
for (int i = 0; i < 30; ++i) {
|
2023-03-19 17:26:43 +03:00
|
|
|
if (m_cancelInstallation) {
|
|
|
|
|
return ErrorCode::ServerCancelInstallation;
|
|
|
|
|
}
|
|
|
|
|
stdOut.clear();
|
2024-04-12 20:00:21 +05:00
|
|
|
runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), genVarsForScript(credentials)),
|
2023-07-14 22:59:49 +09:00
|
|
|
cbReadStdOut, cbReadStdErr);
|
2023-08-16 08:08:08 -07:00
|
|
|
|
2023-09-11 13:56:49 +05:00
|
|
|
if (stdOut.contains("Packet manager not found"))
|
|
|
|
|
return ErrorCode::ServerPacketManagerError;
|
2025-06-23 06:34:40 +04:00
|
|
|
if (stdOut.contains("fuser not installed") || stdOut.contains("cat not installed"))
|
2023-09-11 13:56:49 +05:00
|
|
|
return ErrorCode::NoError;
|
2023-08-16 08:08:08 -07:00
|
|
|
|
|
|
|
|
if (stdOut.isEmpty()) {
|
|
|
|
|
return ErrorCode::NoError;
|
2023-08-16 23:47:21 +05:00
|
|
|
} else {
|
|
|
|
|
#ifdef MZ_DEBUG
|
2023-08-16 08:08:08 -07:00
|
|
|
qDebug().noquote() << stdOut;
|
2023-08-16 23:47:21 +05:00
|
|
|
#endif
|
2023-03-19 17:26:43 +03:00
|
|
|
emit serverIsBusy(true);
|
2023-08-30 20:39:14 +01:00
|
|
|
QThread::msleep(10000);
|
2023-03-19 17:26:43 +03:00
|
|
|
}
|
2023-08-16 08:08:08 -07:00
|
|
|
}
|
|
|
|
|
return ErrorCode::ServerPacketManagerError;
|
2023-03-19 17:26:43 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
QEventLoop wait;
|
|
|
|
|
QObject::connect(&watcher, &QFutureWatcher<ErrorCode>::finished, &wait, &QEventLoop::quit);
|
|
|
|
|
watcher.setFuture(future);
|
|
|
|
|
wait.exec();
|
|
|
|
|
|
|
|
|
|
emit serverIsBusy(false);
|
|
|
|
|
|
|
|
|
|
return future.result();
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-14 22:59:49 +09:00
|
|
|
ErrorCode ServerController::getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey,
|
|
|
|
|
const std::function<QString()> &callback)
|
2023-04-02 09:09:20 +03:00
|
|
|
{
|
2023-04-04 13:32:37 +03:00
|
|
|
auto error = m_sshClient.getDecryptedPrivateKey(credentials, decryptedPrivateKey, callback);
|
2023-04-03 17:27:55 +03:00
|
|
|
return error;
|
2023-04-02 09:09:20 +03:00
|
|
|
}
|