Merge branch 'dev' into feature/custom_drawer_component
This commit is contained in:
commit
023c3474d2
96 changed files with 3897 additions and 1733 deletions
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -1,6 +1,3 @@
|
|||
[submodule "client/3rd/wireguard-apple"]
|
||||
path = client/3rd/wireguard-apple
|
||||
url = https://github.com/WireGuard/wireguard-apple
|
||||
[submodule "client/3rd/OpenVPNAdapter"]
|
||||
path = client/3rd/OpenVPNAdapter
|
||||
url = https://github.com/amnezia-vpn/OpenVPNAdapter.git
|
||||
|
@ -25,3 +22,6 @@
|
|||
[submodule "client/3rd-prebuilt"]
|
||||
path = client/3rd-prebuilt
|
||||
url = https://github.com/amnezia-vpn/3rd-prebuilt
|
||||
[submodule "client/3rd/awg-apple"]
|
||||
path = client/3rd/awg-apple
|
||||
url = https://github.com/amnezia-vpn/awg-apple
|
||||
|
|
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
|||
|
||||
set(PROJECT AmneziaVPN)
|
||||
|
||||
project(${PROJECT} VERSION 4.0.8.1
|
||||
project(${PROJECT} VERSION 4.0.8.5
|
||||
DESCRIPTION "AmneziaVPN"
|
||||
HOMEPAGE_URL "https://amnezia.org/"
|
||||
)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit e8795854a5cf27004fe78caecc90a961688d1d41
|
||||
Subproject commit ac32d33555bd62f0b0af314b1e5119d6d78a1a4e
|
1
client/3rd/awg-apple
vendored
Submodule
1
client/3rd/awg-apple
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit fab07138dbab06ac0de256021e47e273f4df8e88
|
1
client/3rd/wireguard-apple
vendored
1
client/3rd/wireguard-apple
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 23618f994f17d8ad8f2f65d79b4a1e8a0830b334
|
|
@ -74,7 +74,6 @@ qt6_add_resources(QRC ${I18NQRC} ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
|
|||
# -- i18n end
|
||||
|
||||
if(IOS)
|
||||
#execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/scripts/run-build-cloak.sh)
|
||||
execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/ios/scripts/openvpn.sh args
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
|
||||
endif()
|
||||
|
@ -282,6 +281,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
|||
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.h
|
||||
)
|
||||
|
||||
set(SOURCES ${SOURCES}
|
||||
|
@ -292,6 +292,7 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
|||
${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -286,6 +286,8 @@ void AmneziaApplication::initModels()
|
|||
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
|
||||
connect(m_serversModel.get(), &ServersModel::currentlyProcessedServerIndexChanged, m_containersModel.get(),
|
||||
&ContainersModel::setCurrentlyProcessedServerIndex);
|
||||
connect(m_serversModel.get(), &ServersModel::defaultServerIndexChanged, m_containersModel.get(),
|
||||
&ContainersModel::setCurrentlyProcessedServerIndex);
|
||||
|
||||
m_languageModel.reset(new LanguageModel(m_settings, this));
|
||||
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
|
||||
|
@ -315,8 +317,11 @@ void AmneziaApplication::initModels()
|
|||
m_cloakConfigModel.reset(new CloakConfigModel(this));
|
||||
m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get());
|
||||
|
||||
m_wireguardConfigModel.reset(new WireGuardConfigModel(this));
|
||||
m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireguardConfigModel.get());
|
||||
m_wireGuardConfigModel.reset(new WireGuardConfigModel(this));
|
||||
m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireGuardConfigModel.get());
|
||||
|
||||
m_awgConfigModel.reset(new AwgConfigModel(this));
|
||||
m_engine->rootContext()->setContextProperty("AwgConfigModel", m_awgConfigModel.get());
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#ifdef Q_OS_WINDOWS
|
||||
#include "ui/models/protocols/ikev2ConfigModel.h"
|
||||
#endif
|
||||
#include "ui/models/protocols/awgConfigModel.h"
|
||||
#include "ui/models/protocols/openvpnConfigModel.h"
|
||||
#include "ui/models/protocols/shadowsocksConfigModel.h"
|
||||
#include "ui/models/protocols/wireguardConfigModel.h"
|
||||
|
@ -97,7 +98,8 @@ private:
|
|||
QScopedPointer<OpenVpnConfigModel> m_openVpnConfigModel;
|
||||
QScopedPointer<ShadowSocksConfigModel> m_shadowSocksConfigModel;
|
||||
QScopedPointer<CloakConfigModel> m_cloakConfigModel;
|
||||
QScopedPointer<WireGuardConfigModel> m_wireguardConfigModel;
|
||||
QScopedPointer<WireGuardConfigModel> m_wireGuardConfigModel;
|
||||
QScopedPointer<AwgConfigModel> m_awgConfigModel;
|
||||
#ifdef Q_OS_WINDOWS
|
||||
QScopedPointer<Ikev2ConfigModel> m_ikev2ConfigModel;
|
||||
#endif
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
android:label="-- %%INSERT_APP_NAME%% --"
|
||||
android:screenOrientation="unspecified"
|
||||
android:launchMode="singleInstance"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="true">
|
||||
|
||||
<!-- android:theme="@style/splashScreenTheme"-->
|
||||
|
|
|
@ -138,8 +138,8 @@ android {
|
|||
resConfig "en"
|
||||
minSdkVersion = 24
|
||||
targetSdkVersion = 34
|
||||
versionCode 32 // Change to a higher number
|
||||
versionName "3.0.9" // Change to a higher number
|
||||
versionCode 37 // Change to a higher number
|
||||
versionName "4.0.8" // Change to a higher number
|
||||
|
||||
javaCompileOptions.annotationProcessorOptions.arguments = [
|
||||
"room.schemaLocation": "${qtAndroidDir}/schemas".toString()
|
||||
|
|
|
@ -70,6 +70,15 @@ public class BadConfigException extends Exception {
|
|||
EXCLUDED_APPLICATIONS("ExcludedApplications"),
|
||||
INCLUDED_APPLICATIONS("IncludedApplications"),
|
||||
LISTEN_PORT("ListenPort"),
|
||||
JC("Jc"),
|
||||
JMIN("Jmin"),
|
||||
JMAX("Jmax"),
|
||||
S1("S1"),
|
||||
S2("S2"),
|
||||
H1("H1"),
|
||||
H2("H2"),
|
||||
H3("H3"),
|
||||
H4("H4"),
|
||||
MTU("MTU"),
|
||||
PERSISTENT_KEEPALIVE("PersistentKeepalive"),
|
||||
PRE_SHARED_KEY("PresharedKey"),
|
||||
|
|
|
@ -44,6 +44,15 @@ public final class Interface {
|
|||
private final KeyPair keyPair;
|
||||
private final Optional<Integer> listenPort;
|
||||
private final Optional<Integer> mtu;
|
||||
private final Optional<Integer> jc;
|
||||
private final Optional<Integer> jmin;
|
||||
private final Optional<Integer> jmax;
|
||||
private final Optional<Integer> s1;
|
||||
private final Optional<Integer> s2;
|
||||
private final Optional<Long> h1;
|
||||
private final Optional<Long> h2;
|
||||
private final Optional<Long> h3;
|
||||
private final Optional<Long> h4;
|
||||
|
||||
private Interface(final Builder builder) {
|
||||
// Defensively copy to ensure immutability even if the Builder is reused.
|
||||
|
@ -56,6 +65,15 @@ public final class Interface {
|
|||
keyPair = Objects.requireNonNull(builder.keyPair, "Interfaces must have a private key");
|
||||
listenPort = builder.listenPort;
|
||||
mtu = builder.mtu;
|
||||
jc = builder.jc;
|
||||
jmax = builder.jmax;
|
||||
jmin = builder.jmin;
|
||||
s1 = builder.s1;
|
||||
s2 = builder.s2;
|
||||
h1 = builder.h1;
|
||||
h2 = builder.h2;
|
||||
h3 = builder.h3;
|
||||
h4 = builder.h4;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,6 +113,33 @@ public final class Interface {
|
|||
case "privatekey":
|
||||
builder.parsePrivateKey(attribute.getValue());
|
||||
break;
|
||||
case "jc":
|
||||
builder.parseJc(attribute.getValue());
|
||||
break;
|
||||
case "jmin":
|
||||
builder.parseJmin(attribute.getValue());
|
||||
break;
|
||||
case "jmax":
|
||||
builder.parseJmax(attribute.getValue());
|
||||
break;
|
||||
case "s1":
|
||||
builder.parseS1(attribute.getValue());
|
||||
break;
|
||||
case "s2":
|
||||
builder.parseS2(attribute.getValue());
|
||||
break;
|
||||
case "h1":
|
||||
builder.parseH1(attribute.getValue());
|
||||
break;
|
||||
case "h2":
|
||||
builder.parseH2(attribute.getValue());
|
||||
break;
|
||||
case "h3":
|
||||
builder.parseH3(attribute.getValue());
|
||||
break;
|
||||
case "h4":
|
||||
builder.parseH4(attribute.getValue());
|
||||
break;
|
||||
default:
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.TOP_LEVEL, Reason.UNKNOWN_ATTRIBUTE, attribute.getKey());
|
||||
|
@ -111,7 +156,9 @@ public final class Interface {
|
|||
return addresses.equals(other.addresses) && dnsServers.equals(other.dnsServers)
|
||||
&& excludedApplications.equals(other.excludedApplications)
|
||||
&& includedApplications.equals(other.includedApplications) && keyPair.equals(other.keyPair)
|
||||
&& listenPort.equals(other.listenPort) && mtu.equals(other.mtu);
|
||||
&& listenPort.equals(other.listenPort) && mtu.equals(other.mtu) && jc.equals(other.jc) && jmin.equals(other.jmin)
|
||||
&& jmax.equals(other.jmax) && s1.equals(other.s1) && s2.equals(other.s2) && h1.equals(other.h1) && h2.equals(other.h2)
|
||||
&& h3.equals(other.h3) && h4.equals(other.h4);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,6 +228,42 @@ public final class Interface {
|
|||
return mtu;
|
||||
}
|
||||
|
||||
public Optional<Integer> getJc() {
|
||||
return jc;
|
||||
}
|
||||
|
||||
public Optional<Integer> getJmin() {
|
||||
return jmin;
|
||||
}
|
||||
|
||||
public Optional<Integer> getJmax() {
|
||||
return jmax;
|
||||
}
|
||||
|
||||
public Optional<Integer> getS1() {
|
||||
return s1;
|
||||
}
|
||||
|
||||
public Optional<Integer> getS2() {
|
||||
return s2;
|
||||
}
|
||||
|
||||
public Optional<Long> getH1() {
|
||||
return h1;
|
||||
}
|
||||
|
||||
public Optional<Long> getH2() {
|
||||
return h2;
|
||||
}
|
||||
|
||||
public Optional<Long> getH3() {
|
||||
return h3;
|
||||
}
|
||||
|
||||
public Optional<Long> getH4() {
|
||||
return h4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 1;
|
||||
|
@ -191,6 +274,15 @@ public final class Interface {
|
|||
hash = 31 * hash + keyPair.hashCode();
|
||||
hash = 31 * hash + listenPort.hashCode();
|
||||
hash = 31 * hash + mtu.hashCode();
|
||||
hash = 31 * hash + jc.hashCode();
|
||||
hash = 31 * hash + jmin.hashCode();
|
||||
hash = 31 * hash + jmax.hashCode();
|
||||
hash = 31 * hash + s1.hashCode();
|
||||
hash = 31 * hash + s2.hashCode();
|
||||
hash = 31 * hash + h1.hashCode();
|
||||
hash = 31 * hash + h2.hashCode();
|
||||
hash = 31 * hash + h3.hashCode();
|
||||
hash = 31 * hash + h4.hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
@ -234,6 +326,19 @@ public final class Interface {
|
|||
.append('\n');
|
||||
listenPort.ifPresent(lp -> sb.append("ListenPort = ").append(lp).append('\n'));
|
||||
mtu.ifPresent(m -> sb.append("MTU = ").append(m).append('\n'));
|
||||
|
||||
jc.ifPresent(t_jc -> sb.append("Jc = ").append(t_jc).append('\n'));
|
||||
jmin.ifPresent(t_jmin -> sb.append("Jmin = ").append(t_jmin).append('\n'));
|
||||
jmax.ifPresent(t_jmax -> sb.append("Jmax = ").append(t_jmax).append('\n'));
|
||||
|
||||
s1.ifPresent(t_s1 -> sb.append("S1 = ").append(t_s1).append('\n'));
|
||||
s2.ifPresent(t_s2 -> sb.append("S2 = ").append(t_s2).append('\n'));
|
||||
|
||||
h1.ifPresent(t_h1 -> sb.append("H1 = ").append(t_h1).append('\n'));
|
||||
h2.ifPresent(t_h2 -> sb.append("H2 = ").append(t_h2).append('\n'));
|
||||
h3.ifPresent(t_h3 -> sb.append("H3 = ").append(t_h3).append('\n'));
|
||||
h4.ifPresent(t_h4 -> sb.append("H4 = ").append(t_h4).append('\n'));
|
||||
|
||||
sb.append("PrivateKey = ").append(keyPair.getPrivateKey().toBase64()).append('\n');
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -248,6 +353,18 @@ public final class Interface {
|
|||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("private_key=").append(keyPair.getPrivateKey().toHex()).append('\n');
|
||||
listenPort.ifPresent(lp -> sb.append("listen_port=").append(lp).append('\n'));
|
||||
|
||||
jc.ifPresent(t_jc -> sb.append("jc=").append(t_jc).append('\n'));
|
||||
jmin.ifPresent(t_jmin -> sb.append("jmin=").append(t_jmin).append('\n'));
|
||||
jmax.ifPresent(t_jmax -> sb.append("jmax=").append(t_jmax).append('\n'));
|
||||
|
||||
s1.ifPresent(t_s1 -> sb.append("s1=").append(t_s1).append('\n'));
|
||||
s2.ifPresent(t_s2 -> sb.append("s2=").append(t_s2).append('\n'));
|
||||
|
||||
h1.ifPresent(t_h1 -> sb.append("h1=").append(t_h1).append('\n'));
|
||||
h2.ifPresent(t_h2 -> sb.append("h2=").append(t_h2).append('\n'));
|
||||
h3.ifPresent(t_h3 -> sb.append("h3=").append(t_h3).append('\n'));
|
||||
h4.ifPresent(t_h4 -> sb.append("h4=").append(t_h4).append('\n'));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
@ -267,6 +384,17 @@ public final class Interface {
|
|||
private Optional<Integer> listenPort = Optional.empty();
|
||||
// Defaults to not present.
|
||||
private Optional<Integer> mtu = Optional.empty();
|
||||
private Optional<Integer> jc = Optional.empty();
|
||||
private Optional<Integer> jmin = Optional.empty();
|
||||
private Optional<Integer> jmax = Optional.empty();
|
||||
|
||||
private Optional<Integer> s1 = Optional.empty();
|
||||
private Optional<Integer> s2 = Optional.empty();
|
||||
|
||||
private Optional<Long> h1 = Optional.empty();
|
||||
private Optional<Long> h2 = Optional.empty();
|
||||
private Optional<Long> h3 = Optional.empty();
|
||||
private Optional<Long> h4 = Optional.empty();
|
||||
|
||||
public Builder addAddress(final InetNetwork address) {
|
||||
addresses.add(address);
|
||||
|
@ -362,6 +490,78 @@ public final class Interface {
|
|||
}
|
||||
}
|
||||
|
||||
public Builder parseJc(final String jc) throws BadConfigException {
|
||||
try {
|
||||
return setJc(Integer.parseInt(jc));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.JC, jc, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseJmax(final String jmax) throws BadConfigException {
|
||||
try {
|
||||
return setJmax(Integer.parseInt(jmax));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.JMAX, jmax, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseJmin(final String jmin) throws BadConfigException {
|
||||
try {
|
||||
return setJmin(Integer.parseInt(jmin));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.JMIN, jmin, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseS1(final String s1) throws BadConfigException {
|
||||
try {
|
||||
return setS1(Integer.parseInt(s1));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.S1, s1, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseS2(final String s2) throws BadConfigException {
|
||||
try {
|
||||
return setS2(Integer.parseInt(s2));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.S2, s2, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseH1(final String h1) throws BadConfigException {
|
||||
try {
|
||||
return setH1(Long.parseLong(h1));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.H1, h1, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseH2(final String h2) throws BadConfigException {
|
||||
try {
|
||||
return setH2(Long.parseLong(h2));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.H2, h2, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseH3(final String h3) throws BadConfigException {
|
||||
try {
|
||||
return setH3(Long.parseLong(h3));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.H3, h3, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parseH4(final String h4) throws BadConfigException {
|
||||
try {
|
||||
return setH4(Long.parseLong(h4));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.H4, h4, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Builder parsePrivateKey(final String privateKey) throws BadConfigException {
|
||||
try {
|
||||
return setKeyPair(new KeyPair(Key.fromBase64(privateKey)));
|
||||
|
@ -386,9 +586,81 @@ public final class Interface {
|
|||
public Builder setMtu(final int mtu) throws BadConfigException {
|
||||
if (mtu < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.LISTEN_PORT, Reason.INVALID_VALUE, String.valueOf(mtu));
|
||||
Section.INTERFACE, Location.MTU, Reason.INVALID_VALUE, String.valueOf(mtu));
|
||||
this.mtu = mtu == 0 ? Optional.empty() : Optional.of(mtu);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setJc(final int jc) throws BadConfigException {
|
||||
if (jc < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.JC, Reason.INVALID_VALUE, String.valueOf(jc));
|
||||
this.jc = Optional.of(jc);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setJmin(final int jmin) throws BadConfigException {
|
||||
if (jmin < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.JMIN, Reason.INVALID_VALUE, String.valueOf(jmin));
|
||||
this.jmin = Optional.of(jmin);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setJmax(final int jmax) throws BadConfigException {
|
||||
if (jmax < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.JMAX, Reason.INVALID_VALUE, String.valueOf(jmax));
|
||||
this.jmax = Optional.of(jmax);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setS1(final int s1) throws BadConfigException {
|
||||
if (s1 < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.S1, Reason.INVALID_VALUE, String.valueOf(s1));
|
||||
this.s1 = Optional.of(s1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setS2(final int s2) throws BadConfigException {
|
||||
if (s2 < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.S2, Reason.INVALID_VALUE, String.valueOf(s2));
|
||||
this.s2 = Optional.of(s2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setH1(final long h1) throws BadConfigException {
|
||||
if (h1 < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.H1, Reason.INVALID_VALUE, String.valueOf(h1));
|
||||
this.h1 = Optional.of(h1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setH2(final long h2) throws BadConfigException {
|
||||
if (h2 < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.H2, Reason.INVALID_VALUE, String.valueOf(h2));
|
||||
this.h2 = Optional.of(h2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setH3(final long h3) throws BadConfigException {
|
||||
if (h3 < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.H3, Reason.INVALID_VALUE, String.valueOf(h3));
|
||||
this.h3 = Optional.of(h3);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setH4(final long h4) throws BadConfigException {
|
||||
if (h4 < 0)
|
||||
throw new BadConfigException(
|
||||
Section.INTERFACE, Location.H4, Reason.INVALID_VALUE, String.valueOf(h4));
|
||||
this.h4 = Optional.of(h4);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -380,7 +380,10 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
mNetworkState.bindNetworkListener()
|
||||
}
|
||||
"wireguard" -> {
|
||||
startWireGuard()
|
||||
startWireGuard("wireguard")
|
||||
}
|
||||
"awg" -> {
|
||||
startWireGuard("awg")
|
||||
}
|
||||
"shadowsocks" -> {
|
||||
startShadowsocks()
|
||||
|
@ -457,7 +460,8 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
fun turnOff() {
|
||||
Log.v(tag, "Aman: turnOff....................")
|
||||
when (mProtocol) {
|
||||
"wireguard" -> {
|
||||
"wireguard",
|
||||
"awg" -> {
|
||||
GoBackend.wgTurnOff(currentTunnelHandle)
|
||||
}
|
||||
"cloak",
|
||||
|
@ -564,9 +568,9 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
* Create a Wireguard [Config] from a [json] string -
|
||||
* The [json] will be created in AndroidVpnProtocol.cpp
|
||||
*/
|
||||
private fun buildWireguardConfig(obj: JSONObject): Config {
|
||||
private fun buildWireguardConfig(obj: JSONObject, type: String): Config {
|
||||
val confBuilder = Config.Builder()
|
||||
val wireguardConfigData = obj.getJSONObject("wireguard_config_data")
|
||||
val wireguardConfigData = obj.getJSONObject(type)
|
||||
val config = parseConfigData(wireguardConfigData.getString("config"))
|
||||
val peerBuilder = Peer.Builder()
|
||||
val peerConfig = config["Peer"]!!
|
||||
|
@ -599,6 +603,30 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
ifaceConfig["DNS"]!!.split(",").forEach {
|
||||
ifaceBuilder.addDnsServer(InetNetwork.parse(it.trim()).address)
|
||||
}
|
||||
|
||||
ifaceBuilder.parsePrivateKey(ifaceConfig["PrivateKey"])
|
||||
if (type == "awg_config_data") {
|
||||
ifaceBuilder.parseJc(ifaceConfig["Jc"])
|
||||
ifaceBuilder.parseJmin(ifaceConfig["Jmin"])
|
||||
ifaceBuilder.parseJmax(ifaceConfig["Jmax"])
|
||||
ifaceBuilder.parseS1(ifaceConfig["S1"])
|
||||
ifaceBuilder.parseS2(ifaceConfig["S2"])
|
||||
ifaceBuilder.parseH1(ifaceConfig["H1"])
|
||||
ifaceBuilder.parseH2(ifaceConfig["H2"])
|
||||
ifaceBuilder.parseH3(ifaceConfig["H3"])
|
||||
ifaceBuilder.parseH4(ifaceConfig["H4"])
|
||||
} else {
|
||||
ifaceBuilder.parseJc("0")
|
||||
ifaceBuilder.parseJmin("0")
|
||||
ifaceBuilder.parseJmax("0")
|
||||
ifaceBuilder.parseS1("0")
|
||||
ifaceBuilder.parseS2("0")
|
||||
ifaceBuilder.parseH1("0")
|
||||
ifaceBuilder.parseH2("0")
|
||||
ifaceBuilder.parseH3("0")
|
||||
ifaceBuilder.parseH4("0")
|
||||
|
||||
}
|
||||
/*val jExcludedApplication = obj.getJSONArray("excludedApps")
|
||||
(0 until jExcludedApplication.length()).toList().forEach {
|
||||
val appName = jExcludedApplication.get(it).toString()
|
||||
|
@ -716,8 +744,8 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
}).start()
|
||||
}
|
||||
|
||||
private fun startWireGuard() {
|
||||
val wireguard_conf = buildWireguardConfig(mConfig!!)
|
||||
private fun startWireGuard(type: String) {
|
||||
val wireguard_conf = buildWireguardConfig(mConfig!!, type + "_config_data")
|
||||
Log.i(tag, "startWireGuard: wireguard_conf : $wireguard_conf")
|
||||
if (currentTunnelHandle != -1) {
|
||||
Log.e(tag, "Tunnel already up")
|
||||
|
@ -728,9 +756,15 @@ class VPNService : BaseVpnService(), LocalDnsService.Interface {
|
|||
val builder = Builder()
|
||||
setupBuilder(wireguard_conf, builder)
|
||||
builder.setSession("Amnezia")
|
||||
|
||||
|
||||
builder.establish().use { tun ->
|
||||
if (tun == null) return
|
||||
currentTunnelHandle = GoBackend.wgTurnOn("Amnezia", tun.detachFd(), wgConfig)
|
||||
if (tun == null) return
|
||||
if (type == "awg"){
|
||||
currentTunnelHandle = GoBackend.wgTurnOn("awg0", tun.detachFd(), wgConfig)
|
||||
} else {
|
||||
currentTunnelHandle = GoBackend.wgTurnOn("amn0", tun.detachFd(), wgConfig)
|
||||
}
|
||||
}
|
||||
if (currentTunnelHandle < 0) {
|
||||
Log.e(tag, "Activation Error Code -> $currentTunnelHandle")
|
||||
|
|
|
@ -97,7 +97,7 @@ target_compile_options(${PROJECT} PRIVATE
|
|||
-DVPN_NE_BUNDLEID=\"${BUILD_IOS_APP_IDENTIFIER}.network-extension\"
|
||||
)
|
||||
|
||||
set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/wireguard-apple/Sources)
|
||||
set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/awg-apple/Sources)
|
||||
|
||||
target_sources(${PROJECT} PRIVATE
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/iosvpnprotocol.swift
|
||||
|
|
59
client/configurators/awg_configurator.cpp
Normal file
59
client/configurators/awg_configurator.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "awg_configurator.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
AwgConfigurator::AwgConfigurator(std::shared_ptr<Settings> settings, QObject *parent)
|
||||
: WireguardConfigurator(settings, true, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QString AwgConfigurator::genAwgConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
QString config = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
QJsonObject jsonConfig = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||
|
||||
ServerController serverController(m_settings);
|
||||
QString serverConfig = serverController.getTextFileFromContainer(container, credentials, protocols::awg::serverConfigPath, errorCode);
|
||||
|
||||
QMap<QString, QString> serverConfigMap;
|
||||
auto serverConfigLines = serverConfig.split("\n");
|
||||
for (auto &line : serverConfigLines) {
|
||||
auto trimmedLine = line.trimmed();
|
||||
if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) {
|
||||
continue;
|
||||
} else {
|
||||
QStringList parts = trimmedLine.split(" = ");
|
||||
if (parts.count() == 2) {
|
||||
serverConfigMap.insert(parts[0].trimmed(), parts[1].trimmed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.replace("$JUNK_PACKET_COUNT", serverConfigMap.value(config_key::junkPacketCount));
|
||||
config.replace("$JUNK_PACKET_MIN_SIZE", serverConfigMap.value(config_key::junkPacketMinSize));
|
||||
config.replace("$JUNK_PACKET_MAX_SIZE", serverConfigMap.value(config_key::junkPacketMaxSize));
|
||||
config.replace("$INIT_PACKET_JUNK_SIZE", serverConfigMap.value(config_key::initPacketJunkSize));
|
||||
config.replace("$RESPONSE_PACKET_JUNK_SIZE", serverConfigMap.value(config_key::responsePacketJunkSize));
|
||||
config.replace("$INIT_PACKET_MAGIC_HEADER", serverConfigMap.value(config_key::initPacketMagicHeader));
|
||||
config.replace("$RESPONSE_PACKET_MAGIC_HEADER", serverConfigMap.value(config_key::responsePacketMagicHeader));
|
||||
config.replace("$UNDERLOAD_PACKET_MAGIC_HEADER", serverConfigMap.value(config_key::underloadPacketMagicHeader));
|
||||
config.replace("$TRANSPORT_PACKET_MAGIC_HEADER", serverConfigMap.value(config_key::transportPacketMagicHeader));
|
||||
|
||||
jsonConfig[config_key::junkPacketCount] = serverConfigMap.value(config_key::junkPacketCount);
|
||||
jsonConfig[config_key::junkPacketMinSize] = serverConfigMap.value(config_key::junkPacketMinSize);
|
||||
jsonConfig[config_key::junkPacketMaxSize] = serverConfigMap.value(config_key::junkPacketMaxSize);
|
||||
jsonConfig[config_key::initPacketJunkSize] = serverConfigMap.value(config_key::initPacketJunkSize);
|
||||
jsonConfig[config_key::responsePacketJunkSize] = serverConfigMap.value(config_key::responsePacketJunkSize);
|
||||
jsonConfig[config_key::initPacketMagicHeader] = serverConfigMap.value(config_key::initPacketMagicHeader);
|
||||
jsonConfig[config_key::responsePacketMagicHeader] = serverConfigMap.value(config_key::responsePacketMagicHeader);
|
||||
jsonConfig[config_key::underloadPacketMagicHeader] = serverConfigMap.value(config_key::underloadPacketMagicHeader);
|
||||
jsonConfig[config_key::transportPacketMagicHeader] = serverConfigMap.value(config_key::transportPacketMagicHeader);
|
||||
|
||||
return QJsonDocument(jsonConfig).toJson();
|
||||
}
|
18
client/configurators/awg_configurator.h
Normal file
18
client/configurators/awg_configurator.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef AWGCONFIGURATOR_H
|
||||
#define AWGCONFIGURATOR_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "wireguard_configurator.h"
|
||||
|
||||
class AwgConfigurator : public WireguardConfigurator
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AwgConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
QString genAwgConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
};
|
||||
|
||||
#endif // AWGCONFIGURATOR_H
|
|
@ -1,32 +1,34 @@
|
|||
#include "vpn_configurator.h"
|
||||
#include "openvpn_configurator.h"
|
||||
#include "cloak_configurator.h"
|
||||
#include "shadowsocks_configurator.h"
|
||||
#include "wireguard_configurator.h"
|
||||
#include "ikev2_configurator.h"
|
||||
#include "openvpn_configurator.h"
|
||||
#include "shadowsocks_configurator.h"
|
||||
#include "ssh_configurator.h"
|
||||
#include "wireguard_configurator.h"
|
||||
#include "awg_configurator.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
#include "utilities.h"
|
||||
#include "settings.h"
|
||||
#include "utilities.h"
|
||||
|
||||
VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent):
|
||||
ConfiguratorBase(settings, parent)
|
||||
VpnConfigurator::VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent)
|
||||
: ConfiguratorBase(settings, parent)
|
||||
{
|
||||
openVpnConfigurator = std::shared_ptr<OpenVpnConfigurator>(new OpenVpnConfigurator(settings, this));
|
||||
shadowSocksConfigurator = std::shared_ptr<ShadowSocksConfigurator>(new ShadowSocksConfigurator(settings, this));
|
||||
cloakConfigurator = std::shared_ptr<CloakConfigurator>(new CloakConfigurator(settings, this));
|
||||
wireguardConfigurator = std::shared_ptr<WireguardConfigurator>(new WireguardConfigurator(settings, this));
|
||||
wireguardConfigurator = std::shared_ptr<WireguardConfigurator>(new WireguardConfigurator(settings, false, this));
|
||||
ikev2Configurator = std::shared_ptr<Ikev2Configurator>(new Ikev2Configurator(settings, this));
|
||||
sshConfigurator = std::shared_ptr<SshConfigurator>(new SshConfigurator(settings, this));
|
||||
awgConfigurator = std::shared_ptr<AwgConfigurator>(new AwgConfigurator(settings, this));
|
||||
}
|
||||
|
||||
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
|
||||
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
|
||||
{
|
||||
switch (proto) {
|
||||
case Proto::OpenVpn:
|
||||
|
@ -35,17 +37,17 @@ QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentia
|
|||
case Proto::ShadowSocks:
|
||||
return shadowSocksConfigurator->genShadowSocksConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::Cloak:
|
||||
return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
|
||||
case Proto::Cloak: return cloakConfigurator->genCloakConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::WireGuard:
|
||||
return wireguardConfigurator->genWireguardConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
case Proto::Ikev2:
|
||||
return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
|
||||
case Proto::Awg:
|
||||
return awgConfigurator->genAwgConfig(credentials, container, containerConfig, errorCode);
|
||||
|
||||
default:
|
||||
return "";
|
||||
case Proto::Ikev2: return ikev2Configurator->genIkev2Config(credentials, container, containerConfig, errorCode);
|
||||
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,8 +64,8 @@ QPair<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
|
|||
if (dns.first.isEmpty() || !Utils::checkIPv4Format(dns.first)) {
|
||||
if (useAmneziaDns && m_settings->containers(serverIndex).contains(DockerContainer::Dns)) {
|
||||
dns.first = protocols::dns::amneziaDnsIp;
|
||||
}
|
||||
else dns.first = m_settings->primaryDns();
|
||||
} else
|
||||
dns.first = m_settings->primaryDns();
|
||||
}
|
||||
if (dns.second.isEmpty() || !Utils::checkIPv4Format(dns.second)) {
|
||||
dns.second = m_settings->secondaryDns();
|
||||
|
@ -73,8 +75,8 @@ QPair<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
|
|||
return dns;
|
||||
}
|
||||
|
||||
QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container,
|
||||
Proto proto, QString &config)
|
||||
QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto,
|
||||
QString &config)
|
||||
{
|
||||
auto dns = getDnsForConfig(serverIndex);
|
||||
|
||||
|
@ -84,8 +86,8 @@ QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerCo
|
|||
return config;
|
||||
}
|
||||
|
||||
QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container,
|
||||
Proto proto, QString &config)
|
||||
QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto,
|
||||
QString &config)
|
||||
{
|
||||
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
||||
|
||||
|
@ -95,8 +97,8 @@ QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, Docker
|
|||
return config;
|
||||
}
|
||||
|
||||
QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container,
|
||||
Proto proto, QString &config)
|
||||
QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto,
|
||||
QString &config)
|
||||
{
|
||||
processConfigWithDnsSettings(serverIndex, container, proto, config);
|
||||
|
||||
|
@ -107,7 +109,7 @@ QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, Docke
|
|||
}
|
||||
|
||||
void VpnConfigurator::updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig,
|
||||
const QString &stdOut)
|
||||
const QString &stdOut)
|
||||
{
|
||||
Proto mainProto = ContainerProps::defaultProtocol(container);
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@ class CloakConfigurator;
|
|||
class WireguardConfigurator;
|
||||
class Ikev2Configurator;
|
||||
class SshConfigurator;
|
||||
class AwgConfigurator;
|
||||
|
||||
// Retrieve connection settings from server
|
||||
class VpnConfigurator : ConfiguratorBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
explicit VpnConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr);
|
||||
|
@ -40,6 +41,7 @@ public:
|
|||
std::shared_ptr<WireguardConfigurator> wireguardConfigurator;
|
||||
std::shared_ptr<Ikev2Configurator> ikev2Configurator;
|
||||
std::shared_ptr<SshConfigurator> sshConfigurator;
|
||||
std::shared_ptr<AwgConfigurator> awgConfigurator;
|
||||
};
|
||||
|
||||
#endif // VPN_CONFIGURATOR_H
|
||||
|
|
|
@ -19,9 +19,20 @@
|
|||
#include "settings.h"
|
||||
#include "utilities.h"
|
||||
|
||||
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> settings, QObject *parent)
|
||||
: ConfiguratorBase(settings, parent)
|
||||
WireguardConfigurator::WireguardConfigurator(std::shared_ptr<Settings> settings, bool isAwg, QObject *parent)
|
||||
: ConfiguratorBase(settings, parent), m_isAwg(isAwg)
|
||||
{
|
||||
m_serverConfigPath = m_isAwg ? amnezia::protocols::awg::serverConfigPath
|
||||
: amnezia::protocols::wireguard::serverConfigPath;
|
||||
m_serverPublicKeyPath = m_isAwg ? amnezia::protocols::awg::serverPublicKeyPath
|
||||
: amnezia::protocols::wireguard::serverPublicKeyPath;
|
||||
m_serverPskKeyPath = m_isAwg ? amnezia::protocols::awg::serverPskKeyPath
|
||||
: amnezia::protocols::wireguard::serverPskKeyPath;
|
||||
m_configTemplate = m_isAwg ? ProtocolScriptType::awg_template
|
||||
: ProtocolScriptType::wireguard_template;
|
||||
|
||||
m_protocolName = m_isAwg ? config_key::awg : config_key::wireguard;
|
||||
m_defaultPort = m_isAwg ? protocols::wireguard::defaultPort : protocols::awg::defaultPort;
|
||||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
||||
|
@ -62,7 +73,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
{
|
||||
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
|
||||
connData.host = credentials.hostName;
|
||||
connData.port = containerConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||
connData.port = containerConfig.value(m_protocolName).toObject().value(config_key::port).toString(m_defaultPort);
|
||||
|
||||
if (connData.clientPrivKey.isEmpty() || connData.clientPubKey.isEmpty()) {
|
||||
if (errorCode)
|
||||
|
@ -76,7 +87,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
// Get list of already created clients (only IP addresses)
|
||||
QString nextIpNumber;
|
||||
{
|
||||
QString script = QString("cat %1 | grep AllowedIPs").arg(amnezia::protocols::wireguard::serverConfigPath);
|
||||
QString script = QString("cat %1 | grep AllowedIPs").arg(m_serverConfigPath);
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
||||
stdOut += data + "\n";
|
||||
|
@ -123,8 +134,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
}
|
||||
|
||||
// Get keys
|
||||
connData.serverPubKey = serverController.getTextFileFromContainer(
|
||||
container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e);
|
||||
connData.serverPubKey = serverController.getTextFileFromContainer(container, credentials, m_serverPublicKeyPath, &e);
|
||||
connData.serverPubKey.replace("\n", "");
|
||||
if (e) {
|
||||
if (errorCode)
|
||||
|
@ -132,8 +142,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
return connData;
|
||||
}
|
||||
|
||||
connData.pskKey = serverController.getTextFileFromContainer(container, credentials,
|
||||
amnezia::protocols::wireguard::serverPskKeyPath, &e);
|
||||
connData.pskKey = serverController.getTextFileFromContainer(container, credentials, m_serverPskKeyPath, &e);
|
||||
connData.pskKey.replace("\n", "");
|
||||
|
||||
if (e) {
|
||||
|
@ -147,12 +156,9 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
"PublicKey = %1\n"
|
||||
"PresharedKey = %2\n"
|
||||
"AllowedIPs = %3/32\n\n")
|
||||
.arg(connData.clientPubKey)
|
||||
.arg(connData.pskKey)
|
||||
.arg(connData.clientIP);
|
||||
.arg(connData.clientPubKey, connData.pskKey, connData.clientIP);
|
||||
|
||||
e = serverController.uploadTextFileToContainer(container, credentials, configPart,
|
||||
protocols::wireguard::serverConfigPath,
|
||||
e = serverController.uploadTextFileToContainer(container, credentials, configPart, m_serverConfigPath,
|
||||
libssh::SftpOverwriteMode::SftpAppendToExisting);
|
||||
|
||||
if (e) {
|
||||
|
@ -161,11 +167,11 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
|
|||
return connData;
|
||||
}
|
||||
|
||||
QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'")
|
||||
.arg(m_serverConfigPath);
|
||||
|
||||
e = serverController.runScript(
|
||||
credentials,
|
||||
serverController.replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick "
|
||||
"strip /opt/amnezia/wireguard/wg0.conf)'",
|
||||
serverController.genVarsForScript(credentials, container)));
|
||||
credentials, serverController.replaceVars(script, serverController.genVarsForScript(credentials, container)));
|
||||
|
||||
return connData;
|
||||
}
|
||||
|
@ -174,9 +180,9 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede
|
|||
const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
ServerController serverController(m_settings);
|
||||
QString config =
|
||||
serverController.replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
|
||||
serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
QString scriptData = amnezia::scriptData(m_configTemplate, container);
|
||||
QString config = serverController.replaceVars(
|
||||
scriptData, serverController.genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode);
|
||||
if (errorCode && *errorCode) {
|
||||
|
|
|
@ -6,35 +6,44 @@
|
|||
|
||||
#include "configurator_base.h"
|
||||
#include "core/defs.h"
|
||||
#include "core/scripts_registry.h"
|
||||
|
||||
class WireguardConfigurator : ConfiguratorBase
|
||||
class WireguardConfigurator : public ConfiguratorBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WireguardConfigurator(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
WireguardConfigurator(std::shared_ptr<Settings> settings, bool isAwg, QObject *parent = nullptr);
|
||||
|
||||
struct ConnectionData {
|
||||
struct ConnectionData
|
||||
{
|
||||
QString clientPrivKey; // client private key
|
||||
QString clientPubKey; // client public key
|
||||
QString clientIP; // internal client IP address
|
||||
QString serverPubKey; // tls-auth key
|
||||
QString pskKey; // preshared key
|
||||
QString host; // host ip
|
||||
QString clientPubKey; // client public key
|
||||
QString clientIP; // internal client IP address
|
||||
QString serverPubKey; // tls-auth key
|
||||
QString pskKey; // preshared key
|
||||
QString host; // host ip
|
||||
QString port;
|
||||
};
|
||||
|
||||
QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
QString processConfigWithLocalSettings(QString config);
|
||||
QString processConfigWithExportSettings(QString config);
|
||||
|
||||
|
||||
private:
|
||||
ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
ConnectionData prepareWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
ConnectionData genClientKeys();
|
||||
|
||||
bool m_isAwg;
|
||||
QString m_serverConfigPath;
|
||||
QString m_serverPublicKeyPath;
|
||||
QString m_serverPskKeyPath;
|
||||
amnezia::ProtocolScriptType m_configTemplate;
|
||||
QString m_protocolName;
|
||||
QString m_defaultPort;
|
||||
};
|
||||
|
||||
#endif // WIREGUARD_CONFIGURATOR_H
|
||||
|
|
|
@ -84,11 +84,11 @@ QMap<DockerContainer, QString> ContainerProps::containerHumanNames()
|
|||
{ DockerContainer::ShadowSocks, "ShadowSocks" },
|
||||
{ DockerContainer::Cloak, "OpenVPN over Cloak" },
|
||||
{ DockerContainer::WireGuard, "WireGuard" },
|
||||
{ DockerContainer::Awg, "AmneziaWG" },
|
||||
{ DockerContainer::Ipsec, QObject::tr("IPsec") },
|
||||
|
||||
{ DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
|
||||
{ DockerContainer::Dns, QObject::tr("Amnezia DNS") },
|
||||
//{DockerContainer::FileShare, QObject::tr("SMB file sharing service")},
|
||||
{ DockerContainer::Sftp, QObject::tr("Sftp file sharing service") } };
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,10 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
|
|||
{ DockerContainer::WireGuard,
|
||||
QObject::tr("WireGuard - New popular VPN protocol with high performance, high speed and low power "
|
||||
"consumption. Recommended for regions with low levels of censorship.") },
|
||||
{ DockerContainer::Awg,
|
||||
QObject::tr("AmneziaWG - Special protocol from Amnezia, based on WireGuard. It's fast like WireGuard, "
|
||||
"but very resistant to blockages. "
|
||||
"Recommended for regions with high levels of censorship.") },
|
||||
{ DockerContainer::Ipsec,
|
||||
QObject::tr("IKEv2 - Modern stable protocol, a bit faster than others, restores connection after "
|
||||
"signal loss. It has native support on the latest versions of Android and iOS.") },
|
||||
|
@ -114,42 +118,108 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
|
|||
{ DockerContainer::TorWebSite, QObject::tr("Deploy a WordPress site on the Tor network in two clicks.") },
|
||||
{ DockerContainer::Dns,
|
||||
QObject::tr("Replace the current DNS server with your own. This will increase your privacy level.") },
|
||||
//{DockerContainer::FileShare, QObject::tr("SMB file sharing service - is Window file sharing protocol")},
|
||||
{ DockerContainer::Sftp,
|
||||
QObject::tr("Creates a file vault on your server to securely store and transfer files.") } };
|
||||
}
|
||||
|
||||
QMap<DockerContainer, QString> ContainerProps::containerDetailedDescriptions()
|
||||
{
|
||||
return { { DockerContainer::OpenVpn, QObject::tr("OpenVPN container") },
|
||||
{ DockerContainer::ShadowSocks, QObject::tr("Container with OpenVpn and ShadowSocks") },
|
||||
{ DockerContainer::Cloak,
|
||||
QObject::tr("Container with OpenVpn and ShadowSocks protocols "
|
||||
"configured with traffic masking by Cloak plugin") },
|
||||
{ DockerContainer::WireGuard, QObject::tr("WireGuard container") },
|
||||
{ DockerContainer::Ipsec, QObject::tr("IPsec container") },
|
||||
return {
|
||||
{ DockerContainer::OpenVpn,
|
||||
QObject::tr(
|
||||
"OpenVPN stands as one of the most popular and time-tested VPN protocols available.\n"
|
||||
"It employs its unique security protocol, "
|
||||
"leveraging the strength of SSL/TLS for encryption and key exchange. "
|
||||
"Furthermore, OpenVPN's support for a multitude of authentication methods makes it versatile and adaptable, "
|
||||
"catering to a wide range of devices and operating systems. "
|
||||
"Due to its open-source nature, OpenVPN benefits from extensive scrutiny by the global community, "
|
||||
"which continually reinforces its security. "
|
||||
"With a strong balance of performance, security, and compatibility, "
|
||||
"OpenVPN remains a top choice for privacy-conscious individuals and businesses alike.\n\n"
|
||||
"* Available in the AmneziaVPN across all platforms\n"
|
||||
"* Normal power consumption on mobile devices\n"
|
||||
"* Flexible customisation to suit user needs to work with different operating systems and devices\n"
|
||||
"* Recognised by DPI analysis systems and therefore susceptible to blocking\n"
|
||||
"* Can operate over both TCP and UDP network protocols.") },
|
||||
{ DockerContainer::ShadowSocks,
|
||||
QObject::tr("Shadowsocks, inspired by the SOCKS5 protocol, safeguards the connection using the AEAD cipher. "
|
||||
"Although Shadowsocks is designed to be discreet and challenging to identify, it isn't identical to a standard HTTPS connection."
|
||||
"However, certain traffic analysis systems might still detect a Shadowsocks connection. "
|
||||
"Due to limited support in Amnezia, it's recommended to use AmneziaWG protocol.\n\n"
|
||||
"* Available in the AmneziaVPN only on desktop platforms\n"
|
||||
"* Normal power consumption on mobile devices\n\n"
|
||||
"* Configurable encryption protocol\n"
|
||||
"* Detectable by some DPI systems\n"
|
||||
"* Works over TCP network protocol.") },
|
||||
{ DockerContainer::Cloak,
|
||||
QObject::tr("This is a combination of the OpenVPN protocol and the Cloak plugin designed specifically for "
|
||||
"blocking protection.\n\n"
|
||||
"OpenVPN provides a secure VPN connection by encrypting all Internet traffic between the client "
|
||||
"and the server.\n\n"
|
||||
"Cloak protects OpenVPN from detection and blocking. \n\n"
|
||||
"Cloak can modify packet metadata so that it completely masks VPN traffic as normal web traffic, "
|
||||
"and also protects the VPN from detection by Active Probing. This makes it very resistant to "
|
||||
"being detected\n\n"
|
||||
"Immediately after receiving the first data packet, Cloak authenticates the incoming connection. "
|
||||
"If authentication fails, the plugin masks the server as a fake website and your VPN becomes "
|
||||
"invisible to analysis systems.\n\n"
|
||||
"If there is a extreme level of Internet censorship in your region, we advise you to use only "
|
||||
"OpenVPN over Cloak from the first connection\n\n"
|
||||
"* Available in the AmneziaVPN across all platforms\n"
|
||||
"* High power consumption on mobile devices\n"
|
||||
"* Flexible settings\n"
|
||||
"* Not recognised by DPI analysis systems\n"
|
||||
"* Works over TCP network protocol, 443 port.\n") },
|
||||
{ DockerContainer::WireGuard,
|
||||
QObject::tr("A relatively new popular VPN protocol with a simplified architecture.\n"
|
||||
"Provides stable VPN connection, high performance on all devices. Uses hard-coded encryption "
|
||||
"settings. WireGuard compared to OpenVPN has lower latency and better data transfer throughput.\n"
|
||||
"WireGuard is very susceptible to blocking due to its distinct packet signatures. "
|
||||
"Unlike some other VPN protocols that employ obfuscation techniques, "
|
||||
"the consistent signature patterns of WireGuard packets can be more easily identified and "
|
||||
"thus blocked by advanced Deep Packet Inspection (DPI) systems and other network monitoring tools.\n\n"
|
||||
"* Available in the AmneziaVPN across all platforms\n"
|
||||
"* Low power consumption\n"
|
||||
"* Minimum number of settings\n"
|
||||
"* Easily recognised by DPI analysis systems, susceptible to blocking\n"
|
||||
"* Works over UDP network protocol.") },
|
||||
{ DockerContainer::Awg,
|
||||
QObject::tr("A modern iteration of the popular VPN protocol, "
|
||||
"AmneziaWG builds upon the foundation set by WireGuard, "
|
||||
"retaining its simplified architecture and high-performance capabilities across devices.\n"
|
||||
"While WireGuard is known for its efficiency, "
|
||||
"it had issues with being easily detected due to its distinct packet signatures. "
|
||||
"AmneziaWG solves this problem by using better obfuscation methods, "
|
||||
"making its traffic blend in with regular internet traffic.\n"
|
||||
"This means that AmneziaWG keeps the fast performance of the original "
|
||||
"while adding an extra layer of stealth, "
|
||||
"making it a great choice for those wanting a fast and discreet VPN connection.\n\n"
|
||||
"* Available in the AmneziaVPN across all platforms\n"
|
||||
"* Low power consumption\n"
|
||||
"* Minimum number of settings\n"
|
||||
"* Not recognised by DPI analysis systems, resistant to blocking\n"
|
||||
"* Works over UDP network protocol.") },
|
||||
{ DockerContainer::Ipsec,
|
||||
QObject::tr("IKEv2, paired with the IPSec encryption layer, stands as a modern and stable VPN protocol.\n"
|
||||
"One of its distinguishing features is its ability to swiftly switch between networks and devices, "
|
||||
"making it particularly adaptive in dynamic network environments. \n"
|
||||
"While it offers a blend of security, stability, and speed, "
|
||||
"it's essential to note that IKEv2 can be easily detected and is susceptible to blocking.\n\n"
|
||||
"* Available in the AmneziaVPN only on Windows\n"
|
||||
"* Low power consumption, on mobile devices\n"
|
||||
"* Minimal configuration\n"
|
||||
"* Recognised by DPI analysis systems\n"
|
||||
"* Works over UDP network protocol, ports 500 and 4500.") },
|
||||
|
||||
{ DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
|
||||
{ DockerContainer::Dns, QObject::tr("DNS Service") },
|
||||
//{DockerContainer::FileShare, QObject::tr("SMB file sharing service - is Window file sharing protocol")},
|
||||
{ DockerContainer::Sftp, QObject::tr("Sftp file sharing service - is secure FTP service") } };
|
||||
{ DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
|
||||
{ DockerContainer::Dns, QObject::tr("DNS Service") },
|
||||
{ DockerContainer::Sftp, QObject::tr("Sftp file sharing service - is secure FTP service") }
|
||||
};
|
||||
}
|
||||
|
||||
amnezia::ServiceType ContainerProps::containerService(DockerContainer c)
|
||||
{
|
||||
switch (c) {
|
||||
case DockerContainer::None: return ServiceType::None;
|
||||
case DockerContainer::OpenVpn: return ServiceType::Vpn;
|
||||
case DockerContainer::Cloak: return ServiceType::Vpn;
|
||||
case DockerContainer::ShadowSocks: return ServiceType::Vpn;
|
||||
case DockerContainer::WireGuard: return ServiceType::Vpn;
|
||||
case DockerContainer::Ipsec: return ServiceType::Vpn;
|
||||
case DockerContainer::TorWebSite: return ServiceType::Other;
|
||||
case DockerContainer::Dns: return ServiceType::Other;
|
||||
// case DockerContainer::FileShare : return ServiceType::Other;
|
||||
case DockerContainer::Sftp: return ServiceType::Other;
|
||||
default: return ServiceType::Other;
|
||||
}
|
||||
return ProtocolProps::protocolService(defaultProtocol(c));
|
||||
}
|
||||
|
||||
Proto ContainerProps::defaultProtocol(DockerContainer c)
|
||||
|
@ -160,11 +230,11 @@ Proto ContainerProps::defaultProtocol(DockerContainer c)
|
|||
case DockerContainer::Cloak: return Proto::Cloak;
|
||||
case DockerContainer::ShadowSocks: return Proto::ShadowSocks;
|
||||
case DockerContainer::WireGuard: return Proto::WireGuard;
|
||||
case DockerContainer::Awg: return Proto::Awg;
|
||||
case DockerContainer::Ipsec: return Proto::Ikev2;
|
||||
|
||||
case DockerContainer::TorWebSite: return Proto::TorWebSite;
|
||||
case DockerContainer::Dns: return Proto::Dns;
|
||||
// case DockerContainer::FileShare : return Protocol::FileShare;
|
||||
case DockerContainer::Sftp: return Proto::Sftp;
|
||||
default: return Proto::Any;
|
||||
}
|
||||
|
@ -179,6 +249,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
|
|||
switch (c) {
|
||||
case DockerContainer::WireGuard: return true;
|
||||
case DockerContainer::OpenVpn: return true;
|
||||
case DockerContainer::Awg: return true;
|
||||
case DockerContainer::Cloak:
|
||||
return true;
|
||||
// case DockerContainer::ShadowSocks: return true;
|
||||
|
@ -196,6 +267,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
|
|||
case DockerContainer::WireGuard: return true;
|
||||
case DockerContainer::OpenVpn: return true;
|
||||
case DockerContainer::ShadowSocks: return true;
|
||||
case DockerContainer::Awg: return true;
|
||||
case DockerContainer::Cloak: return true;
|
||||
default: return false;
|
||||
}
|
||||
|
@ -224,8 +296,8 @@ bool ContainerProps::isEasySetupContainer(DockerContainer container)
|
|||
{
|
||||
switch (container) {
|
||||
case DockerContainer::WireGuard: return true;
|
||||
case DockerContainer::Awg: return true;
|
||||
case DockerContainer::Cloak: return true;
|
||||
case DockerContainer::OpenVpn: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
@ -234,8 +306,8 @@ QString ContainerProps::easySetupHeader(DockerContainer container)
|
|||
{
|
||||
switch (container) {
|
||||
case DockerContainer::WireGuard: return tr("Low");
|
||||
case DockerContainer::Cloak: return tr("High");
|
||||
case DockerContainer::OpenVpn: return tr("Medium");
|
||||
case DockerContainer::Awg: return tr("Medium or High");
|
||||
case DockerContainer::Cloak: return tr("Extreme");
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
@ -243,9 +315,10 @@ QString ContainerProps::easySetupHeader(DockerContainer container)
|
|||
QString ContainerProps::easySetupDescription(DockerContainer container)
|
||||
{
|
||||
switch (container) {
|
||||
case DockerContainer::WireGuard: return tr("I just want to increase the level of privacy");
|
||||
case DockerContainer::Cloak: return tr("Many foreign websites and VPN providers are blocked");
|
||||
case DockerContainer::OpenVpn: return tr("Some foreign sites are blocked, but VPN providers are not blocked");
|
||||
case DockerContainer::WireGuard: return tr("I just want to increase the level of my privacy.");
|
||||
case DockerContainer::Awg: return tr("I want to bypass censorship. This option recommended in most cases.");
|
||||
case DockerContainer::Cloak:
|
||||
return tr("Most VPN protocols are blocked. Recommended if other options are not working.");
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
@ -253,9 +326,9 @@ QString ContainerProps::easySetupDescription(DockerContainer container)
|
|||
int ContainerProps::easySetupOrder(DockerContainer container)
|
||||
{
|
||||
switch (container) {
|
||||
case DockerContainer::WireGuard: return 1;
|
||||
case DockerContainer::Cloak: return 3;
|
||||
case DockerContainer::OpenVpn: return 2;
|
||||
case DockerContainer::WireGuard: return 3;
|
||||
case DockerContainer::Awg: return 2;
|
||||
case DockerContainer::Cloak: return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,16 +16,16 @@ namespace amnezia
|
|||
Q_NAMESPACE
|
||||
enum DockerContainer {
|
||||
None = 0,
|
||||
OpenVpn,
|
||||
ShadowSocks,
|
||||
Cloak,
|
||||
Awg,
|
||||
WireGuard,
|
||||
OpenVpn,
|
||||
Cloak,
|
||||
ShadowSocks,
|
||||
Ipsec,
|
||||
|
||||
// non-vpn
|
||||
TorWebSite,
|
||||
Dns,
|
||||
// FileShare,
|
||||
Sftp
|
||||
};
|
||||
Q_ENUM_NS(DockerContainer)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "scripts_registry.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
|
||||
QString amnezia::scriptFolder(amnezia::DockerContainer container)
|
||||
{
|
||||
|
@ -11,11 +11,11 @@ QString amnezia::scriptFolder(amnezia::DockerContainer container)
|
|||
case DockerContainer::Cloak: return QLatin1String("openvpn_cloak");
|
||||
case DockerContainer::ShadowSocks: return QLatin1String("openvpn_shadowsocks");
|
||||
case DockerContainer::WireGuard: return QLatin1String("wireguard");
|
||||
case DockerContainer::Awg: return QLatin1String("awg");
|
||||
case DockerContainer::Ipsec: return QLatin1String("ipsec");
|
||||
|
||||
case DockerContainer::TorWebSite: return QLatin1String("website_tor");
|
||||
case DockerContainer::Dns: return QLatin1String("dns");
|
||||
//case DockerContainer::FileShare: return QLatin1String("file_share");
|
||||
case DockerContainer::Sftp: return QLatin1String("sftp");
|
||||
default: return "";
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ QString amnezia::scriptName(ProtocolScriptType type)
|
|||
case ProtocolScriptType::container_startup: return QLatin1String("start.sh");
|
||||
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
||||
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
|
||||
case ProtocolScriptType::awg_template: return QLatin1String("template.conf");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +53,7 @@ QString amnezia::scriptData(amnezia::SharedScriptType type)
|
|||
{
|
||||
QString fileName = QString(":/server_scripts/%1").arg(amnezia::scriptName(type));
|
||||
QFile file(fileName);
|
||||
if (! file.open(QIODevice::ReadOnly)) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qDebug() << "Warning: script missing" << fileName;
|
||||
return "";
|
||||
}
|
||||
|
@ -67,7 +68,7 @@ QString amnezia::scriptData(amnezia::ProtocolScriptType type, DockerContainer co
|
|||
{
|
||||
QString fileName = QString(":/server_scripts/%1/%2").arg(amnezia::scriptFolder(container), amnezia::scriptName(type));
|
||||
QFile file(fileName);
|
||||
if (! file.open(QIODevice::ReadOnly)) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qDebug() << "Warning: script missing" << fileName;
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@ enum ProtocolScriptType {
|
|||
configure_container,
|
||||
container_startup,
|
||||
openvpn_template,
|
||||
wireguard_template
|
||||
wireguard_template,
|
||||
awg_template
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -338,6 +338,10 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
|
|||
return true;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Awg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -486,6 +490,7 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||
const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Proto::Cloak)).toObject();
|
||||
const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Proto::ShadowSocks)).toObject();
|
||||
const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject();
|
||||
const QJsonObject &amneziaWireguarConfig = config.value(ProtocolProps::protoToString(Proto::Awg)).toObject();
|
||||
const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject();
|
||||
|
||||
Vars vars;
|
||||
|
@ -582,6 +587,25 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
|||
vars.append({ { "$SFTP_USER", sftpConfig.value(config_key::userName).toString() } });
|
||||
vars.append({ { "$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() } });
|
||||
|
||||
// Amnezia wireguard vars
|
||||
vars.append({ { "$AWG_SERVER_PORT",
|
||||
amneziaWireguarConfig.value(config_key::port).toString(protocols::awg::defaultPort) } });
|
||||
|
||||
vars.append({ { "$JUNK_PACKET_COUNT", amneziaWireguarConfig.value(config_key::junkPacketCount).toString() } });
|
||||
vars.append({ { "$JUNK_PACKET_MIN_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMinSize).toString() } });
|
||||
vars.append({ { "$JUNK_PACKET_MAX_SIZE", amneziaWireguarConfig.value(config_key::junkPacketMaxSize).toString() } });
|
||||
vars.append({ { "$INIT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::initPacketJunkSize).toString() } });
|
||||
vars.append({ { "$RESPONSE_PACKET_JUNK_SIZE",
|
||||
amneziaWireguarConfig.value(config_key::responsePacketJunkSize).toString() } });
|
||||
vars.append({ { "$INIT_PACKET_MAGIC_HEADER",
|
||||
amneziaWireguarConfig.value(config_key::initPacketMagicHeader).toString() } });
|
||||
vars.append({ { "$RESPONSE_PACKET_MAGIC_HEADER",
|
||||
amneziaWireguarConfig.value(config_key::responsePacketMagicHeader).toString() } });
|
||||
vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER",
|
||||
amneziaWireguarConfig.value(config_key::underloadPacketMagicHeader).toString() } });
|
||||
vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER",
|
||||
amneziaWireguarConfig.value(config_key::transportPacketMagicHeader).toString() } });
|
||||
|
||||
QString serverIp = Utils::getIPAddress(credentials.hostName);
|
||||
if (!serverIp.isEmpty()) {
|
||||
vars.append({ { "$SERVER_IP_ADDRESS", serverIp } });
|
||||
|
|
|
@ -359,6 +359,23 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
|||
if (!parseStringList(obj, "vpnDisabledApps", config.m_vpnDisabledApps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obj.value("Jc").isNull() && !obj.value("Jmin").isNull()
|
||||
&& !obj.value("Jmax").isNull() && !obj.value("S1").isNull()
|
||||
&& !obj.value("S2").isNull() && !obj.value("H1").isNull()
|
||||
&& !obj.value("H2").isNull() && !obj.value("H3").isNull()
|
||||
&& !obj.value("H4").isNull()) {
|
||||
config.m_junkPacketCount = obj.value("Jc").toString();
|
||||
config.m_junkPacketMinSize = obj.value("Jmin").toString();
|
||||
config.m_junkPacketMaxSize = obj.value("Jmax").toString();
|
||||
config.m_initPacketJunkSize = obj.value("S1").toString();
|
||||
config.m_responsePacketJunkSize = obj.value("S2").toString();
|
||||
config.m_initPacketMagicHeader = obj.value("H1").toString();
|
||||
config.m_responsePacketMagicHeader = obj.value("H2").toString();
|
||||
config.m_underloadPacketMagicHeader = obj.value("H3").toString();
|
||||
config.m_transportPacketMagicHeader = obj.value("H4").toString();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,34 @@ QString InterfaceConfig::toWgConf(const QMap<QString, QString>& extra) const {
|
|||
out << "DNS = " << dnsServers.join(", ") << "\n";
|
||||
}
|
||||
|
||||
if (!m_junkPacketCount.isNull()) {
|
||||
out << "Jc = " << m_junkPacketCount << "\n";
|
||||
}
|
||||
if (!m_junkPacketMinSize.isNull()) {
|
||||
out << "JMin = " << m_junkPacketMinSize << "\n";
|
||||
}
|
||||
if (!m_junkPacketMaxSize.isNull()) {
|
||||
out << "JMax = " << m_junkPacketMaxSize << "\n";
|
||||
}
|
||||
if (!m_initPacketJunkSize.isNull()) {
|
||||
out << "S1 = " << m_initPacketJunkSize << "\n";
|
||||
}
|
||||
if (!m_responsePacketJunkSize.isNull()) {
|
||||
out << "S2 = " << m_responsePacketJunkSize << "\n";
|
||||
}
|
||||
if (!m_initPacketMagicHeader.isNull()) {
|
||||
out << "H1 = " << m_initPacketMagicHeader << "\n";
|
||||
}
|
||||
if (!m_responsePacketMagicHeader.isNull()) {
|
||||
out << "H2 = " << m_responsePacketMagicHeader << "\n";
|
||||
}
|
||||
if (!m_underloadPacketMagicHeader.isNull()) {
|
||||
out << "H3 = " << m_underloadPacketMagicHeader << "\n";
|
||||
}
|
||||
if (!m_transportPacketMagicHeader.isNull()) {
|
||||
out << "H4 = " << m_transportPacketMagicHeader << "\n";
|
||||
}
|
||||
|
||||
// If any extra config was provided, append it now.
|
||||
for (const QString& key : extra.keys()) {
|
||||
out << key << " = " << extra[key] << "\n";
|
||||
|
|
|
@ -40,6 +40,16 @@ class InterfaceConfig {
|
|||
QString m_installationId;
|
||||
#endif
|
||||
|
||||
QString m_junkPacketCount;
|
||||
QString m_junkPacketMinSize;
|
||||
QString m_junkPacketMaxSize;
|
||||
QString m_initPacketJunkSize;
|
||||
QString m_responsePacketJunkSize;
|
||||
QString m_initPacketMagicHeader;
|
||||
QString m_responsePacketMagicHeader;
|
||||
QString m_underloadPacketMagicHeader;
|
||||
QString m_transportPacketMagicHeader;
|
||||
|
||||
QJsonObject toJson() const;
|
||||
QString toWgConf(
|
||||
const QMap<QString, QString>& extra = QMap<QString, QString>()) const;
|
||||
|
|
|
@ -58,7 +58,7 @@ target_link_libraries(networkextension PRIVATE ${FW_UI_KIT})
|
|||
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
||||
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
|
||||
|
||||
set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/wireguard-apple/Sources)
|
||||
set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/awg-apple/Sources)
|
||||
|
||||
target_sources(networkextension PRIVATE
|
||||
${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "wireguard-go-version.h"
|
||||
#include "3rd/wireguard-apple/Sources/WireGuardKitGo/wireguard.h"
|
||||
#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
#include "3rd/awg-apple/Sources/WireGuardKitGo/wireguard.h"
|
||||
#include "3rd/awg-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "wireguard-go-version.h"
|
||||
#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
#include "3rd/awg-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "macos/gobridge/wireguard.h"
|
||||
#include "wireguard-go-version.h"
|
||||
#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
#include "3rd/awg-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
#include "3rd/ShadowSocks/ShadowSocks/ShadowSocks.h"
|
||||
#include "platforms/ios/ssconnectivity.h"
|
||||
#include "platforms/ios/iosopenvpn2ssadapter.h"
|
||||
|
|
|
@ -115,7 +115,9 @@ void LocalSocketController::daemonConnected() {
|
|||
}
|
||||
|
||||
void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||
QJsonObject wgConfig = rawConfig.value("wireguard_config_data").toObject();
|
||||
QString protocolName = rawConfig.value("protocol").toString();
|
||||
|
||||
QJsonObject wgConfig = rawConfig.value(protocolName + "_config_data").toObject();
|
||||
|
||||
QJsonObject json;
|
||||
json.insert("type", "activate");
|
||||
|
@ -160,6 +162,19 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
|||
// splitTunnelApps.append(QJsonValue(uri));
|
||||
// }
|
||||
// json.insert("vpnDisabledApps", splitTunnelApps);
|
||||
|
||||
if (protocolName == amnezia::config_key::awg) {
|
||||
json.insert(amnezia::config_key::junkPacketCount, wgConfig.value(amnezia::config_key::junkPacketCount));
|
||||
json.insert(amnezia::config_key::junkPacketMinSize, wgConfig.value(amnezia::config_key::junkPacketMinSize));
|
||||
json.insert(amnezia::config_key::junkPacketMaxSize, wgConfig.value(amnezia::config_key::junkPacketMaxSize));
|
||||
json.insert(amnezia::config_key::initPacketJunkSize, wgConfig.value(amnezia::config_key::initPacketJunkSize));
|
||||
json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize));
|
||||
json.insert(amnezia::config_key::initPacketMagicHeader, wgConfig.value(amnezia::config_key::initPacketMagicHeader));
|
||||
json.insert(amnezia::config_key::responsePacketMagicHeader, wgConfig.value(amnezia::config_key::responsePacketMagicHeader));
|
||||
json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader));
|
||||
json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader));
|
||||
}
|
||||
|
||||
write(json);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
#include "3rd/awg-apple/Sources/WireGuardKitC/WireGuardKitC.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -62,6 +62,7 @@ private:
|
|||
bool setupOpenVPN();
|
||||
bool setupCloak();
|
||||
bool setupWireGuard();
|
||||
bool setupAwg();
|
||||
|
||||
bool startOpenVPN(const QString &config);
|
||||
bool startWireGuard(const QString &jsonConfig);
|
||||
|
|
|
@ -204,6 +204,9 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
|
|||
if (proto == amnezia::Proto::WireGuard) {
|
||||
return setupWireGuard();
|
||||
}
|
||||
if (proto == amnezia::Proto::Awg) {
|
||||
return setupAwg();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -307,6 +310,15 @@ bool IosController::setupWireGuard()
|
|||
return startWireGuard(wgConfig);
|
||||
}
|
||||
|
||||
bool IosController::setupAwg()
|
||||
{
|
||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
||||
|
||||
QString wgConfig = config[config_key::config].toString();
|
||||
|
||||
return startWireGuard(wgConfig);
|
||||
}
|
||||
|
||||
bool IosController::startOpenVPN(const QString &config)
|
||||
{
|
||||
qDebug() << "IosController::startOpenVPN";
|
||||
|
|
|
@ -100,6 +100,19 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
|
|||
QTextStream out(&message);
|
||||
out << "private_key=" << QString(privateKey.toHex()) << "\n";
|
||||
out << "replace_peers=true\n";
|
||||
|
||||
if (config.m_junkPacketCount != "") {
|
||||
out << "jc=" << config.m_junkPacketCount << "\n";
|
||||
out << "jmin=" << config.m_junkPacketMinSize << "\n";
|
||||
out << "jmax=" << config.m_junkPacketMaxSize << "\n";
|
||||
out << "s1=" << config.m_initPacketJunkSize << "\n";
|
||||
out << "s2=" << config.m_responsePacketJunkSize << "\n";
|
||||
out << "h1=" << config.m_initPacketMagicHeader << "\n";
|
||||
out << "h2=" << config.m_responsePacketMagicHeader << "\n";
|
||||
out << "h3=" << config.m_underloadPacketMagicHeader << "\n";
|
||||
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
|
||||
}
|
||||
|
||||
int err = uapiErrno(uapiCommand(message));
|
||||
if (err != 0) {
|
||||
logger.error() << "Interface configuration failed:" << strerror(err);
|
||||
|
|
|
@ -100,6 +100,19 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
|
|||
QTextStream out(&message);
|
||||
out << "private_key=" << QString(privateKey.toHex()) << "\n";
|
||||
out << "replace_peers=true\n";
|
||||
|
||||
if (config.m_junkPacketCount != "") {
|
||||
out << "jc=" << config.m_junkPacketCount << "\n";
|
||||
out << "jmin=" << config.m_junkPacketMinSize << "\n";
|
||||
out << "jmax=" << config.m_junkPacketMaxSize << "\n";
|
||||
out << "s1=" << config.m_initPacketJunkSize << "\n";
|
||||
out << "s2=" << config.m_responsePacketJunkSize << "\n";
|
||||
out << "h1=" << config.m_initPacketMagicHeader << "\n";
|
||||
out << "h2=" << config.m_responsePacketMagicHeader << "\n";
|
||||
out << "h3=" << config.m_underloadPacketMagicHeader << "\n";
|
||||
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
|
||||
}
|
||||
|
||||
int err = uapiErrno(uapiCommand(message));
|
||||
if (err != 0) {
|
||||
logger.error() << "Interface configuration failed:" << strerror(err);
|
||||
|
|
10
client/protocols/awgprotocol.cpp
Normal file
10
client/protocols/awgprotocol.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "awgprotocol.h"
|
||||
|
||||
Awg::Awg(const QJsonObject &configuration, QObject *parent)
|
||||
: WireguardProtocol(configuration, parent)
|
||||
{
|
||||
}
|
||||
|
||||
Awg::~Awg()
|
||||
{
|
||||
}
|
17
client/protocols/awgprotocol.h
Normal file
17
client/protocols/awgprotocol.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef AWGPROTOCOL_H
|
||||
#define AWGPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "wireguardprotocol.h"
|
||||
|
||||
class Awg : public WireguardProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Awg(const QJsonObject &configuration, QObject *parent = nullptr);
|
||||
virtual ~Awg() override;
|
||||
};
|
||||
|
||||
#endif // AWGPROTOCOL_H
|
|
@ -1,5 +1,7 @@
|
|||
#include "protocols_defs.h"
|
||||
|
||||
#include <QRandomGenerator>
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
QDebug operator<<(QDebug debug, const amnezia::ProtocolEnumNS::Proto &p)
|
||||
|
@ -66,12 +68,12 @@ QMap<amnezia::Proto, QString> ProtocolProps::protocolHumanNames()
|
|||
{ Proto::ShadowSocks, "ShadowSocks" },
|
||||
{ Proto::Cloak, "Cloak" },
|
||||
{ Proto::WireGuard, "WireGuard" },
|
||||
{ Proto::Awg, "AmneziaWG" },
|
||||
{ Proto::Ikev2, "IKEv2" },
|
||||
{ Proto::L2tp, "L2TP" },
|
||||
|
||||
{ Proto::TorWebSite, "Website in Tor network" },
|
||||
{ Proto::Dns, "DNS Service" },
|
||||
{ Proto::FileShare, "File Sharing Service" },
|
||||
{ Proto::Sftp, QObject::tr("Sftp service") } };
|
||||
}
|
||||
|
||||
|
@ -88,27 +90,43 @@ amnezia::ServiceType ProtocolProps::protocolService(Proto p)
|
|||
case Proto::Cloak: return ServiceType::Vpn;
|
||||
case Proto::ShadowSocks: return ServiceType::Vpn;
|
||||
case Proto::WireGuard: return ServiceType::Vpn;
|
||||
case Proto::Awg: return ServiceType::Vpn;
|
||||
case Proto::Ikev2: return ServiceType::Vpn;
|
||||
|
||||
case Proto::TorWebSite: return ServiceType::Other;
|
||||
case Proto::Dns: return ServiceType::Other;
|
||||
case Proto::FileShare: return ServiceType::Other;
|
||||
case Proto::Sftp: return ServiceType::Other;
|
||||
default: return ServiceType::Other;
|
||||
}
|
||||
}
|
||||
|
||||
int ProtocolProps::getPortForInstall(Proto p)
|
||||
{
|
||||
switch (p) {
|
||||
case Awg:
|
||||
case WireGuard:
|
||||
case ShadowSocks:
|
||||
case OpenVpn:
|
||||
return QRandomGenerator::global()->bounded(30000, 50000);
|
||||
default:
|
||||
return defaultPort(p);
|
||||
}
|
||||
}
|
||||
|
||||
int ProtocolProps::defaultPort(Proto p)
|
||||
{
|
||||
switch (p) {
|
||||
case Proto::Any: return -1;
|
||||
case Proto::OpenVpn: return 1194;
|
||||
case Proto::Cloak: return 443;
|
||||
case Proto::ShadowSocks: return 6789;
|
||||
case Proto::WireGuard: return 51820;
|
||||
case Proto::OpenVpn: return QString(protocols::openvpn::defaultPort).toInt();
|
||||
case Proto::Cloak: return QString(protocols::cloak::defaultPort).toInt();
|
||||
case Proto::ShadowSocks: return QString(protocols::shadowsocks::defaultPort).toInt();
|
||||
case Proto::WireGuard: return QString(protocols::wireguard::defaultPort).toInt();
|
||||
case Proto::Awg: return QString(protocols::awg::defaultPort).toInt();
|
||||
case Proto::Ikev2: return -1;
|
||||
case Proto::L2tp: return -1;
|
||||
|
||||
case Proto::TorWebSite: return -1;
|
||||
case Proto::Dns: return 53;
|
||||
case Proto::FileShare: return 139;
|
||||
case Proto::Sftp: return 222;
|
||||
default: return -1;
|
||||
}
|
||||
|
@ -122,13 +140,14 @@ bool ProtocolProps::defaultPortChangeable(Proto p)
|
|||
case Proto::Cloak: return true;
|
||||
case Proto::ShadowSocks: return true;
|
||||
case Proto::WireGuard: return true;
|
||||
case Proto::Awg: return true;
|
||||
case Proto::Ikev2: return false;
|
||||
case Proto::L2tp: return false;
|
||||
|
||||
case Proto::TorWebSite: return true;
|
||||
case Proto::TorWebSite: return false;
|
||||
case Proto::Dns: return false;
|
||||
case Proto::FileShare: return false;
|
||||
default: return -1;
|
||||
case Proto::Sftp: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,12 +159,12 @@ TransportProto ProtocolProps::defaultTransportProto(Proto p)
|
|||
case Proto::Cloak: return TransportProto::Tcp;
|
||||
case Proto::ShadowSocks: return TransportProto::Tcp;
|
||||
case Proto::WireGuard: return TransportProto::Udp;
|
||||
case Proto::Awg: return TransportProto::Udp;
|
||||
case Proto::Ikev2: return TransportProto::Udp;
|
||||
case Proto::L2tp: return TransportProto::Udp;
|
||||
// non-vpn
|
||||
case Proto::TorWebSite: return TransportProto::Tcp;
|
||||
case Proto::Dns: return TransportProto::Udp;
|
||||
case Proto::FileShare: return TransportProto::Udp;
|
||||
case Proto::Sftp: return TransportProto::Tcp;
|
||||
}
|
||||
}
|
||||
|
@ -158,12 +177,12 @@ bool ProtocolProps::defaultTransportProtoChangeable(Proto p)
|
|||
case Proto::Cloak: return false;
|
||||
case Proto::ShadowSocks: return false;
|
||||
case Proto::WireGuard: return false;
|
||||
case Proto::Awg: return false;
|
||||
case Proto::Ikev2: return false;
|
||||
case Proto::L2tp: return false;
|
||||
// non-vpn
|
||||
case Proto::TorWebSite: return false;
|
||||
case Proto::Dns: return false;
|
||||
case Proto::FileShare: return false;
|
||||
case Proto::Sftp: return false;
|
||||
default: return false;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#define PROTOCOLS_DEFS_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QMetaEnum>
|
||||
#include <QObject>
|
||||
|
||||
namespace amnezia
|
||||
{
|
||||
|
@ -61,11 +61,22 @@ namespace amnezia
|
|||
|
||||
constexpr char isThirdPartyConfig[] = "isThirdPartyConfig";
|
||||
|
||||
constexpr char junkPacketCount[] = "Jc";
|
||||
constexpr char junkPacketMinSize[] = "Jmin";
|
||||
constexpr char junkPacketMaxSize[] = "Jmax";
|
||||
constexpr char initPacketJunkSize[] = "S1";
|
||||
constexpr char responsePacketJunkSize[] = "S2";
|
||||
constexpr char initPacketMagicHeader[] = "H1";
|
||||
constexpr char responsePacketMagicHeader[] = "H2";
|
||||
constexpr char underloadPacketMagicHeader[] = "H3";
|
||||
constexpr char transportPacketMagicHeader[] = "H4";
|
||||
|
||||
constexpr char openvpn[] = "openvpn";
|
||||
constexpr char wireguard[] = "wireguard";
|
||||
constexpr char shadowsocks[] = "shadowsocks";
|
||||
constexpr char cloak[] = "cloak";
|
||||
constexpr char sftp[] = "sftp";
|
||||
constexpr char awg[] = "awg";
|
||||
|
||||
}
|
||||
|
||||
|
@ -140,6 +151,25 @@ namespace amnezia
|
|||
|
||||
} // namespace sftp
|
||||
|
||||
namespace awg
|
||||
{
|
||||
constexpr char defaultPort[] = "55424";
|
||||
|
||||
constexpr char serverConfigPath[] = "/opt/amnezia/awg/wg0.conf";
|
||||
constexpr char serverPublicKeyPath[] = "/opt/amnezia/awg/wireguard_server_public_key.key";
|
||||
constexpr char serverPskKeyPath[] = "/opt/amnezia/awg/wireguard_psk.key";
|
||||
|
||||
constexpr char defaultJunkPacketCount[] = "3";
|
||||
constexpr char defaultJunkPacketMinSize[] = "10";
|
||||
constexpr char defaultJunkPacketMaxSize[] = "30";
|
||||
constexpr char defaultInitPacketJunkSize[] = "15";
|
||||
constexpr char defaultResponsePacketJunkSize[] = "18";
|
||||
constexpr char defaultInitPacketMagicHeader[] = "1020325451";
|
||||
constexpr char defaultResponsePacketMagicHeader[] = "3288052141";
|
||||
constexpr char defaultTransportPacketMagicHeader[] = "2528465083";
|
||||
constexpr char defaultUnderloadPacketMagicHeader[] = "1766607858";
|
||||
}
|
||||
|
||||
} // namespace protocols
|
||||
|
||||
namespace ProtocolEnumNS
|
||||
|
@ -158,13 +188,13 @@ namespace amnezia
|
|||
ShadowSocks,
|
||||
Cloak,
|
||||
WireGuard,
|
||||
Awg,
|
||||
Ikev2,
|
||||
L2tp,
|
||||
|
||||
// non-vpn
|
||||
TorWebSite,
|
||||
Dns,
|
||||
FileShare,
|
||||
Sftp
|
||||
};
|
||||
Q_ENUM_NS(Proto)
|
||||
|
@ -198,6 +228,8 @@ namespace amnezia
|
|||
|
||||
Q_INVOKABLE static ServiceType protocolService(Proto p);
|
||||
|
||||
Q_INVOKABLE static int getPortForInstall(Proto p);
|
||||
|
||||
Q_INVOKABLE static int defaultPort(Proto p);
|
||||
Q_INVOKABLE static bool defaultPortChangeable(Proto p);
|
||||
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
#include "vpnprotocol.h"
|
||||
#include "core/errorstrings.h"
|
||||
#include "vpnprotocol.h"
|
||||
|
||||
#if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
|
||||
#include "openvpnprotocol.h"
|
||||
#include "shadowsocksvpnprotocol.h"
|
||||
#include "openvpnovercloakprotocol.h"
|
||||
#include "wireguardprotocol.h"
|
||||
#include "openvpnovercloakprotocol.h"
|
||||
#include "openvpnprotocol.h"
|
||||
#include "shadowsocksvpnprotocol.h"
|
||||
#include "wireguardprotocol.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
#include "ikev2_vpn_protocol_windows.h"
|
||||
#include "ikev2_vpn_protocol_windows.h"
|
||||
#endif
|
||||
|
||||
|
||||
VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject* parent)
|
||||
VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_connectionState(Vpn::ConnectionState::Unknown),
|
||||
m_rawConfig(configuration),
|
||||
|
@ -31,7 +30,7 @@ VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject* parent)
|
|||
void VpnProtocol::setLastError(ErrorCode lastError)
|
||||
{
|
||||
m_lastError = lastError;
|
||||
if (lastError){
|
||||
if (lastError) {
|
||||
setConnectionState(Vpn::ConnectionState::Error);
|
||||
}
|
||||
qCritical().noquote() << "VpnProtocol error, code" << m_lastError << errorString(m_lastError);
|
||||
|
@ -103,7 +102,7 @@ QString VpnProtocol::vpnGateway() const
|
|||
return m_vpnGateway;
|
||||
}
|
||||
|
||||
VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject& configuration)
|
||||
VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject &configuration)
|
||||
{
|
||||
switch (container) {
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
|
@ -114,6 +113,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject&
|
|||
case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration);
|
||||
case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration);
|
||||
case DockerContainer::WireGuard: return new WireguardProtocol(configuration);
|
||||
case DockerContainer::Awg: return new WireguardProtocol(configuration);
|
||||
#endif
|
||||
default: return nullptr;
|
||||
}
|
||||
|
@ -135,8 +135,7 @@ QString VpnProtocol::textConnectionState(Vpn::ConnectionState connectionState)
|
|||
case Vpn::ConnectionState::Disconnecting: return tr("Disconnecting...");
|
||||
case Vpn::ConnectionState::Reconnecting: return tr("Reconnecting...");
|
||||
case Vpn::ConnectionState::Error: return tr("Error");
|
||||
default:
|
||||
;
|
||||
default:;
|
||||
}
|
||||
|
||||
return QString();
|
||||
|
|
|
@ -217,5 +217,11 @@
|
|||
<file>ui/qml/Controls2/TopCloseButtonType.qml</file>
|
||||
<file>images/controls/x-circle.svg</file>
|
||||
<file>ui/qml/Controls2/Drawer2Type.qml</file>
|
||||
<file>ui/qml/Pages2/PageProtocolAwgSettings.qml</file>
|
||||
<file>server_scripts/awg/template.conf</file>
|
||||
<file>server_scripts/awg/start.sh</file>
|
||||
<file>server_scripts/awg/configure_container.sh</file>
|
||||
<file>server_scripts/awg/run_container.sh</file>
|
||||
<file>server_scripts/awg/Dockerfile</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
46
client/server_scripts/awg/Dockerfile
Normal file
46
client/server_scripts/awg/Dockerfile
Normal file
|
@ -0,0 +1,46 @@
|
|||
FROM amneziavpn/amnezia-wg:latest
|
||||
|
||||
LABEL maintainer="AmneziaVPN"
|
||||
|
||||
#Install required packages
|
||||
RUN apk add --no-cache bash curl dumb-init
|
||||
RUN apk --update upgrade --no-cache
|
||||
|
||||
RUN mkdir -p /opt/amnezia
|
||||
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
||||
RUN chmod a+x /opt/amnezia/start.sh
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
fs.file-max = 51200 \n\
|
||||
\n\
|
||||
net.core.rmem_max = 67108864 \n\
|
||||
net.core.wmem_max = 67108864 \n\
|
||||
net.core.netdev_max_backlog = 250000 \n\
|
||||
net.core.somaxconn = 4096 \n\
|
||||
\n\
|
||||
net.ipv4.tcp_syncookies = 1 \n\
|
||||
net.ipv4.tcp_tw_reuse = 1 \n\
|
||||
net.ipv4.tcp_tw_recycle = 0 \n\
|
||||
net.ipv4.tcp_fin_timeout = 30 \n\
|
||||
net.ipv4.tcp_keepalive_time = 1200 \n\
|
||||
net.ipv4.ip_local_port_range = 10000 65000 \n\
|
||||
net.ipv4.tcp_max_syn_backlog = 8192 \n\
|
||||
net.ipv4.tcp_max_tw_buckets = 5000 \n\
|
||||
net.ipv4.tcp_fastopen = 3 \n\
|
||||
net.ipv4.tcp_mem = 25600 51200 102400 \n\
|
||||
net.ipv4.tcp_rmem = 4096 87380 67108864 \n\
|
||||
net.ipv4.tcp_wmem = 4096 65536 67108864 \n\
|
||||
net.ipv4.tcp_mtu_probing = 1 \n\
|
||||
net.ipv4.tcp_congestion_control = hybla \n\
|
||||
# for low-latency network, use cubic instead \n\
|
||||
# net.ipv4.tcp_congestion_control = cubic \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/sysctl.conf && \
|
||||
mkdir -p /etc/security && \
|
||||
echo -e " \n\
|
||||
* soft nofile 51200 \n\
|
||||
* hard nofile 51200 \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
||||
|
||||
ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ]
|
||||
CMD [ "" ]
|
26
client/server_scripts/awg/configure_container.sh
Normal file
26
client/server_scripts/awg/configure_container.sh
Normal file
|
@ -0,0 +1,26 @@
|
|||
mkdir -p /opt/amnezia/awg
|
||||
cd /opt/amnezia/awg
|
||||
WIREGUARD_SERVER_PRIVATE_KEY=$(wg genkey)
|
||||
echo $WIREGUARD_SERVER_PRIVATE_KEY > /opt/amnezia/awg/wireguard_server_private_key.key
|
||||
|
||||
WIREGUARD_SERVER_PUBLIC_KEY=$(echo $WIREGUARD_SERVER_PRIVATE_KEY | wg pubkey)
|
||||
echo $WIREGUARD_SERVER_PUBLIC_KEY > /opt/amnezia/awg/wireguard_server_public_key.key
|
||||
|
||||
WIREGUARD_PSK=$(wg genpsk)
|
||||
echo $WIREGUARD_PSK > /opt/amnezia/awg/wireguard_psk.key
|
||||
|
||||
cat > /opt/amnezia/awg/wg0.conf <<EOF
|
||||
[Interface]
|
||||
PrivateKey = $WIREGUARD_SERVER_PRIVATE_KEY
|
||||
Address = $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR
|
||||
ListenPort = $AWG_SERVER_PORT
|
||||
Jc = $JUNK_PACKET_COUNT
|
||||
Jmin = $JUNK_PACKET_MIN_SIZE
|
||||
Jmax = $JUNK_PACKET_MAX_SIZE
|
||||
S1 = $INIT_PACKET_JUNK_SIZE
|
||||
S2 = $RESPONSE_PACKET_JUNK_SIZE
|
||||
H1 = $INIT_PACKET_MAGIC_HEADER
|
||||
H2 = $RESPONSE_PACKET_MAGIC_HEADER
|
||||
H3 = $UNDERLOAD_PACKET_MAGIC_HEADER
|
||||
H4 = $TRANSPORT_PACKET_MAGIC_HEADER
|
||||
EOF
|
18
client/server_scripts/awg/run_container.sh
Normal file
18
client/server_scripts/awg/run_container.sh
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Run container
|
||||
sudo docker run -d \
|
||||
--log-driver none \
|
||||
--restart always \
|
||||
--privileged \
|
||||
--cap-add=NET_ADMIN \
|
||||
--cap-add=SYS_MODULE \
|
||||
-p $AWG_SERVER_PORT:$AWG_SERVER_PORT/udp \
|
||||
-v /lib/modules:/lib/modules \
|
||||
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
|
||||
--name $CONTAINER_NAME \
|
||||
$CONTAINER_NAME
|
||||
|
||||
sudo docker network connect amnezia-dns-net $CONTAINER_NAME
|
||||
|
||||
# Prevent to route packets outside of the container in case if server behind of the NAT
|
||||
#sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
|
||||
|
28
client/server_scripts/awg/start.sh
Normal file
28
client/server_scripts/awg/start.sh
Normal file
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
#ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||
|
||||
# kill daemons in case of restart
|
||||
wg-quick down /opt/amnezia/awg/wg0.conf
|
||||
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/awg/wg0.conf ]; then (wg-quick up /opt/amnezia/awg/wg0.conf); fi
|
||||
|
||||
# Allow traffic on the TUN interface.
|
||||
iptables -A INPUT -i wg0 -j ACCEPT
|
||||
iptables -A FORWARD -i wg0 -j ACCEPT
|
||||
iptables -A OUTPUT -o wg0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i wg0 -o eth0 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
|
||||
iptables -A FORWARD -i wg0 -o eth1 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
|
||||
|
||||
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth1 -j MASQUERADE
|
||||
|
||||
tail -f /dev/null
|
20
client/server_scripts/awg/template.conf
Normal file
20
client/server_scripts/awg/template.conf
Normal file
|
@ -0,0 +1,20 @@
|
|||
[Interface]
|
||||
Address = $WIREGUARD_CLIENT_IP/32
|
||||
DNS = $PRIMARY_DNS, $SECONDARY_DNS
|
||||
PrivateKey = $WIREGUARD_CLIENT_PRIVATE_KEY
|
||||
Jc = $JUNK_PACKET_COUNT
|
||||
Jmin = $JUNK_PACKET_MIN_SIZE
|
||||
Jmax = $JUNK_PACKET_MAX_SIZE
|
||||
S1 = $INIT_PACKET_JUNK_SIZE
|
||||
S2 = $RESPONSE_PACKET_JUNK_SIZE
|
||||
H1 = $INIT_PACKET_MAGIC_HEADER
|
||||
H2 = $RESPONSE_PACKET_MAGIC_HEADER
|
||||
H3 = $UNDERLOAD_PACKET_MAGIC_HEADER
|
||||
H4 = $TRANSPORT_PACKET_MAGIC_HEADER
|
||||
|
||||
[Peer]
|
||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||
PresharedKey = $WIREGUARD_PSK
|
||||
AllowedIPs = 0.0.0.0/0, ::/0
|
||||
Endpoint = $SERVER_IP_ADDRESS:$AWG_SERVER_PORT
|
||||
PersistentKeepalive = 25
|
|
@ -1 +1 @@
|
|||
sudo docker build -t $CONTAINER_NAME $DOCKERFILE_FOLDER --build-arg SERVER_ARCH=$(uname -m)
|
||||
sudo docker build --no-cache --pull -t $CONTAINER_NAME $DOCKERFILE_FOLDER --build-arg SERVER_ARCH=$(uname -m)
|
||||
|
|
|
@ -8,7 +8,7 @@ if ! command -v sudo > /dev/null 2>&1; then $pm update -yq; $pm install -yq sudo
|
|||
if ! command -v fuser > /dev/null 2>&1; then sudo $pm install -yq psmisc; fi;\
|
||||
if ! command -v lsof > /dev/null 2>&1; then sudo $pm install -yq lsof; fi;\
|
||||
if ! command -v docker > /dev/null 2>&1; then sudo $pm update -yq; sudo $pm install -yq $docker_pkg;\
|
||||
if [ "$dist" = "fedora" ] || [ "$dist" = "debian" ]; then sudo systemctl enable docker && sudo systemctl start docker; fi;\
|
||||
if [ "$dist" = "fedora" ] || [ "$dist" = "centos" ] || [ "$dist" = "debian" ]; then sudo systemctl enable docker && sudo systemctl start docker; fi;\
|
||||
fi;\
|
||||
if [ "$dist" = "debian" ]; then \
|
||||
docker_service=$(systemctl list-units --full --all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -144,8 +144,6 @@ void ImportController::importConfig()
|
|||
if (credentials.isValid() || m_config.contains(config_key::containers)) {
|
||||
m_serversModel->addServer(m_config);
|
||||
|
||||
m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1);
|
||||
|
||||
emit importFinished();
|
||||
} else {
|
||||
qDebug() << "Failed to import profile";
|
||||
|
@ -214,21 +212,75 @@ QJsonObject ImportController::extractOpenVpnConfig(const QString &data)
|
|||
|
||||
QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
{
|
||||
QMap<QString, QString> configMap;
|
||||
auto configByLines = data.split("\n");
|
||||
for (const QString &line : configByLines) {
|
||||
QString trimmedLine = line.trimmed();
|
||||
if (trimmedLine.startsWith("[") && trimmedLine.endsWith("]")) {
|
||||
continue;
|
||||
} else {
|
||||
QStringList parts = trimmedLine.split(" = ");
|
||||
if (parts.count() == 2) {
|
||||
configMap[parts.at(0).trimmed()] = parts.at(1).trimmed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject lastConfig;
|
||||
lastConfig[config_key::config] = data;
|
||||
|
||||
const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*)(?::([0-9]*))?");
|
||||
const static QRegularExpression hostNameAndPortRegExp("Endpoint = (.*):([0-9]*)");
|
||||
QRegularExpressionMatch hostNameAndPortMatch = hostNameAndPortRegExp.match(data);
|
||||
QString hostName;
|
||||
QString port;
|
||||
if (hostNameAndPortMatch.hasCaptured(1)) {
|
||||
hostName = hostNameAndPortMatch.captured(1);
|
||||
} /*else {
|
||||
qDebug() << "send error?"
|
||||
}*/
|
||||
} else {
|
||||
qDebug() << "Failed to import profile";
|
||||
emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError));
|
||||
}
|
||||
|
||||
if (hostNameAndPortMatch.hasCaptured(2)) {
|
||||
port = hostNameAndPortMatch.captured(2);
|
||||
} else {
|
||||
port = protocols::wireguard::defaultPort;
|
||||
}
|
||||
|
||||
lastConfig[config_key::hostName] = hostName;
|
||||
lastConfig[config_key::port] = port.toInt();
|
||||
|
||||
// if (!configMap.value("PrivateKey").isEmpty() && !configMap.value("Address").isEmpty()
|
||||
// && !configMap.value("PresharedKey").isEmpty() && !configMap.value("PublicKey").isEmpty()) {
|
||||
lastConfig[config_key::client_priv_key] = configMap.value("PrivateKey");
|
||||
lastConfig[config_key::client_ip] = configMap.value("Address");
|
||||
lastConfig[config_key::psk_key] = configMap.value("PresharedKey");
|
||||
lastConfig[config_key::server_pub_key] = configMap.value("PublicKey");
|
||||
// } else {
|
||||
// qDebug() << "Failed to import profile";
|
||||
// emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError));
|
||||
// return QJsonObject();
|
||||
// }
|
||||
|
||||
QString protocolName = "wireguard";
|
||||
if (!configMap.value(config_key::junkPacketCount).isEmpty()
|
||||
&& !configMap.value(config_key::junkPacketMinSize).isEmpty()
|
||||
&& !configMap.value(config_key::junkPacketMaxSize).isEmpty()
|
||||
&& !configMap.value(config_key::initPacketJunkSize).isEmpty()
|
||||
&& !configMap.value(config_key::responsePacketJunkSize).isEmpty()
|
||||
&& !configMap.value(config_key::initPacketMagicHeader).isEmpty()
|
||||
&& !configMap.value(config_key::responsePacketMagicHeader).isEmpty()
|
||||
&& !configMap.value(config_key::underloadPacketMagicHeader).isEmpty()
|
||||
&& !configMap.value(config_key::transportPacketMagicHeader).isEmpty()) {
|
||||
lastConfig[config_key::junkPacketCount] = configMap.value(config_key::junkPacketCount);
|
||||
lastConfig[config_key::junkPacketMinSize] = configMap.value(config_key::junkPacketMinSize);
|
||||
lastConfig[config_key::junkPacketMaxSize] = configMap.value(config_key::junkPacketMaxSize);
|
||||
lastConfig[config_key::initPacketJunkSize] = configMap.value(config_key::initPacketJunkSize);
|
||||
lastConfig[config_key::responsePacketJunkSize] = configMap.value(config_key::responsePacketJunkSize);
|
||||
lastConfig[config_key::initPacketMagicHeader] = configMap.value(config_key::initPacketMagicHeader);
|
||||
lastConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader);
|
||||
lastConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader);
|
||||
lastConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader);
|
||||
protocolName = "awg";
|
||||
}
|
||||
|
||||
QJsonObject wireguardConfig;
|
||||
|
@ -238,15 +290,15 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
|||
wireguardConfig[config_key::transport_proto] = "udp";
|
||||
|
||||
QJsonObject containers;
|
||||
containers.insert(config_key::container, QJsonValue("amnezia-wireguard"));
|
||||
containers.insert(config_key::wireguard, QJsonValue(wireguardConfig));
|
||||
containers.insert(config_key::container, QJsonValue("amnezia-" + protocolName));
|
||||
containers.insert(protocolName, QJsonValue(wireguardConfig));
|
||||
|
||||
QJsonArray arr;
|
||||
arr.push_back(containers);
|
||||
|
||||
QJsonObject config;
|
||||
config[config_key::containers] = arr;
|
||||
config[config_key::defaultContainer] = "amnezia-wireguard";
|
||||
config[config_key::defaultContainer] = "amnezia-" + protocolName;
|
||||
config[config_key::description] = m_settings->nextAvailableServerName();
|
||||
|
||||
const static QRegularExpression dnsRegExp(
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QEventLoop>
|
||||
#include <QJsonObject>
|
||||
#include <QStandardPaths>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
#include "core/errorstrings.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
@ -73,6 +74,38 @@ void InstallController::install(DockerContainer container, int port, TransportPr
|
|||
containerConfig.insert(config_key::transport_proto,
|
||||
ProtocolProps::transportProtoToString(transportProto, protocol));
|
||||
|
||||
if (container == DockerContainer::Awg) {
|
||||
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(3, 10));
|
||||
QString junkPacketMinSize = QString::number(50);
|
||||
QString junkPacketMaxSize = QString::number(1000);
|
||||
QString initPacketJunkSize = QString::number(QRandomGenerator::global()->bounded(15, 150));
|
||||
QString responsePacketJunkSize = QString::number(QRandomGenerator::global()->bounded(15, 150));
|
||||
|
||||
QSet<QString> headersValue;
|
||||
while (headersValue.size() != 4) {
|
||||
|
||||
auto max = (std::numeric_limits<qint32>::max)();
|
||||
headersValue.insert(QString::number(QRandomGenerator::global()->bounded(1, max)));
|
||||
}
|
||||
|
||||
auto headersValueList = headersValue.values();
|
||||
|
||||
QString initPacketMagicHeader = headersValueList.at(0);
|
||||
QString responsePacketMagicHeader = headersValueList.at(1);
|
||||
QString underloadPacketMagicHeader = headersValueList.at(2);
|
||||
QString transportPacketMagicHeader = headersValueList.at(3);
|
||||
|
||||
containerConfig[config_key::junkPacketCount] = junkPacketCount;
|
||||
containerConfig[config_key::junkPacketMinSize] = junkPacketMinSize;
|
||||
containerConfig[config_key::junkPacketMaxSize] = junkPacketMaxSize;
|
||||
containerConfig[config_key::initPacketJunkSize] = initPacketJunkSize;
|
||||
containerConfig[config_key::responsePacketJunkSize] = responsePacketJunkSize;
|
||||
containerConfig[config_key::initPacketMagicHeader] = initPacketMagicHeader;
|
||||
containerConfig[config_key::responsePacketMagicHeader] = responsePacketMagicHeader;
|
||||
containerConfig[config_key::underloadPacketMagicHeader] = underloadPacketMagicHeader;
|
||||
containerConfig[config_key::transportPacketMagicHeader] = transportPacketMagicHeader;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Sftp) {
|
||||
containerConfig.insert(config_key::userName, protocols::sftp::defaultUserName);
|
||||
containerConfig.insert(config_key::password, Utils::getRandomString(10));
|
||||
|
@ -132,7 +165,6 @@ void InstallController::installServer(DockerContainer container, QJsonObject &co
|
|||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||
|
||||
m_serversModel->addServer(server);
|
||||
m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1);
|
||||
|
||||
emit installServerFinished(finishMessage);
|
||||
return;
|
||||
|
@ -183,7 +215,6 @@ void InstallController::installContainer(DockerContainer container, QJsonObject
|
|||
"All installed containers have been added to the application");
|
||||
}
|
||||
|
||||
m_containersModel->setData(m_containersModel->index(0, 0), container, ContainersModel::Roles::IsDefaultRole);
|
||||
emit installContainerFinished(finishMessage, ContainerProps::containerService(container) == ServiceType::Other);
|
||||
return;
|
||||
}
|
||||
|
@ -473,8 +504,9 @@ void InstallController::addEmptyServer()
|
|||
server.insert(config_key::port, m_currentlyInstalledServerCredentials.port);
|
||||
server.insert(config_key::description, m_settings->nextAvailableServerName());
|
||||
|
||||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
||||
|
||||
m_serversModel->addServer(server);
|
||||
m_serversModel->setDefaultServerIndex(m_serversModel->getServersCount() - 1);
|
||||
|
||||
emit installServerFinished(tr("Server added successfully"));
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace PageLoader
|
|||
PageProtocolShadowSocksSettings,
|
||||
PageProtocolCloakSettings,
|
||||
PageProtocolWireGuardSettings,
|
||||
PageProtocolAwgSettings,
|
||||
PageProtocolIKev2Settings,
|
||||
PageProtocolRaw
|
||||
};
|
||||
|
|
|
@ -97,7 +97,7 @@ void SitesController::importSites(const QString &fileName, bool replaceExisting)
|
|||
}
|
||||
|
||||
if (!jsonDocument.isArray()) {
|
||||
emit errorOccurred(tr("The JSON data is not an array in file: ").arg(fileName));
|
||||
emit errorOccurred(tr("The JSON data is not an array in file: %1").arg(fileName));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ bool ContainersModel::setData(const QModelIndex &index, const QVariant &value, i
|
|||
// return container;
|
||||
case IsInstalledRole:
|
||||
// return m_settings->containers(m_currentlyProcessedServerIndex).contains(container);
|
||||
case IsDefaultRole: {
|
||||
case IsDefaultRole: { //todo remove
|
||||
m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, container);
|
||||
m_defaultContainerIndex = container;
|
||||
emit defaultContainerChanged();
|
||||
|
@ -117,6 +117,13 @@ QString ContainersModel::getDefaultContainerName()
|
|||
return ContainerProps::containerHumanNames().value(m_defaultContainerIndex);
|
||||
}
|
||||
|
||||
void ContainersModel::setDefaultContainer(DockerContainer container)
|
||||
{
|
||||
m_settings->setDefaultContainer(m_currentlyProcessedServerIndex, container);
|
||||
m_defaultContainerIndex = container;
|
||||
emit defaultContainerChanged();
|
||||
}
|
||||
|
||||
int ContainersModel::getCurrentlyProcessedContainerIndex()
|
||||
{
|
||||
return m_currentlyProcessedContainerIndex;
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
public slots:
|
||||
DockerContainer getDefaultContainer();
|
||||
QString getDefaultContainerName();
|
||||
void setDefaultContainer(DockerContainer container);
|
||||
|
||||
void setCurrentlyProcessedServerIndex(const int index);
|
||||
|
||||
|
|
137
client/ui/models/protocols/awgConfigModel.cpp
Normal file
137
client/ui/models/protocols/awgConfigModel.cpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include "awgConfigModel.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
AwgConfigModel::AwgConfigModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int AwgConfigModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::JunkPacketCountRole: m_protocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||
case Roles::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||
case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||
case Roles::InitPacketJunkSizeRole:
|
||||
m_protocolConfig.insert(config_key::initPacketJunkSize, value.toString());
|
||||
break;
|
||||
case Roles::ResponsePacketJunkSizeRole:
|
||||
m_protocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
|
||||
break;
|
||||
case Roles::InitPacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::initPacketMagicHeader, value.toString());
|
||||
break;
|
||||
case Roles::ResponsePacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
|
||||
break;
|
||||
case Roles::UnderloadPacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString());
|
||||
break;
|
||||
case Roles::TransportPacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::transportPacketMagicHeader, value.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
emit dataChanged(index, index, QList { role });
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||
case Roles::JunkPacketCountRole: return m_protocolConfig.value(config_key::junkPacketCount);
|
||||
case Roles::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize);
|
||||
case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize);
|
||||
case Roles::InitPacketJunkSizeRole: return m_protocolConfig.value(config_key::initPacketJunkSize);
|
||||
case Roles::ResponsePacketJunkSizeRole: return m_protocolConfig.value(config_key::responsePacketJunkSize);
|
||||
case Roles::InitPacketMagicHeaderRole: return m_protocolConfig.value(config_key::initPacketMagicHeader);
|
||||
case Roles::ResponsePacketMagicHeaderRole: return m_protocolConfig.value(config_key::responsePacketMagicHeader);
|
||||
case Roles::UnderloadPacketMagicHeaderRole: return m_protocolConfig.value(config_key::underloadPacketMagicHeader);
|
||||
case Roles::TransportPacketMagicHeaderRole: return m_protocolConfig.value(config_key::transportPacketMagicHeader);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void AwgConfigModel::updateModel(const QJsonObject &config)
|
||||
{
|
||||
beginResetModel();
|
||||
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
|
||||
|
||||
m_fullConfig = config;
|
||||
|
||||
QJsonObject protocolConfig = config.value(config_key::awg).toObject();
|
||||
|
||||
m_protocolConfig[config_key::port] =
|
||||
protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||
m_protocolConfig[config_key::junkPacketCount] =
|
||||
protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||
m_protocolConfig[config_key::junkPacketMinSize] =
|
||||
protocolConfig.value(config_key::junkPacketMinSize)
|
||||
.toString(protocols::awg::defaultJunkPacketMinSize);
|
||||
m_protocolConfig[config_key::junkPacketMaxSize] =
|
||||
protocolConfig.value(config_key::junkPacketMaxSize)
|
||||
.toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||
m_protocolConfig[config_key::initPacketJunkSize] =
|
||||
protocolConfig.value(config_key::initPacketJunkSize)
|
||||
.toString(protocols::awg::defaultInitPacketJunkSize);
|
||||
m_protocolConfig[config_key::responsePacketJunkSize] =
|
||||
protocolConfig.value(config_key::responsePacketJunkSize)
|
||||
.toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||
m_protocolConfig[config_key::initPacketMagicHeader] =
|
||||
protocolConfig.value(config_key::initPacketMagicHeader)
|
||||
.toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||
m_protocolConfig[config_key::responsePacketMagicHeader] =
|
||||
protocolConfig.value(config_key::responsePacketMagicHeader)
|
||||
.toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||
m_protocolConfig[config_key::underloadPacketMagicHeader] =
|
||||
protocolConfig.value(config_key::underloadPacketMagicHeader)
|
||||
.toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||
m_protocolConfig[config_key::transportPacketMagicHeader] =
|
||||
protocolConfig.value(config_key::transportPacketMagicHeader)
|
||||
.toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QJsonObject AwgConfigModel::getConfig()
|
||||
{
|
||||
m_fullConfig.insert(config_key::awg, m_protocolConfig);
|
||||
return m_fullConfig;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
|
||||
roles[PortRole] = "port";
|
||||
roles[JunkPacketCountRole] = "junkPacketCount";
|
||||
roles[JunkPacketMinSizeRole] = "junkPacketMinSize";
|
||||
roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize";
|
||||
roles[InitPacketJunkSizeRole] = "initPacketJunkSize";
|
||||
roles[ResponsePacketJunkSizeRole] = "responsePacketJunkSize";
|
||||
roles[InitPacketMagicHeaderRole] = "initPacketMagicHeader";
|
||||
roles[ResponsePacketMagicHeaderRole] = "responsePacketMagicHeader";
|
||||
roles[UnderloadPacketMagicHeaderRole] = "underloadPacketMagicHeader";
|
||||
roles[TransportPacketMagicHeaderRole] = "transportPacketMagicHeader";
|
||||
|
||||
return roles;
|
||||
}
|
47
client/ui/models/protocols/awgConfigModel.h
Normal file
47
client/ui/models/protocols/awgConfigModel.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef AWGCONFIGMODEL_H
|
||||
#define AWGCONFIGMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
|
||||
class AwgConfigModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
PortRole = Qt::UserRole + 1,
|
||||
JunkPacketCountRole,
|
||||
JunkPacketMinSizeRole,
|
||||
JunkPacketMaxSizeRole,
|
||||
InitPacketJunkSizeRole,
|
||||
ResponsePacketJunkSizeRole,
|
||||
InitPacketMagicHeaderRole,
|
||||
ResponsePacketMagicHeaderRole,
|
||||
UnderloadPacketMagicHeaderRole,
|
||||
TransportPacketMagicHeaderRole
|
||||
};
|
||||
|
||||
explicit AwgConfigModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
public slots:
|
||||
void updateModel(const QJsonObject &config);
|
||||
QJsonObject getConfig();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
DockerContainer m_container;
|
||||
QJsonObject m_protocolConfig;
|
||||
QJsonObject m_fullConfig;
|
||||
};
|
||||
|
||||
#endif // AWGCONFIGMODEL_H
|
|
@ -78,12 +78,11 @@ PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
|
|||
case Proto::ShadowSocks: return PageLoader::PageEnum::PageProtocolShadowSocksSettings;
|
||||
case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardSettings;
|
||||
case Proto::Ikev2: return PageLoader::PageEnum::PageProtocolIKev2Settings;
|
||||
case Proto::L2tp: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
case Proto::L2tp: return PageLoader::PageEnum::PageProtocolIKev2Settings;
|
||||
// non-vpn
|
||||
case Proto::TorWebSite: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
case Proto::Dns: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
case Proto::FileShare: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
case Proto::Sftp: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
case Proto::TorWebSite: return PageLoader::PageEnum::PageServiceTorWebsiteSettings;
|
||||
case Proto::Dns: return PageLoader::PageEnum::PageServiceDnsSettings;
|
||||
case Proto::Sftp: return PageLoader::PageEnum::PageServiceSftpSettings;
|
||||
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ void ServersModel::setDefaultServerIndex(const int index)
|
|||
{
|
||||
m_settings->setDefaultServer(index);
|
||||
m_defaultServerIndex = m_settings->defaultServerIndex();
|
||||
emit defaultServerIndexChanged();
|
||||
emit defaultServerIndexChanged(m_defaultServerIndex);
|
||||
}
|
||||
|
||||
const int ServersModel::getDefaultServerIndex()
|
||||
|
|
|
@ -64,7 +64,7 @@ protected:
|
|||
|
||||
signals:
|
||||
void currentlyProcessedServerIndexChanged(const int index);
|
||||
void defaultServerIndexChanged();
|
||||
void defaultServerIndexChanged(const int index);
|
||||
void defaultServerNameChanged();
|
||||
|
||||
private:
|
||||
|
|
|
@ -142,6 +142,7 @@ Button {
|
|||
PageController.setTriggeredBtConnectButton(true)
|
||||
|
||||
ServersModel.currentlyProcessedIndex = ServersModel.getDefaultServerIndex()
|
||||
InstallController.setShouldCreateServer(false)
|
||||
PageController.goToPage(PageEnum.PageSetupWizardEasy)
|
||||
|
||||
return
|
||||
|
|
|
@ -23,16 +23,14 @@ Drawer2Type {
|
|||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
|
||||
Header2TextType {
|
||||
Header2Type {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.bottomMargin: 32
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: 16
|
||||
|
||||
text: qsTr("Connection data")
|
||||
wrapMode: Text.WordWrap
|
||||
headerText: qsTr("Add new connection")
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
|
@ -40,7 +38,7 @@ Drawer2Type {
|
|||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
text: qsTr("Server IP, login and password")
|
||||
text: qsTr("Configure your server")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
|
@ -54,7 +52,7 @@ Drawer2Type {
|
|||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("QR code, key or configuration file")
|
||||
text: qsTr("Open config file, key or QR code")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
|
|
|
@ -50,35 +50,26 @@ ListView {
|
|||
imageSource: "qrc:/images/controls/download.svg"
|
||||
showImage: !isInstalled
|
||||
|
||||
checkable: isInstalled
|
||||
checkable: isInstalled && !ConnectionController.isConnected && isSupported
|
||||
checked: isDefault
|
||||
|
||||
onPressed: function(mouse) {
|
||||
if (!isSupported) {
|
||||
PageController.showErrorMessage(qsTr("The selected protocol is not supported on the current platform"))
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (checked) {
|
||||
var needReconnected = false
|
||||
if (!isDefault) {
|
||||
needReconnected = true
|
||||
}
|
||||
if (ConnectionController.isConnected && isInstalled) {
|
||||
PageController.showNotificationMessage(qsTr("Unable change protocol while there is an active connection"))
|
||||
return
|
||||
}
|
||||
|
||||
if (checked) {
|
||||
isDefault = true
|
||||
|
||||
menuContent.currentIndex = index
|
||||
containersDropDown.menu.close()
|
||||
|
||||
|
||||
if (needReconnected &&
|
||||
(ConnectionController.isConnected || ConnectionController.isConnectionInProgress)) {
|
||||
PageController.showNotificationMessage(qsTr("Reconnect via VPN Procotol: ") + name)
|
||||
PageController.goToPageHome()
|
||||
ConnectionController.openConnection()
|
||||
}
|
||||
} else {
|
||||
if (!isSupported && isInstalled) {
|
||||
PageController.showErrorMessage(qsTr("The selected protocol is not supported on the current platform"))
|
||||
return
|
||||
}
|
||||
|
||||
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(index))
|
||||
InstallController.setShouldCreateServer(false)
|
||||
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
|
||||
|
|
|
@ -64,6 +64,11 @@ ListView {
|
|||
// goToPage(PageEnum.PageProtocolWireGuardSettings)
|
||||
break
|
||||
}
|
||||
case ContainerEnum.Awg: {
|
||||
AwgConfigModel.updateModel(config)
|
||||
PageController.goToPage(PageEnum.PageProtocolAwgSettings)
|
||||
break
|
||||
}
|
||||
case ContainerEnum.Ipsec: {
|
||||
ProtocolsModel.updateModel(config)
|
||||
PageController.goToPage(PageEnum.PageProtocolRaw)
|
||||
|
|
|
@ -26,4 +26,16 @@ Item {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
TextEdit{
|
||||
id: clipboard
|
||||
visible: false
|
||||
}
|
||||
|
||||
function copyToClipBoard(text) {
|
||||
clipboard.text = text
|
||||
clipboard.selectAll()
|
||||
clipboard.copy()
|
||||
clipboard.select(0, 0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ RadioButton {
|
|||
|
||||
Text {
|
||||
text: root.headerText
|
||||
wrapMode: Text.WordWrap
|
||||
color: "#D7D8DB"
|
||||
font.pixelSize: 25
|
||||
font.weight: 700
|
||||
|
@ -110,6 +111,7 @@ RadioButton {
|
|||
|
||||
Text {
|
||||
text: root.footerText
|
||||
wrapMode: Text.WordWrap
|
||||
visible: root.footerText !== ""
|
||||
color: "#878B91"
|
||||
font.pixelSize: 13
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
import "../Config"
|
||||
|
||||
Drawer {
|
||||
id: drawer
|
||||
property bool needCloseButton: true
|
||||
|
@ -39,6 +41,18 @@ Drawer {
|
|||
|
||||
border.color: "#2C2D30"
|
||||
border.width: 1
|
||||
|
||||
Rectangle {
|
||||
visible: GC.isMobile()
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.topMargin: 10
|
||||
|
||||
width: 20
|
||||
height: 2
|
||||
color: "#2C2D30"
|
||||
}
|
||||
}
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
|
|
|
@ -20,7 +20,9 @@ Item {
|
|||
property bool isLeftImageHoverEnabled: true //todo separete this qml file to 3
|
||||
|
||||
property string textColor: "#d7d8db"
|
||||
property string textDisabledColor: "#878B91"
|
||||
property string descriptionColor: "#878B91"
|
||||
property string descriptionDisabledColor: "#494B50"
|
||||
property real textOpacity: 1.0
|
||||
|
||||
property string rightImageColor: "#d7d8db"
|
||||
|
@ -71,7 +73,14 @@ Item {
|
|||
|
||||
ListItemTitleType {
|
||||
text: root.text
|
||||
color: root.descriptionOnTop ? root.descriptionColor : root.textColor
|
||||
color: {
|
||||
if (root.enabled) {
|
||||
return root.descriptionOnTop ? root.descriptionColor : root.textColor
|
||||
} else {
|
||||
return root.descriptionOnTop ? root.descriptionDisabledColor : root.textDisabledColor
|
||||
}
|
||||
}
|
||||
|
||||
maximumLineCount: root.textMaximumLineCount
|
||||
elide: root.textElide
|
||||
|
||||
|
@ -96,7 +105,13 @@ Item {
|
|||
id: description
|
||||
|
||||
text: root.descriptionText
|
||||
color: root.descriptionOnTop ? root.textColor : root.descriptionColor
|
||||
color: {
|
||||
if (root.enabled) {
|
||||
return root.descriptionOnTop ? root.textColor : root.descriptionColor
|
||||
} else {
|
||||
return root.descriptionOnTop ? root.textDisabledColor : root.descriptionDisabledColor
|
||||
}
|
||||
}
|
||||
|
||||
opacity: root.textOpacity
|
||||
|
||||
|
@ -157,7 +172,7 @@ Item {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
hoverEnabled: root.enabled
|
||||
|
||||
onEntered: {
|
||||
if (rightImageSource) {
|
||||
|
|
|
@ -30,17 +30,13 @@ Switch {
|
|||
property string hoveredIndicatorBackgroundColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
property string defaultIndicatorBackgroundColor: "transparent"
|
||||
|
||||
implicitWidth: content.implicitWidth + switcher.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
hoverEnabled: enabled ? true : false
|
||||
|
||||
indicator: Rectangle {
|
||||
id: switcher
|
||||
|
||||
anchors.left: content.right
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 4
|
||||
|
||||
implicitWidth: 52
|
||||
implicitHeight: 32
|
||||
|
@ -90,11 +86,11 @@ Switch {
|
|||
contentItem: ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: switcher.implicitWidth
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
ListItemTitleType {
|
||||
Layout.fillWidth: true
|
||||
rightPadding: indicator.width
|
||||
|
||||
text: root.text
|
||||
color: root.enabled ? root.textColor : root.textDisabledColor
|
||||
|
@ -104,6 +100,7 @@ Switch {
|
|||
id: description
|
||||
|
||||
Layout.fillWidth: true
|
||||
rightPadding: indicator.width
|
||||
|
||||
color: root.enabled ? root.descriptionTextColor : root.descriptionTextDisabledColor
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ Item {
|
|||
property string headerTextColor: "#878b91"
|
||||
|
||||
property alias errorText: errorField.text
|
||||
property bool checkEmptyText: false
|
||||
|
||||
property string buttonText
|
||||
property string buttonImageSource
|
||||
|
@ -99,6 +100,12 @@ Item {
|
|||
root.errorText = ""
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (checkEmptyText && textFieldText === "") {
|
||||
errorText = qsTr("The field can't be empty")
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
|
|
|
@ -138,8 +138,16 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: false
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 2
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: 24
|
||||
Layout.topMargin: 14
|
||||
Layout.leftMargin: 24
|
||||
Layout.rightMargin: 24
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
@ -210,9 +218,17 @@ PageType {
|
|||
|
||||
visible: buttonContent.expandedVisibility
|
||||
|
||||
DividerType {
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: false
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 2
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
}
|
||||
|
||||
Header1TextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.topMargin: 14
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
|
@ -386,10 +402,16 @@ PageType {
|
|||
}
|
||||
|
||||
checked: index === serversMenuContent.currentIndex
|
||||
checkable: !ConnectionController.isConnected
|
||||
|
||||
ButtonGroup.group: serversRadioButtonGroup
|
||||
|
||||
onClicked: {
|
||||
if (ConnectionController.isConnected) {
|
||||
PageController.showNotificationMessage(qsTr("Unable change server while there is an active connection"))
|
||||
return
|
||||
}
|
||||
|
||||
serversMenuContent.currentIndex = index
|
||||
|
||||
ServersModel.currentlyProcessedIndex = index
|
||||
|
|
329
client/ui/qml/Pages2/PageProtocolAwgSettings.qml
Normal file
329
client/ui/qml/Pages2/PageProtocolAwgSettings.qml
Normal file
|
@ -0,0 +1,329 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
import "../Components"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
Column {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
||||
|
||||
ListView {
|
||||
id: listview
|
||||
|
||||
width: parent.width
|
||||
height: listview.contentItem.height
|
||||
|
||||
clip: true
|
||||
interactive: false
|
||||
|
||||
model: AwgConfigModel
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: listview.width
|
||||
implicitHeight: col.implicitHeight
|
||||
|
||||
ColumnLayout {
|
||||
id: col
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
spacing: 0
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
headerText: qsTr("AmneziaWG settings")
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: portTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 40
|
||||
|
||||
headerText: qsTr("Port")
|
||||
textFieldText: port
|
||||
textField.maximumLength: 5
|
||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== port) {
|
||||
port = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: junkPacketCountTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Junk packet count")
|
||||
textFieldText: junkPacketCount
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
console.log("1")
|
||||
if (textFieldText === "") {
|
||||
textFieldText = "0"
|
||||
}
|
||||
|
||||
if (textFieldText !== junkPacketCount) {
|
||||
junkPacketCount = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: junkPacketMinSizeTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Junk packet minimum size")
|
||||
textFieldText: junkPacketMinSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== junkPacketMinSize) {
|
||||
junkPacketMinSize = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: junkPacketMaxSizeTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Junk packet maximum size")
|
||||
textFieldText: junkPacketMaxSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== junkPacketMaxSize) {
|
||||
junkPacketMaxSize = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: initPacketJunkSizeTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Init packet junk size")
|
||||
textFieldText: initPacketJunkSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== initPacketJunkSize) {
|
||||
initPacketJunkSize = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: responsePacketJunkSizeTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Response packet junk size")
|
||||
textFieldText: responsePacketJunkSize
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== responsePacketJunkSize) {
|
||||
responsePacketJunkSize = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: initPacketMagicHeaderTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Init packet magic header")
|
||||
textFieldText: initPacketMagicHeader
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== initPacketMagicHeader) {
|
||||
initPacketMagicHeader = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: responsePacketMagicHeaderTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Response packet magic header")
|
||||
textFieldText: responsePacketMagicHeader
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== responsePacketMagicHeader) {
|
||||
responsePacketMagicHeader = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: transportPacketMagicHeaderTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Transport packet magic header")
|
||||
textFieldText: transportPacketMagicHeader
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== transportPacketMagicHeader) {
|
||||
transportPacketMagicHeader = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: underloadPacketMagicHeaderTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Underload packet magic header")
|
||||
textFieldText: underloadPacketMagicHeader
|
||||
textField.validator: IntValidator { bottom: 0 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== underloadPacketMagicHeader) {
|
||||
underloadPacketMagicHeader = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.topMargin: 24
|
||||
Layout.leftMargin: -8
|
||||
implicitHeight: 32
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
textColor: "#EB5757"
|
||||
|
||||
text: qsTr("Remove AmneziaWG")
|
||||
|
||||
onClicked: {
|
||||
questionDrawer.headerText = qsTr("Remove AmneziaWG from server?")
|
||||
questionDrawer.descriptionText = qsTr("All users who you shared a connection with will no longer be able to connect to it.")
|
||||
questionDrawer.yesButtonText = qsTr("Continue")
|
||||
questionDrawer.noButtonText = qsTr("Cancel")
|
||||
|
||||
questionDrawer.yesButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||
InstallController.removeCurrentlyProcessedContainer()
|
||||
}
|
||||
questionDrawer.noButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
}
|
||||
questionDrawer.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 24
|
||||
|
||||
enabled: underloadPacketMagicHeaderTextField.errorText === "" &&
|
||||
transportPacketMagicHeaderTextField.errorText === "" &&
|
||||
responsePacketMagicHeaderTextField.errorText === "" &&
|
||||
initPacketMagicHeaderTextField.errorText === "" &&
|
||||
responsePacketJunkSizeTextField.errorText === "" &&
|
||||
initPacketJunkSizeTextField.errorText === "" &&
|
||||
junkPacketMaxSizeTextField.errorText === "" &&
|
||||
junkPacketMinSizeTextField.errorText === "" &&
|
||||
junkPacketCountTextField.errorText === "" &&
|
||||
portTextField.errorText === ""
|
||||
|
||||
text: qsTr("Save and Restart Amnezia")
|
||||
|
||||
onClicked: {
|
||||
forceActiveFocus()
|
||||
PageController.showBusyIndicator(true)
|
||||
InstallController.updateContainer(AwgConfigModel.getConfig())
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QuestionDrawer {
|
||||
id: questionDrawer
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import QtQuick.Layouts
|
|||
import SortFilterProxyModel 0.2
|
||||
|
||||
import PageEnum 1.0
|
||||
import ContainerEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
|
@ -256,6 +257,8 @@ PageType {
|
|||
|
||||
ColumnLayout {
|
||||
id: checkboxLayout
|
||||
|
||||
anchors.fill: parent
|
||||
CheckBoxType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
@ -355,6 +358,8 @@ PageType {
|
|||
Layout.leftMargin: -8
|
||||
implicitHeight: 32
|
||||
|
||||
visible: ContainersModel.getCurrentlyProcessedContainerIndex() === ContainerEnum.OpenVpn
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
|
|
|
@ -131,7 +131,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("Connection options ") + protocolName
|
||||
headerText: qsTr("Connection options %1").arg(protocolName)
|
||||
}
|
||||
|
||||
TextArea {
|
||||
|
@ -173,6 +173,8 @@ PageType {
|
|||
|
||||
width: parent.width
|
||||
|
||||
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
||||
|
||||
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
||||
textColor: "#EB5757"
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ PageType {
|
|||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
col.copyToClipBoard(descriptionText)
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ PageType {
|
|||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
col.copyToClipBoard(descriptionText)
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ PageType {
|
|||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
col.copyToClipBoard(descriptionText)
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
|
@ -147,23 +147,11 @@ PageType {
|
|||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
col.copyToClipBoard(descriptionText)
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
|
||||
TextEdit{
|
||||
id: clipboard
|
||||
visible: false
|
||||
}
|
||||
|
||||
function copyToClipBoard(text) {
|
||||
clipboard.text = text
|
||||
clipboard.selectAll()
|
||||
clipboard.copy()
|
||||
clipboard.select(0, 0)
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
visible: !GC.isMobile()
|
||||
|
||||
|
|
|
@ -78,23 +78,11 @@ PageType {
|
|||
rightImageColor: "#D7D8DB"
|
||||
|
||||
clickedFunction: function() {
|
||||
content.copyToClipBoard(descriptionText)
|
||||
GC.copyToClipBoard(descriptionText)
|
||||
PageController.showNotificationMessage(qsTr("Copied"))
|
||||
}
|
||||
}
|
||||
|
||||
TextEdit{
|
||||
id: clipboard
|
||||
visible: false
|
||||
}
|
||||
|
||||
function copyToClipBoard(text) {
|
||||
clipboard.text = text
|
||||
clipboard.selectAll()
|
||||
clipboard.copy()
|
||||
clipboard.select(0, 0)
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 40
|
||||
|
@ -121,7 +109,7 @@ PageType {
|
|||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("When configuring WordPress set the domain as this onion address.")
|
||||
text: qsTr("When configuring WordPress set the this onion address as domain.")
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
|
|
|
@ -95,6 +95,7 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
id: about
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("About AmneziaVPN")
|
||||
|
@ -109,7 +110,9 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
visible: GC.isDesktop()
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: about.height
|
||||
|
||||
text: qsTr("Close application")
|
||||
leftImageSource: "qrc:/images/controls/x-circle.svg"
|
||||
|
@ -120,7 +123,9 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
DividerType {
|
||||
visible: GC.isDesktop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ PageType {
|
|||
Layout.margins: 16
|
||||
|
||||
text: qsTr("Auto start")
|
||||
descriptionText: qsTr("Launch the application every time ") + Qt.platform.os + qsTr(" starts")
|
||||
descriptionText: qsTr("Launch the application every time the device is starts")
|
||||
|
||||
checked: SettingsController.isAutoStartEnabled()
|
||||
onCheckedChanged: {
|
||||
|
|
|
@ -103,6 +103,7 @@ PageType {
|
|||
PageController.showBusyIndicator(true)
|
||||
SettingsController.backupAppConfig(fileName)
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Backup file saved"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,10 +94,12 @@ PageType {
|
|||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
visible: GC.isDesktop()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Split site tunneling")
|
||||
descriptionText: qsTr("Allows you to choose which sites you want to use the VPN for.")
|
||||
text: qsTr("Site-based split tunneling")
|
||||
descriptionText: qsTr("Allows you to select which sites you want to access through the VPN")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
|
@ -105,12 +107,16 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
DividerType {
|
||||
visible: GC.isDesktop()
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
visible: false
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Separate application tunneling")
|
||||
text: qsTr("App-based split tunneling")
|
||||
descriptionText: qsTr("Allows you to use the VPN only for certain applications")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
|
@ -118,7 +124,9 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
DividerType {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ PageType {
|
|||
}
|
||||
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("If AmneziaDNS is not used or installed")
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ PageType {
|
|||
PageController.showBusyIndicator(true)
|
||||
SettingsController.exportLogsFile(fileName)
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Logs file saved"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
property bool pageEnabled: {
|
||||
return !ConnectionController.isConnected
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SitesController
|
||||
|
||||
|
@ -46,12 +50,12 @@ PageType {
|
|||
|
||||
QtObject {
|
||||
id: onlyForwardSites
|
||||
property string name: qsTr("Only the addresses in the list must be opened via VPN")
|
||||
property string name: qsTr("Addresses from the list should be accessed via VPN")
|
||||
property int type: routeMode.onlyForwardSites
|
||||
}
|
||||
QtObject {
|
||||
id: allExceptSites
|
||||
property string name: qsTr("Addresses from the list should never be opened via VPN")
|
||||
property string name: qsTr("Addresses from the list should not be accessed via VPN")
|
||||
property int type: routeMode.allExceptSites
|
||||
}
|
||||
|
||||
|
@ -78,10 +82,12 @@ PageType {
|
|||
|
||||
RowLayout {
|
||||
HeaderType {
|
||||
enabled: root.pageEnabled
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
|
||||
headerText: qsTr("Split site tunneling")
|
||||
headerText: qsTr("Split tunneling")
|
||||
}
|
||||
|
||||
SwitcherType {
|
||||
|
@ -89,6 +95,8 @@ PageType {
|
|||
|
||||
property int lastActiveRouteMode: routeMode.onlyForwardSites
|
||||
|
||||
enabled: root.pageEnabled
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
|
||||
|
@ -117,7 +125,7 @@ PageType {
|
|||
|
||||
drawerHeight: 0.4375
|
||||
|
||||
enabled: switcher.checked
|
||||
enabled: switcher.checked && root.pageEnabled
|
||||
|
||||
headerText: qsTr("Mode")
|
||||
|
||||
|
@ -157,9 +165,9 @@ PageType {
|
|||
FlickableType {
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: 16
|
||||
contentHeight: col.implicitHeight + connectButton.implicitHeight + connectButton.anchors.bottomMargin + connectButton.anchors.topMargin
|
||||
contentHeight: col.implicitHeight + addSiteButton.implicitHeight + addSiteButton.anchors.bottomMargin + addSiteButton.anchors.topMargin
|
||||
|
||||
enabled: switcher.checked
|
||||
enabled: switcher.checked && root.pageEnabled
|
||||
|
||||
Column {
|
||||
id: col
|
||||
|
@ -224,8 +232,17 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: addSiteButton
|
||||
anchors.bottomMargin: -24
|
||||
color: "#0E0E11"
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: connectButton
|
||||
id: addSiteButton
|
||||
|
||||
enabled: root.pageEnabled
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
|
|
|
@ -41,7 +41,7 @@ PageType {
|
|||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
headerText: qsTr("Server connection")
|
||||
headerText: qsTr("Configure your server")
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
|
@ -107,6 +107,14 @@ PageType {
|
|||
PageController.goToPage(PageEnum.PageSetupWizardEasy)
|
||||
}
|
||||
}
|
||||
|
||||
LabelTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 12
|
||||
|
||||
text: qsTr("All data you enter will remain strictly confidential
|
||||
and will not be shared or disclosed to the Amnezia or any third parties")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@ PageType {
|
|||
target: InstallController
|
||||
|
||||
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
|
||||
if (!ConnectionController.isConnected && !isServiceInstall) {
|
||||
ContainersModel.setDefaultContainer(ContainersModel.getCurrentlyProcessedContainerIndex)
|
||||
}
|
||||
|
||||
PageController.goToStartPage()
|
||||
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageHome)) {
|
||||
PageController.restorePageHomeState(true)
|
||||
|
@ -41,6 +45,10 @@ PageType {
|
|||
}
|
||||
|
||||
function onInstallServerFinished(finishedMessage) {
|
||||
if (!ConnectionController.isConnected) {
|
||||
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
||||
}
|
||||
|
||||
PageController.goToStartPage()
|
||||
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageSetupWizardStart)) {
|
||||
PageController.replaceStartPage()
|
||||
|
@ -59,8 +67,8 @@ PageType {
|
|||
|
||||
function onServerIsBusy(isBusy) {
|
||||
if (isBusy) {
|
||||
root.progressBarText = qsTr("Amnesia has detected that your server is currently ") +
|
||||
qsTr("busy installing other software. Amnesia installation ") +
|
||||
root.progressBarText = qsTr("Amnezia has detected that your server is currently ") +
|
||||
qsTr("busy installing other software. Amnezia installation ") +
|
||||
qsTr("will pause until the server finishes installing other software")
|
||||
root.isTimerRunning = false
|
||||
} else {
|
||||
|
|
|
@ -151,33 +151,16 @@ PageType {
|
|||
headerText: name
|
||||
}
|
||||
|
||||
TextField {
|
||||
implicitWidth: parent.width
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
Layout.bottomMargin: 16
|
||||
|
||||
padding: 0
|
||||
leftPadding: 0
|
||||
height: 24
|
||||
|
||||
color: "#D7D8DB"
|
||||
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.Medium
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
text: detailedDescription
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
readOnly: true
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
}
|
||||
textFormat: Text.MarkdownText
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
color: "transparent"
|
||||
|
@ -248,7 +231,7 @@ PageType {
|
|||
if (ProtocolProps.defaultPort(defaultContainerProto) < 0) {
|
||||
port.visible = false
|
||||
} else {
|
||||
port.textFieldText = ProtocolProps.defaultPort(defaultContainerProto)
|
||||
port.textFieldText = ProtocolProps.getPortForInstall(defaultContainerProto)
|
||||
}
|
||||
transportProtoSelector.currentIndex = ProtocolProps.defaultTransportProto(defaultContainerProto)
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ PageType {
|
|||
function onInstallationErrorOccurred(errorMessage) {
|
||||
PageController.showErrorMessage(errorMessage)
|
||||
|
||||
var currentPageName = tabBarStackView.currentItem.objectName
|
||||
var currentPageName = stackView.currentItem.objectName
|
||||
|
||||
if (currentPageName === PageController.getPagePath(PageEnum.PageSetupWizardInstalling)) {
|
||||
PageController.closePage()
|
||||
|
|
|
@ -24,6 +24,10 @@ PageType {
|
|||
}
|
||||
|
||||
function onImportFinished() {
|
||||
if (ConnectionController.isConnected) {
|
||||
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
||||
}
|
||||
|
||||
PageController.goToStartPage()
|
||||
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageSetupWizardStart)) {
|
||||
PageController.replaceStartPage()
|
||||
|
|
|
@ -172,7 +172,7 @@ PageType {
|
|||
Layout.bottomMargin: 24
|
||||
|
||||
text: accessTypeSelector.currentIndex === 0 ? qsTr("VPN access without the ability to manage the server") :
|
||||
qsTr("Access to server management. The user with whom you share full access to the connection will be able to add and remove your protocols and services to the servers, as well as change settings.")
|
||||
qsTr("Access to server management. The user with whom you share full access to the connection will be able to add and remove your protocols and services to the server, as well as change settings.")
|
||||
color: "#878B91"
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ PageType {
|
|||
tabBar.enabled = !visible
|
||||
}
|
||||
|
||||
function onShowTopCloseButton(visible) {
|
||||
topCloseButton.visible = visible
|
||||
}
|
||||
// function onShowTopCloseButton(visible) {
|
||||
// topCloseButton.visible = visible
|
||||
// }
|
||||
|
||||
function onEnableTabBar(enabled) {
|
||||
tabBar.enabled = enabled
|
||||
|
@ -139,10 +139,10 @@ PageType {
|
|||
connectionTypeSelection.parent = tabBarStackView
|
||||
}
|
||||
|
||||
onWidthChanged: {
|
||||
topCloseButton.x = tabBarStackView.x + tabBarStackView.width -
|
||||
topCloseButton.buttonWidth - topCloseButton.rightPadding
|
||||
}
|
||||
// onWidthChanged: {
|
||||
// topCloseButton.x = tabBarStackView.x + tabBarStackView.width -
|
||||
// topCloseButton.buttonWidth - topCloseButton.rightPadding
|
||||
// }
|
||||
}
|
||||
|
||||
TabBar {
|
||||
|
@ -242,11 +242,12 @@ PageType {
|
|||
z: 1
|
||||
}
|
||||
|
||||
TopCloseButtonType {
|
||||
id: topCloseButton
|
||||
x: tabBarStackView.width - topCloseButton.buttonWidth - topCloseButton.rightPadding
|
||||
z: 1
|
||||
}
|
||||
// TopCloseButtonType {
|
||||
// id: topCloseButton
|
||||
|
||||
// x: tabBarStackView.width - topCloseButton.buttonWidth - topCloseButton.rightPadding
|
||||
// z: 1
|
||||
// }
|
||||
|
||||
ConnectionTypeSelectionDrawer {
|
||||
id: connectionTypeSelection
|
||||
|
|
|
@ -96,16 +96,16 @@ if [ "${MAC_CERT_PW+x}" ]; then
|
|||
security find-identity -p codesigning
|
||||
|
||||
echo "Signing App bundle..."
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $BUNDLE_DIR
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "$MAC_SIGNER_ID" $BUNDLE_DIR
|
||||
/usr/bin/codesign --verify -vvvv $BUNDLE_DIR || true
|
||||
spctl -a -vvvv $BUNDLE_DIR || true
|
||||
|
||||
if [ "${NOTARIZE_APP+x}" ]; then
|
||||
echo "Notarizing App bundle..."
|
||||
/usr/bin/ditto -c -k --keepParent $BUNDLE_DIR $PROJECT_DIR/Bundle_to_notarize.zip
|
||||
xcrun altool --notarize-app -f $PROJECT_DIR/Bundle_to_notarize.zip -t osx --primary-bundle-id "$APP_DOMAIN" -u "$APPLE_DEV_EMAIL" -p $APPLE_DEV_PASSWORD
|
||||
xcrun notarytool submit $PROJECT_DIR/Bundle_to_notarize.zip --apple-id $APPLE_DEV_EMAIL --team-id $MAC_TEAM_ID --password $APPLE_DEV_PASSWORD
|
||||
rm $PROJECT_DIR/Bundle_to_notarize.zip
|
||||
sleep 600
|
||||
sleep 300
|
||||
xcrun stapler staple $BUNDLE_DIR
|
||||
xcrun stapler validate $BUNDLE_DIR
|
||||
spctl -a -vvvv $BUNDLE_DIR || true
|
||||
|
@ -130,15 +130,15 @@ $QIF_BIN_DIR/binarycreator --offline-only -v -c $BUILD_DIR/installer/config/maco
|
|||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
echo "Signing installer bundle..."
|
||||
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $INSTALLER_BUNDLE_DIR
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "$MAC_SIGNER_ID" $INSTALLER_BUNDLE_DIR
|
||||
/usr/bin/codesign --verify -vvvv $INSTALLER_BUNDLE_DIR || true
|
||||
|
||||
if [ "${NOTARIZE_APP+x}" ]; then
|
||||
echo "Notarizing installer bundle..."
|
||||
/usr/bin/ditto -c -k --keepParent $INSTALLER_BUNDLE_DIR $PROJECT_DIR/Installer_bundle_to_notarize.zip
|
||||
xcrun altool --notarize-app -f $PROJECT_DIR/Installer_bundle_to_notarize.zip -t osx --primary-bundle-id "$APP_DOMAIN" -u "$APPLE_DEV_EMAIL" -p $APPLE_DEV_PASSWORD
|
||||
xcrun notarytool submit $PROJECT_DIR/Installer_bundle_to_notarize.zip --apple-id $APPLE_DEV_EMAIL --team-id $MAC_TEAM_ID --password $APPLE_DEV_PASSWORD
|
||||
rm $PROJECT_DIR/Installer_bundle_to_notarize.zip
|
||||
sleep 600
|
||||
sleep 300
|
||||
xcrun stapler staple $INSTALLER_BUNDLE_DIR
|
||||
xcrun stapler validate $INSTALLER_BUNDLE_DIR
|
||||
spctl -a -vvvv $INSTALLER_BUNDLE_DIR || true
|
||||
|
@ -151,13 +151,13 @@ hdiutil create -volname AmneziaVPN -srcfolder $BUILD_DIR/installer/$APP_NAME.app
|
|||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
echo "Signing DMG installer..."
|
||||
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $DMG_FILENAME
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "$MAC_SIGNER_ID" $DMG_FILENAME
|
||||
/usr/bin/codesign --verify -vvvv $DMG_FILENAME || true
|
||||
|
||||
if [ "${NOTARIZE_APP+x}" ]; then
|
||||
echo "Notarizing DMG installer..."
|
||||
xcrun altool --notarize-app -f $DMG_FILENAME -t osx --primary-bundle-id $APP_DOMAIN -u $APPLE_DEV_EMAIL -p $APPLE_DEV_PASSWORD
|
||||
sleep 600
|
||||
xcrun notarytool submit $DMG_FILENAME --apple-id $APPLE_DEV_EMAIL --team-id $MAC_TEAM_ID --password $APPLE_DEV_PASSWORD
|
||||
sleep 300
|
||||
xcrun stapler staple $DMG_FILENAME
|
||||
xcrun stapler validate $DMG_FILENAME
|
||||
fi
|
||||
|
|
|
@ -47,7 +47,7 @@ cd %PROJECT_DIR%
|
|||
call "%QT_BIN_DIR:"=%\qt-cmake" . -B %WORK_DIR%
|
||||
|
||||
cd %WORK_DIR%
|
||||
cmake --build . --config release
|
||||
cmake --build . --config release -- /p:UseMultiToolTask=true /m
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
cmake --build . --target clean
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue