feat: add telemt container (#2435)

* Feat: Add MtProxy (Telegram)

* add path files

* Feat: Add Telemt (MtProxy)

* fixed secret & enum

* remove old path

* refactor: move logic from ui to core

---------

Co-authored-by: vkamn <vk@amnezia.org>
This commit is contained in:
yp
2026-05-18 15:01:09 +03:00
committed by GitHub
parent 277b295fd8
commit a49892c7e7
42 changed files with 2721 additions and 8 deletions
+7
View File
@@ -15,6 +15,7 @@
#include "core/models/protocols/sftpProtocolConfig.h"
#include "core/models/protocols/socks5ProxyProtocolConfig.h"
#include "core/models/protocols/mtProxyProtocolConfig.h"
#include "core/models/protocols/telemtProtocolConfig.h"
#include "core/models/protocols/ikev2ProtocolConfig.h"
#include "core/models/protocols/torProtocolConfig.h"
@@ -98,6 +99,12 @@ ContainerConfig InstallerBase::createBaseConfig(DockerContainer container, int p
config.protocolConfig = mtConfig;
break;
}
case Proto::Telemt: {
TelemtProtocolConfig telemtConfig;
telemtConfig.port = portStr;
config.protocolConfig = telemtConfig;
break;
}
case Proto::Ikev2: {
Ikev2ProtocolConfig ikev2Config;
config.protocolConfig = ikev2Config;
+3 -3
View File
@@ -68,11 +68,11 @@ ErrorCode MtProxyInstaller::extractConfigFromContainer(DockerContainer container
}
ErrorCode MtProxyInstaller::queryDiagnostics(SshSession &sshSession, const ServerCredentials &credentials,
DockerContainer container, int listenPort,
MtProxyContainerDiagnostics &out)
DockerContainer container, int listenPort,
MtProxyContainerDiagnostics &out)
{
out = {};
if (container != DockerContainer::MtProxy) {
if (container != DockerContainer::MtProxy && container != DockerContainer::Telemt) {
return ErrorCode::InternalError;
}
const QString containerName = ContainerUtils::containerToString(container);
@@ -0,0 +1,79 @@
#include "telemtInstaller.h"
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/selfhosted/sshSession.h"
#include "core/models/containerConfig.h"
#include "core/models/protocols/telemtProtocolConfig.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QRegularExpression>
#include <QtGlobal>
using namespace amnezia;
namespace {
constexpr QLatin1String kTelemtClientJsonPath("/data/amnezia-telemt-client.json");
constexpr QLatin1String kTelemtClientJsonUploadPath("data/amnezia-telemt-client.json");
constexpr QLatin1String kTelemtSecretPath("/data/secret");
}
TelemtInstaller::TelemtInstaller(QObject *parent) : InstallerBase(parent) {}
ErrorCode TelemtInstaller::extractConfigFromContainer(DockerContainer container, const ServerCredentials &credentials,
SshSession *sshSession, ContainerConfig &config) {
if (container != DockerContainer::Telemt || !sshSession) {
return ErrorCode::NoError;
}
TelemtProtocolConfig *tc = config.getTelemtProtocolConfig();
if (!tc) {
return ErrorCode::NoError;
}
ErrorCode jsonErr = ErrorCode::NoError;
const QByteArray jsonRaw =
sshSession->getTextFileFromContainer(container, credentials, QString(kTelemtClientJsonPath), jsonErr);
if (jsonErr == ErrorCode::NoError && !jsonRaw.trimmed().isEmpty()) {
QJsonParseError parseError;
const QJsonDocument doc = QJsonDocument::fromJson(jsonRaw.trimmed(), &parseError);
if (parseError.error == QJsonParseError::NoError && doc.isObject()) {
QJsonObject merged = tc->toJson();
const QJsonObject snap = doc.object();
for (auto it = snap.constBegin(); it != snap.constEnd(); ++it) {
merged.insert(it.key(), it.value());
}
*tc = TelemtProtocolConfig::fromJson(merged);
}
}
ErrorCode secretErr = ErrorCode::NoError;
const QByteArray secretRaw =
sshSession->getTextFileFromContainer(container, credentials, QString(kTelemtSecretPath), secretErr);
const QString sec = QString::fromUtf8(secretRaw).trimmed();
if (sec.length() == 32) {
static const QRegularExpression hex32(QStringLiteral("^[0-9a-fA-F]{32}$"));
if (hex32.match(sec).hasMatch()) {
tc->secret = sec;
}
}
return ErrorCode::NoError;
}
void TelemtInstaller::uploadClientSettingsSnapshot(SshSession &sshSession, const ServerCredentials &credentials,
DockerContainer container, const ContainerConfig &config) {
const TelemtProtocolConfig *tc = config.getTelemtProtocolConfig();
if (!tc) {
return;
}
const QByteArray payload = QJsonDocument(tc->toJson()).toJson(QJsonDocument::Compact);
const ErrorCode err = sshSession.uploadTextFileToContainer(container, credentials, QString::fromUtf8(payload),
QString(kTelemtClientJsonUploadPath));
if (err != ErrorCode::NoError) {
qWarning() << "TelemtInstaller::uploadClientSettingsSnapshot failed" << err;
}
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef TELEMTINSTALLER_H
#define TELEMTINSTALLER_H
#include "installerBase.h"
class TelemtInstaller : public InstallerBase {
Q_OBJECT
public:
explicit TelemtInstaller(QObject *parent = nullptr);
amnezia::ErrorCode
extractConfigFromContainer(amnezia::DockerContainer container, const amnezia::ServerCredentials &credentials,
SshSession *sshSession, amnezia::ContainerConfig &config) override;
static void uploadClientSettingsSnapshot(SshSession &sshSession, const amnezia::ServerCredentials &credentials,
amnezia::DockerContainer container,
const amnezia::ContainerConfig &config);
};
#endif // TELEMTINSTALLER_H