mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-20 02:00:55 +07:00
host/SNI/path validation backend + flow-default flag
This commit is contained in:
@@ -4,6 +4,10 @@
|
|||||||
#include "core/protocols/protocolUtils.h"
|
#include "core/protocols/protocolUtils.h"
|
||||||
#include "core/utils/constants/configKeys.h"
|
#include "core/utils/constants/configKeys.h"
|
||||||
#include "core/utils/constants/protocolConstants.h"
|
#include "core/utils/constants/protocolConstants.h"
|
||||||
|
#include "core/utils/networkUtilities.h"
|
||||||
|
|
||||||
|
#include <QHostAddress>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
using namespace amnezia;
|
using namespace amnezia;
|
||||||
using namespace ProtocolUtils;
|
using namespace ProtocolUtils;
|
||||||
@@ -272,7 +276,7 @@ void XrayConfigModel::updateModel(amnezia::DockerContainer container, const amne
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!m_protocolConfig.serverConfig.isThirdPartyConfig) {
|
if (!m_protocolConfig.serverConfig.isThirdPartyConfig) {
|
||||||
applyDefaultsToServerConfig(m_protocolConfig.serverConfig);
|
applyDefaultsToServerConfig(m_protocolConfig.serverConfig, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_originalProtocolConfig = m_protocolConfig;
|
m_originalProtocolConfig = m_protocolConfig;
|
||||||
@@ -283,7 +287,7 @@ void XrayConfigModel::updateModel(amnezia::DockerContainer container, const amne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XrayConfigModel::applyDefaultsToServerConfig(amnezia::XrayServerConfig &config)
|
void XrayConfigModel::applyDefaultsToServerConfig(amnezia::XrayServerConfig &config, bool fillFlowDefault)
|
||||||
{
|
{
|
||||||
if (config.port.isEmpty()) {
|
if (config.port.isEmpty()) {
|
||||||
config.port = protocols::xray::defaultPort;
|
config.port = protocols::xray::defaultPort;
|
||||||
@@ -306,7 +310,7 @@ void XrayConfigModel::applyDefaultsToServerConfig(amnezia::XrayServerConfig &con
|
|||||||
config.security = protocols::xray::defaultSecurity;
|
config.security = protocols::xray::defaultSecurity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.flow.isEmpty()) {
|
if (fillFlowDefault && config.flow.isEmpty()) {
|
||||||
config.flow = protocols::xray::defaultFlow;
|
config.flow = protocols::xray::defaultFlow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,3 +589,87 @@ QString XrayConfigModel::mkcpDefaultWriteBufferSize()
|
|||||||
{
|
{
|
||||||
return QString::fromLatin1(protocols::xray::defaultMkcpWriteBufferSize);
|
return QString::fromLatin1(protocols::xray::defaultMkcpWriteBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool isValidSingleHost(const QString &t)
|
||||||
|
{
|
||||||
|
if (t.isEmpty() || t.length() > 253) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QHostAddress a(t);
|
||||||
|
if (a.protocol() == QHostAddress::IPv4Protocol) {
|
||||||
|
return NetworkUtilities::checkIPv4Format(t);
|
||||||
|
}
|
||||||
|
if (a.protocol() == QHostAddress::IPv6Protocol) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static const QRegularExpression onlyDigits(QStringLiteral(R"(^\d+$)"));
|
||||||
|
if (onlyDigits.match(t).hasMatch()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QRegExp re = NetworkUtilities::domainRegExp();
|
||||||
|
re.setCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
return re.exactMatch(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XrayConfigModel::isValidHost(const QString &host)
|
||||||
|
{
|
||||||
|
const QString t = host.trimmed();
|
||||||
|
if (t.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return isValidSingleHost(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XrayConfigModel::isValidSni(const QString &sni)
|
||||||
|
{
|
||||||
|
const QString t = sni.trimmed();
|
||||||
|
if (t.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (t.startsWith(QLatin1String("*."))) {
|
||||||
|
return isValidSingleHost(t.mid(2));
|
||||||
|
}
|
||||||
|
return isValidSingleHost(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XrayConfigModel::isValidPath(const QString &path)
|
||||||
|
{
|
||||||
|
const QString t = path.trimmed();
|
||||||
|
if (t.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return t.startsWith(QLatin1Char('/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList XrayConfigModel::validationErrors() const
|
||||||
|
{
|
||||||
|
QStringList errs;
|
||||||
|
const auto &srv = m_protocolConfig.serverConfig;
|
||||||
|
|
||||||
|
if (!srv.port.isEmpty()) {
|
||||||
|
bool ok = false;
|
||||||
|
const int p = srv.port.toInt(&ok);
|
||||||
|
if (!ok || p < 1 || p > 65535) {
|
||||||
|
errs << tr("Port must be in the range of 1 to 65535");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srv.security == QLatin1String("tls") || srv.security == QLatin1String("reality")) {
|
||||||
|
if (!isValidSni(srv.sni)) {
|
||||||
|
errs << tr("SNI: enter a valid IP address or domain name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srv.transport == QLatin1String("xhttp")) {
|
||||||
|
if (!isValidHost(srv.xhttp.host)) {
|
||||||
|
errs << tr("Host: enter a valid IP address or domain name");
|
||||||
|
}
|
||||||
|
if (!isValidPath(srv.xhttp.path)) {
|
||||||
|
errs << tr("Path must start with \"/\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs;
|
||||||
|
}
|
||||||
|
|||||||
@@ -118,6 +118,11 @@ public:
|
|||||||
Q_INVOKABLE static QString mkcpDefaultReadBufferSize();
|
Q_INVOKABLE static QString mkcpDefaultReadBufferSize();
|
||||||
Q_INVOKABLE static QString mkcpDefaultWriteBufferSize();
|
Q_INVOKABLE static QString mkcpDefaultWriteBufferSize();
|
||||||
|
|
||||||
|
Q_INVOKABLE static bool isValidHost(const QString &host);
|
||||||
|
Q_INVOKABLE static bool isValidSni(const QString &sni);
|
||||||
|
Q_INVOKABLE static bool isValidPath(const QString &path);
|
||||||
|
Q_INVOKABLE QStringList validationErrors() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateModel(amnezia::DockerContainer container, const amnezia::XrayProtocolConfig& protocolConfig);
|
void updateModel(amnezia::DockerContainer container, const amnezia::XrayProtocolConfig& protocolConfig);
|
||||||
amnezia::XrayProtocolConfig getProtocolConfig();
|
amnezia::XrayProtocolConfig getProtocolConfig();
|
||||||
@@ -137,7 +142,7 @@ private:
|
|||||||
amnezia::XrayProtocolConfig m_protocolConfig;
|
amnezia::XrayProtocolConfig m_protocolConfig;
|
||||||
amnezia::XrayProtocolConfig m_originalProtocolConfig;
|
amnezia::XrayProtocolConfig m_originalProtocolConfig;
|
||||||
|
|
||||||
void applyDefaultsToServerConfig(amnezia::XrayServerConfig& config);
|
void applyDefaultsToServerConfig(amnezia::XrayServerConfig& config, bool fillFlowDefault = true);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // XRAYCONFIGMODEL_H
|
#endif // XRAYCONFIGMODEL_H
|
||||||
|
|||||||
Reference in New Issue
Block a user