Compare commits

...

23 Commits

Author SHA1 Message Date
aiamnezia bb576450b2 Fix AmneziaWG settings 2025-07-28 15:36:49 +04:00
aiamnezia b01e9864cf Merge branch 'dev' into feature/add-new-awg-docker-image 2025-07-25 18:00:33 +04:00
aiamnezia 6b756f87b8 Remove AwgLegacy from wizard manual installation page 2025-07-25 17:12:35 +04:00
aiamnezia 5163d0edc4 Fix not opening awg settings 2025-07-25 16:58:10 +04:00
Nethius f51fd2bf3e chore: update link to submodule (#1738) 2025-07-24 10:13:14 +08:00
Nethius c8378fd32d chore: update link to submodule (#1733) 2025-07-22 19:50:57 +08:00
aiamnezia 8d830e726c Add native config sharing for new Awg container 2025-07-18 17:06:07 +04:00
Nethius d767214f10 chore: fixed amneziavpn-service version (#1726) 2025-07-17 15:22:21 +08:00
Nethius e027c504ae chore: bump version and add version to amneziavpn-service (#1725) 2025-07-16 13:49:29 +08:00
MrMirDan 669a95d975 chore: updated amnezia_ru_RU.ts (#1720)
* Update amneziavpn_ru_RU.ts

* Update amneziavpn_ru_RU.ts

* Update amneziavpn_ru_RU.ts

* Deleted corrupted ru translation

* Updated amneziavpn_ru_RU.ts

* Saved amneziavpn_ru_RU.ts

* Rewrite some back on english

* Rewrite small issues

* Rewrite another small issues

* Create deploy_mod.yml

Modificated deploy.yml - removed Linux, IOS and MacOS jobs
Made just for test and learning

* some changes

* deleted my uneccessary file

* new translations
2025-07-16 13:26:49 +08:00
Nethius a96df5d518 fix: temporarily removed vless for api native configs (#1724) 2025-07-16 13:26:19 +08:00
aiamnezia c5c81735a0 fix: split tunneling with vless api configs (#1716) 2025-07-16 10:04:49 +08:00
aiamnezia f6441b8b80 Add role for allowed for installation containers 2025-07-13 20:11:45 +04:00
aiamnezia bd30191060 Merge branch 'dev' into feature/add-new-awg-docker-image 2025-07-11 18:14:18 +04:00
aiamnezia 321ceb225c Fix resources file 2025-07-11 18:13:55 +04:00
aiamnezia 7fba1a50de Hide uninstalled AwgLegacy container 2025-07-11 17:26:49 +04:00
aiamnezia 151dac2316 add missing files 2025-07-11 07:49:00 +04:00
aiamnezia c40506f2f2 Add updated awg container 2025-07-11 07:10:58 +04:00
Nethius c933745707 chore: downgrade qt version for macos cicd build (#1705) 2025-07-10 19:48:03 +08:00
Nethius 6710fd18b3 chore: bump version (#1703) 2025-07-10 19:40:18 +08:00
Yaroslav 1b78a71529 feat: ci/cd for macos signed pkg bundle (#1699)
* Fixing broken ci/cd for macos pkg bundle

* chore: fix cert parsing

* chore: added notarization flag to macos build

* refactor: update certificate import logic in build_macos.sh script

---------

Co-authored-by: vladimir.kuznetsov <nethiuswork@gmail.com>
2025-07-10 10:04:59 +08:00
Nethius 1909d3c94e chore: bump version (#1701) 2025-07-08 15:11:45 +08:00
Nethius 10a107716c fix: fixed awg 1.5 fields processing for ios (#1700) 2025-07-08 15:06:52 +08:00
42 changed files with 851 additions and 321 deletions
+30 -2
View File
@@ -255,6 +255,20 @@ jobs:
env:
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
QT_VERSION: 6.4.3
MAC_TEAM_ID: ${{ secrets.MAC_TEAM_ID }}
MAC_APP_CERT_CERT: ${{ secrets.MAC_APP_CERT_CERT }}
MAC_SIGNER_ID: ${{ secrets.MAC_SIGNER_ID }}
MAC_APP_CERT_PW: ${{ secrets.MAC_APP_CERT_PW }}
MAC_INSTALLER_SIGNER_CERT: ${{ secrets.MAC_INSTALLER_SIGNER_CERT }}
MAC_INSTALLER_SIGNER_ID: ${{ secrets.MAC_INSTALLER_SIGNER_ID }}
MAC_INSTALL_CERT_PW: ${{ secrets.MAC_INSTALL_CERT_PW }}
APPLE_DEV_EMAIL: ${{ secrets.APPLE_DEV_EMAIL }}
APPLE_DEV_PASSWORD: ${{ secrets.APPLE_DEV_PASSWORD }}
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
@@ -295,7 +309,7 @@ jobs:
- name: 'Build project'
run: |
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
bash deploy/build_macos.sh
bash deploy/build_macos.sh -n
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v4
@@ -318,6 +332,20 @@ jobs:
env:
QT_VERSION: 6.8.0
MAC_TEAM_ID: ${{ secrets.MAC_TEAM_ID }}
MAC_APP_CERT_CERT: ${{ secrets.MAC_APP_CERT_CERT }}
MAC_SIGNER_ID: ${{ secrets.MAC_SIGNER_ID }}
MAC_APP_CERT_PW: ${{ secrets.MAC_APP_CERT_PW }}
MAC_INSTALLER_SIGNER_CERT: ${{ secrets.MAC_INSTALLER_SIGNER_CERT }}
MAC_INSTALLER_SIGNER_ID: ${{ secrets.MAC_INSTALLER_SIGNER_ID }}
MAC_INSTALL_CERT_PW: ${{ secrets.MAC_INSTALL_CERT_PW }}
APPLE_DEV_EMAIL: ${{ secrets.APPLE_DEV_EMAIL }}
APPLE_DEV_PASSWORD: ${{ secrets.APPLE_DEV_PASSWORD }}
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
@@ -358,7 +386,7 @@ jobs:
- name: 'Build project'
run: |
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
bash deploy/build_macos.sh
bash deploy/build_macos.sh -n
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v4
+1
View File
@@ -138,3 +138,4 @@ CMakeFiles/
ios-ne-build.sh
macos-ne-build.sh
macos-signed-build.sh
macos-with-sign-build.sh
+3 -2
View File
@@ -1,8 +1,9 @@
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
set(AMNEZIAVPN_VERSION 4.8.9.0)
project(${PROJECT} VERSION 4.8.8.1
project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION}
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,7 +12,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 2087)
set(APP_ANDROID_VERSION_CODE 2090)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")
+9 -1
View File
@@ -18,7 +18,15 @@ set(LIBS ${LIBS}
${FW_NETWORK_EXTENSION}
)
set_target_properties(${PROJECT} PROPERTIES MACOSX_BUNDLE TRUE)
set_target_properties(${PROJECT} PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/macos/app/Info.plist
XCODE_ATTRIBUTE_MARKETING_VERSION "${APP_MAJOR_VERSION}"
XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${BUILD_ID}"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER ${BUILD_OSX_APP_IDENTIFIER}
XCODE_ATTRIBUTE_PRODUCT_NAME "AmneziaVPN"
XCODE_ATTRIBUTE_EXECUTABLE_NAME "AmneziaVPN"
)
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE INTERNAL "" FORCE)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15)
@@ -103,7 +103,11 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
return connData;
}
QString getIpsScript = QString("cat %1 | grep AllowedIPs").arg(m_serverConfigPath);
QString configPath = m_serverConfigPath;
if (container == DockerContainer::AwgLegacy) {
configPath = amnezia::protocols::awg::serverLegacyConfigPath;
}
QString getIpsScript = QString("cat %1 | grep AllowedIPs").arg(configPath);
QString stdOut;
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
stdOut += data + "\n";
@@ -161,15 +165,18 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
"AllowedIPs = %3/32\n\n")
.arg(connData.clientPubKey, connData.pskKey, connData.clientIP);
errorCode = m_serverController->uploadTextFileToContainer(container, credentials, configPart, m_serverConfigPath,
errorCode = m_serverController->uploadTextFileToContainer(container, credentials, configPart, configPath,
libssh::ScpOverwriteMode::ScpAppendToExisting);
if (errorCode != ErrorCode::NoError) {
return connData;
}
QString script = QString("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'")
.arg(m_serverConfigPath);
bool isAwg = (container == DockerContainer::Awg);
QString bin = isAwg ? QStringLiteral("awg") : QStringLiteral("wg");
QString iface = isAwg ? QStringLiteral("awg0") : QStringLiteral("wg0");
QString script = QString(
"sudo docker exec -i $CONTAINER_NAME bash -c '%1 syncconf %2 <(%1-quick strip %3)'").arg(bin, iface, configPath);
errorCode = m_serverController->runScript(
credentials,
+37
View File
@@ -28,6 +28,10 @@ QString ContainerProps::containerToString(amnezia::DockerContainer c)
return "none";
if (c == DockerContainer::Cloak)
return "amnezia-openvpn-cloak";
if (c == DockerContainer::AwgLegacy)
return "amnezia-awg";
if (c == DockerContainer::Awg)
return "amnezia-awg-go";
QMetaEnum metaEnum = QMetaEnum::fromType<DockerContainer>();
QString containerKey = metaEnum.valueToKey(static_cast<int>(c));
@@ -41,6 +45,10 @@ QString ContainerProps::containerTypeToString(amnezia::DockerContainer c)
return "none";
if (c == DockerContainer::Ipsec)
return "ikev2";
if (c == DockerContainer::AwgLegacy)
return "awg";
if (c == DockerContainer::Awg)
return "awg-go";
QMetaEnum metaEnum = QMetaEnum::fromType<DockerContainer>();
QString containerKey = metaEnum.valueToKey(static_cast<int>(c));
@@ -71,6 +79,8 @@ QVector<amnezia::Proto> ContainerProps::protocolsForContainer(amnezia::DockerCon
case DockerContainer::Socks5Proxy: return { Proto::Socks5Proxy };
case DockerContainer::AwgLegacy: return { Proto::Awg };
default: return { defaultProtocol(container) };
}
}
@@ -94,6 +104,7 @@ QMap<DockerContainer, QString> ContainerProps::containerHumanNames()
{ DockerContainer::Cloak, "OpenVPN over Cloak" },
{ DockerContainer::WireGuard, "WireGuard" },
{ DockerContainer::Awg, "AmneziaWG" },
{ DockerContainer::AwgLegacy, "AmneziaWG Legacy" },
{ DockerContainer::Xray, "XRay" },
{ DockerContainer::Ipsec, QObject::tr("IPsec") },
{ DockerContainer::SSXray, "Shadowsocks"},
@@ -120,6 +131,9 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
{ DockerContainer::Awg,
QObject::tr("AmneziaWG is a special protocol from Amnezia based on WireGuard. "
"It provides high connection speed and ensures stable operation even in the most challenging network conditions.") },
{ DockerContainer::AwgLegacy,
QObject::tr("AmneziaWG Legacy is an old version of AmneziaWG protocol from Amnezia based on WireGuard. "
"It provides high connection speed and ensures stable operation even in the most challenging network conditions.") },
{ DockerContainer::Xray,
QObject::tr("XRay with REALITY masks VPN traffic as web traffic and protects against active probing. "
"It is highly resistant to detection and offers high speed.") },
@@ -194,6 +208,17 @@ QMap<DockerContainer, QString> ContainerProps::containerDetailedDescriptions()
"* Minimal settings required\n"
"* Undetectable by traffic analysis systems (DPI)\n"
"* Operates over UDP protocol") },
{ DockerContainer::AwgLegacy,
QObject::tr("AmneziaWG Legacy is an older version of the AmneziaWG protocol based on WireGuard."
"It addresses WireGuard's main vulnerability (easy detection by DPI systems) through advanced obfuscation techniques, "
"making VPN traffic indistinguishable from regular internet traffic.\n"
"\nAmneziaWG is an excellent choice for those seeking a fast, stealthy VPN connection.\n"
"\nFeatures:\n"
"* Available on all AmneziaVPN platforms\n"
"* Low battery consumption on mobile devices\n"
"* Minimal settings required\n"
"* Undetectable by traffic analysis systems (DPI)\n"
"* Operates over UDP protocol") },
{ DockerContainer::Xray,
QObject::tr("REALITY is an innovative protocol developed by the creators of XRay, designed specifically to combat high levels of internet censorship. "
"REALITY identifies censorship systems during the TLS handshake, "
@@ -243,6 +268,7 @@ Proto ContainerProps::defaultProtocol(DockerContainer c)
case DockerContainer::ShadowSocks: return Proto::ShadowSocks;
case DockerContainer::WireGuard: return Proto::WireGuard;
case DockerContainer::Awg: return Proto::Awg;
case DockerContainer::AwgLegacy: return Proto::Awg;
case DockerContainer::Xray: return Proto::Xray;
case DockerContainer::Ipsec: return Proto::Ikev2;
case DockerContainer::SSXray: return Proto::SSXray;
@@ -255,6 +281,15 @@ Proto ContainerProps::defaultProtocol(DockerContainer c)
}
}
QString ContainerProps::containerTypeToProtocolString(DockerContainer c)
{
if (c == DockerContainer::None)
return "none";
Proto p = defaultProtocol(c);
return ProtocolProps::protoToString(p);
}
bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
{
#ifdef Q_OS_WINDOWS
@@ -265,6 +300,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
case DockerContainer::WireGuard: return true;
case DockerContainer::OpenVpn: return true;
case DockerContainer::Awg: return true;
case DockerContainer::AwgLegacy: return true;
case DockerContainer::Xray: return true;
case DockerContainer::Cloak: return true;
case DockerContainer::SSXray: return true;
@@ -284,6 +320,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
case DockerContainer::OpenVpn: return true;
case DockerContainer::ShadowSocks: return false;
case DockerContainer::Awg: return true;
case DockerContainer::AwgLegacy: return true;
case DockerContainer::Cloak: return true;
case DockerContainer::Xray: return true;
case DockerContainer::SSXray: return true;
+2
View File
@@ -17,6 +17,7 @@ namespace amnezia
enum DockerContainer {
None = 0,
Awg,
AwgLegacy,
WireGuard,
OpenVpn,
Cloak,
@@ -45,6 +46,7 @@ namespace amnezia
Q_INVOKABLE static amnezia::DockerContainer containerFromString(const QString &container);
Q_INVOKABLE static QString containerToString(amnezia::DockerContainer container);
Q_INVOKABLE static QString containerTypeToString(amnezia::DockerContainer c);
Q_INVOKABLE static QString containerTypeToProtocolString(amnezia::DockerContainer c);
Q_INVOKABLE static QList<amnezia::DockerContainer> allContainers();
@@ -299,13 +299,10 @@ void CoreController::setQmlRoot()
void CoreController::initApiCountryModelUpdateHandler()
{
// TODO
connect(m_serversModel.get(), &ServersModel::updateApiCountryModel, this, [this]() {
m_apiCountryModel->updateModel(m_serversModel->getProcessedServerData("apiAvailableCountries").toJsonArray(),
m_serversModel->getProcessedServerData("apiServerCountryCode").toString());
});
connect(m_serversModel.get(), &ServersModel::updateApiServicesModel, this,
[this]() { m_apiServicesModel->updateModel(m_serversModel->getProcessedServerData("apiConfig").toJsonObject()); });
}
void CoreController::initContainerModelUpdateHandler()
+4 -3
View File
@@ -345,7 +345,7 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
return true;
}
if (container == DockerContainer::Awg) {
if (container == DockerContainer::Awg || container == DockerContainer::AwgLegacy) {
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
!= newProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress))
|| (oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)
@@ -657,7 +657,8 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
vars.append({ { "$SOCKS5_USER", socks5user } });
vars.append({ { "$SOCKS5_AUTH_TYPE", socks5user.isEmpty() ? "none" : "strong" } });
QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::WireGuard && container != DockerContainer::Xray)
QString serverIp = (container != DockerContainer::Awg && container != DockerContainer::AwgLegacy &&
container != DockerContainer::WireGuard && container != DockerContainer::Xray)
? NetworkUtilities::getIPAddress(credentials.hostName)
: credentials.hostName;
if (!serverIp.isEmpty()) {
@@ -866,4 +867,4 @@ ErrorCode ServerController::getDecryptedPrivateKey(const ServerCredentials &cred
{
auto error = m_sshClient.getDecryptedPrivateKey(credentials, decryptedPrivateKey, callback);
return error;
}
}
@@ -99,11 +99,12 @@ QJsonObject VpnConfigurationsController::createVpnConfiguration(const QPair<QStr
protocolConfigString = configurator->processConfigWithLocalSettings(dns, isApiConfig, protocolConfigString);
QJsonObject vpnConfigData = QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
if (container == DockerContainer::Awg || container == DockerContainer::WireGuard) {
if (container == DockerContainer::Awg || container == DockerContainer::AwgLegacy || container == DockerContainer::WireGuard) {
// add mtu for old configs
if (vpnConfigData[config_key::mtu].toString().isEmpty()) {
vpnConfigData[config_key::mtu] =
container == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
(container == DockerContainer::Awg || container == DockerContainer::AwgLegacy) ? protocols::awg::defaultMtu :
protocols::wireguard::defaultMtu;
}
}
+1
View File
@@ -12,6 +12,7 @@ QString amnezia::scriptFolder(amnezia::DockerContainer container)
case DockerContainer::ShadowSocks: return QLatin1String("openvpn_shadowsocks");
case DockerContainer::WireGuard: return QLatin1String("wireguard");
case DockerContainer::Awg: return QLatin1String("awg");
case DockerContainer::AwgLegacy: return QLatin1String("awg_legacy");
case DockerContainer::Ipsec: return QLatin1String("ipsec");
case DockerContainer::Xray: return QLatin1String("xray");
+53 -23
View File
@@ -46,29 +46,59 @@ struct WGConfig: Decodable {
}
var settings: String {
junkPacketCount == nil ? "" :
"""
Jc = \(junkPacketCount!)
Jmin = \(junkPacketMinSize!)
Jmax = \(junkPacketMaxSize!)
S1 = \(initPacketJunkSize!)
S2 = \(responsePacketJunkSize!)
S3 = \(cookieReplyPacketJunkSize!)
S4 = \(transportPacketJunkSize!)
H1 = \(initPacketMagicHeader!)
H2 = \(responsePacketMagicHeader!)
H3 = \(underloadPacketMagicHeader!)
H4 = \(transportPacketMagicHeader!)
I1 = \(specialJunk1!)
I2 = \(specialJunk2!)
I3 = \(specialJunk3!)
I4 = \(specialJunk4!)
I5 = \(specialJunk5!)
J1 = \(controlledJunk1!)
J2 = \(controlledJunk2!)
J3 = \(controlledJunk3!)
Itime = \(specialHandshakeTimeout!)
"""
guard junkPacketCount != nil else { return "" }
var settingsLines: [String] = []
// Required parameters when junkPacketCount is present
settingsLines.append("Jc = \(junkPacketCount!)")
settingsLines.append("Jmin = \(junkPacketMinSize!)")
settingsLines.append("Jmax = \(junkPacketMaxSize!)")
settingsLines.append("S1 = \(initPacketJunkSize!)")
settingsLines.append("S2 = \(responsePacketJunkSize!)")
settingsLines.append("H1 = \(initPacketMagicHeader!)")
settingsLines.append("H2 = \(responsePacketMagicHeader!)")
settingsLines.append("H3 = \(underloadPacketMagicHeader!)")
settingsLines.append("H4 = \(transportPacketMagicHeader!)")
// Optional parameters - only add if not nil and not empty
if let s3 = cookieReplyPacketJunkSize, !s3.isEmpty {
settingsLines.append("S3 = \(s3)")
}
if let s4 = transportPacketJunkSize, !s4.isEmpty {
settingsLines.append("S4 = \(s4)")
}
if let i1 = specialJunk1, !i1.isEmpty {
settingsLines.append("I1 = \(i1)")
}
if let i2 = specialJunk2, !i2.isEmpty {
settingsLines.append("I2 = \(i2)")
}
if let i3 = specialJunk3, !i3.isEmpty {
settingsLines.append("I3 = \(i3)")
}
if let i4 = specialJunk4, !i4.isEmpty {
settingsLines.append("I4 = \(i4)")
}
if let i5 = specialJunk5, !i5.isEmpty {
settingsLines.append("I5 = \(i5)")
}
if let j1 = controlledJunk1, !j1.isEmpty {
settingsLines.append("J1 = \(j1)")
}
if let j2 = controlledJunk2, !j2.isEmpty {
settingsLines.append("J2 = \(j2)")
}
if let j3 = controlledJunk3, !j3.isEmpty {
settingsLines.append("J3 = \(j3)")
}
if let itime = specialHandshakeTimeout, !itime.isEmpty {
settingsLines.append("Itime = \(itime)")
}
return settingsLines.joined(separator: "\n")
}
var str: String {
+2 -1
View File
@@ -218,7 +218,8 @@ namespace amnezia
constexpr char defaultMtu[] = "1376";
#endif
constexpr char serverConfigPath[] = "/opt/amnezia/awg/wg0.conf";
constexpr char serverConfigPath[] = "/opt/amnezia/awg/awg0.conf";
constexpr char serverLegacyConfigPath[] = "/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";
+1
View File
@@ -115,6 +115,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject &
case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration);
case DockerContainer::WireGuard: return new WireguardProtocol(configuration);
case DockerContainer::Awg: return new WireguardProtocol(configuration);
case DockerContainer::AwgLegacy: return new WireguardProtocol(configuration);
case DockerContainer::Xray: return new XrayProtocol(configuration);
case DockerContainer::SSXray: return new XrayProtocol(configuration);
#endif
+5
View File
@@ -64,6 +64,11 @@
<file>server_scripts/awg/run_container.sh</file>
<file>server_scripts/awg/start.sh</file>
<file>server_scripts/awg/template.conf</file>
<file>server_scripts/awg_legacy/configure_container.sh</file>
<file>server_scripts/awg_legacy/Dockerfile</file>
<file>server_scripts/awg_legacy/run_container.sh</file>
<file>server_scripts/awg_legacy/start.sh</file>
<file>server_scripts/awg_legacy/template.conf</file>
<file>server_scripts/build_container.sh</file>
<file>server_scripts/check_connection.sh</file>
<file>server_scripts/check_server_is_busy.sh</file>
+1 -1
View File
@@ -1,4 +1,4 @@
FROM amneziavpn/amnezia-wg:latest
FROM amneziavpn/amneziawg-go:latest
LABEL maintainer="AmneziaVPN"
@@ -1,15 +1,15 @@
mkdir -p /opt/amnezia/awg
cd /opt/amnezia/awg
WIREGUARD_SERVER_PRIVATE_KEY=$(wg genkey)
WIREGUARD_SERVER_PRIVATE_KEY=$(awg 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)
WIREGUARD_SERVER_PUBLIC_KEY=$(echo $WIREGUARD_SERVER_PRIVATE_KEY | awg pubkey)
echo $WIREGUARD_SERVER_PUBLIC_KEY > /opt/amnezia/awg/wireguard_server_public_key.key
WIREGUARD_PSK=$(wg genpsk)
WIREGUARD_PSK=$(awg genpsk)
echo $WIREGUARD_PSK > /opt/amnezia/awg/wireguard_psk.key
cat > /opt/amnezia/awg/wg0.conf <<EOF
cat > /opt/amnezia/awg/awg0.conf <<EOF
[Interface]
PrivateKey = $WIREGUARD_SERVER_PRIVATE_KEY
Address = $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR
+7 -7
View File
@@ -6,19 +6,19 @@ 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
awg-quick down /opt/amnezia/awg/awg0.conf
# start daemons if configured
if [ -f /opt/amnezia/awg/wg0.conf ]; then (wg-quick up /opt/amnezia/awg/wg0.conf); fi
if [ -f /opt/amnezia/awg/awg0.conf ]; then (awg-quick up /opt/amnezia/awg/awg0.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
iptables -A INPUT -i awg0 -j ACCEPT
iptables -A FORWARD -i awg0 -j ACCEPT
iptables -A OUTPUT -o awg0 -j ACCEPT
# Allow forwarding traffic only from the VPN.
iptables -A FORWARD -i wg0 -o eth0 -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i wg0 -o eth1 -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i awg0 -o eth0 -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i awg0 -o eth1 -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
@@ -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 [ "" ]
@@ -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 = $AWG_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
@@ -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
View 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 $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i wg0 -o eth1 -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s $AWG_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth1 -j MASQUERADE
tail -f /dev/null
@@ -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
File diff suppressed because it is too large Load Diff
@@ -158,7 +158,7 @@ namespace
return ErrorCode::ApiConfigEmptyError;
}
auto container = containers.at(0).toObject();
QString containerName = ContainerProps::containerTypeToString(DockerContainer::Awg);
QString containerName = ContainerProps::containerTypeToProtocolString(DockerContainer::Awg);
auto serverProtocolConfig = container.value(containerName).toObject();
auto clientProtocolConfig =
QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object();
@@ -248,10 +248,10 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
apiConfigObject.value(configKey::userCountryCode).toString(),
serverCountryCode,
apiConfigObject.value(configKey::serviceType).toString(),
m_apiServicesModel->getSelectedServiceProtocol(),
configKey::awg, // apiConfigObject.value(configKey::serviceProtocol).toString(),
serverConfigObject.value(configKey::authData).toObject() };
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
QString protocol = gatewayRequestData.serviceProtocol;
ProtocolData protocolData = generateProtocolData(protocol);
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
@@ -283,7 +283,7 @@ bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode)
apiConfigObject.value(configKey::userCountryCode).toString(),
serverCountryCode,
apiConfigObject.value(configKey::serviceType).toString(),
m_apiServicesModel->getSelectedServiceProtocol(),
configKey::awg, // apiConfigObject.value(configKey::serviceProtocol).toString(),
serverConfigObject.value(configKey::authData).toObject() };
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
+5 -5
View File
@@ -271,7 +271,7 @@ void ImportController::processNativeWireGuardConfig()
auto containers = m_config.value(config_key::containers).toArray();
if (!containers.isEmpty()) {
auto container = containers.at(0).toObject();
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::WireGuard)).toObject();
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToProtocolString(DockerContainer::WireGuard)).toObject();
auto clientProtocolConfig = QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object();
QString junkPacketCount = QString::number(QRandomGenerator::global()->bounded(2, 5));
@@ -727,8 +727,8 @@ void ImportController::processAmneziaConfig(QJsonObject &config)
for (auto i = 0; i < containers.size(); i++) {
auto container = containers.at(i).toObject();
auto dockerContainer = ContainerProps::containerFromString(container.value(config_key::container).toString());
if (dockerContainer == DockerContainer::Awg || dockerContainer == DockerContainer::WireGuard) {
auto containerConfig = container.value(ContainerProps::containerTypeToString(dockerContainer)).toObject();
if (dockerContainer == DockerContainer::Awg || dockerContainer == DockerContainer::AwgLegacy || dockerContainer == DockerContainer::WireGuard) {
auto containerConfig = container.value(ContainerProps::containerTypeToProtocolString(dockerContainer)).toObject();
auto protocolConfig = containerConfig.value(config_key::last_config).toString();
if (protocolConfig.isEmpty()) {
return;
@@ -736,11 +736,11 @@ void ImportController::processAmneziaConfig(QJsonObject &config)
QJsonObject jsonConfig = QJsonDocument::fromJson(protocolConfig.toUtf8()).object();
jsonConfig[config_key::mtu] =
dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
(dockerContainer == DockerContainer::Awg || dockerContainer == DockerContainer::AwgLegacy) ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
containerConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
container[ContainerProps::containerTypeToString(dockerContainer)] = containerConfig;
container[ContainerProps::containerTypeToProtocolString(dockerContainer)] = containerConfig;
containers.replace(i, container);
config.insert(config_key::containers, containers);
}
+5 -1
View File
@@ -410,8 +410,12 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
containerConfig.insert(config_key::transport_proto, transportProto);
if (protocol == Proto::Awg) {
QString configPath = amnezia::protocols::awg::serverConfigPath;
if (container == DockerContainer::AwgLegacy) {
configPath = amnezia::protocols::awg::serverLegacyConfigPath;
}
QString serverConfig = serverController->getTextFileFromContainer(container, credentials,
protocols::awg::serverConfigPath, errorCode);
configPath, errorCode);
QMap<QString, QString> serverConfigMap;
auto serverConfigLines = serverConfig.split("\n");
+41 -14
View File
@@ -104,7 +104,7 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
error = getOpenVpnClients(container, credentials, serverController, count);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg || container == DockerContainer::AwgLegacy) {
error = getWireGuardClients(container, credentials, serverController, count);
} else if (container == DockerContainer::Xray) {
error = getXrayClients(container, credentials, serverController, count);
@@ -209,8 +209,15 @@ ErrorCode ClientManagementModel::getWireGuardClients(const DockerContainer conta
{
ErrorCode error = ErrorCode::NoError;
const QString wireGuardConfigFile = QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
QString configPath;
if (container == DockerContainer::AwgLegacy) {
configPath = QString::fromLatin1(amnezia::protocols::awg::serverLegacyConfigPath);
} else if (container == DockerContainer::Awg) {
configPath = QString::fromLatin1(amnezia::protocols::awg::serverConfigPath);
} else {
configPath = QString::fromLatin1(amnezia::protocols::wireguard::serverConfigPath);
}
const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, configPath, error);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server";
return error;
@@ -307,7 +314,7 @@ ErrorCode ClientManagementModel::getXrayClients(const DockerContainer container,
ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, std::vector<WgShowData> &data)
{
if (container != DockerContainer::WireGuard && container != DockerContainer::Awg) {
if (container != DockerContainer::WireGuard && container != DockerContainer::Awg && container != DockerContainer::AwgLegacy) {
return ErrorCode::NoError;
}
@@ -318,7 +325,11 @@ ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const S
return ErrorCode::NoError;
};
const QString command = QString("sudo docker exec -i $CONTAINER_NAME bash -c '%1'").arg("wg show all");
QString showBin = (container == DockerContainer::Awg)
? QStringLiteral("awg")
: QStringLiteral("wg");
const QString command = QString("sudo docker exec -i $CONTAINER_NAME bash -c '%1 show all'")
.arg(showBin);
QString script = serverController->replaceVars(command, serverController->genVarsForScript(credentials, container));
error = serverController->runScript(credentials, script, cbReadStdOut);
@@ -398,6 +409,7 @@ ErrorCode ClientManagementModel::appendClient(const DockerContainer container, c
case DockerContainer::OpenVpn:
case DockerContainer::WireGuard:
case DockerContainer::Awg:
case DockerContainer::AwgLegacy:
case DockerContainer::Xray:
protocol = ContainerProps::defaultProtocol(container);
break;
@@ -545,7 +557,8 @@ ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContain
break;
}
case DockerContainer::WireGuard:
case DockerContainer::Awg: {
case DockerContainer::Awg:
case DockerContainer::AwgLegacy: {
errorCode = revokeWireGuard(row, container, credentials, serverController);
break;
}
@@ -605,6 +618,7 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
case DockerContainer::OpenVpn:
case DockerContainer::WireGuard:
case DockerContainer::Awg:
case DockerContainer::AwgLegacy:
case DockerContainer::Xray: {
protocol = ContainerProps::defaultProtocol(container);
break;
@@ -677,6 +691,7 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
break;
}
case DockerContainer::WireGuard:
case DockerContainer::AwgLegacy:
case DockerContainer::Awg: {
errorCode = revokeWireGuard(row, container, credentials, serverController);
break;
@@ -736,9 +751,15 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
{
ErrorCode error = ErrorCode::NoError;
const QString wireGuardConfigFile =
QString("/opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
QString configPath;
if (container == DockerContainer::AwgLegacy) {
configPath = QString::fromLatin1(amnezia::protocols::awg::serverLegacyConfigPath);
} else if (container == DockerContainer::Awg) {
configPath = QString::fromLatin1(amnezia::protocols::awg::serverConfigPath);
} else {
configPath = QString::fromLatin1(amnezia::protocols::wireguard::serverConfigPath);
}
const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, configPath, error);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server";
return error;
@@ -756,7 +777,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
}
QString newWireGuardConfig = configSections.join("[");
newWireGuardConfig.insert(0, "[");
error = serverController->uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile);
error = serverController->uploadTextFileToContainer(container, credentials, newWireGuardConfig, configPath);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the wg conf file to the server";
return error;
@@ -780,12 +801,18 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
return error;
}
const QString script = "sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'";
bool isAwg = (container == DockerContainer::Awg);
QString command = isAwg ? QStringLiteral("awg") : QStringLiteral("wg");
QString iface = isAwg ? QStringLiteral("awg0") : QStringLiteral("wg0");
QString script = QString(
"sudo docker exec -i $CONTAINER_NAME bash -c '%1 syncconf %2 <(%1-quick strip %3)'"
).arg(command, iface, configPath);
error = serverController->runScript(
credentials,
serverController->replaceVars(script.arg(wireGuardConfigFile), serverController->genVarsForScript(credentials, container)));
credentials,
serverController->replaceVars(script, serverController->genVarsForScript(credentials, container))
);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to execute the command 'wg syncconf' on the server";
logger.error() << QString("Failed to execute command '%1 syncconf %2' on the server").arg(command, iface);
return error;
}
+12 -1
View File
@@ -31,12 +31,17 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const
}
return m_containers.value(container);
}
case IsThirdPartyConfigRole: {
QString protocolKey = ContainerProps::containerTypeToProtocolString(container);
return m_containers.value(container).value(protocolKey).toObject().value(config_key::isThirdPartyConfig).toBool();
}
case ServiceTypeRole: return ContainerProps::containerService(container);
case DockerContainerRole: return container;
case IsEasySetupContainerRole: return ContainerProps::isEasySetupContainer(container);
case EasySetupHeaderRole: return ContainerProps::easySetupHeader(container);
case EasySetupDescriptionRole: return ContainerProps::easySetupDescription(container);
case EasySetupOrderRole: return ContainerProps::easySetupOrder(container);
case IsInstallationAllowedRole: return ContainersModel::isInstallationAllowed(container);
case IsInstalledRole: return m_containers.contains(container);
case IsCurrentlyProcessedRole: return container == static_cast<DockerContainer>(m_processedContainerIndex);
case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container);
@@ -114,6 +119,11 @@ bool ContainersModel::hasInstalledProtocols()
return false;
}
bool ContainersModel::isInstallationAllowed(DockerContainer container)
{
return container != DockerContainer::AwgLegacy;
}
QHash<int, QByteArray> ContainersModel::roleNames() const
{
QHash<int, QByteArray> roles;
@@ -123,6 +133,7 @@ QHash<int, QByteArray> ContainersModel::roleNames() const
roles[ServiceTypeRole] = "serviceType";
roles[DockerContainerRole] = "dockerContainer";
roles[ConfigRole] = "config";
roles[IsThirdPartyConfigRole] = "isThirdPartyConfig";
roles[IsEasySetupContainerRole] = "isEasySetupContainer";
roles[EasySetupHeaderRole] = "easySetupHeader";
@@ -133,7 +144,7 @@ QHash<int, QByteArray> ContainersModel::roleNames() const
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
roles[IsSupportedRole] = "isSupported";
roles[IsShareableRole] = "isShareable";
roles[IsInstallationAllowedRole] = "isInstallationAllowed";
roles[InstallPageOrderRole] = "installPageOrder";
return roles;
}
+4
View File
@@ -20,6 +20,7 @@ public:
DetailedDescriptionRole,
ServiceTypeRole,
ConfigRole,
IsThirdPartyConfigRole,
DockerContainerRole,
IsEasySetupContainerRole,
@@ -27,6 +28,7 @@ public:
EasySetupDescriptionRole,
EasySetupOrderRole,
IsInstallationAllowedRole,
IsInstalledRole,
IsCurrentlyProcessedRole,
IsDefaultRole,
@@ -57,6 +59,8 @@ public slots:
bool hasInstalledServices();
bool hasInstalledProtocols();
static bool isInstallationAllowed(DockerContainer container);
protected:
QHash<int, QByteArray> roleNames() const override;
+3 -2
View File
@@ -42,7 +42,7 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
return static_cast<int>(clientProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
case RawConfigRole: {
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
auto protocolConfig = m_content.value(ContainerProps::containerTypeToProtocolString(m_container)).toObject();
auto lastConfigJsonDoc =
QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8());
auto lastConfigJson = lastConfigJsonDoc.object();
@@ -55,7 +55,8 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
return rawConfig;
}
case IsClientProtocolExistsRole: {
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
QString protocolKey = ContainerProps::containerTypeToProtocolString(m_container);
auto protocolConfig = m_content.value(protocolKey).toObject();
auto lastConfigJsonDoc =
QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8());
auto lastConfigJson = lastConfigJsonDoc.object();
+3 -3
View File
@@ -733,8 +733,8 @@ bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
if (container.value(config_key::container).toString() != ContainerProps::containerToString(defaultContainer)) {
continue;
}
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) {
QJsonObject serverProtocolConfig = container.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::AwgLegacy || defaultContainer == DockerContainer::WireGuard) {
QJsonObject serverProtocolConfig = container.value(ContainerProps::containerTypeToProtocolString(defaultContainer)).toObject();
QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString();
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(clientProtocolConfigString.toUtf8()).object();
return (clientProtocolConfigString.contains("AllowedIPs") && !clientProtocolConfigString.contains("AllowedIPs = 0.0.0.0/0, ::/0"))
@@ -742,7 +742,7 @@ bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
&& !clientProtocolConfig.value(config_key::allowed_ips).toArray().contains("0.0.0.0/0"));
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn
|| defaultContainer == DockerContainer::ShadowSocks) {
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)).toObject();
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToProtocolString(DockerContainer::OpenVpn)).toObject();
QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString();
return !clientProtocolConfigString.isEmpty() && !clientProtocolConfigString.contains("redirect-gateway");
}
@@ -46,12 +46,10 @@ ListView {
var containerIndex = root.model.mapToSource(index)
ContainersModel.setProcessedContainerIndex(containerIndex)
if (serviceType !== ProtocolEnum.Other) {
if (config[ContainerProps.containerTypeToString(containerIndex)]["isThirdPartyConfig"]) {
ProtocolsModel.updateModel(config)
PageController.goToPage(PageEnum.PageProtocolRaw)
return
}
if (serviceType !== ProtocolEnum.Other && isThirdPartyConfig) {
ProtocolsModel.updateModel(config)
PageController.goToPage(PageEnum.PageProtocolRaw)
return
}
switch (containerIndex) {
@@ -31,8 +31,19 @@ Item {
value: true
}
ValueFilter {
id: installationAllowedFilter
roleName: "isInstallationAllowed"
value: true
}
AnyOf {
id: showProtocolFilter
filters: [ installedFilter, installationAllowedFilter ]
}
function getWriteAccessProtocolsListFilters() {
return [vpnTypeFilter]
return [ vpnTypeFilter, showProtocolFilter ]
}
function getReadAccessProtocolsListFilters() {
return [vpnTypeFilter, installedFilter]
@@ -26,6 +26,10 @@ PageType {
ValueFilter {
roleName: "isSupported"
value: true
},
ValueFilter {
roleName: "isInstallationAllowed"
value: true
}
]
sorters: RoleSorter {
+2
View File
@@ -453,6 +453,8 @@ PageType {
root.connectionTypesModel.push(wireGuardConnectionFormat)
} else if (index === ContainerProps.containerFromString("amnezia-awg")) {
root.connectionTypesModel.push(awgConnectionFormat)
} else if (index === ContainerProps.containerFromString("amnezia-awg-go")) {
root.connectionTypesModel.push(awgConnectionFormat)
} else if (index === ContainerProps.containerFromString("amnezia-shadowsocks")) {
root.connectionTypesModel.push(openVpnConnectionFormat)
root.connectionTypesModel.push(shadowSocksConnectionFormat)
+3 -2
View File
@@ -85,8 +85,9 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state)
IpcClient::Interface()->resetIpStack();
IpcClient::Interface()->flushDns();
if (!m_vpnConfiguration.value(config_key::configVersion).toInt() && container != DockerContainer::Awg
&& container != DockerContainer::WireGuard) {
if (container != DockerContainer::Awg &&
container != DockerContainer::AwgLegacy &&
container != DockerContainer::WireGuard) {
QString dns1 = m_vpnConfiguration.value(config_key::dns1).toString();
QString dns2 = m_vpnConfiguration.value(config_key::dns2).toString();
+47 -4
View File
@@ -71,11 +71,54 @@ cmake --build . --config release --target all
KEYCHAIN_PATH="$PROJECT_DIR/mac_sign.keychain"
trap 'echo "Cleaning up mac_sign.keychain..."; security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true; rm -f "$KEYCHAIN_PATH" 2>/dev/null || true' EXIT
KEYCHAIN=$(security default-keychain -d user | tr -d '"[:space:]"')
security list-keychains -d user -s "$KEYCHAIN_PATH" "$KEYCHAIN" "$(security list-keychains -d user | tr '\n' ' ')"
security create-keychain -p "" "$KEYCHAIN_PATH"
security import "$DEPLOY_DIR/DeveloperIdApplicationCertificate.p12" -k "$KEYCHAIN_PATH" -P "$MAC_APP_CERT_PW" -T /usr/bin/codesign
security import "$DEPLOY_DIR/DeveloperIdInstallerCertificate.p12" -k "$KEYCHAIN_PATH" -P "$MAC_INSTALL_CERT_PW" -T /usr/bin/codesign
# Build a clean list of the *existing* user key-chains. The raw output of
# security list-keychains -d user
# looks roughly like:
# " \"/Users/foo/Library/Keychains/login.keychain-db\"\n \"/Library/Keychains/System.keychain\""
# Every entry is surrounded by quotes and indented with a few blanks. Feeding
# that verbatim back to `security list-keychains -s` inside a single quoted
# argument leads to one long, invalid path on some systems. We therefore strip
# the quotes and rely on the shell to split the string on whitespace so that
# each path becomes its own argument.
read -ra EXISTING_KEYCHAINS <<< "$(security list-keychains -d user | tr -d '"')"
security list-keychains -d user -s "$KEYCHAIN_PATH" "$KEYCHAIN" "${EXISTING_KEYCHAINS[@]}"
KEYCHAIN_PWD="" # Empty password keeps things simple for CI jobs
# Create, unlock and configure the temporary key-chain so that `codesign` can
# access the imported identities without triggering interactive prompts.
security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_PATH"
# Keep the key-chain unlocked for the duration of the job (6 hours is plenty).
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_PATH"
# Import the signing certificates only when the corresponding passwords are
# available in the environment. This allows the script to run in environments
# where code-signing is intentionally turned off (e.g. CI jobs that just build
# the artefacts without releasing them).
if [ -n "${MAC_APP_CERT_PW-}" ]; then
# If the certificate is provided via environment variable, decode it.
if [ -n "${MAC_APP_CERT_CERT-}" ]; then
echo "$MAC_APP_CERT_CERT" | base64 -d > "$DEPLOY_DIR/DeveloperIdApplicationCertificate.p12"
fi
security import "$DEPLOY_DIR/DeveloperIdApplicationCertificate.p12" \
-k "$KEYCHAIN_PATH" -P "$MAC_APP_CERT_PW" -A
fi
if [ -n "${MAC_INSTALL_CERT_PW-}" ]; then
# Same logic for the installer certificate.
if [ -n "${MAC_INSTALLER_SIGNER_CERT-}" ]; then
echo "$MAC_INSTALLER_SIGNER_CERT" | base64 -d > "$DEPLOY_DIR/DeveloperIdInstallerCertificate.p12"
fi
security import "$DEPLOY_DIR/DeveloperIdInstallerCertificate.p12" \
-k "$KEYCHAIN_PATH" -P "$MAC_INSTALL_CERT_PW" -A
fi
# This certificate has no password.
security import "$DEPLOY_DIR/DeveloperIDG2CA.cer" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign
security list-keychains -d user -s "$KEYCHAIN_PATH"
echo "____________________________________"
+1 -1
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT service)
project(${PROJECT})
project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION})
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+13 -2
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN-service)
project(${PROJECT})
project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION})
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -162,7 +162,14 @@ if (WIN32 OR APPLE OR LINUX)
)
endif()
set(RESOURCES)
if(WIN32)
configure_file(
${CMAKE_CURRENT_LIST_DIR}/amneziavpn-service.rc.in
${CMAKE_CURRENT_BINARY_DIR}/amneziavpn-service.rc
)
set(HEADERS ${HEADERS}
${CMAKE_CURRENT_LIST_DIR}/tapcontroller_win.h
${CMAKE_CURRENT_LIST_DIR}/router_win.h
@@ -203,6 +210,10 @@ if(WIN32)
${CMAKE_CURRENT_SOURCE_DIR}/../../client/platforms/windows/windowsutils.cpp
)
set(RESOURCES ${RESOURCES}
${CMAKE_CURRENT_BINARY_DIR}/amneziavpn-service.rc
)
set(LIBS
user32
rasapi32
@@ -308,7 +319,7 @@ include_directories(
)
add_executable(${PROJECT} ${SOURCES} ${HEADERS})
add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES})
target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Widgets Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat Qt6::DBus ${LIBS})
target_compile_definitions(${PROJECT} PRIVATE "MZ_$<UPPER_CASE:${MZ_PLATFORM_NAME}>")
+38
View File
@@ -0,0 +1,38 @@
#include <windows.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#define VER_COMPANYNAME_STR "AmneziaVPN"
#define VER_FILEDESCRIPTION_STR "AmneziaVPN Service"
#define VER_INTERNALNAME_STR VER_FILEDESCRIPTION_STR
#define VER_LEGALCOPYRIGHT_STR "AmneziaVPN."
#define VER_LEGALTRADEMARKS1_STR "All Rights Reserved"
#define VER_LEGALTRADEMARKS2_STR VER_LEGALTRADEMARKS1_STR
#define VER_ORIGINALFILENAME_STR "AmneziaVPN-service.exe"
#define VER_PRODUCTNAME_STR VER_FILEDESCRIPTION_STR
VS_VERSION_INFO VERSIONINFO
FILEVERSION @CMAKE_PROJECT_VERSION_MAJOR@,@CMAKE_PROJECT_VERSION_MINOR@,@CMAKE_PROJECT_VERSION_PATCH@,@CMAKE_PROJECT_VERSION_TWEAK@
PRODUCTVERSION @CMAKE_PROJECT_VERSION_MAJOR@,@CMAKE_PROJECT_VERSION_MINOR@,@CMAKE_PROJECT_VERSION_PATCH@
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", VER_COMPANYNAME_STR
VALUE "FileDescription", VER_FILEDESCRIPTION_STR
VALUE "FileVersion", "@CMAKE_PROJECT_VERSION@"
VALUE "InternalName", VER_INTERNALNAME_STR
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR
VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR
VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
VALUE "ProductName", VER_PRODUCTNAME_STR
VALUE "ProductVersion", "@CMAKE_PROJECT_VERSION@"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END