Xray with Reality protocol (#494)

* Xray with Reality for desktops
This commit is contained in:
Mykola Baibuz 2024-03-27 11:02:34 +00:00 committed by GitHub
parent f6acec53c0
commit ba4237f1dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
64 changed files with 1933 additions and 336 deletions

View file

@ -337,6 +337,38 @@ void ExportController::generateCloakConfig()
emit exportConfigChanged();
}
void ExportController::generateXrayConfig()
{
clearPreviousConfig();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
ErrorCode errorCode = ErrorCode::NoError;
QString clientId;
QString config =
m_configurator->genVpnProtocolConfig(credentials, container, containerConfig, Proto::Xray, clientId, &errorCode);
if (errorCode) {
emit exportErrorOccurred(errorString(errorCode));
return;
}
config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Xray, config);
QJsonObject configJson = QJsonDocument::fromJson(config.toUtf8()).object();
QStringList lines = QString(QJsonDocument(configJson).toJson()).replace("\r", "").split("\n");
for (const QString &line : lines) {
m_config.append(line + "\n");
}
emit exportConfigChanged();
}
QString ExportController::getConfig()
{
return m_config;

View file

@ -37,6 +37,7 @@ public slots:
void generateAwgConfig(const QString &clientName);
void generateShadowSocksConfig();
void generateCloakConfig();
void generateXrayConfig();
QString getConfig();
QString getNativeConfigString();

View file

@ -19,6 +19,7 @@ namespace
Amnezia,
OpenVpn,
WireGuard,
Xray,
Backup,
Invalid
};
@ -34,6 +35,9 @@ namespace
const QString wireguardConfigPatternSectionInterface = "[Interface]";
const QString wireguardConfigPatternSectionPeer = "[Peer]";
const QString xrayConfigPatternInbound = "inbounds";
const QString xrayConfigPatternOutbound = "outbounds";
const QString amneziaConfigPattern = "containers";
const QString amneziaFreeConfigPattern = "api_key";
const QString backupPattern = "Servers/serversList";
@ -49,6 +53,8 @@ namespace
} else if (config.contains(wireguardConfigPatternSectionInterface)
&& config.contains(wireguardConfigPatternSectionPeer)) {
return ConfigTypes::WireGuard;
} else if ((config.contains(xrayConfigPatternInbound)) && (config.contains(xrayConfigPatternOutbound))) {
return ConfigTypes::Xray;
}
return ConfigTypes::Invalid;
}
@ -109,6 +115,10 @@ bool ImportController::extractConfigFromData(QString data)
m_config = extractWireGuardConfig(config);
return m_config.empty() ? false : true;
}
case ConfigTypes::Xray: {
m_config = extractXrayConfig(config);
return m_config.empty() ? false : true;
}
case ConfigTypes::Amnezia: {
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
return m_config.empty() ? false : true;
@ -349,6 +359,42 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
return config;
}
QJsonObject ImportController::extractXrayConfig(const QString &data)
{
QJsonParseError parserErr;
QJsonDocument jsonConf = QJsonDocument::fromJson(data.toLocal8Bit(), &parserErr);
QJsonObject xrayVpnConfig;
xrayVpnConfig[config_key::config] = jsonConf.toJson().constData();
QJsonObject lastConfig;
lastConfig[config_key::last_config] = jsonConf.toJson().constData();
lastConfig[config_key::isThirdPartyConfig] = true;
QJsonObject containers;
containers.insert(config_key::container, QJsonValue("amnezia-xray"));
containers.insert(config_key::xray, QJsonValue(lastConfig));
QJsonArray arr;
arr.push_back(containers);
QString hostName;
const static QRegularExpression hostNameRegExp("\"address\":\\s*\"([^\"]+)");
QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(data);
if (hostNameMatch.hasMatch()) {
hostName = hostNameMatch.captured(1);
}
QJsonObject config;
config[config_key::containers] = arr;
config[config_key::defaultContainer] = "amnezia-xray";
config[config_key::description] = m_settings->nextAvailableServerName();
config[config_key::hostName] = hostName;
return config;
}
#ifdef Q_OS_ANDROID
static QMutex qrDecodeMutex;

View file

@ -47,6 +47,7 @@ signals:
private:
QJsonObject extractOpenVpnConfig(const QString &data);
QJsonObject extractWireGuardConfig(const QString &data);
QJsonObject extractXrayConfig(const QString &data);
#if defined Q_OS_ANDROID || defined Q_OS_IOS
void stopDecodingQr();

View file

@ -9,6 +9,7 @@
#include "core/errorstrings.h"
#include "core/controllers/serverController.h"
#include "core/networkUtilities.h"
#include "utilities.h"
#include "ui/models/protocols/awgConfigModel.h"
#include "ui/models/protocols/wireguardConfigModel.h"
@ -352,12 +353,12 @@ void InstallController::removeCurrentlyProcessedContainer()
QRegularExpression InstallController::ipAddressPortRegExp()
{
return Utils::ipAddressPortRegExp();
return NetworkUtilities::ipAddressPortRegExp();
}
QRegularExpression InstallController::ipAddressRegExp()
{
return Utils::ipAddressRegExp();
return NetworkUtilities::ipAddressRegExp();
}
void InstallController::setCurrentlyInstalledServerCredentials(const QString &hostName, const QString &userName,
@ -450,7 +451,6 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw
process->write((password + "\n").toUtf8());
}
// qDebug().noquote() << "onPushButtonSftpMountDriveClicked" << args;
#endif
}

View file

@ -48,6 +48,7 @@ namespace PageLoader
PageProtocolOpenVpnSettings,
PageProtocolShadowSocksSettings,
PageProtocolCloakSettings,
PageProtocolXraySettings,
PageProtocolWireGuardSettings,
PageProtocolAwgSettings,
PageProtocolIKev2Settings,

View file

@ -5,7 +5,7 @@
#include <QStandardPaths>
#include "systemController.h"
#include "utilities.h"
#include "core/networkUtilities.h"
SitesController::SitesController(const std::shared_ptr<Settings> &settings,
const QSharedPointer<VpnConnection> &vpnConnection,
@ -25,7 +25,7 @@ void SitesController::addSite(QString hostname)
return;
}
if (!Utils::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
if (!NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
// get domain name if it present
hostname.replace("https://", "");
hostname.replace("http://", "");
@ -40,7 +40,7 @@ void SitesController::addSite(QString hostname)
if (!ip.isEmpty()) {
QMetaObject::invokeMethod(m_vpnConnection.get(), "addRoutes", Qt::QueuedConnection,
Q_ARG(QStringList, QStringList() << ip));
} else if (Utils::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
} else if (NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
QMetaObject::invokeMethod(m_vpnConnection.get(), "addRoutes", Qt::QueuedConnection,
Q_ARG(QStringList, QStringList() << hostname));
}
@ -57,7 +57,7 @@ void SitesController::addSite(QString hostname)
}
};
if (Utils::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
if (NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
processSite(hostname, "");
} else {
processSite(hostname, "");
@ -110,7 +110,7 @@ void SitesController::importSites(const QString &fileName, bool replaceExisting)
auto hostname = jsonObject.value("hostname").toString("");
auto ip = jsonObject.value("ip").toString("");
if (!hostname.contains(".") && !Utils::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
if (!hostname.contains(".") && !NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
qDebug() << hostname << " not look like ip adress or domain name";
continue;
}