Merge pull request #128 from amnezia-vpn/feature/ovpn-config-import

added import of configs in openvpn and wireguard formats
This commit is contained in:
pokamest 2023-01-08 22:26:39 +00:00 committed by GitHub
commit 3259e6f0e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 696 additions and 383 deletions

View file

@ -74,6 +74,7 @@ HEADERS += \
ui/pages_logic/protocols/OtherProtocolsLogic.h \
ui/pages_logic/protocols/PageProtocolLogicBase.h \
ui/pages_logic/protocols/ShadowSocksLogic.h \
ui/pages_logic/protocols/WireGuardLogic.h \
ui/property_helper.h \
ui/models/servers_model.h \
ui/uilogic.h \
@ -136,6 +137,7 @@ SOURCES += \
ui/pages_logic/protocols/PageProtocolLogicBase.cpp \
ui/pages_logic/protocols/ShadowSocksLogic.cpp \
ui/models/servers_model.cpp \
ui/pages_logic/protocols/WireGuardLogic.cpp \
ui/uilogic.cpp \
ui/qautostart.cpp \
ui/models/sites_model.cpp \

View file

@ -58,6 +58,12 @@ constexpr char additional_server_config[] = "additional_server_config";
// proto config keys
constexpr char last_config[] = "last_config";
constexpr char isThirdPartyConfig[] = "isThirdPartyConfig";
constexpr char openvpn[] = "openvpn";
constexpr char wireguard[] = "wireguard";
}
namespace protocols {

View file

@ -63,6 +63,7 @@
<file>server_scripts/website_tor/run_container.sh</file>
<file>ui/qml/main.qml</file>
<file>ui/qml/TitleBar.qml</file>
<file>ui/qml/Pages/PageBase.qml</file>
<file>ui/qml/Pages/PageAppSetting.qml</file>
<file>ui/qml/Pages/PageGeneralSettings.qml</file>
<file>ui/qml/Pages/PageNetworkSetting.qml</file>
@ -81,6 +82,28 @@
<file>ui/qml/Pages/PageSites.qml</file>
<file>ui/qml/Pages/PageStart.qml</file>
<file>ui/qml/Pages/PageVPN.qml</file>
<file>ui/qml/Pages/PageQrDecoder.qml</file>
<file>ui/qml/Pages/PageAbout.qml</file>
<file>ui/qml/Pages/PageQrDecoderIos.qml</file>
<file>ui/qml/Pages/PageViewConfig.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoCloak.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoOpenVPN.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoShadowSocks.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoSftp.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoTorWebSite.qml</file>
<file>ui/qml/Pages/Protocols/PageProtocolBase.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoWireGuard.qml</file>
<file>ui/qml/Pages/InstallSettings/InstallSettingsBase.qml</file>
<file>ui/qml/Pages/InstallSettings/SelectContainer.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoCloak.qml</file>
<file>ui/qml/Pages/Share/PageShareProtocolBase.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoOpenVPN.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoSftp.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoShadowSocks.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoTorWebSite.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoAmnezia.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoWireGuard.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoIkev2.qml</file>
<file>ui/qml/Controls/BasicButtonType.qml</file>
<file>ui/qml/Controls/BlueButtonType.qml</file>
<file>ui/qml/Controls/CheckBoxType.qml</file>
@ -92,57 +115,40 @@
<file>ui/qml/Controls/ShareConnectionButtonType.qml</file>
<file>ui/qml/Controls/ShareConnectionContent.qml</file>
<file>ui/qml/Controls/TextFieldType.qml</file>
<file>ui/qml/Pages/PageBase.qml</file>
<file>ui/qml/Config/GlobalConfig.qml</file>
<file>ui/qml/Config/qmldir</file>
<file>images/background_connected.png</file>
<file>images/background_connected@2x.png</file>
<file>ui/qml/Pages/Protocols/PageProtoCloak.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoOpenVPN.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoShadowSocks.qml</file>
<file>ui/qml/Controls/BackButton.qml</file>
<file>ui/qml/Pages/InstallSettings/InstallSettingsBase.qml</file>
<file>ui/qml/Controls/Caption.qml</file>
<file>ui/qml/Controls/Logo.qml</file>
<file>ui/qml/Pages/InstallSettings/SelectContainer.qml</file>
<file>ui/qml/Pages/Protocols/PageProtocolBase.qml</file>
<file>images/delete.png</file>
<file>ui/qml/Controls/RichLabelType.qml</file>
<file>ui/qml/Controls/SvgImageType.qml</file>
<file>ui/qml/Controls/FlickableType.qml</file>
<file>ui/qml/Controls/UrlButtonType.qml</file>
<file>ui/qml/Controls/TextAreaType.qml</file>
<file>ui/qml/Controls/ContextMenu.qml</file>
<file>ui/qml/Controls/FadeBehavior.qml</file>
<file>ui/qml/Controls/VisibleBehavior.qml</file>
<file>ui/qml/Controls/Caption.qml</file>
<file>ui/qml/Controls/Logo.qml</file>
<file>ui/qml/Controls/BackButton.qml</file>
<file>ui/qml/Controls/ShareConnectionButtonCopyType.qml</file>
<file>ui/qml/Controls/SvgButtonType.qml</file>
<file>ui/qml/Config/GlobalConfig.qml</file>
<file>ui/qml/Config/qmldir</file>
<file>server_scripts/dns/configure_container.sh</file>
<file>server_scripts/dns/Dockerfile</file>
<file>server_scripts/dns/run_container.sh</file>
<file>server_scripts/sftp/configure_container.sh</file>
<file>server_scripts/sftp/Dockerfile</file>
<file>server_scripts/sftp/run_container.sh</file>
<file>ui/qml/Pages/Protocols/PageProtoSftp.qml</file>
<file>ui/qml/Pages/Protocols/PageProtoTorWebSite.qml</file>
<file>server_scripts/ipsec/configure_container.sh</file>
<file>server_scripts/ipsec/Dockerfile</file>
<file>server_scripts/ipsec/run_container.sh</file>
<file>server_scripts/ipsec/start.sh</file>
<file>ui/qml/Pages/Share/PageShareProtoCloak.qml</file>
<file>ui/qml/Pages/Share/PageShareProtocolBase.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoOpenVPN.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoSftp.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoShadowSocks.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoTorWebSite.qml</file>
<file>ui/qml/Controls/TextAreaType.qml</file>
<file>ui/qml/Controls/ContextMenu.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoAmnezia.qml</file>
<file>ui/qml/Controls/ShareConnectionButtonCopyType.qml</file>
<file>ui/qml/Pages/Share/PageShareProtoWireGuard.qml</file>
<file>server_scripts/ipsec/mobileconfig.plist</file>
<file>ui/qml/Pages/Share/PageShareProtoIkev2.qml</file>
<file>server_scripts/ipsec/strongswan.profile</file>
<file>images/background_connected.png</file>
<file>images/background_connected@2x.png</file>
<file>images/delete.png</file>
<file>images/animation.gif</file>
<file>images/connected.png</file>
<file>images/disconnected.png</file>
<file>ui/qml/Pages/PageQrDecoder.qml</file>
<file>ui/qml/Pages/PageAbout.qml</file>
<file>ui/qml/Controls/RichLabelType.qml</file>
<file>images/svg/gpp_good_black_24dp.svg</file>
<file>ui/qml/Controls/SvgImageType.qml</file>
<file>images/svg/gpp_maybe_black_24dp.svg</file>
<file>images/svg/close_black_24dp.svg</file>
<file>images/svg/delete_black_24dp.svg</file>
@ -156,11 +162,6 @@
<file>images/svg/vpn_key_black_24dp.svg</file>
<file>images/svg/control_point_black_24dp.svg</file>
<file>images/svg/settings_suggest_black_24dp.svg</file>
<file>ui/qml/Controls/SvgButtonType.qml</file>
<file>ui/qml/Pages/PageQrDecoderIos.qml</file>
<file>server_scripts/website_tor/Dockerfile</file>
<file>ui/qml/Pages/PageViewConfig.qml</file>
<file>ui/qml/Controls/FlickableType.qml</file>
<file>ui/qml/Controls/UrlButtonType.qml</file>
</qresource>
</RCC>

View file

@ -29,6 +29,7 @@ void ServerContainersLogic::onUpdatePage()
ProtocolsModel *p_model = qobject_cast<ProtocolsModel *>(uiLogic()->protocolsModel());
p_model->setSelectedServerIndex(uiLogic()->selectedServerIndex);
set_isManagedServer(m_settings->haveAuthData(uiLogic()->selectedServerIndex));
emit updatePage();
}

