Compare commits

..
35 changed files with 497 additions and 87 deletions

No files matched your search

@@ -66,6 +66,8 @@ ProtocolConfig AwgConfigurator::createConfig(const ServerCredentials &credential
newClientConfig.nativeConfig = awgConfig;
newClientConfig.hostName = wgConfig->clientConfig->hostName;
newClientConfig.port = wgConfig->clientConfig->port;
newClientConfig.cascadeEndpoint = wgConfig->clientConfig->cascadeEndpoint;
newClientConfig.cascadePort = wgConfig->clientConfig->cascadePort;
newClientConfig.clientIp = wgConfig->clientConfig->clientIp;
newClientConfig.clientPrivateKey = wgConfig->clientConfig->clientPrivateKey;
newClientConfig.clientPublicKey = wgConfig->clientConfig->clientPublicKey;
@@ -266,6 +266,11 @@ ProtocolConfig WireguardConfigurator::createConfig(const ServerCredentials &cred
clientConfig.nativeConfig = config;
clientConfig.hostName = connData.host;
clientConfig.port = connData.port.toInt();
if (wireguardServerConfig) {
clientConfig.setCascade(wireguardServerConfig->cascadeEndpoint, wireguardServerConfig->cascadePort);
} else if (awgServerConfig) {
clientConfig.setCascade(awgServerConfig->cascadeEndpoint, awgServerConfig->cascadePort);
}
clientConfig.clientIp = connData.clientIP;
clientConfig.clientPrivateKey = connData.clientPrivKey;
clientConfig.clientPublicKey = connData.clientPubKey;
@@ -289,6 +289,15 @@ QJsonObject ConnectionController::createConnectionConfiguration(const QPair<QStr
ContainerUtils::isAwgContainer(container) ? protocols::awg::defaultMtu :
protocols::wireguard::defaultMtu;
}
const QString cascadeEndpoint = vpnConfigData.value(configKey::cascadeEndpoint).toString();
if (!cascadeEndpoint.isEmpty()) {
vpnConfigData[configKey::hostName] = cascadeEndpoint;
}
const QString cascadePort = vpnConfigData.value(configKey::cascadePort).toString();
if (!cascadePort.isEmpty()) {
vpnConfigData[configKey::port] = cascadePort.toInt();
}
}
vpnConfiguration.insert(ProtocolUtils::key_proto_config_data(proto), vpnConfigData);
+7 -2
View File
@@ -1,5 +1,8 @@
#include "installerBase.h"
#include <QRandomGenerator>
#include <iterator>
#include "core/utils/containerEnum.h"
#include "core/utils/containers/containerUtils.h"
#include "core/utils/protocolEnum.h"
@@ -85,8 +88,10 @@ ContainerConfig InstallerBase::createBaseConfig(DockerContainer container, int p
srv.transport = protocols::xray::defaultTransport;
srv.security = protocols::xray::defaultSecurity;
srv.flow = protocols::xray::defaultFlow;
srv.site = protocols::xray::defaultSite;
srv.sni = protocols::xray::defaultSni;
const int siteIndex =
QRandomGenerator::global()->bounded(static_cast<int>(std::size(protocols::xray::defaultSites)));
srv.site = protocols::xray::defaultSites[siteIndex];
srv.sni = srv.site;
srv.alpn = protocols::xray::defaultAlpn;
srv.fingerprint = protocols::xray::defaultFingerprint;
config.protocolConfig = xrayConfig;
@@ -72,6 +72,12 @@ QJsonObject AwgServerConfig::toJson() const
if (!port.isEmpty()) {
obj[configKey::port] = this->port;
}
if (!cascadeEndpoint.isEmpty()) {
obj[configKey::cascadeEndpoint] = cascadeEndpoint;
}
if (!cascadePort.isEmpty()) {
obj[configKey::cascadePort] = cascadePort;
}
if (!transportProto.isEmpty()) {
obj[configKey::transportProto] = transportProto;
}
@@ -166,6 +172,8 @@ AwgServerConfig AwgServerConfig::fromJson(const QJsonObject& json)
AwgServerConfig config;
config.port = json.value(configKey::port).toString();
config.cascadeEndpoint = json.value(configKey::cascadeEndpoint).toString();
config.cascadePort = json.value(configKey::cascadePort).toString();
config.transportProto = json.value(configKey::transportProto).toString();
config.protocolVersion = json.value(configKey::protocolVersion).toString();
config.subnetAddress = json.value(configKey::subnetAddress).toString();
@@ -218,6 +226,12 @@ QJsonObject AwgClientConfig::toJson() const
if (port > 0) {
obj[configKey::port] = port;
}
if (!cascadeEndpoint.isEmpty()) {
obj[configKey::cascadeEndpoint] = cascadeEndpoint;
}
if (!cascadePort.isEmpty()) {
obj[configKey::cascadePort] = cascadePort;
}
if (!clientIp.isEmpty()) {
obj[configKey::clientIp] = clientIp;
}
@@ -333,6 +347,14 @@ QJsonObject AwgClientConfig::toJson() const
return obj;
}
void AwgClientConfig::setCascade(const QString &newEndpoint, const QString &newPort)
{
cascadeEndpoint = newEndpoint;
cascadePort = newPort;
nativeConfig = replaceWireGuardEndpoint(nativeConfig, newEndpoint.isEmpty() ? hostName : newEndpoint,
newPort.isEmpty() ? port : newPort.toInt());
}
AwgClientConfig AwgClientConfig::fromJson(const QJsonObject& json)
{
AwgClientConfig config;
@@ -340,6 +362,8 @@ AwgClientConfig AwgClientConfig::fromJson(const QJsonObject& json)
config.nativeConfig = json.value(configKey::config).toString();
config.hostName = json.value(configKey::hostName).toString();
config.port = json.value(configKey::port).toInt(0);
config.cascadeEndpoint = json.value(configKey::cascadeEndpoint).toString();
config.cascadePort = json.value(configKey::cascadePort).toString();
config.clientIp = json.value(configKey::clientIp).toString();
config.clientPrivateKey = json.value(configKey::clientPrivKey).toString();
config.clientPublicKey = json.value(configKey::clientPubKey).toString();
@@ -19,6 +19,8 @@ namespace AwgConstant
struct AwgServerConfig {
QString port;
QString cascadeEndpoint;
QString cascadePort;
QString transportProto;
QString protocolVersion;
QString subnetAddress;
@@ -61,6 +63,8 @@ struct AwgClientConfig {
QString nativeConfig;
QString hostName;
int port;
QString cascadeEndpoint;
QString cascadePort;
QString clientIp;
QString clientPrivateKey;
QString clientPublicKey;
@@ -95,6 +99,9 @@ struct AwgClientConfig {
QString maxHandshakeAttempts;
QString randomTrailers;
QString disableCookies;
void setCascade(const QString &newEndpoint, const QString &newPort);
QJsonObject toJson() const;
static AwgClientConfig fromJson(const QJsonObject& json);
};
@@ -20,6 +20,12 @@ QJsonObject WireGuardServerConfig::toJson() const
if (!port.isEmpty()) {
obj[configKey::port] = port;
}
if (!cascadeEndpoint.isEmpty()) {
obj[configKey::cascadeEndpoint] = cascadeEndpoint;
}
if (!cascadePort.isEmpty()) {
obj[configKey::cascadePort] = cascadePort;
}
if (!transportProto.isEmpty()) {
obj[configKey::transportProto] = transportProto;
}
@@ -45,6 +51,8 @@ WireGuardServerConfig WireGuardServerConfig::fromJson(const QJsonObject& json)
WireGuardServerConfig config;
config.port = json.value(configKey::port).toString();
config.cascadeEndpoint = json.value(configKey::cascadeEndpoint).toString();
config.cascadePort = json.value(configKey::cascadePort).toString();
config.transportProto = json.value(configKey::transportProto).toString();
config.subnetAddress = json.value(configKey::subnetAddress).toString();
config.subnetMask = json.value(configKey::subnetMask).toString();
@@ -73,6 +81,12 @@ QJsonObject WireGuardClientConfig::toJson() const
if (port > 0) {
obj[configKey::port] = port;
}
if (!cascadeEndpoint.isEmpty()) {
obj[configKey::cascadeEndpoint] = cascadeEndpoint;
}
if (!cascadePort.isEmpty()) {
obj[configKey::cascadePort] = cascadePort;
}
if (!clientIp.isEmpty()) {
obj[configKey::clientIp] = clientIp;
}
@@ -119,6 +133,14 @@ QJsonObject WireGuardClientConfig::toJson() const
return obj;
}
void WireGuardClientConfig::setCascade(const QString &newEndpoint, const QString &newPort)
{
cascadeEndpoint = newEndpoint;
cascadePort = newPort;
nativeConfig = replaceWireGuardEndpoint(nativeConfig, newEndpoint.isEmpty() ? hostName : newEndpoint,
newPort.isEmpty() ? port : newPort.toInt());
}
WireGuardClientConfig WireGuardClientConfig::fromJson(const QJsonObject& json)
{
WireGuardClientConfig config;
@@ -126,6 +148,8 @@ WireGuardClientConfig WireGuardClientConfig::fromJson(const QJsonObject& json)
config.nativeConfig = json.value(configKey::config).toString();
config.hostName = json.value(configKey::hostName).toString();
config.port = json.value(configKey::port).toInt(0);
config.cascadeEndpoint = json.value(configKey::cascadeEndpoint).toString();
config.cascadePort = json.value(configKey::cascadePort).toString();
config.clientIp = json.value(configKey::clientIp).toString();
config.clientPrivateKey = json.value(configKey::clientPrivKey).toString();
config.clientPublicKey = json.value(configKey::clientPubKey).toString();
@@ -12,6 +12,8 @@ namespace amnezia
struct WireGuardServerConfig {
QString port;
QString cascadeEndpoint;
QString cascadePort;
QString transportProto;
QString subnetAddress;
QString subnetMask;
@@ -28,6 +30,8 @@ struct WireGuardClientConfig {
QString nativeConfig;
QString hostName;
int port;
QString cascadeEndpoint;
QString cascadePort;
QString clientIp;
QString clientPrivateKey;
QString clientPublicKey;
@@ -41,6 +45,8 @@ struct WireGuardClientConfig {
QMap<QString, QString> awgParams;
bool isObfuscationEnabled = false;
void setCascade(const QString &newEndpoint, const QString &newPort);
QJsonObject toJson() const;
static WireGuardClientConfig fromJson(const QJsonObject& json);
};
@@ -354,9 +354,6 @@ void XrayServerConfig::applyDefaults(bool fillFlowDefault)
transportProto = ProtocolUtils::transportProtoToString(ProtocolUtils::defaultTransportProto(Proto::Xray),
Proto::Xray);
}
if (site.isEmpty()) {
site = protocols::xray::defaultSite;
}
if (transport.isEmpty()) {
transport = protocols::xray::defaultTransport;
}
@@ -367,7 +364,7 @@ void XrayServerConfig::applyDefaults(bool fillFlowDefault)
flow = protocols::xray::defaultFlow;
}
if (sni.isEmpty()) {
sni = site.isEmpty() ? QString::fromLatin1(protocols::xray::defaultSni) : site;
sni = site;
}
if (alpn.isEmpty()) {
alpn = protocols::xray::defaultAlpn;
@@ -569,7 +566,7 @@ QJsonObject XrayServerConfig::streamSettingsJson(XrayStreamSide side) const
if (securityEff == QLatin1String(px::securityTls)) {
QJsonObject tlsSettings;
tlsSettings[px::serverName] = sni.isEmpty() ? QString::fromLatin1(px::defaultSni) : sni;
tlsSettings[px::serverName] = sni;
const QString alpnEff = alpn.isEmpty() ? QString::fromLatin1(px::defaultAlpn) : alpn;
QJsonArray alpnArray;
for (const QString &a : alpnEff.split(QLatin1Char(','))) {
@@ -598,7 +595,7 @@ QJsonObject XrayServerConfig::streamSettingsJson(XrayStreamSide side) const
if (clientSide && securityEff == QLatin1String(px::securityReality)) {
QJsonObject realitySettings;
realitySettings[px::fingerprint] = fingerprintEff;
realitySettings[px::serverName] = sni.isEmpty() ? QString::fromLatin1(px::defaultSni) : sni;
realitySettings[px::serverName] = sni;
streamSettings[px::realitySettings] = realitySettings;
}
@@ -1139,11 +1136,10 @@ QJsonObject XrayServerConfig::toServerInboundJson(const XrayServerInboundInputs
QJsonObject streamSettings = serverStreamSettings();
if (xrayEffective::security(*this) == QLatin1String(px::securityReality)) {
const QString siteEff = site.isEmpty() ? QString::fromLatin1(px::defaultSite) : site;
QJsonObject realitySettings;
realitySettings[px::dest] = siteEff + QStringLiteral(":443");
realitySettings[px::dest] = site + QStringLiteral(":443");
realitySettings[px::privateKey] = inputs.realityPrivateKey;
realitySettings[px::serverNames] = QJsonArray { sni.isEmpty() ? siteEff : sni };
realitySettings[px::serverNames] = QJsonArray { sni.isEmpty() ? site : sni };
realitySettings[px::shortIds] = QJsonArray { inputs.realityShortId };
streamSettings[px::realitySettings] = realitySettings;
}
@@ -1323,10 +1319,9 @@ QJsonObject XrayServerConfig::serverView() const
view[px::streamSettings] = serverStreamSettings();
if (xrayEffective::security(*this) == QLatin1String(px::securityReality)) {
const QString siteEff = site.isEmpty() ? QString::fromLatin1(px::defaultSite) : site;
QJsonObject reality;
reality[px::dest] = siteEff;
reality[px::serverName] = sni.isEmpty() ? siteEff : sni;
reality[px::dest] = site;
reality[px::serverName] = sni.isEmpty() ? site : sni;
view[QStringLiteral("reality")] = reality;
}
+8
View File
@@ -1,6 +1,7 @@
#include "protocolUtils.h"
#include <QRandomGenerator>
#include <QRegularExpression>
#include <QJsonObject>
#include <QObject>
@@ -216,3 +217,10 @@ QString ProtocolUtils::key_proto_config_path(Proto p)
return protoToString(p) + "_config_path";
}
QString ProtocolUtils::replaceWireGuardEndpoint(QString nativeConfig, const QString &host, int port)
{
static const QRegularExpression endpointLine(QString(R"(^(\s*%1\s*=\s*).*$)").arg(protocols::wireguard::Endpoint),
QRegularExpression::MultilineOption);
const QString endpointHost = host.contains(':') ? QString("[%1]").arg(host) : host;
return nativeConfig.replace(endpointLine, QString("\\1%1:%2").arg(endpointHost).arg(port));
}
+2
View File
@@ -39,6 +39,8 @@ namespace amnezia
QString key_proto_config_data(Proto p);
QString key_proto_config_path(Proto p);
QString replaceWireGuardEndpoint(QString nativeConfig, const QString &host, int port);
}
}
+2
View File
@@ -13,6 +13,8 @@ namespace amnezia
constexpr QLatin1String password("password");
constexpr QLatin1String port("port");
constexpr QLatin1String localPort("local_port");
constexpr QLatin1String cascadeEndpoint("cascade_endpoint");
constexpr QLatin1String cascadePort("cascade_port");
constexpr QLatin1String dns1("dns1");
constexpr QLatin1String dns2("dns2");
@@ -57,7 +57,22 @@ namespace amnezia
constexpr char shortidPath[] = "/opt/amnezia/xray/xray_short_id.key";
constexpr char tlsCertPath[] = "/opt/amnezia/xray/tls_cert.pem";
constexpr char tlsKeyPath[] = "/opt/amnezia/xray/tls_key.pem";
constexpr char defaultSite[] = "www.googletagmanager.com";
constexpr const char *defaultSites[] = {
"www.microsoft.com",
"www.apple.com",
"www.icloud.com",
"dl.google.com",
"www.bing.com",
"www.samsung.com",
"www.nvidia.com",
"www.cisco.com",
"www.asus.com",
"www.logitech.com",
"www.dropbox.com",
"www.mozilla.org",
"addons.mozilla.org",
"www.speedtest.net",
};
constexpr char defaultPort[] = "443";
constexpr char defaultLocalProxyPort[] = "10808";
@@ -69,8 +84,7 @@ namespace amnezia
constexpr char defaultSecurity[] = "reality";
constexpr char defaultFlow[] = "xtls-rprx-vision";
constexpr char defaultTransport[] = "raw";
constexpr char defaultFingerprint[] = "hellochrome_120";
constexpr char defaultSni[] = "www.googletagmanager.com";
constexpr char defaultFingerprint[] = "firefox";
constexpr char defaultAlpn[] = "h2";
constexpr char defaultXhttpMode[] = "Stream-one";
@@ -208,7 +208,7 @@ amnezia::ScriptVars amnezia::genXrayVars(const ContainerConfig &containerConfig)
if (auto* xrayProtocolConfig = containerConfig.getXrayProtocolConfig()) {
const XrayServerConfig& config = xrayProtocolConfig->serverConfig;
vars.append({ { "$XRAY_SITE_NAME", config.site.isEmpty() ? protocols::xray::defaultSite : config.site } });
vars.append({ { "$XRAY_SITE_NAME", config.site } });
vars.append({ { "$XRAY_SERVER_PORT", config.port.isEmpty() ? protocols::xray::defaultPort : config.port } });
}
@@ -205,10 +205,10 @@ extension PacketTunnelProvider {
}
}
func stopXray(completionHandler: @escaping () -> Void) {
func stopXray(completionHandler: () -> Void) {
Socks5Tunnel.quit()
LibXrayStopXray()
hevSocksTunnelGroup.notify(queue: .main, execute: completionHandler)
completionHandler()
}
func sockCallback(fd: uintptr_t) {
@@ -345,13 +345,10 @@ extension PacketTunnelProvider {
return
}
hevSocksTunnelGroup.enter()
DispatchQueue.global().async { [hevSocksTunnelGroup] in
DispatchQueue.global().async {
xrayLog(.info, message: "Hev socks started")
completionHandler(nil)
let result = Socks5Tunnel.run(withConfig: configurationFilePath)
xrayLog(.info, message: "Hev socks stopped: \(result)")
hevSocksTunnelGroup.leave()
Socks5Tunnel.run(withConfig: configurationFilePath)
}
}
}
@@ -69,7 +69,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
var protoType: TunnelProtoType?
var activeIfaceIdx: UInt32 = 0
let hevSocksTunnelGroup = DispatchGroup()
func openVPNPacketFlow() -> OpenVPNAdapterPacketFlow {
openVPNPacketFlowAdapter
@@ -317,11 +316,10 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
updateActiveInterfaceIndex(for: changePath)
reasserting = true
xrayLog(.info, message: "Applying network change to xray tunnel")
stopXray { [weak self] in
self?.startXray { [weak self] error in
self?.reasserting = false
completion(error)
}
stopXray { }
startXray { [weak self] error in
self?.reasserting = false
completion(error)
}
}
+1 -1
View File
@@ -75,7 +75,7 @@ void TestXrayConfigModel::isValidSni_data()
{
QTest::addColumn<QString>("sni");
QTest::addColumn<bool>("valid");
QTest::newRow("empty") << "" << true;
QTest::newRow("empty") << "" << false;
QTest::newRow("domain") << "www.example.com" << true;
QTest::newRow("ipv4") << "203.0.113.10" << true;
QTest::newRow("star") << "*" << false;
@@ -58,6 +58,73 @@ void AwgConfigModel::setPort(const QString &value)
emit changed();
}
QString AwgConfigModel::cascadeEndpoint() const
{
return m_protocolConfig.serverConfig.cascadeEndpoint;
}
void AwgConfigModel::setCascadeEndpoint(const QString &value)
{
if (m_protocolConfig.serverConfig.cascadeEndpoint == value) {
return;
}
m_protocolConfig.serverConfig.cascadeEndpoint = value;
emit changed();
}
QString AwgConfigModel::cascadePort() const
{
return m_protocolConfig.serverConfig.cascadePort;
}
void AwgConfigModel::setCascadePort(const QString &value)
{
if (m_protocolConfig.serverConfig.cascadePort == value) {
return;
}
m_protocolConfig.serverConfig.cascadePort = value;
emit changed();
}
QString AwgConfigModel::clientHostName() const
{
return m_protocolConfig.clientConfig->hostName;
}
QString AwgConfigModel::clientPort() const
{
const int port = m_protocolConfig.clientConfig->port;
return port > 0 ? QString::number(port) : QString();
}
QString AwgConfigModel::clientCascadeEndpoint() const
{
return m_protocolConfig.clientConfig->cascadeEndpoint;
}
void AwgConfigModel::setClientCascadeEndpoint(const QString &value)
{
if (m_protocolConfig.clientConfig->cascadeEndpoint == value) {
return;
}
m_protocolConfig.clientConfig->setCascade(value, m_protocolConfig.clientConfig->cascadePort);
emit changed();
}
QString AwgConfigModel::clientCascadePort() const
{
return m_protocolConfig.clientConfig->cascadePort;
}
void AwgConfigModel::setClientCascadePort(const QString &value)
{
if (m_protocolConfig.clientConfig->cascadePort == value) {
return;
}
m_protocolConfig.clientConfig->setCascade(m_protocolConfig.clientConfig->cascadeEndpoint, value);
emit changed();
}
QString AwgConfigModel::clientMtu() const
{
return m_protocolConfig.clientConfig->mtu;
@@ -709,8 +776,15 @@ amnezia::AwgProtocolConfig AwgConfigModel::getProtocolConfig()
{
bool serverSettingsChanged = !m_protocolConfig.serverConfig.hasEqualServerSettings(m_originalProtocolConfig.serverConfig);
const auto &serverConfig = m_protocolConfig.serverConfig;
const auto &originalServerConfig = m_originalProtocolConfig.serverConfig;
const bool cascadeChanged = serverConfig.cascadeEndpoint != originalServerConfig.cascadeEndpoint
|| serverConfig.cascadePort != originalServerConfig.cascadePort;
if (serverSettingsChanged) {
m_protocolConfig.clearClientConfig();
} else if (cascadeChanged) {
m_protocolConfig.clientConfig->setCascade(serverConfig.cascadeEndpoint, serverConfig.cascadePort);
}
return m_protocolConfig;
@@ -14,7 +14,13 @@ class AwgConfigModel : public QObject
Q_PROPERTY(QString subnetAddress READ subnetAddress WRITE setSubnetAddress NOTIFY changed)
Q_PROPERTY(QString port READ port WRITE setPort NOTIFY changed)
Q_PROPERTY(QString cascadeEndpoint READ cascadeEndpoint WRITE setCascadeEndpoint NOTIFY changed)
Q_PROPERTY(QString cascadePort READ cascadePort WRITE setCascadePort NOTIFY changed)
Q_PROPERTY(QString clientMtu READ clientMtu WRITE setClientMtu NOTIFY changed)
Q_PROPERTY(QString clientHostName READ clientHostName NOTIFY changed)
Q_PROPERTY(QString clientPort READ clientPort NOTIFY changed)
Q_PROPERTY(QString clientCascadeEndpoint READ clientCascadeEndpoint WRITE setClientCascadeEndpoint NOTIFY changed)
Q_PROPERTY(QString clientCascadePort READ clientCascadePort WRITE setClientCascadePort NOTIFY changed)
Q_PROPERTY(QString clientJunkPacketCount READ clientJunkPacketCount WRITE setClientJunkPacketCount NOTIFY changed)
Q_PROPERTY(QString clientJunkPacketMinSize READ clientJunkPacketMinSize WRITE setClientJunkPacketMinSize NOTIFY changed)
Q_PROPERTY(QString clientJunkPacketMaxSize READ clientJunkPacketMaxSize WRITE setClientJunkPacketMaxSize NOTIFY changed)
@@ -69,6 +75,21 @@ public:
QString port() const;
void setPort(const QString &value);
QString cascadeEndpoint() const;
void setCascadeEndpoint(const QString &value);
QString cascadePort() const;
void setCascadePort(const QString &value);
QString clientHostName() const;
QString clientPort() const;
QString clientCascadeEndpoint() const;
void setClientCascadeEndpoint(const QString &value);
QString clientCascadePort() const;
void setClientCascadePort(const QString &value);
QString clientMtu() const;
void setClientMtu(const QString &value);
@@ -40,6 +40,73 @@ void WireGuardConfigModel::setPort(const QString &value)
emit changed();
}
QString WireGuardConfigModel::cascadeEndpoint() const
{
return m_protocolConfig.serverConfig.cascadeEndpoint;
}
void WireGuardConfigModel::setCascadeEndpoint(const QString &value)
{
if (m_protocolConfig.serverConfig.cascadeEndpoint == value) {
return;
}
m_protocolConfig.serverConfig.cascadeEndpoint = value;
emit changed();
}
QString WireGuardConfigModel::cascadePort() const
{
return m_protocolConfig.serverConfig.cascadePort;
}
void WireGuardConfigModel::setCascadePort(const QString &value)
{
if (m_protocolConfig.serverConfig.cascadePort == value) {
return;
}
m_protocolConfig.serverConfig.cascadePort = value;
emit changed();
}
QString WireGuardConfigModel::clientHostName() const
{
return m_protocolConfig.clientConfig->hostName;
}
QString WireGuardConfigModel::clientPort() const
{
const int port = m_protocolConfig.clientConfig->port;
return port > 0 ? QString::number(port) : QString();
}
QString WireGuardConfigModel::clientCascadeEndpoint() const
{
return m_protocolConfig.clientConfig->cascadeEndpoint;
}
void WireGuardConfigModel::setClientCascadeEndpoint(const QString &value)
{
if (m_protocolConfig.clientConfig->cascadeEndpoint == value) {
return;
}
m_protocolConfig.clientConfig->setCascade(value, m_protocolConfig.clientConfig->cascadePort);
emit changed();
}
QString WireGuardConfigModel::clientCascadePort() const
{
return m_protocolConfig.clientConfig->cascadePort;
}
void WireGuardConfigModel::setClientCascadePort(const QString &value)
{
if (m_protocolConfig.clientConfig->cascadePort == value) {
return;
}
m_protocolConfig.clientConfig->setCascade(m_protocolConfig.clientConfig->cascadeEndpoint, value);
emit changed();
}
QString WireGuardConfigModel::clientMtu() const
{
if (m_protocolConfig.clientConfig.has_value()) {
@@ -96,8 +163,15 @@ amnezia::WireGuardProtocolConfig WireGuardConfigModel::getProtocolConfig()
{
bool serverSettingsChanged = !m_protocolConfig.serverConfig.hasEqualServerSettings(m_originalProtocolConfig.serverConfig);
const auto &serverConfig = m_protocolConfig.serverConfig;
const auto &originalServerConfig = m_originalProtocolConfig.serverConfig;
const bool cascadeChanged = serverConfig.cascadeEndpoint != originalServerConfig.cascadeEndpoint
|| serverConfig.cascadePort != originalServerConfig.cascadePort;
if (serverSettingsChanged) {
m_protocolConfig.clearClientConfig();
} else if (cascadeChanged) {
m_protocolConfig.clientConfig->setCascade(serverConfig.cascadeEndpoint, serverConfig.cascadePort);
}
return m_protocolConfig;
@@ -14,7 +14,13 @@ class WireGuardConfigModel : public QObject
Q_PROPERTY(QString subnetAddress READ subnetAddress WRITE setSubnetAddress NOTIFY changed)
Q_PROPERTY(QString port READ port WRITE setPort NOTIFY changed)
Q_PROPERTY(QString cascadeEndpoint READ cascadeEndpoint WRITE setCascadeEndpoint NOTIFY changed)
Q_PROPERTY(QString cascadePort READ cascadePort WRITE setCascadePort NOTIFY changed)
Q_PROPERTY(QString clientMtu READ clientMtu WRITE setClientMtu NOTIFY changed)
Q_PROPERTY(QString clientHostName READ clientHostName NOTIFY changed)
Q_PROPERTY(QString clientPort READ clientPort NOTIFY changed)
Q_PROPERTY(QString clientCascadeEndpoint READ clientCascadeEndpoint WRITE setClientCascadeEndpoint NOTIFY changed)
Q_PROPERTY(QString clientCascadePort READ clientCascadePort WRITE setClientCascadePort NOTIFY changed)
public:
explicit WireGuardConfigModel(QObject *parent = nullptr);
@@ -25,6 +31,21 @@ public:
QString port() const;
void setPort(const QString &value);
QString cascadeEndpoint() const;
void setCascadeEndpoint(const QString &value);
QString cascadePort() const;
void setCascadePort(const QString &value);
QString clientHostName() const;
QString clientPort() const;
QString clientCascadeEndpoint() const;
void setClientCascadeEndpoint(const QString &value);
QString clientCascadePort() const;
void setClientCascadePort(const QString &value);
QString clientMtu() const;
void setClientMtu(const QString &value);
+2 -10
View File
@@ -759,7 +759,7 @@ QStringList XrayConfigModel::transportOptions()
QStringList XrayConfigModel::fingerprintOptions()
{
return { "hellochrome_120", "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random" };
return { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random" };
}
QStringList XrayConfigModel::alpnOptions()
@@ -833,11 +833,6 @@ QString XrayConfigModel::portDefault()
return QString::fromLatin1(protocols::xray::defaultPort);
}
QString XrayConfigModel::sniDefault()
{
return QString::fromLatin1(protocols::xray::defaultSni);
}
QString XrayConfigModel::xhttpHostDefault()
{
return QString::fromLatin1(protocols::xray::defaultXhttpHost);
@@ -933,10 +928,7 @@ bool XrayConfigModel::isValidHost(const QString &host)
bool XrayConfigModel::isValidSni(const QString &sni)
{
const QString t = sni.trimmed();
if (t.isEmpty()) {
return true;
}
if (t.contains(QLatin1Char('*'))) {
if (t.isEmpty() || t.contains(QLatin1Char('*'))) {
return false;
}
return isValidSingleHost(t);
@@ -251,7 +251,6 @@ public:
Q_INVOKABLE static QString mkcpDefaultCwndMultiplier();
Q_INVOKABLE static QString portDefault();
Q_INVOKABLE static QString sniDefault();
Q_INVOKABLE static QString xhttpHostDefault();
Q_INVOKABLE static QString xhttpUplinkChunkSizeDefault();
Q_INVOKABLE static QString scMaxEachPostBytesMinDefault();
@@ -0,0 +1,87 @@
import QtQuick
import QtQuick.Layouts
import MtProxyConfig 1.0
import "../Controls2"
import "../Controls2/TextTypes"
ColumnLayout {
id: root
property string endpoint
property string port
property string endpointPlaceholder
property string portPlaceholder
property bool warningVisible: false
property var scroller: null
signal endpointEdited(string text)
signal portEdited(string text)
spacing: 12
H2TextType {
Layout.fillWidth: true
Layout.topMargin: 28
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("Cascade connection")
}
NotificationType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
visible: root.warningVisible
variant: NotificationType.Warning
text: qsTr("Cascade endpoint and port are the address and port of the entry server that forwards traffic to this server. New client configs will connect to them instead of this server's address and port. Existing configs are not changed")
}
TextFieldType {
id: endpointTextField
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Cascade endpoint")
textField.placeholderText: root.endpointPlaceholder
textField.text: root.endpoint
textField.maximumLength: 253
textField.validator: PublicHostInputValidator {}
textField.onTextEdited: root.endpointEdited(textField.text.trim())
textField.onActiveFocusChanged: {
if (textField.activeFocus && root.scroller) {
root.scroller.scrollToItem(endpointTextField)
}
}
}
TextFieldType {
id: portTextField
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Cascade port")
textField.placeholderText: root.portPlaceholder
textField.text: root.port
textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 }
textField.onTextEdited: root.portEdited(textField.text)
textField.onActiveFocusChanged: {
if (textField.activeFocus && root.scroller) {
root.scroller.scrollToItem(portTextField)
}
}
}
}
@@ -118,7 +118,6 @@ Item {
enabled: d.scrolled > 0
acceptedButtons: Qt.AllButtons
hoverEnabled: true
}
IconButtonType {
-10
View File
@@ -15,16 +15,6 @@ TabButton {
readonly property int maximumHorizontalPadding: root.size === TabButtonType.Large ? 24 : 10
implicitWidth: implicitContentWidth + 2 * root.maximumHorizontalPadding
width: {
if (!root.visible) {
return 0
}
const tabBar = root.TabBar.tabBar
if (!tabBar || tabBar.visibleTabCount === undefined) {
return implicitWidth
}
return tabBar.availableWidth / Math.max(1, tabBar.visibleTabCount)
}
implicitHeight: root.size === TabButtonType.Large ? 48 : 36
horizontalPadding: Math.max(4, Math.min(root.maximumHorizontalPadding, (root.width - implicitContentWidth) / 2))
-11
View File
@@ -4,17 +4,6 @@ import QtQuick.Controls
TabBar {
id: root
readonly property int visibleTabCount: {
let visibleCount = 0
for (let i = 0; i < root.count; ++i) {
const tab = root.itemAt(i)
if (tab && tab.visible) {
++visibleCount
}
}
return visibleCount
}
spacing: 0
background: null
}
@@ -271,6 +271,20 @@ PageType {
}
}
CascadeSettings {
Layout.fillWidth: true
scroller: smartScroll
endpoint: AwgConfigModel.clientCascadeEndpoint
port: AwgConfigModel.clientCascadePort
endpointPlaceholder: AwgConfigModel.clientHostName
portPlaceholder: AwgConfigModel.clientPort
onEndpointEdited: (text) => { AwgConfigModel.clientCascadeEndpoint = text }
onPortEdited: (text) => { AwgConfigModel.clientCascadePort = text }
}
H2TextType {
Layout.fillWidth: true
Layout.topMargin: 28
@@ -464,6 +464,23 @@ PageType {
}
}
}
CascadeSettings {
Layout.fillWidth: true
enabled: root.isEnabled
warningVisible: true
scroller: smartScroll
endpoint: AwgConfigModel.cascadeEndpoint
port: AwgConfigModel.cascadePort
endpointPlaceholder: ServersUiController.serverHostName(ServersUiController.processedServerId)
portPlaceholder: AwgConfigModel.port
onEndpointEdited: (text) => { AwgConfigModel.cascadeEndpoint = text }
onPortEdited: (text) => { AwgConfigModel.cascadePort = text }
}
}
}
@@ -60,6 +60,18 @@ PageType {
checkEmptyText: true
}
CascadeSettings {
Layout.fillWidth: true
endpoint: WireGuardConfigModel.clientCascadeEndpoint
port: WireGuardConfigModel.clientCascadePort
endpointPlaceholder: WireGuardConfigModel.clientHostName
portPlaceholder: WireGuardConfigModel.clientPort
onEndpointEdited: (text) => { WireGuardConfigModel.clientCascadeEndpoint = text }
onPortEdited: (text) => { WireGuardConfigModel.clientCascadePort = text }
}
H2TextType {
Layout.fillWidth: true
Layout.topMargin: 40
@@ -77,6 +77,20 @@ PageType {
checkEmptyText: true
}
CascadeSettings {
Layout.fillWidth: true
warningVisible: true
endpoint: WireGuardConfigModel.cascadeEndpoint
port: WireGuardConfigModel.cascadePort
endpointPlaceholder: ServersUiController.serverHostName(ServersUiController.processedServerId)
portPlaceholder: WireGuardConfigModel.port
onEndpointEdited: (text) => { WireGuardConfigModel.cascadeEndpoint = text }
onPortEdited: (text) => { WireGuardConfigModel.cascadePort = text }
}
}
}
@@ -159,7 +159,6 @@ PageType {
id: sniFieldTls
Layout.fillWidth: true
headerText: qsTr("Server Name (SNI)")
placeholderText: XrayConfigModel.sniDefault()
textField.text: XrayConfigModel.sni
textField.validator: RegularExpressionValidator { regularExpression: /^[A-Za-z0-9._-]*$/ }
textField.onTextEdited: XrayConfigModel.sni = textField.text
@@ -216,7 +215,6 @@ PageType {
id: sniFieldReality
Layout.fillWidth: true
headerText: qsTr("Server Name (SNI)")
placeholderText: XrayConfigModel.sniDefault()
textField.text: XrayConfigModel.sni
textField.validator: RegularExpressionValidator { regularExpression: /^[A-Za-z0-9._-]*$/ }
textField.onTextEdited: XrayConfigModel.sni = textField.text
+28 -18
View File
@@ -21,13 +21,30 @@ PageType {
readonly property int pageSettingsServerServices: 1
readonly property int pageSettingsServerData: 2
readonly property var tabTitles: [qsTr("Protocols"), qsTr("Services"), qsTr("Management")]
readonly property var availableTabs: {
const tabs = []
if (protocolsPage.installedProtocolsCount > 0) {
tabs.push(root.pageSettingsServerProtocols)
}
if (servicesPage.installedServicesCount > 0) {
tabs.push(root.pageSettingsServerServices)
}
tabs.push(root.pageSettingsServerData)
return tabs
}
property int currentTab: (ServersUiController.isServerFromApi(ServersUiController.processedServerId)
&& !ServersUiController.serverHasInstalledContainers(ServersUiController.processedServerId)) ?
root.pageSettingsServerData : root.pageSettingsServerProtocols
property var processedServer
Connections {
target: PageController
function onGoToPageSettingsServerServices() {
tabBar.setCurrentIndex(root.pageSettingsServerServices)
root.currentTab = root.pageSettingsServerServices
}
}
@@ -111,25 +128,18 @@ PageType {
Layout.leftMargin: 16
Layout.rightMargin: 16
currentIndex: (ServersUiController.isServerFromApi(ServersUiController.processedServerId)
&& !ServersUiController.serverHasInstalledContainers(ServersUiController.processedServerId)) ?
root.pageSettingsServerData : root.pageSettingsServerProtocols
currentIndex: root.availableTabs.indexOf(root.currentTab)
TabButtonType {
id: protocolsTab
visible: protocolsPage.installedProtocolsCount > 0
text: qsTr("Protocols")
}
Repeater {
model: root.availableTabs
TabButtonType {
id: servicesTab
visible: servicesPage.installedServicesCount > 0
text: qsTr("Services")
}
TabButtonType {
required property int modelData
TabButtonType {
id: dataTab
text: qsTr("Management")
text: root.tabTitles[modelData]
onClicked: root.currentTab = modelData
}
}
}
@@ -140,7 +150,7 @@ PageType {
Layout.fillHeight: true
Layout.topMargin: 24
currentIndex: tabBar.currentIndex
currentIndex: root.currentTab
PageSettingsServerProtocols {
id: protocolsPage
+1
View File
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/ui/qml">
<file>Components/CopyableValueRow.qml</file>
<file>Components/CascadeSettings.qml</file>
<file>Components/ConfigContentSheet.qml</file>
<file>Components/QrCodeCard.qml</file>
<file>Components/ShareClientInfoSheet.qml</file>
+2 -2
View File
@@ -9,7 +9,7 @@ import os
class AwgApple(ConanFile):
name = "awg-apple"
version = "3.1.5"
version = "3.1.4"
settings = "os", "arch", "compiler"
@property
@@ -45,7 +45,7 @@ class AwgApple(ConanFile):
def source(self):
get(self, f"https://github.com/amnezia-vpn/amneziawg-apple/archive/refs/tags/v{self.version}.zip",
sha256="b3bd3680fa966dae67162c261e1b0a42235a0bd706ec6ea67cc04e707ef3b7a8", strip_root=True
sha256="09d7b760d18232fdf121ed2286b2f171b501dc31137e5e7d557c1ee3a99ef772", strip_root=True
)
def generate(self):