View file

@ -19,6 +19,8 @@ public:
Q_INVOKABLE void onPushButtonRemoveClicked(DockerContainer c);
Q_INVOKABLE void onPushButtonContinueClicked(DockerContainer c, int port, TransportProto tp);
AUTO_PROPERTY(bool, isManagedServer)
public:
explicit ServerContainersLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~ServerContainersLogic() = default;

View file

@ -37,11 +37,17 @@ void ServerSettingsLogic::onUpdatePage()
set_pushButtonShareFullVisible(m_settings->haveAuthData(uiLogic()->selectedServerIndex));
const QJsonObject &server = m_settings->server(uiLogic()->selectedServerIndex);
const QString &port = server.value(config_key::port).toString();
set_labelServerText(QString("%1@%2%3%4")
.arg(server.value(config_key::userName).toString())
.arg(server.value(config_key::hostName).toString())
.arg(port.isEmpty() ? "" : ":")
.arg(port));
const QString &userName = server.value(config_key::userName).toString();
const QString &hostName = server.value(config_key::hostName).toString();
QString name = QString("%1%2%3%4%5")
.arg(userName)
.arg(userName.isEmpty() ? "" : "@")
.arg(hostName)
.arg(port.isEmpty() ? "" : ":")
.arg(port);
set_labelServerText(name);
set_lineEditDescriptionText(server.value(config_key::description).toString());
DockerContainer selectedContainer = m_settings->defaultContainer(uiLogic()->selectedServerIndex);

View file

@ -15,6 +15,36 @@
#include "platforms/android/android_controller.h"
#endif
namespace {
enum class ConfigTypes {
Amnezia,
OpenVpn,
WireGuard
};
ConfigTypes checkConfigFormat(const QString &config)
{
const QString openVpnConfigPatternCli = "client";
const QString openVpnConfigPatternProto1 = "proto tcp";
const QString openVpnConfigPatternProto2 = "proto udp";
const QString openVpnConfigPatternDriver1 = "dev tun";
const QString openVpnConfigPatternDriver2 = "dev tap";
const QString wireguardConfigPatternSectionInterface = "[Interface]";
const QString wireguardConfigPatternSectionPeer = "[Peer]";
if (config.contains(openVpnConfigPatternCli) &&
(config.contains(openVpnConfigPatternProto1) || config.contains(openVpnConfigPatternProto2)) &&
(config.contains(openVpnConfigPatternDriver1) || config.contains(openVpnConfigPatternDriver2))) {
return ConfigTypes::OpenVpn;
} else if (config.contains(wireguardConfigPatternSectionInterface) &&
config.contains(wireguardConfigPatternSectionPeer))
return ConfigTypes::WireGuard;
return ConfigTypes::Amnezia;
}
}
StartPageLogic::StartPageLogic(UiLogic *logic, QObject *parent):
PageLogicBase(logic, parent),
m_pushButtonConnectEnabled{true},
@ -135,15 +165,22 @@ void StartPageLogic::onPushButtonImport()
void StartPageLogic::onPushButtonImportOpenFile()
{
QString fileName = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Open profile"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), tr("*.vpn"));
QString fileName = QFileDialog::getOpenFileName(Q_NULLPTR, tr("Open config file"),
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), "*.vpn *.ovpn *.conf");
if (fileName.isEmpty()) return;
QFile file(fileName);
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
importConnectionFromCode(QString(data));
auto configFormat = checkConfigFormat(QString(data));
if (configFormat == ConfigTypes::OpenVpn) {
importConnectionFromOpenVpnConfig(QString(data));
} else if (configFormat == ConfigTypes::WireGuard) {
importConnectionFromWireguardConfig(QString(data));
} else {
importConnectionFromCode(QString(data));
}
}
bool StartPageLogic::importConnection(const QJsonObject &profile)
@ -205,3 +242,90 @@ bool StartPageLogic::importConnectionFromQr(const QByteArray &data)
return false;
}
bool StartPageLogic::importConnectionFromOpenVpnConfig(const QString &config)
{
QJsonObject openVpnConfig;
openVpnConfig[config_key::config] = config;
QJsonObject lastConfig;
lastConfig[config_key::last_config] = QString(QJsonDocument(openVpnConfig).toJson());
lastConfig[config_key::isThirdPartyConfig] = true;
QJsonObject containers;
containers.insert(config_key::container, QJsonValue("amnezia-openvpn"));
containers.insert(config_key::openvpn, QJsonValue(lastConfig));
QJsonArray arr;
arr.push_back(containers);
QString hostName;
const static QRegularExpression hostNameRegExp("remote (.*) [0-9]*");
QRegularExpressionMatch hostNameMatch = hostNameRegExp.match(config);
if (hostNameMatch.hasMatch()) {
hostName = hostNameMatch.captured(1);
}
QJsonObject o;
o[config_key::containers] = arr;
o[config_key::defaultContainer] = "amnezia-openvpn";
o[config_key::description] = m_settings->nextAvailableServerName();
const static QRegularExpression dnsRegExp("dhcp-option DNS (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
QRegularExpressionMatchIterator dnsMatch = dnsRegExp.globalMatch(config);
if (dnsMatch.hasNext()) {
o[config_key::dns1] = dnsMatch.next().captured(1);
}
if (dnsMatch.hasNext()) {
o[config_key::dns2] = dnsMatch.next().captured(1);
}
o[config_key::hostName] = hostName;
return importConnection(o);
}
bool StartPageLogic::importConnectionFromWireguardConfig(const QString &config)
{
QJsonObject lastConfig;
lastConfig[config_key::config] = config;
const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*):([0-9]*)");
QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(config);
QString hostName;
QString port;
if (hostNameAndPortMatch.hasMatch()) {
hostName = hostNameAndPortMatch.captured(1);
port = hostNameAndPortMatch.captured(2);
}
QJsonObject wireguardConfig;
wireguardConfig[config_key::last_config] = QString(QJsonDocument(lastConfig).toJson());
wireguardConfig[config_key::isThirdPartyConfig] = true;
wireguardConfig[config_key::port] = port;
wireguardConfig[config_key::transport_proto] = "udp";
QJsonObject containers;
containers.insert(config_key::container, QJsonValue("amnezia-wireguard"));
containers.insert(config_key::wireguard, QJsonValue(wireguardConfig));
QJsonArray arr;
arr.push_back(containers);
QJsonObject o;
o[config_key::containers] = arr;
o[config_key::defaultContainer] = "amnezia-wireguard";
o[config_key::description] = m_settings->nextAvailableServerName();
const static QRegularExpression dnsRegExp("DNS = (\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b).*(\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b)");
QRegularExpressionMatch dnsMatch = dnsRegExp.match(config);
if (dnsMatch.hasMatch()) {
o[config_key::dns1] = dnsMatch.captured(1);
o[config_key::dns2] = dnsMatch.captured(2);
}
o[config_key::hostName] = hostName;
return importConnection(o);
}

View file

@ -32,6 +32,8 @@ public:
bool importConnection(const QJsonObject &profile);
bool importConnectionFromCode(QString code);
bool importConnectionFromQr(const QByteArray &data);
bool importConnectionFromOpenVpnConfig(const QString &config);
bool importConnectionFromWireguardConfig(const QString &config);
public:
explicit StartPageLogic(UiLogic *uiLogic, QObject *parent = nullptr);

View file

@ -13,6 +13,8 @@ void ViewConfigLogic::onUpdatePage()
{
set_configText(QJsonDocument(configJson()).toJson());
auto s = configJson()[config_key::isThirdPartyConfig].toBool();
m_openVpnLastConfigs = m_openVpnMalStrings =
"<style> \
div { line-height: 0.5; } \
@ -24,28 +26,42 @@ void ViewConfigLogic::onUpdatePage()
const QJsonArray &containers = configJson()[config_key::containers].toArray();
int i = 0;
for (const QJsonValue &v: containers) {
QString cfg_json = v.toObject()[ProtocolProps::protoToString(Proto::OpenVpn)]
.toObject()[config_key::last_config].toString();
QString openvpn_cfg = QJsonDocument::fromJson(cfg_json.toUtf8()).object()[config_key::config]
.toString();
openvpn_cfg.replace("\r", "");
QStringList lines = openvpn_cfg.split("\n");
for (const QString &l: lines) {
i++;
QRegularExpressionMatch match = m_re.match(l);
if (dangerousTags.contains(match.captured(0))) {
QString t = QString("<p><font color=\"red\">%1</font>").arg(l);
m_openVpnLastConfigs.append(t + "\n");
m_openVpnMalStrings.append(t);
if (m_warningStringNumber == 3) m_warningStringNumber = i - 3;
m_warningActive = true;
qDebug() << "ViewConfigLogic : malicious scripts warning:" << l;
auto containerName = v.toObject()[config_key::container].toString();
QJsonObject containerConfig = v.toObject()[containerName.replace("amnezia-", "")].toObject();
if (containerConfig[config_key::isThirdPartyConfig].toBool()) {
auto lastConfig = containerConfig.value(config_key::last_config).toString();
auto lastConfigJson = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n");
QString lastConfigText;
for (const QString &l: lines) {
lastConfigText.append(l + "\n");
}
else {
m_openVpnLastConfigs.append("<p>" + l + "&nbsp;\n");
set_configText(lastConfigText);
}
if (v.toObject()[config_key::container].toString() == "amnezia-openvpn") {
QString lastConfig = v.toObject()[ProtocolProps::protoToString(Proto::OpenVpn)]
.toObject()[config_key::last_config].toString();
QString lastConfigJson = QJsonDocument::fromJson(lastConfig.toUtf8()).object()[config_key::config]
.toString();
QStringList lines = lastConfigJson.replace("\r", "").split("\n");
for (const QString &l: lines) {
i++;
QRegularExpressionMatch match = m_re.match(l);
if (dangerousTags.contains(match.captured(0))) {
QString t = QString("<p><font color=\"red\">%1</font>").arg(l);
m_openVpnLastConfigs.append(t + "\n");
m_openVpnMalStrings.append(t);
if (m_warningStringNumber == 3) m_warningStringNumber = i - 3;
m_warningActive = true;
qDebug() << "ViewConfigLogic : malicious scripts warning:" << l;
}
else {
m_openVpnLastConfigs.append("<p>" + l + "&nbsp;\n");
}
}
}
}

View file

@ -28,7 +28,7 @@ public:
explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~CloakLogic() = default;
void updateProtocolPage (const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData) override;
void updateProtocolPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData) override;
QJsonObject getProtocolConfigFromPage(QJsonObject oldConfig) override;
private:

View file

@ -87,6 +87,17 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo
toString(protocols::openvpn::defaultPort));
set_lineEditPortEnabled(container == DockerContainer::OpenVpn);
auto lastConfig = openvpnConfig.value(config_key::last_config).toString();
auto lastConfigJson = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n");
QString openVpnLastConfigText;
for (const QString &l: lines) {
openVpnLastConfigText.append(l + "\n");
}
set_openVpnLastConfigText(openVpnLastConfigText);
set_isThirdPartyConfig(openvpnConfig.value(config_key::isThirdPartyConfig).isBool());
}
void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked()

View file

@ -35,6 +35,9 @@ class OpenVpnLogic : public PageProtocolLogicBase
AUTO_PROPERTY(int, progressBarResetValue)
AUTO_PROPERTY(int, progressBarResetMaximium)
AUTO_PROPERTY(QString, openVpnLastConfigText)
AUTO_PROPERTY(bool, isThirdPartyConfig)
public:
Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked();

View file

@ -0,0 +1,30 @@
#include "WireGuardLogic.h"
#include "core/servercontroller.h"
#include <functional>
#include "../../uilogic.h"
using namespace amnezia;
using namespace PageEnumNS;
WireGuardLogic::WireGuardLogic(UiLogic *logic, QObject *parent):
PageProtocolLogicBase(logic, parent)
{
}
void WireGuardLogic::updateProtocolPage(const QJsonObject &wireGuardConfig, DockerContainer container, bool haveAuthData)
{
qDebug() << "WireGuardLogic::updateProtocolPage";
auto lastConfigJsonDoc = QJsonDocument::fromJson(wireGuardConfig.value(config_key::last_config).toString().toUtf8());
auto lastConfigJson = lastConfigJsonDoc.object();
QString wireGuardLastConfigText;
QStringList lines = lastConfigJson.value(config_key::config).toString().replace("\r", "").split("\n");
for (const QString &l: lines) {
wireGuardLastConfigText.append(l + "\n");
}
set_wireGuardLastConfigText(wireGuardLastConfigText);
set_isThirdPartyConfig(wireGuardConfig.value(config_key::isThirdPartyConfig).toBool());
}

View file

@ -0,0 +1,26 @@
#ifndef WIREGUARDLOGIC_H
#define WIREGUARDLOGIC_H
#include "PageProtocolLogicBase.h"
class UiLogic;
class WireGuardLogic : public PageProtocolLogicBase
{
Q_OBJECT
AUTO_PROPERTY(QString, wireGuardLastConfigText)
AUTO_PROPERTY(bool, isThirdPartyConfig)
public:
explicit WireGuardLogic(UiLogic *uiLogic, QObject *parent = nullptr);
~WireGuardLogic() = default;
void updateProtocolPage(const QJsonObject &wireGuardConfig, DockerContainer container, bool haveAuthData) override;
private:
UiLogic *m_uiLogic;
};
#endif // WIREGUARDLOGIC_H

View file

@ -32,6 +32,7 @@ PageBase {
BackButton {
id: back
onClicked: tb_c.currentIndex = -1
}
Caption {
id: caption
@ -288,7 +289,7 @@ PageBase {
ImageButtonType {
id: button_remove
visible: index === tb_c.currentIndex
visible: (index === tb_c.currentIndex) && ServerContainersLogic.isManagedServer
Layout.alignment: Qt.AlignRight
checkable: true
icon.source: "qrc:/images/delete.png"
@ -315,7 +316,7 @@ PageBase {
ImageButtonType {
id: button_share
visible: index === tb_c.currentIndex
visible: (index === tb_c.currentIndex) && ServerContainersLogic.isManagedServer
Layout.alignment: Qt.AlignRight
icon.source: "qrc:/images/share.png"
implicitWidth: 30

View file

@ -93,14 +93,14 @@ PageBase {
id: label_address
x: 20
y: 40
width: 141
width: listWidget_servers.width - 100
height: 16
text: address
}
Text {
x: 10
y: 10
width: 181
width: listWidget_servers.width - 100
height: 21
font.family: "Lato"
font.styleName: "normal"

View file

@ -26,369 +26,391 @@ PageProtocolBase {
ColumnLayout {
id: content
enabled: logic.pageEnabled
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 15
anchors.rightMargin: GC.defaultMargin - 1
LabelType {
id: lb_subnet
height: 21
text: qsTr("VPN Addresses Subnet")
}
TextFieldType {
id: tf_subnet
ColumnLayout {
visible: !logic.isThirdPartyConfig
enabled: logic.pageEnabled
implicitWidth: parent.width
height: 31
text: logic.lineEditSubnetText
onEditingFinished: {
logic.lineEditSubnetText = text
}
}
//
LabelType {
id: lb_proto
Layout.topMargin: 20
height: 21
text: qsTr("Network protocol")
}
Rectangle {
id: rect_proto
implicitWidth: parent.width
height: 71
border.width: 1
border.color: "lightgray"
radius: 2
RadioButtonType {
x: 10
y: 40
width: parent.width
height: 19
text: qsTr("TCP")
enabled: logic.radioButtonTcpEnabled
checked: logic.radioButtonTcpChecked
onCheckedChanged: {
UiLogic.radioButtonTcpChecked = checked
}
}
RadioButtonType {
x: 10
y: 10
width: parent.width
height: 19
text: qsTr("UDP")
checked: logic.radioButtonUdpChecked
onCheckedChanged: {
logic.radioButtonUdpChecked = checked
}
enabled: logic.radioButtonUdpEnabled
}
}
//
RowLayout {
Layout.topMargin: 10
implicitWidth: parent.width
LabelType {
id: lb_port
height: 31
text: qsTr("Port")
Layout.preferredWidth: content.width / 2 - 5
id: lb_subnet
height: 21
text: qsTr("VPN Addresses Subnet")
}
TextFieldType {
id: tf_port
Layout.preferredWidth: content.width / 2 - 5
Layout.alignment: Qt.AlignRight
id: tf_subnet
implicitWidth: parent.width
height: 31
text: logic.lineEditSubnetText
onEditingFinished: {
logic.lineEditSubnetText = text
}
}
//
LabelType {
id: lb_proto
Layout.topMargin: 20
height: 21
text: qsTr("Network protocol")
}
Rectangle {
id: rect_proto
implicitWidth: parent.width
height: 71
border.width: 1
border.color: "lightgray"
radius: 2
RadioButtonType {
x: 10
y: 40
width: 171
height: 19
text: qsTr("TCP")
enabled: logic.radioButtonTcpEnabled
checked: logic.radioButtonTcpChecked
onCheckedChanged: {
logic.radioButtonTcpChecked = checked
}
}
RadioButtonType {
x: 10
y: 10
width: 171
height: 19
text: qsTr("UDP")
checked: logic.radioButtonUdpChecked
onCheckedChanged: {
logic.radioButtonUdpChecked = checked
}
enabled: logic.radioButtonUdpEnabled
}
}
//
RowLayout {
Layout.topMargin: 10
Layout.fillWidth: true
LabelType {
id: lb_port
height: 31
text: qsTr("Port")
Layout.preferredWidth: root.width / 2 - 10
}
TextFieldType {
id: tf_port
Layout.fillWidth: true
height: 31
text: logic.lineEditPortText
onEditingFinished: {
logic.lineEditPortText = text
}
enabled: logic.lineEditPortEnabled
}
}
//
CheckBoxType {
id: check_auto_enc
implicitWidth: parent.width
height: 21
text: qsTr("Auto-negotiate encryption")
checked: logic.checkBoxAutoEncryptionChecked
onCheckedChanged: {
logic.checkBoxAutoEncryptionChecked = checked
}
onClicked: {
logic.checkBoxAutoEncryptionClicked()
}
}
//
LabelType {
id: lb_cipher
height: 21
text: qsTr("Cipher")
}
ComboBoxType {
id: cb_cipher
implicitWidth: parent.width
height: 31
text: logic.lineEditPortText
onEditingFinished: {
logic.lineEditPortText = text
}
enabled: logic.lineEditPortEnabled
}
}
//
CheckBoxType {
id: check_auto_enc
implicitWidth: parent.width
height: 21
text: qsTr("Auto-negotiate encryption")
checked: logic.checkBoxAutoEncryptionChecked
onCheckedChanged: {
logic.checkBoxAutoEncryptionChecked = checked
}
onClicked: {
logic.checkBoxAutoEncryptionClicked()
}
}
//
LabelType {
id: lb_cipher
height: 21
text: qsTr("Cipher")
}
ComboBoxType {
id: cb_cipher
implicitWidth: parent.width
height: 31
model: [
qsTr("AES-256-GCM"),
qsTr("AES-192-GCM"),
qsTr("AES-128-GCM"),
qsTr("AES-256-CBC"),
qsTr("AES-192-CBC"),
qsTr("AES-128-CBC"),
qsTr("ChaCha20-Poly1305"),
qsTr("ARIA-256-CBC"),
qsTr("CAMELLIA-256-CBC"),
qsTr("none")
]
currentIndex: {
for (let i = 0; i < model.length; ++i) {
if (logic.comboBoxVpnCipherText === model[i]) {
return i
model: [
qsTr("AES-256-GCM"),
qsTr("AES-192-GCM"),
qsTr("AES-128-GCM"),
qsTr("AES-256-CBC"),
qsTr("AES-192-CBC"),
qsTr("AES-128-CBC"),
qsTr("ChaCha20-Poly1305"),
qsTr("ARIA-256-CBC"),
qsTr("CAMELLIA-256-CBC"),
qsTr("none")
]
currentIndex: {
for (let i = 0; i < model.length; ++i) {
if (logic.comboBoxVpnCipherText === model[i]) {
return i
}
}
return -1
}
return -1
onCurrentTextChanged: {
logic.comboBoxVpnCipherText = currentText
}
enabled: !check_auto_enc.checked
}
onCurrentTextChanged: {
logic.comboBoxVpnCipherText = currentText
}
enabled: !check_auto_enc.checked
}
//
LabelType {
id: lb_hash
height: 21
Layout.topMargin: 20
text: qsTr("Hash")
}
ComboBoxType {
id: cb_hash
height: 31
implicitWidth: parent.width
model: [
qsTr("SHA512"),
qsTr("SHA384"),
qsTr("SHA256"),
qsTr("SHA3-512"),
qsTr("SHA3-384"),
qsTr("SHA3-256"),
qsTr("whirlpool"),
qsTr("BLAKE2b512"),
qsTr("BLAKE2s256"),
qsTr("SHA1")
]
currentIndex: {
for (let i = 0; i < model.length; ++i) {
if (logic.comboBoxVpnHashText === model[i]) {
return i
//
LabelType {
id: lb_hash
height: 21
Layout.topMargin: 20
text: qsTr("Hash")
}
ComboBoxType {
id: cb_hash
height: 31
implicitWidth: parent.width
model: [
qsTr("SHA512"),
qsTr("SHA384"),
qsTr("SHA256"),
qsTr("SHA3-512"),
qsTr("SHA3-384"),
qsTr("SHA3-256"),
qsTr("whirlpool"),
qsTr("BLAKE2b512"),
qsTr("BLAKE2s256"),
qsTr("SHA1")
]
currentIndex: {
for (let i = 0; i < model.length; ++i) {
if (logic.comboBoxVpnHashText === model[i]) {
return i
}
}
return -1
}
return -1
}
onCurrentTextChanged: {
logic.comboBoxVpnHashText = currentText
}
enabled: !check_auto_enc.checked
}
CheckBoxType {
id: check_tls
implicitWidth: parent.width
Layout.topMargin: 20
height: 21
text: qsTr("Enable TLS auth")
checked: logic.checkBoxTlsAuthChecked
onCheckedChanged: {
logic.checkBoxTlsAuthChecked = checked
onCurrentTextChanged: {
logic.comboBoxVpnHashText = currentText
}
enabled: !check_auto_enc.checked
}
}
CheckBoxType {
id: check_tls
implicitWidth: parent.width
Layout.topMargin: 20
height: 21
text: qsTr("Enable TLS auth")
checked: logic.checkBoxTlsAuthChecked
onCheckedChanged: {
logic.checkBoxTlsAuthChecked = checked
}
CheckBoxType {
id: check_block_dns
implicitWidth: parent.width
height: 21
text: qsTr("Block DNS requests outside of VPN")
checked: logic.checkBoxBlockDnsChecked
onCheckedChanged: {
logic.checkBoxBlockDnsChecked = checked
}
}
BasicButtonType {
id: pb_client_config
implicitWidth: parent.width
height: 21
text: qsTr("Additional client config commands →")
background: Item {
anchors.fill: parent
}
contentItem: Text {
anchors.fill: parent
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#15CDCB";
text: pb_client_config.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
CheckBoxType {
id: check_block_dns
implicitWidth: parent.width
height: 21
text: qsTr("Block DNS requests outside of VPN")
checked: logic.checkBoxBlockDnsChecked
onCheckedChanged: {
logic.checkBoxBlockDnsChecked = checked
}
}
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
}
Rectangle {
id: rect_client_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_client_config.checked
ScrollView {
anchors.fill: parent
TextArea {
id: te_client_config
BasicButtonType {
id: pb_client_config
implicitWidth: parent.width
height: 21
text: qsTr("Additional client config commands →")
background: Item {
anchors.fill: parent
}
contentItem: Text {
anchors.fill: parent
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
text: logic.textAreaAdditionalClientConfig
onEditingFinished: {
logic.textAreaAdditionalClientConfig = text
color: "#15CDCB";
text: pb_client_config.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
}
Rectangle {
id: rect_client_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_client_config.checked
ScrollView {
anchors.fill: parent
TextArea {
id: te_client_config
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
text: logic.textAreaAdditionalClientConfig
onEditingFinished: {
logic.textAreaAdditionalClientConfig = text
}
}
}
}
}
BasicButtonType {
id: pb_server_config
implicitWidth: parent.width
height: 21
text: qsTr("Additional server config commands →")
background: Item {
anchors.fill: parent
}
BasicButtonType {
id: pb_server_config
implicitWidth: parent.width
height: 21
text: qsTr("Additional server config commands →")
background: Item {
anchors.fill: parent
}
contentItem: Text {
anchors.fill: parent
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#15CDCB";
text: pb_server_config.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
}
Rectangle {
id: rect_server_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_server_config.checked
ScrollView {
anchors.fill: parent
TextArea {
id: te_server_config
contentItem: Text {
anchors.fill: parent
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
text: logic.textAreaAdditionalServerConfig
onEditingFinished: {
logic.textAreaAdditionalServerConfig = text
}
color: "#15CDCB";
text: pb_server_config.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
antialiasing: true
checkable: true
checked: StartPageLogic.pushButtonConnectKeyChecked
}
Rectangle {
id: rect_server_conf
implicitWidth: root.width - 60
height: 101
border.width: 1
border.color: "lightgray"
radius: 2
visible: pb_server_config.checked
}
ScrollView {
anchors.fill: parent
TextArea {
id: te_server_config
font.family: "Lato"
font.styleName: "normal"
font.pixelSize: 16
color: "#181922"
text: logic.textAreaAdditionalServerConfig
onEditingFinished: {
logic.textAreaAdditionalServerConfig = text
}
}
}
LabelType {
id: label_proto_openvpn_info
height: 41
visible: logic.labelProtoOpenVpnInfoVisible
text: logic.labelProtoOpenVpnInfoText
}
}
Rectangle {
id: it_save
implicitWidth: parent.width
Layout.topMargin: 20
height: 40
LabelType {
id: label_proto_openvpn_info
BlueButtonType {
id: pb_save
z: 1
height: 41
visible: logic.labelProtoOpenVpnInfoVisible
text: logic.labelProtoOpenVpnInfoText
}
Rectangle {
id: it_save
implicitWidth: parent.width
Layout.topMargin: 20
height: 40
text: qsTr("Save and restart VPN")
width: parent.width
visible: logic.pushButtonSaveVisible
onClicked: {
logic.onPushButtonProtoOpenVpnSaveClicked()
}
}
ProgressBar {
id: progress_save
anchors.fill: pb_save
from: 0
to: logic.progressBarResetMaximium
value: logic.progressBarResetValue
visible: logic.progressBarResetVisible
background: Rectangle {
implicitWidth: parent.width
implicitHeight: parent.height
color: "#100A44"
radius: 4
}
contentItem: Item {
implicitWidth: parent.width
implicitHeight: parent.height
Rectangle {
width: progress_save.visualPosition * parent.width
height: parent.height
radius: 4
color: Qt.rgba(255, 255, 255, 0.15);
BlueButtonType {
id: pb_save
z: 1
height: 40
text: qsTr("Save and restart VPN")
width: parent.width
visible: logic.pushButtonSaveVisible
onClicked: {
logic.onPushButtonProtoOpenVpnSaveClicked()
}
}
ProgressBar {
id: progress_save
anchors.fill: pb_save
from: 0
to: logic.progressBarResetMaximium
value: logic.progressBarResetValue
visible: logic.progressBarResetVisible
background: Rectangle {
implicitWidth: parent.width
implicitHeight: parent.height
color: "#100A44"
radius: 4
}
contentItem: Item {
implicitWidth: parent.width
implicitHeight: parent.height
Rectangle {
width: progress_save.visualPosition * parent.width
height: parent.height
radius: 4
color: Qt.rgba(255, 255, 255, 0.15);
}
}
}
}
}
}
ColumnLayout {
visible: logic.isThirdPartyConfig
TextAreaType {
id: ta_config
Layout.topMargin: 5
Layout.bottomMargin: 20
Layout.fillWidth: true
Layout.leftMargin: 1
Layout.rightMargin: 1
Layout.preferredHeight: fl.height - 70
flickableDirection: Flickable.AutoFlickIfNeeded
textArea.readOnly: true
textArea.text: logic.openVpnLastConfigText
}
}
}
}
}

View file

@ -0,0 +1,60 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.15
import ProtocolEnum 1.0
import "../"
import "../../Controls"
import "../../Config"
PageProtocolBase {
id: root
protocol: ProtocolEnum.WireGuard
logic: UiLogic.protocolLogic(protocol)
BackButton {
id: back
}
Caption {
id: caption
text: qsTr("WireGuard Settings")
}
Flickable {
id: fl
width: root.width
anchors.top: caption.bottom
anchors.topMargin: 20
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
anchors.left: root.left
anchors.leftMargin: 30
anchors.right: root.right
anchors.rightMargin: 30
contentHeight: content.height
clip: true
ColumnLayout {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
TextAreaType {
id: ta_config
Layout.topMargin: 5
Layout.bottomMargin: 20
Layout.fillWidth: true
Layout.leftMargin: 1
Layout.rightMargin: 1
Layout.preferredHeight: fl.height - 70
flickableDirection: Flickable.AutoFlickIfNeeded
textArea.readOnly: true
textArea.text: logic.wireGuardLastConfigText
}
}
}
}

View file

@ -71,7 +71,7 @@
#include "pages_logic/protocols/OpenVpnLogic.h"
#include "pages_logic/protocols/ShadowSocksLogic.h"
#include "pages_logic/protocols/OtherProtocolsLogic.h"
#include "pages_logic/protocols/WireGuardLogic.h"
using namespace amnezia;
using namespace PageEnumNS;
@ -94,7 +94,7 @@ UiLogic::UiLogic(std::shared_ptr<Settings> settings, std::shared_ptr<VpnConfigur
m_protocolLogicMap.insert(Proto::OpenVpn, new OpenVpnLogic(this));
m_protocolLogicMap.insert(Proto::ShadowSocks, new ShadowSocksLogic(this));
m_protocolLogicMap.insert(Proto::Cloak, new CloakLogic(this));
//m_protocolLogicMap->insert(Proto::WireGuard, new WireguardLogic(this));
m_protocolLogicMap.insert(Proto::WireGuard, new WireGuardLogic(this));
m_protocolLogicMap.insert(Proto::Dns, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Proto::Sftp, new OtherProtocolsLogic(this));