Compare commits
1 commit
dev
...
bugfix/ope
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4fbad76d81 |
106 changed files with 1924 additions and 3605 deletions
84
.github/workflows/deploy.yml
vendored
84
.github/workflows/deploy.yml
vendored
|
@ -20,8 +20,6 @@ jobs:
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
||||||
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
||||||
FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
|
|
||||||
PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install Qt'
|
- name: 'Install Qt'
|
||||||
|
@ -92,8 +90,6 @@ jobs:
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
||||||
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
||||||
FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
|
|
||||||
PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Get sources'
|
- name: 'Get sources'
|
||||||
|
@ -160,8 +156,6 @@ jobs:
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
||||||
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
||||||
FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
|
|
||||||
PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
|
@ -249,82 +243,18 @@ jobs:
|
||||||
|
|
||||||
# ------------------------------------------------------
|
# ------------------------------------------------------
|
||||||
|
|
||||||
Build-MacOS-old:
|
Build-MacOS:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
|
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
|
||||||
QT_VERSION: 6.4.3
|
QT_VERSION: 6.4.3
|
||||||
|
QIF_VERSION: 4.6
|
||||||
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
|
||||||
PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
|
PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
||||||
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
||||||
FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
|
|
||||||
PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: 'Setup xcode'
|
|
||||||
uses: maxim-lobanov/setup-xcode@v1
|
|
||||||
with:
|
|
||||||
xcode-version: '15.4.0'
|
|
||||||
|
|
||||||
- name: 'Install Qt'
|
|
||||||
uses: jurplel/install-qt-action@v3
|
|
||||||
with:
|
|
||||||
version: ${{ env.QT_VERSION }}
|
|
||||||
host: 'mac'
|
|
||||||
target: 'desktop'
|
|
||||||
arch: 'clang_64'
|
|
||||||
modules: 'qtremoteobjects qt5compat qtshadertools'
|
|
||||||
dir: ${{ runner.temp }}
|
|
||||||
setup-python: 'true'
|
|
||||||
set-env: 'true'
|
|
||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
|
||||||
|
|
||||||
|
|
||||||
- name: 'Get sources'
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: 'true'
|
|
||||||
fetch-depth: 10
|
|
||||||
|
|
||||||
- name: 'Setup ccache'
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
|
||||||
|
|
||||||
- name: 'Build project'
|
|
||||||
run: |
|
|
||||||
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
|
|
||||||
bash deploy/build_macos.sh
|
|
||||||
|
|
||||||
- name: 'Upload installer artifact'
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: AmneziaVPN_MacOS_old_installer
|
|
||||||
path: deploy/build/pkg/AmneziaVPN.pkg
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
- name: 'Upload unpacked artifact'
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: AmneziaVPN_MacOS_old_unpacked
|
|
||||||
path: deploy/build/client/AmneziaVPN.app
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
# ------------------------------------------------------
|
|
||||||
|
|
||||||
Build-MacOS:
|
|
||||||
runs-on: macos-latest
|
|
||||||
|
|
||||||
env:
|
|
||||||
QT_VERSION: 6.8.0
|
|
||||||
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 }}
|
|
||||||
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
|
||||||
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
|
||||||
FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
|
|
||||||
PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
|
@ -345,6 +275,11 @@ jobs:
|
||||||
set-env: 'true'
|
set-env: 'true'
|
||||||
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
|
||||||
|
|
||||||
|
- name: 'Install Qt Installer Framework ${{ env.QIF_VERSION }}'
|
||||||
|
run: |
|
||||||
|
mkdir -pv ${{ runner.temp }}/Qt/Tools/QtInstallerFramework
|
||||||
|
wget https://qt.amzsvc.com/tools/ifw/${{ env.QIF_VERSION }}.zip
|
||||||
|
unzip ${{ env.QIF_VERSION }}.zip -d ${{ runner.temp }}/Qt/Tools/QtInstallerFramework/
|
||||||
|
|
||||||
- name: 'Get sources'
|
- name: 'Get sources'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
@ -358,13 +293,14 @@ jobs:
|
||||||
- name: 'Build project'
|
- name: 'Build project'
|
||||||
run: |
|
run: |
|
||||||
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
|
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
|
||||||
|
export QIF_BIN_DIR="${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin"
|
||||||
bash deploy/build_macos.sh
|
bash deploy/build_macos.sh
|
||||||
|
|
||||||
- name: 'Upload installer artifact'
|
- name: 'Upload installer artifact'
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: AmneziaVPN_MacOS_installer
|
name: AmneziaVPN_MacOS_installer
|
||||||
path: deploy/build/pkg/AmneziaVPN.pkg
|
path: AmneziaVPN.dmg
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
- name: 'Upload unpacked artifact'
|
- name: 'Upload unpacked artifact'
|
||||||
|
@ -388,8 +324,6 @@ jobs:
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
||||||
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
||||||
FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
|
|
||||||
PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install desktop Qt'
|
- name: 'Install desktop Qt'
|
||||||
|
|
2
.github/workflows/tag-deploy.yml
vendored
2
.github/workflows/tag-deploy.yml
vendored
|
@ -20,8 +20,6 @@ jobs:
|
||||||
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
|
||||||
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
|
||||||
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
|
||||||
FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
|
|
||||||
PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install desktop Qt'
|
- name: 'Install desktop Qt'
|
||||||
|
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -133,8 +133,4 @@ client/3rd/ShadowSocks/ss_ios.xcconfig
|
||||||
out/
|
out/
|
||||||
|
|
||||||
# CMake files
|
# CMake files
|
||||||
CMakeFiles/
|
CMakeFiles/
|
||||||
|
|
||||||
ios-ne-build.sh
|
|
||||||
macos-ne-build.sh
|
|
||||||
macos-signed-build.sh
|
|
1
.gitmodules
vendored
1
.gitmodules
vendored
|
@ -7,7 +7,6 @@
|
||||||
[submodule "client/3rd-prebuilt"]
|
[submodule "client/3rd-prebuilt"]
|
||||||
path = client/3rd-prebuilt
|
path = client/3rd-prebuilt
|
||||||
url = https://github.com/amnezia-vpn/3rd-prebuilt
|
url = https://github.com/amnezia-vpn/3rd-prebuilt
|
||||||
branch = feature/special-handshake
|
|
||||||
[submodule "client/3rd/amneziawg-apple"]
|
[submodule "client/3rd/amneziawg-apple"]
|
||||||
path = client/3rd/amneziawg-apple
|
path = client/3rd/amneziawg-apple
|
||||||
url = https://github.com/amnezia-vpn/amneziawg-apple
|
url = https://github.com/amnezia-vpn/amneziawg-apple
|
||||||
|
|
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
||||||
|
|
||||||
set(PROJECT AmneziaVPN)
|
set(PROJECT AmneziaVPN)
|
||||||
|
|
||||||
project(${PROJECT} VERSION 4.8.8.1
|
project(${PROJECT} VERSION 4.8.6.0
|
||||||
DESCRIPTION "AmneziaVPN"
|
DESCRIPTION "AmneziaVPN"
|
||||||
HOMEPAGE_URL "https://amnezia.org/"
|
HOMEPAGE_URL "https://amnezia.org/"
|
||||||
)
|
)
|
||||||
|
@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
|
||||||
set(RELEASE_DATE "${CURRENT_DATE}")
|
set(RELEASE_DATE "${CURRENT_DATE}")
|
||||||
|
|
||||||
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
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 2083)
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(MZ_PLATFORM_NAME "linux")
|
set(MZ_PLATFORM_NAME "linux")
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 840b7b070e6ac8b90dda2fac6e98859b23727c0c
|
Subproject commit efad1a5b5cb8e8ab61e49ccdca18c9090a0da8d3
|
2
client/3rd/amneziawg-apple
vendored
2
client/3rd/amneziawg-apple
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 811af0a83b3faeade89a9093a588595666d32066
|
Subproject commit 76e7db556a6d7e2582f9481df91db188a46c009c
|
|
@ -31,9 +31,6 @@ add_definitions(-DDEV_AGW_PUBLIC_KEY="$ENV{DEV_AGW_PUBLIC_KEY}")
|
||||||
add_definitions(-DDEV_AGW_ENDPOINT="$ENV{DEV_AGW_ENDPOINT}")
|
add_definitions(-DDEV_AGW_ENDPOINT="$ENV{DEV_AGW_ENDPOINT}")
|
||||||
add_definitions(-DDEV_S3_ENDPOINT="$ENV{DEV_S3_ENDPOINT}")
|
add_definitions(-DDEV_S3_ENDPOINT="$ENV{DEV_S3_ENDPOINT}")
|
||||||
|
|
||||||
add_definitions(-DFREE_V2_ENDPOINT="$ENV{FREE_V2_ENDPOINT}")
|
|
||||||
add_definitions(-DPREM_V1_ENDPOINT="$ENV{PREM_V1_ENDPOINT}")
|
|
||||||
|
|
||||||
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
||||||
set(PACKAGES ${PACKAGES} Widgets)
|
set(PACKAGES ${PACKAGES} Widgets)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -120,21 +120,10 @@ open class Wireguard : Protocol() {
|
||||||
configData.optStringOrNull("Jmax")?.let { setJmax(it.toInt()) }
|
configData.optStringOrNull("Jmax")?.let { setJmax(it.toInt()) }
|
||||||
configData.optStringOrNull("S1")?.let { setS1(it.toInt()) }
|
configData.optStringOrNull("S1")?.let { setS1(it.toInt()) }
|
||||||
configData.optStringOrNull("S2")?.let { setS2(it.toInt()) }
|
configData.optStringOrNull("S2")?.let { setS2(it.toInt()) }
|
||||||
configData.optStringOrNull("S3")?.let { setS3(it.toInt()) }
|
|
||||||
configData.optStringOrNull("S4")?.let { setS4(it.toInt()) }
|
|
||||||
configData.optStringOrNull("H1")?.let { setH1(it.toLong()) }
|
configData.optStringOrNull("H1")?.let { setH1(it.toLong()) }
|
||||||
configData.optStringOrNull("H2")?.let { setH2(it.toLong()) }
|
configData.optStringOrNull("H2")?.let { setH2(it.toLong()) }
|
||||||
configData.optStringOrNull("H3")?.let { setH3(it.toLong()) }
|
configData.optStringOrNull("H3")?.let { setH3(it.toLong()) }
|
||||||
configData.optStringOrNull("H4")?.let { setH4(it.toLong()) }
|
configData.optStringOrNull("H4")?.let { setH4(it.toLong()) }
|
||||||
configData.optStringOrNull("I1")?.let { setI1(it) }
|
|
||||||
configData.optStringOrNull("I2")?.let { setI2(it) }
|
|
||||||
configData.optStringOrNull("I3")?.let { setI3(it) }
|
|
||||||
configData.optStringOrNull("I4")?.let { setI4(it) }
|
|
||||||
configData.optStringOrNull("I5")?.let { setI5(it) }
|
|
||||||
configData.optStringOrNull("J1")?.let { setJ1(it) }
|
|
||||||
configData.optStringOrNull("J2")?.let { setJ2(it) }
|
|
||||||
configData.optStringOrNull("J3")?.let { setJ3(it) }
|
|
||||||
configData.optStringOrNull("Itime")?.let { setItime(it.toInt()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
|
||||||
|
|
|
@ -20,21 +20,10 @@ open class WireguardConfig protected constructor(
|
||||||
val jmax: Int?,
|
val jmax: Int?,
|
||||||
val s1: Int?,
|
val s1: Int?,
|
||||||
val s2: Int?,
|
val s2: Int?,
|
||||||
val s3: Int?,
|
|
||||||
val s4: Int?,
|
|
||||||
val h1: Long?,
|
val h1: Long?,
|
||||||
val h2: Long?,
|
val h2: Long?,
|
||||||
val h3: Long?,
|
val h3: Long?,
|
||||||
val h4: Long?,
|
val h4: Long?
|
||||||
var i1: String?,
|
|
||||||
var i2: String?,
|
|
||||||
var i3: String?,
|
|
||||||
var i4: String?,
|
|
||||||
var i5: String?,
|
|
||||||
var j1: String?,
|
|
||||||
var j2: String?,
|
|
||||||
var j3: String?,
|
|
||||||
var itime: Int?
|
|
||||||
) : ProtocolConfig(protocolConfigBuilder) {
|
) : ProtocolConfig(protocolConfigBuilder) {
|
||||||
|
|
||||||
protected constructor(builder: Builder) : this(
|
protected constructor(builder: Builder) : this(
|
||||||
|
@ -50,21 +39,10 @@ open class WireguardConfig protected constructor(
|
||||||
builder.jmax,
|
builder.jmax,
|
||||||
builder.s1,
|
builder.s1,
|
||||||
builder.s2,
|
builder.s2,
|
||||||
builder.s3,
|
|
||||||
builder.s4,
|
|
||||||
builder.h1,
|
builder.h1,
|
||||||
builder.h2,
|
builder.h2,
|
||||||
builder.h3,
|
builder.h3,
|
||||||
builder.h4,
|
builder.h4
|
||||||
builder.i1,
|
|
||||||
builder.i2,
|
|
||||||
builder.i3,
|
|
||||||
builder.i4,
|
|
||||||
builder.i5,
|
|
||||||
builder.j1,
|
|
||||||
builder.j2,
|
|
||||||
builder.j3,
|
|
||||||
builder.itime
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun toWgUserspaceString(): String = with(StringBuilder()) {
|
fun toWgUserspaceString(): String = with(StringBuilder()) {
|
||||||
|
@ -83,21 +61,10 @@ open class WireguardConfig protected constructor(
|
||||||
appendLine("jmax=$jmax")
|
appendLine("jmax=$jmax")
|
||||||
appendLine("s1=$s1")
|
appendLine("s1=$s1")
|
||||||
appendLine("s2=$s2")
|
appendLine("s2=$s2")
|
||||||
s3?.let { appendLine("s3=$it") }
|
|
||||||
s4?.let { appendLine("s4=$it") }
|
|
||||||
appendLine("h1=$h1")
|
appendLine("h1=$h1")
|
||||||
appendLine("h2=$h2")
|
appendLine("h2=$h2")
|
||||||
appendLine("h3=$h3")
|
appendLine("h3=$h3")
|
||||||
appendLine("h4=$h4")
|
appendLine("h4=$h4")
|
||||||
i1?.let { appendLine("i1=$it") }
|
|
||||||
i2?.let { appendLine("i2=$it") }
|
|
||||||
i3?.let { appendLine("i3=$it") }
|
|
||||||
i4?.let { appendLine("i4=$it") }
|
|
||||||
i5?.let { appendLine("i5=$it") }
|
|
||||||
j1?.let { appendLine("j1=$it") }
|
|
||||||
j2?.let { appendLine("j2=$it") }
|
|
||||||
j3?.let { appendLine("j3=$it") }
|
|
||||||
itime?.let { appendLine("itime=$it") }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,21 +117,10 @@ open class WireguardConfig protected constructor(
|
||||||
internal var jmax: Int? = null
|
internal var jmax: Int? = null
|
||||||
internal var s1: Int? = null
|
internal var s1: Int? = null
|
||||||
internal var s2: Int? = null
|
internal var s2: Int? = null
|
||||||
internal var s3: Int? = null
|
|
||||||
internal var s4: Int? = null
|
|
||||||
internal var h1: Long? = null
|
internal var h1: Long? = null
|
||||||
internal var h2: Long? = null
|
internal var h2: Long? = null
|
||||||
internal var h3: Long? = null
|
internal var h3: Long? = null
|
||||||
internal var h4: Long? = null
|
internal var h4: Long? = null
|
||||||
internal var i1: String? = null
|
|
||||||
internal var i2: String? = null
|
|
||||||
internal var i3: String? = null
|
|
||||||
internal var i4: String? = null
|
|
||||||
internal var i5: String? = null
|
|
||||||
internal var j1: String? = null
|
|
||||||
internal var j2: String? = null
|
|
||||||
internal var j3: String? = null
|
|
||||||
internal var itime: Int? = null
|
|
||||||
|
|
||||||
fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint }
|
fun setEndpoint(endpoint: InetEndpoint) = apply { this.endpoint = endpoint }
|
||||||
|
|
||||||
|
@ -183,21 +139,10 @@ open class WireguardConfig protected constructor(
|
||||||
fun setJmax(jmax: Int) = apply { this.jmax = jmax }
|
fun setJmax(jmax: Int) = apply { this.jmax = jmax }
|
||||||
fun setS1(s1: Int) = apply { this.s1 = s1 }
|
fun setS1(s1: Int) = apply { this.s1 = s1 }
|
||||||
fun setS2(s2: Int) = apply { this.s2 = s2 }
|
fun setS2(s2: Int) = apply { this.s2 = s2 }
|
||||||
fun setS3(s3: Int) = apply { this.s3 = s3 }
|
|
||||||
fun setS4(s4: Int) = apply { this.s4 = s4 }
|
|
||||||
fun setH1(h1: Long) = apply { this.h1 = h1 }
|
fun setH1(h1: Long) = apply { this.h1 = h1 }
|
||||||
fun setH2(h2: Long) = apply { this.h2 = h2 }
|
fun setH2(h2: Long) = apply { this.h2 = h2 }
|
||||||
fun setH3(h3: Long) = apply { this.h3 = h3 }
|
fun setH3(h3: Long) = apply { this.h3 = h3 }
|
||||||
fun setH4(h4: Long) = apply { this.h4 = h4 }
|
fun setH4(h4: Long) = apply { this.h4 = h4 }
|
||||||
fun setI1(i1: String) = apply { this.i1 = i1 }
|
|
||||||
fun setI2(i2: String) = apply { this.i2 = i2 }
|
|
||||||
fun setI3(i3: String) = apply { this.i3 = i3 }
|
|
||||||
fun setI4(i4: String) = apply { this.i4 = i4 }
|
|
||||||
fun setI5(i5: String) = apply { this.i5 = i5 }
|
|
||||||
fun setJ1(j1: String) = apply { this.j1 = j1 }
|
|
||||||
fun setJ2(j2: String) = apply { this.j2 = j2 }
|
|
||||||
fun setJ3(j3: String) = apply { this.j3 = j3 }
|
|
||||||
fun setItime(itime: Int) = apply { this.itime = itime }
|
|
||||||
|
|
||||||
override fun build(): WireguardConfig = configBuild().run { WireguardConfig(this@Builder) }
|
override fun build(): WireguardConfig = configBuild().run { WireguardConfig(this@Builder) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,22 +76,8 @@ set_target_properties(${PROJECT} PROPERTIES
|
||||||
XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION
|
XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION
|
||||||
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks"
|
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks"
|
||||||
XCODE_EMBED_APP_EXTENSIONS networkextension
|
XCODE_EMBED_APP_EXTENSIONS networkextension
|
||||||
|
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic
|
||||||
)
|
)
|
||||||
|
|
||||||
if(DEFINED DEPLOY)
|
|
||||||
set_target_properties(${PROJECT} PROPERTIES
|
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
|
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development"
|
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual
|
|
||||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "distr ios.org.amnezia.AmneziaVPN"
|
|
||||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "dev ios.org.amnezia.AmneziaVPN"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
set_target_properties(${PROJECT} PROPERTIES
|
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(${PROJECT} PROPERTIES
|
set_target_properties(${PROJECT} PROPERTIES
|
||||||
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
|
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
|
||||||
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES"
|
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES"
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include "awg_configurator.h"
|
#include "awg_configurator.h"
|
||||||
#include "protocols/protocols_defs.h"
|
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
@ -40,20 +39,6 @@ QString AwgConfigurator::createConfig(const ServerCredentials &credentials, Dock
|
||||||
jsonConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader);
|
jsonConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader);
|
||||||
jsonConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader);
|
jsonConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader);
|
||||||
jsonConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader);
|
jsonConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader);
|
||||||
|
|
||||||
// jsonConfig[config_key::cookieReplyPacketJunkSize] = configMap.value(config_key::cookieReplyPacketJunkSize);
|
|
||||||
// jsonConfig[config_key::transportPacketJunkSize] = configMap.value(config_key::transportPacketJunkSize);
|
|
||||||
|
|
||||||
// jsonConfig[config_key::specialJunk1] = configMap.value(amnezia::config_key::specialJunk1);
|
|
||||||
// jsonConfig[config_key::specialJunk2] = configMap.value(amnezia::config_key::specialJunk2);
|
|
||||||
// jsonConfig[config_key::specialJunk3] = configMap.value(amnezia::config_key::specialJunk3);
|
|
||||||
// jsonConfig[config_key::specialJunk4] = configMap.value(amnezia::config_key::specialJunk4);
|
|
||||||
// jsonConfig[config_key::specialJunk5] = configMap.value(amnezia::config_key::specialJunk5);
|
|
||||||
// jsonConfig[config_key::controlledJunk1] = configMap.value(amnezia::config_key::controlledJunk1);
|
|
||||||
// jsonConfig[config_key::controlledJunk2] = configMap.value(amnezia::config_key::controlledJunk2);
|
|
||||||
// jsonConfig[config_key::controlledJunk3] = configMap.value(amnezia::config_key::controlledJunk3);
|
|
||||||
// jsonConfig[config_key::specialHandshakeTimeout] = configMap.value(amnezia::config_key::specialHandshakeTimeout);
|
|
||||||
|
|
||||||
jsonConfig[config_key::mtu] =
|
jsonConfig[config_key::mtu] =
|
||||||
containerConfig.value(ProtocolProps::protoToString(Proto::Awg)).toObject().value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
containerConfig.value(ProtocolProps::protoToString(Proto::Awg)).toObject().value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
||||||
|
|
||||||
|
|
|
@ -118,14 +118,15 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair<QString,
|
||||||
QRegularExpression regex("redirect-gateway.*");
|
QRegularExpression regex("redirect-gateway.*");
|
||||||
config.replace(regex, "");
|
config.replace(regex, "");
|
||||||
|
|
||||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
|
||||||
if (dns.first.contains(protocols::dns::amneziaDnsIp)) {
|
|
||||||
QRegularExpression dnsRegex("dhcp-option DNS " + dns.second);
|
|
||||||
config.replace(dnsRegex, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_settings->isSitesSplitTunnelingEnabled()) {
|
if (!m_settings->isSitesSplitTunnelingEnabled()) {
|
||||||
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
||||||
|
|
||||||
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||||
|
// Prevent ipv6 leak
|
||||||
|
if (NetworkUtilities::checkIpv6Enabled()) {
|
||||||
|
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
config.append("block-ipv6\n");
|
config.append("block-ipv6\n");
|
||||||
} else if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
} else if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
||||||
|
|
||||||
|
@ -134,6 +135,7 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair<QString,
|
||||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||||
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
|
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
|
||||||
// Prevent ipv6 leak
|
// Prevent ipv6 leak
|
||||||
|
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
|
||||||
#endif
|
#endif
|
||||||
config.append("block-ipv6\n");
|
config.append("block-ipv6\n");
|
||||||
}
|
}
|
||||||
|
@ -167,15 +169,10 @@ QString OpenVpnConfigurator::processConfigWithExportSettings(const QPair<QString
|
||||||
QRegularExpression regex("redirect-gateway.*");
|
QRegularExpression regex("redirect-gateway.*");
|
||||||
config.replace(regex, "");
|
config.replace(regex, "");
|
||||||
|
|
||||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
|
||||||
if (dns.first.contains(protocols::dns::amneziaDnsIp)) {
|
|
||||||
QRegularExpression dnsRegex("dhcp-option DNS " + dns.second);
|
|
||||||
config.replace(dnsRegex, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
|
||||||
|
|
||||||
// Prevent ipv6 leak
|
// Prevent ipv6 leak
|
||||||
|
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
|
||||||
config.append("block-ipv6\n");
|
config.append("block-ipv6\n");
|
||||||
|
|
||||||
// remove block-outside-dns for all exported configs
|
// remove block-outside-dns for all exported configs
|
||||||
|
|
|
@ -140,83 +140,98 @@ QMap<DockerContainer, QString> ContainerProps::containerDetailedDescriptions()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
{ DockerContainer::OpenVpn,
|
{ DockerContainer::OpenVpn,
|
||||||
QObject::tr("OpenVPN is one of the most popular and reliable VPN protocols. "
|
QObject::tr(
|
||||||
"It uses SSL/TLS encryption, supports a wide variety of devices and operating systems, "
|
"OpenVPN stands as one of the most popular and time-tested VPN protocols available.\n"
|
||||||
"and is continuously improved by the community due to its open-source nature. "
|
"It employs its unique security protocol, "
|
||||||
"It provides a good balance between speed and security but is easily recognized by DPI systems, "
|
"leveraging the strength of SSL/TLS for encryption and key exchange. "
|
||||||
"making it susceptible to blocking.\n"
|
"Furthermore, OpenVPN's support for a multitude of authentication methods makes it versatile and adaptable, "
|
||||||
"\nFeatures:\n"
|
"catering to a wide range of devices and operating systems. "
|
||||||
"* Available on all AmneziaVPN platforms\n"
|
"Due to its open-source nature, OpenVPN benefits from extensive scrutiny by the global community, "
|
||||||
"* Normal battery consumption on mobile devices\n"
|
"which continually reinforces its security. "
|
||||||
"* Flexible customization for various devices and OS\n"
|
"With a strong balance of performance, security, and compatibility, "
|
||||||
"* Operates over both TCP and UDP protocols") },
|
"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 systems and therefore susceptible to blocking\n"
|
||||||
|
"* Can operate over both TCP and UDP network protocols.") },
|
||||||
{ DockerContainer::ShadowSocks,
|
{ DockerContainer::ShadowSocks,
|
||||||
QObject::tr("Shadowsocks is based on the SOCKS5 protocol and encrypts connections using AEAD cipher. "
|
QObject::tr("Shadowsocks, inspired by the SOCKS5 protocol, safeguards the connection using the AEAD cipher. "
|
||||||
"Although designed to be discreet, it doesn't mimic a standard HTTPS connection and can be detected by some DPI systems. "
|
"Although Shadowsocks is designed to be discreet and challenging to identify, it isn't identical to a standard HTTPS connection."
|
||||||
"Due to limited support in Amnezia, we recommend using the AmneziaWG protocol.\n"
|
"However, certain traffic analysis systems might still detect a Shadowsocks connection. "
|
||||||
"\nFeatures:\n"
|
"Due to limited support in Amnezia, it's recommended to use AmneziaWG protocol.\n\n"
|
||||||
"* Available in AmneziaVPN only on desktop platforms\n"
|
"* Available in the AmneziaVPN only on desktop platforms\n"
|
||||||
"* Customizable encryption protocol\n"
|
"* Configurable encryption protocol\n"
|
||||||
"* Detectable by some DPI systems\n"
|
"* Detectable by some DPI systems\n"
|
||||||
"* Operates over TCP protocol\n") },
|
"* Works over TCP network protocol.") },
|
||||||
{ DockerContainer::Cloak,
|
{ DockerContainer::Cloak,
|
||||||
QObject::tr("This combination includes the OpenVPN protocol and the Cloak plugin, specifically designed to protect against blocking.\n"
|
QObject::tr("This is a combination of the OpenVPN protocol and the Cloak plugin designed specifically for "
|
||||||
"\nOpenVPN securely encrypts all internet traffic between your device and the server.\n"
|
"protecting against detection.\n\n"
|
||||||
"\nThe Cloak plugin further protects the connection from DPI detection. "
|
"OpenVPN provides a secure VPN connection by encrypting all internet traffic between the client "
|
||||||
"It modifies traffic metadata to disguise VPN traffic as regular web traffic and prevents detection through active probing. "
|
"and the server.\n\n"
|
||||||
"If an incoming connection fails authentication, Cloak serves a fake website, making your VPN invisible to traffic analysis systems.\n"
|
"Cloak protects OpenVPN from detection. \n\n"
|
||||||
"\nIn regions with heavy internet censorship, we strongly recommend using OpenVPN with Cloak from your first connection.\n"
|
"Cloak can modify packet metadata so that it completely masks VPN traffic as normal web traffic, "
|
||||||
"\nFeatures:\n"
|
"and also protects the VPN from detection by Active Probing. This makes it very resistant to "
|
||||||
"* Available on all AmneziaVPN platforms\n"
|
"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"
|
||||||
|
"* Available in the AmneziaVPN across all platforms\n"
|
||||||
"* High power consumption on mobile devices\n"
|
"* High power consumption on mobile devices\n"
|
||||||
"* Flexible configuration options\n"
|
"* Flexible settings\n"
|
||||||
"* Undetectable by DPI systems\n"
|
"* Not recognised by detection systems\n"
|
||||||
"* Operates over TCP protocol on port 443") },
|
"* Works over TCP network protocol, 443 port.\n") },
|
||||||
{ DockerContainer::WireGuard,
|
{ DockerContainer::WireGuard,
|
||||||
QObject::tr("WireGuard is a modern, streamlined VPN protocol offering stable connectivity and excellent performance across all devices. "
|
QObject::tr("A relatively new popular VPN protocol with a simplified architecture.\n"
|
||||||
"It uses fixed encryption settings, delivering lower latency and higher data transfer speeds compared to OpenVPN. "
|
"WireGuard provides stable VPN connection and high performance on all devices. It uses hard-coded encryption "
|
||||||
"However, WireGuard is easily identifiable by DPI systems due to its distinctive packet signatures, making it susceptible to blocking.\n"
|
"settings. WireGuard compared to OpenVPN has lower latency and better data transfer throughput.\n"
|
||||||
"\nFeatures:\n"
|
"WireGuard is very susceptible to detection and blocking due to its distinct packet signatures. "
|
||||||
"* Available on all AmneziaVPN platforms\n"
|
"Unlike some other VPN protocols that employ obfuscation techniques, "
|
||||||
"* Low power consumption on mobile devices\n"
|
"the consistent signature patterns of WireGuard packets can be more easily identified and "
|
||||||
"* Minimal configuration required\n"
|
"thus blocked by advanced Deep Packet Inspection (DPI) systems and other network monitoring tools.\n\n"
|
||||||
"* Easily detected by DPI systems (susceptible to blocking)\n"
|
"* Available in the AmneziaVPN across all platforms\n"
|
||||||
"* Operates over UDP protocol") },
|
"* 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,
|
{ DockerContainer::Awg,
|
||||||
QObject::tr("AmneziaWG is a modern VPN protocol based on WireGuard, "
|
QObject::tr("A modern iteration of the popular VPN protocol, "
|
||||||
"combining simplified architecture with high performance across all devices. "
|
"AmneziaWG builds upon the foundation set by WireGuard, "
|
||||||
"It addresses WireGuard's main vulnerability (easy detection by DPI systems) through advanced obfuscation techniques, "
|
"retaining its simplified architecture and high-performance capabilities across devices.\n"
|
||||||
"making VPN traffic indistinguishable from regular internet traffic.\n"
|
"While WireGuard is known for its efficiency, "
|
||||||
"\nAmneziaWG is an excellent choice for those seeking a fast, stealthy VPN connection.\n"
|
"it had issues with being easily detected due to its distinct packet signatures. "
|
||||||
"\nFeatures:\n"
|
"AmneziaWG solves this problem by using better obfuscation methods, "
|
||||||
"* Available on all AmneziaVPN platforms\n"
|
"making its traffic blend in with regular internet traffic.\n"
|
||||||
"* Low battery consumption on mobile devices\n"
|
"This means that AmneziaWG keeps the fast performance of the original "
|
||||||
"* Minimal settings required\n"
|
"while adding an extra layer of stealth, "
|
||||||
"* Undetectable by traffic analysis systems (DPI)\n"
|
"making it a great choice for those wanting a fast and discreet VPN connection.\n\n"
|
||||||
"* Operates over UDP protocol") },
|
"* Available in the AmneziaVPN across all platforms\n"
|
||||||
|
"* Low power consumption\n"
|
||||||
|
"* Minimum number of settings\n"
|
||||||
|
"* Not recognised by traffic analysis systems\n"
|
||||||
|
"* Works over UDP network protocol.") },
|
||||||
{ DockerContainer::Xray,
|
{ DockerContainer::Xray,
|
||||||
QObject::tr("REALITY is an innovative protocol developed by the creators of XRay, designed specifically to combat high levels of internet censorship. "
|
QObject::tr("The REALITY protocol, a pioneering development by the creators of XRay, "
|
||||||
"REALITY identifies censorship systems during the TLS handshake, "
|
"is designed to provide the highest level of protection against detection through its innovative approach to security and privacy.\n"
|
||||||
"redirecting suspicious traffic seamlessly to legitimate websites like google.com while providing genuine TLS certificates. "
|
"It uniquely identifies attackers during the TLS handshake phase, seamlessly operating as a proxy for legitimate clients while diverting attackers to genuine websites, "
|
||||||
"This allows VPN traffic to blend indistinguishably with regular web traffic without special configuration."
|
"thus presenting an authentic TLS certificate and data. \n"
|
||||||
"\nUnlike older protocols such as VMess, VLESS, and XTLS-Vision, REALITY incorporates an advanced built-in \"friend-or-foe\" detection mechanism, "
|
"This advanced capability differentiates REALITY from similar technologies by its ability to disguise web traffic as coming from random, "
|
||||||
"effectively protecting against DPI and other traffic analysis methods.\n"
|
"legitimate sites without the need for specific configurations. \n"
|
||||||
"\nFeatures:\n"
|
"Unlike older protocols such as VMess, VLESS, and the XTLS-Vision transport, "
|
||||||
"* Resistant to active probing and DPI detection\n"
|
"REALITY's innovative \"friend or foe\" recognition at the TLS handshake enhances security. "
|
||||||
"* No special configuration required to disguise traffic\n"
|
"This makes REALITY a robust solution for maintaining internet freedom.")
|
||||||
"* Highly effective in heavily censored regions\n"
|
},
|
||||||
"* Minimal battery consumption on devices\n"
|
|
||||||
"* Operates over TCP protocol") },
|
|
||||||
{ DockerContainer::Ipsec,
|
{ DockerContainer::Ipsec,
|
||||||
QObject::tr("IKEv2, combined with IPSec encryption, is a modern and reliable VPN protocol. "
|
QObject::tr("IKEv2, paired with the IPSec encryption layer, stands as a modern and stable VPN protocol.\n"
|
||||||
"It reconnects quickly when switching networks or devices, making it ideal for dynamic network environments. "
|
"One of its distinguishing features is its ability to swiftly switch between networks and devices, "
|
||||||
"While it provides good security and speed, it's easily recognized by DPI systems and susceptible to blocking.\n"
|
"making it particularly adaptive in dynamic network environments. \n"
|
||||||
"\nFeatures:\n"
|
"While it offers a blend of security, stability, and speed, "
|
||||||
"* Available in AmneziaVPN only on Windows\n"
|
"it's essential to note that IKEv2 can be easily detected and is susceptible to blocking.\n\n"
|
||||||
"* Low battery consumption on mobile devices\n"
|
"* Available in the AmneziaVPN only on Windows\n"
|
||||||
"* Minimal configuration required\n"
|
"* Low power consumption, on mobile devices\n"
|
||||||
"* Detectable by DPI analysis systems(easily blocked)\n"
|
"* Minimal configuration\n"
|
||||||
"* Operates over UDP protocol(ports 500 and 4500)") },
|
"* Recognised by DPI analysis systems\n"
|
||||||
|
"* Works over UDP network protocol, ports 500 and 4500.") },
|
||||||
|
|
||||||
{ DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
|
{ DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
|
||||||
{ DockerContainer::Dns, QObject::tr("DNS Service") },
|
{ DockerContainer::Dns, QObject::tr("DNS Service") },
|
||||||
|
|
|
@ -22,21 +22,12 @@ namespace apiDefs
|
||||||
namespace key
|
namespace key
|
||||||
{
|
{
|
||||||
constexpr QLatin1String configVersion("config_version");
|
constexpr QLatin1String configVersion("config_version");
|
||||||
constexpr QLatin1String apiEndpoint("api_endpoint");
|
|
||||||
constexpr QLatin1String apiKey("api_key");
|
|
||||||
constexpr QLatin1String description("description");
|
|
||||||
constexpr QLatin1String name("name");
|
|
||||||
constexpr QLatin1String protocol("protocol");
|
|
||||||
|
|
||||||
constexpr QLatin1String apiConfig("api_config");
|
constexpr QLatin1String apiConfig("api_config");
|
||||||
constexpr QLatin1String stackType("stack_type");
|
constexpr QLatin1String stackType("stack_type");
|
||||||
constexpr QLatin1String serviceType("service_type");
|
constexpr QLatin1String serviceType("service_type");
|
||||||
constexpr QLatin1String cliVersion("cli_version");
|
|
||||||
constexpr QLatin1String supportedProtocols("supported_protocols");
|
|
||||||
|
|
||||||
constexpr QLatin1String vpnKey("vpn_key");
|
constexpr QLatin1String vpnKey("vpn_key");
|
||||||
constexpr QLatin1String config("config");
|
|
||||||
constexpr QLatin1String configs("configs");
|
|
||||||
|
|
||||||
constexpr QLatin1String installationUuid("installation_uuid");
|
constexpr QLatin1String installationUuid("installation_uuid");
|
||||||
constexpr QLatin1String workerLastUpdated("worker_last_updated");
|
constexpr QLatin1String workerLastUpdated("worker_last_updated");
|
||||||
|
@ -60,10 +51,6 @@ namespace apiDefs
|
||||||
constexpr QLatin1String website("website");
|
constexpr QLatin1String website("website");
|
||||||
constexpr QLatin1String websiteName("website_name");
|
constexpr QLatin1String websiteName("website_name");
|
||||||
constexpr QLatin1String telegram("telegram");
|
constexpr QLatin1String telegram("telegram");
|
||||||
|
|
||||||
constexpr QLatin1String id("id");
|
|
||||||
constexpr QLatin1String orderId("order_id");
|
|
||||||
constexpr QLatin1String migrationCode("migration_code");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int requestTimeoutMsecs = 12 * 1000; // 12 secs
|
const int requestTimeoutMsecs = 12 * 1000; // 12 secs
|
||||||
|
|
|
@ -3,24 +3,6 @@
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
const QByteArray AMNEZIA_CONFIG_SIGNATURE = QByteArray::fromHex("000000ff");
|
|
||||||
|
|
||||||
QString escapeUnicode(const QString &input)
|
|
||||||
{
|
|
||||||
QString output;
|
|
||||||
for (QChar c : input) {
|
|
||||||
if (c.unicode() < 0x20 || c.unicode() > 0x7E) {
|
|
||||||
output += QString("\\u%1").arg(QString::number(c.unicode(), 16).rightJustified(4, '0'));
|
|
||||||
} else {
|
|
||||||
output += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool apiUtils::isSubscriptionExpired(const QString &subscriptionEndDate)
|
bool apiUtils::isSubscriptionExpired(const QString &subscriptionEndDate)
|
||||||
{
|
{
|
||||||
QDateTime now = QDateTime::currentDateTime();
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
|
@ -41,21 +23,13 @@ bool apiUtils::isServerFromApi(const QJsonObject &serverConfigObject)
|
||||||
apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObject)
|
apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObject)
|
||||||
{
|
{
|
||||||
auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt();
|
auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt();
|
||||||
|
|
||||||
switch (configVersion) {
|
switch (configVersion) {
|
||||||
case apiDefs::ConfigSource::Telegram: {
|
case apiDefs::ConfigSource::Telegram: {
|
||||||
constexpr QLatin1String freeV2Endpoint(FREE_V2_ENDPOINT);
|
|
||||||
constexpr QLatin1String premiumV1Endpoint(PREM_V1_ENDPOINT);
|
|
||||||
|
|
||||||
auto apiEndpoint = serverConfigObject.value(apiDefs::key::apiEndpoint).toString();
|
|
||||||
|
|
||||||
if (apiEndpoint.contains(premiumV1Endpoint)) {
|
|
||||||
return apiDefs::ConfigType::AmneziaPremiumV1;
|
|
||||||
} else if (apiEndpoint.contains(freeV2Endpoint)) {
|
|
||||||
return apiDefs::ConfigType::AmneziaFreeV2;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
case apiDefs::ConfigSource::AmneziaGateway: {
|
case apiDefs::ConfigSource::AmneziaGateway: {
|
||||||
|
constexpr QLatin1String stackPremium("prem");
|
||||||
|
constexpr QLatin1String stackFree("free");
|
||||||
|
|
||||||
constexpr QLatin1String servicePremium("amnezia-premium");
|
constexpr QLatin1String servicePremium("amnezia-premium");
|
||||||
constexpr QLatin1String serviceFree("amnezia-free");
|
constexpr QLatin1String serviceFree("amnezia-free");
|
||||||
constexpr QLatin1String serviceExternalPremium("external-premium");
|
constexpr QLatin1String serviceExternalPremium("external-premium");
|
||||||
|
@ -96,9 +70,6 @@ amnezia::ErrorCode apiUtils::checkNetworkReplyErrors(const QList<QSslError> &ssl
|
||||||
|| reply->error() == QNetworkReply::NetworkError::TimeoutError) {
|
|| reply->error() == QNetworkReply::NetworkError::TimeoutError) {
|
||||||
qDebug() << reply->error();
|
qDebug() << reply->error();
|
||||||
return amnezia::ErrorCode::ApiConfigTimeoutError;
|
return amnezia::ErrorCode::ApiConfigTimeoutError;
|
||||||
} else if (reply->error() == QNetworkReply::NetworkError::OperationNotImplementedError) {
|
|
||||||
qDebug() << reply->error();
|
|
||||||
return amnezia::ErrorCode::ApiUpdateRequestError;
|
|
||||||
} else {
|
} else {
|
||||||
QString err = reply->errorString();
|
QString err = reply->errorString();
|
||||||
int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
@ -124,41 +95,3 @@ bool apiUtils::isPremiumServer(const QJsonObject &serverConfigObject)
|
||||||
apiDefs::ConfigType::ExternalPremium };
|
apiDefs::ConfigType::ExternalPremium };
|
||||||
return premiumTypes.contains(getConfigType(serverConfigObject));
|
return premiumTypes.contains(getConfigType(serverConfigObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString apiUtils::getPremiumV1VpnKey(const QJsonObject &serverConfigObject)
|
|
||||||
{
|
|
||||||
if (apiUtils::getConfigType(serverConfigObject) != apiDefs::ConfigType::AmneziaPremiumV1) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QPair<QString, QVariant>> orderedFields;
|
|
||||||
orderedFields.append(qMakePair(apiDefs::key::name, serverConfigObject[apiDefs::key::name].toString()));
|
|
||||||
orderedFields.append(qMakePair(apiDefs::key::description, serverConfigObject[apiDefs::key::description].toString()));
|
|
||||||
orderedFields.append(qMakePair(apiDefs::key::configVersion, serverConfigObject[apiDefs::key::configVersion].toDouble()));
|
|
||||||
orderedFields.append(qMakePair(apiDefs::key::protocol, serverConfigObject[apiDefs::key::protocol].toString()));
|
|
||||||
orderedFields.append(qMakePair(apiDefs::key::apiEndpoint, serverConfigObject[apiDefs::key::apiEndpoint].toString()));
|
|
||||||
orderedFields.append(qMakePair(apiDefs::key::apiKey, serverConfigObject[apiDefs::key::apiKey].toString()));
|
|
||||||
|
|
||||||
QString vpnKeyStr = "{";
|
|
||||||
for (int i = 0; i < orderedFields.size(); ++i) {
|
|
||||||
const auto &pair = orderedFields[i];
|
|
||||||
if (pair.second.typeId() == QMetaType::Type::QString) {
|
|
||||||
vpnKeyStr += "\"" + pair.first + "\": \"" + pair.second.toString() + "\"";
|
|
||||||
} else if (pair.second.typeId() == QMetaType::Type::Double || pair.second.typeId() == QMetaType::Type::Int) {
|
|
||||||
vpnKeyStr += "\"" + pair.first + "\": " + QString::number(pair.second.toDouble(), 'f', 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < orderedFields.size() - 1) {
|
|
||||||
vpnKeyStr += ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vpnKeyStr += "}";
|
|
||||||
|
|
||||||
QByteArray vpnKeyCompressed = escapeUnicode(vpnKeyStr).toUtf8();
|
|
||||||
vpnKeyCompressed = qCompress(vpnKeyCompressed, 6);
|
|
||||||
vpnKeyCompressed = vpnKeyCompressed.mid(4);
|
|
||||||
|
|
||||||
QByteArray signedData = AMNEZIA_CONFIG_SIGNATURE + vpnKeyCompressed;
|
|
||||||
|
|
||||||
return QString("vpn://%1").arg(QString(signedData.toBase64(QByteArray::Base64UrlEncoding)));
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,8 +19,6 @@ namespace apiUtils
|
||||||
apiDefs::ConfigSource getConfigSource(const QJsonObject &serverConfigObject);
|
apiDefs::ConfigSource getConfigSource(const QJsonObject &serverConfigObject);
|
||||||
|
|
||||||
amnezia::ErrorCode checkNetworkReplyErrors(const QList<QSslError> &sslErrors, QNetworkReply *reply);
|
amnezia::ErrorCode checkNetworkReplyErrors(const QList<QSslError> &sslErrors, QNetworkReply *reply);
|
||||||
|
|
||||||
QString getPremiumV1VpnKey(const QJsonObject &serverConfigObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // APIUTILS_H
|
#endif // APIUTILS_H
|
||||||
|
|
|
@ -148,9 +148,6 @@ void CoreController::initControllers()
|
||||||
|
|
||||||
m_apiConfigsController.reset(new ApiConfigsController(m_serversModel, m_apiServicesModel, m_settings));
|
m_apiConfigsController.reset(new ApiConfigsController(m_serversModel, m_apiServicesModel, m_settings));
|
||||||
m_engine->rootContext()->setContextProperty("ApiConfigsController", m_apiConfigsController.get());
|
m_engine->rootContext()->setContextProperty("ApiConfigsController", m_apiConfigsController.get());
|
||||||
|
|
||||||
m_apiPremV1MigrationController.reset(new ApiPremV1MigrationController(m_serversModel, m_settings, this));
|
|
||||||
m_engine->rootContext()->setContextProperty("ApiPremV1MigrationController", m_apiPremV1MigrationController.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::initAndroidController()
|
void CoreController::initAndroidController()
|
||||||
|
@ -223,8 +220,6 @@ void CoreController::initSignalHandlers()
|
||||||
initAutoConnectHandler();
|
initAutoConnectHandler();
|
||||||
initAmneziaDnsToggledHandler();
|
initAmneziaDnsToggledHandler();
|
||||||
initPrepareConfigHandler();
|
initPrepareConfigHandler();
|
||||||
initImportPremiumV2VpnKeyHandler();
|
|
||||||
initShowMigrationDrawerHandler();
|
|
||||||
initStrictKillSwitchHandler();
|
initStrictKillSwitchHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,29 +363,10 @@ void CoreController::initPrepareConfigHandler()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::initImportPremiumV2VpnKeyHandler()
|
|
||||||
{
|
|
||||||
connect(m_apiPremV1MigrationController.get(), &ApiPremV1MigrationController::importPremiumV2VpnKey, this, [this](const QString &vpnKey) {
|
|
||||||
m_importController->extractConfigFromData(vpnKey);
|
|
||||||
m_importController->importConfig();
|
|
||||||
|
|
||||||
emit m_apiPremV1MigrationController->migrationFinished();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreController::initShowMigrationDrawerHandler()
|
|
||||||
{
|
|
||||||
QTimer::singleShot(1000, this, [this]() {
|
|
||||||
if (m_apiPremV1MigrationController->isPremV1MigrationReminderActive() && m_apiPremV1MigrationController->hasConfigsToMigration()) {
|
|
||||||
m_apiPremV1MigrationController->showMigrationDrawer();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void CoreController::initStrictKillSwitchHandler()
|
void CoreController::initStrictKillSwitchHandler()
|
||||||
{
|
{
|
||||||
connect(m_settingsController.get(), &SettingsController::strictKillSwitchEnabledChanged, m_vpnConnection.get(),
|
connect(m_settingsController.get(), &SettingsController::strictKillSwitchEnabledChanged,
|
||||||
&VpnConnection::onKillSwitchModeChanged);
|
m_vpnConnection.get(), &VpnConnection::onKillSwitchModeChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<PageController> CoreController::pageController() const
|
QSharedPointer<PageController> CoreController::pageController() const
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include "ui/controllers/api/apiConfigsController.h"
|
#include "ui/controllers/api/apiConfigsController.h"
|
||||||
#include "ui/controllers/api/apiSettingsController.h"
|
#include "ui/controllers/api/apiSettingsController.h"
|
||||||
#include "ui/controllers/api/apiPremV1MigrationController.h"
|
|
||||||
#include "ui/controllers/appSplitTunnelingController.h"
|
#include "ui/controllers/appSplitTunnelingController.h"
|
||||||
#include "ui/controllers/allowedDnsController.h"
|
#include "ui/controllers/allowedDnsController.h"
|
||||||
#include "ui/controllers/connectionController.h"
|
#include "ui/controllers/connectionController.h"
|
||||||
|
@ -83,8 +82,6 @@ private:
|
||||||
void initAutoConnectHandler();
|
void initAutoConnectHandler();
|
||||||
void initAmneziaDnsToggledHandler();
|
void initAmneziaDnsToggledHandler();
|
||||||
void initPrepareConfigHandler();
|
void initPrepareConfigHandler();
|
||||||
void initImportPremiumV2VpnKeyHandler();
|
|
||||||
void initShowMigrationDrawerHandler();
|
|
||||||
void initStrictKillSwitchHandler();
|
void initStrictKillSwitchHandler();
|
||||||
|
|
||||||
QQmlApplicationEngine *m_engine {}; // TODO use parent child system here?
|
QQmlApplicationEngine *m_engine {}; // TODO use parent child system here?
|
||||||
|
@ -112,7 +109,6 @@ private:
|
||||||
|
|
||||||
QScopedPointer<ApiSettingsController> m_apiSettingsController;
|
QScopedPointer<ApiSettingsController> m_apiSettingsController;
|
||||||
QScopedPointer<ApiConfigsController> m_apiConfigsController;
|
QScopedPointer<ApiConfigsController> m_apiConfigsController;
|
||||||
QScopedPointer<ApiPremV1MigrationController> m_apiPremV1MigrationController;
|
|
||||||
|
|
||||||
QSharedPointer<ContainersModel> m_containersModel;
|
QSharedPointer<ContainersModel> m_containersModel;
|
||||||
QSharedPointer<ContainersModel> m_defaultServerContainersModel;
|
QSharedPointer<ContainersModel> m_defaultServerContainersModel;
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
#include "amnezia_application.h"
|
#include "amnezia_application.h"
|
||||||
#include "core/api/apiUtils.h"
|
#include "core/api/apiUtils.h"
|
||||||
#include "core/networkUtilities.h"
|
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
#include "core/networkUtilities.h"
|
||||||
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
#include "core/ipcclient.h"
|
#include "core/ipcclient.h"
|
||||||
|
@ -36,17 +36,10 @@ namespace
|
||||||
constexpr QLatin1String errorResponsePattern1("No active configuration found for");
|
constexpr QLatin1String errorResponsePattern1("No active configuration found for");
|
||||||
constexpr QLatin1String errorResponsePattern2("No non-revoked public key found for");
|
constexpr QLatin1String errorResponsePattern2("No non-revoked public key found for");
|
||||||
constexpr QLatin1String errorResponsePattern3("Account not found.");
|
constexpr QLatin1String errorResponsePattern3("Account not found.");
|
||||||
|
|
||||||
constexpr QLatin1String updateRequestResponsePattern("client version update is required");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GatewayController::GatewayController(const QString &gatewayEndpoint, const bool isDevEnvironment, const int requestTimeoutMsecs,
|
GatewayController::GatewayController(const QString &gatewayEndpoint, bool isDevEnvironment, int requestTimeoutMsecs, QObject *parent)
|
||||||
const bool isStrictKillSwitchEnabled, QObject *parent)
|
: QObject(parent), m_gatewayEndpoint(gatewayEndpoint), m_isDevEnvironment(isDevEnvironment), m_requestTimeoutMsecs(requestTimeoutMsecs)
|
||||||
: QObject(parent),
|
|
||||||
m_gatewayEndpoint(gatewayEndpoint),
|
|
||||||
m_isDevEnvironment(isDevEnvironment),
|
|
||||||
m_requestTimeoutMsecs(requestTimeoutMsecs),
|
|
||||||
m_isStrictKillSwitchEnabled(isStrictKillSwitchEnabled)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,11 +58,11 @@ ErrorCode GatewayController::get(const QString &endpoint, QByteArray &responseBo
|
||||||
|
|
||||||
// bypass killSwitch exceptions for API-gateway
|
// bypass killSwitch exceptions for API-gateway
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
if (m_isStrictKillSwitchEnabled) {
|
{
|
||||||
QString host = QUrl(request.url()).host();
|
QString host = QUrl(request.url()).host();
|
||||||
QString ip = NetworkUtilities::getIPAddress(host);
|
QString ip = NetworkUtilities::getIPAddress(host);
|
||||||
if (!ip.isEmpty()) {
|
if (!ip.isEmpty()) {
|
||||||
IpcClient::Interface()->addKillSwitchAllowedRange(QStringList { ip });
|
IpcClient::Interface()->addKillSwitchAllowedRange(QStringList{ip});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -127,11 +120,11 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api
|
||||||
|
|
||||||
// bypass killSwitch exceptions for API-gateway
|
// bypass killSwitch exceptions for API-gateway
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
if (m_isStrictKillSwitchEnabled) {
|
{
|
||||||
QString host = QUrl(request.url()).host();
|
QString host = QUrl(request.url()).host();
|
||||||
QString ip = NetworkUtilities::getIPAddress(host);
|
QString ip = NetworkUtilities::getIPAddress(host);
|
||||||
if (!ip.isEmpty()) {
|
if (!ip.isEmpty()) {
|
||||||
IpcClient::Interface()->addKillSwitchAllowedRange(QStringList { ip });
|
IpcClient::Interface()->addKillSwitchAllowedRange(QStringList{ip});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -313,13 +306,6 @@ bool GatewayController::shouldBypassProxy(QNetworkReply *reply, const QByteArray
|
||||||
qDebug() << reply->error();
|
qDebug() << reply->error();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (reply->error() == QNetworkReply::NetworkError::OperationNotImplementedError) {
|
|
||||||
if (responseBody.contains(updateRequestResponsePattern)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
qDebug() << reply->error();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
} else if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
||||||
qDebug() << reply->error();
|
qDebug() << reply->error();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -15,8 +15,7 @@ class GatewayController : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GatewayController(const QString &gatewayEndpoint, const bool isDevEnvironment, const int requestTimeoutMsecs,
|
explicit GatewayController(const QString &gatewayEndpoint, bool isDevEnvironment, int requestTimeoutMsecs, QObject *parent = nullptr);
|
||||||
const bool isStrictKillSwitchEnabled, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
amnezia::ErrorCode get(const QString &endpoint, QByteArray &responseBody);
|
amnezia::ErrorCode get(const QString &endpoint, QByteArray &responseBody);
|
||||||
amnezia::ErrorCode post(const QString &endpoint, const QJsonObject apiPayload, QByteArray &responseBody);
|
amnezia::ErrorCode post(const QString &endpoint, const QJsonObject apiPayload, QByteArray &responseBody);
|
||||||
|
@ -31,7 +30,6 @@ private:
|
||||||
int m_requestTimeoutMsecs;
|
int m_requestTimeoutMsecs;
|
||||||
QString m_gatewayEndpoint;
|
QString m_gatewayEndpoint;
|
||||||
bool m_isDevEnvironment = false;
|
bool m_isDevEnvironment = false;
|
||||||
bool m_isStrictKillSwitchEnabled = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GATEWAYCONTROLLER_H
|
#endif // GATEWAYCONTROLLER_H
|
||||||
|
|
|
@ -138,7 +138,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||||
|
|
||||||
if (overwriteMode == libssh::ScpOverwriteMode::ScpOverwriteExisting) {
|
if (overwriteMode == libssh::ScpOverwriteMode::ScpOverwriteExisting) {
|
||||||
e = runScript(credentials,
|
e = runScript(credentials,
|
||||||
replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, path),
|
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
|
||||||
genVarsForScript(credentials, container)),
|
genVarsForScript(credentials, container)),
|
||||||
cbReadStd, cbReadStd);
|
cbReadStd, cbReadStd);
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||||
return e;
|
return e;
|
||||||
} else if (overwriteMode == libssh::ScpOverwriteMode::ScpAppendToExisting) {
|
} else if (overwriteMode == libssh::ScpOverwriteMode::ScpAppendToExisting) {
|
||||||
e = runScript(credentials,
|
e = runScript(credentials,
|
||||||
replaceVars(QStringLiteral("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName, tmpFileName),
|
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(tmpFileName),
|
||||||
genVarsForScript(credentials, container)),
|
genVarsForScript(credentials, container)),
|
||||||
cbReadStd, cbReadStd);
|
cbReadStd, cbReadStd);
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||||
return e;
|
return e;
|
||||||
|
|
||||||
e = runScript(credentials,
|
e = runScript(credentials,
|
||||||
replaceVars(QStringLiteral("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName, path),
|
replaceVars(QString("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName).arg(path),
|
||||||
genVarsForScript(credentials, container)),
|
genVarsForScript(credentials, container)),
|
||||||
cbReadStd, cbReadStd);
|
cbReadStd, cbReadStd);
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ QByteArray ServerController::getTextFileFromContainer(DockerContainer container,
|
||||||
|
|
||||||
errorCode = ErrorCode::NoError;
|
errorCode = ErrorCode::NoError;
|
||||||
|
|
||||||
QString script = QStringLiteral("sudo docker exec -i %1 sh -c \"xxd -p '%2'\"").arg(ContainerProps::containerToString(container), path);
|
QString script = QString("sudo docker exec -i %1 sh -c \"xxd -p \'%2\'\"").arg(ContainerProps::containerToString(container)).arg(path);
|
||||||
|
|
||||||
QString stdOut;
|
QString stdOut;
|
||||||
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
auto cbReadStdOut = [&](const QString &data, libssh::Client &) {
|
||||||
|
@ -349,7 +349,7 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
|
||||||
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
||||||
!= newProtoConfig.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)
|
|| (oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)
|
||||||
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
|
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
|
||||||
|| (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)
|
|| (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)
|
||||||
!= newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount))
|
!= newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount))
|
||||||
|| (oldProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize)
|
|| (oldProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize)
|
||||||
|
@ -366,13 +366,8 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
|
||||||
!= newProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader))
|
!= newProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader))
|
||||||
|| (oldProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader)
|
|| (oldProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader)
|
||||||
!= newProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader))
|
!= newProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader))
|
||||||
|| (oldProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader))
|
|| (oldProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader)
|
||||||
!= newProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader))
|
!= newProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader)))
|
||||||
// || (oldProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize)
|
|
||||||
// != newProtoConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize))
|
|
||||||
// || (oldProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize)
|
|
||||||
// != newProtoConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize))
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +375,7 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
|
||||||
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
if ((oldProtoConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress)
|
||||||
!= newProtoConfig.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::wireguard::defaultPort)
|
|| (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)
|
||||||
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)))
|
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,13 +383,6 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container == DockerContainer::Xray) {
|
|
||||||
if (oldProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)
|
|
||||||
!= newProtoConfig.value(config_key::port).toString(protocols::xray::defaultPort)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,13 +448,11 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
||||||
runScript(credentials,
|
runScript(credentials,
|
||||||
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
|
replaceVars(amnezia::scriptData(SharedScriptType::build_container), genVarsForScript(credentials, container, config)),
|
||||||
cbReadStdOut, cbReadStdErr);
|
cbReadStdOut, cbReadStdErr);
|
||||||
|
|
||||||
if (stdOut.contains("doesn't work on cgroups v2"))
|
if (stdOut.contains("doesn't work on cgroups v2"))
|
||||||
return ErrorCode::ServerDockerOnCgroupsV2;
|
return ErrorCode::ServerDockerOnCgroupsV2;
|
||||||
if (stdOut.contains("cgroup mountpoint does not exist"))
|
if (stdOut.contains("cgroup mountpoint does not exist"))
|
||||||
return ErrorCode::ServerCgroupMountpoint;
|
return ErrorCode::ServerCgroupMountpoint;
|
||||||
if (stdOut.contains("have reached") && stdOut.contains("pull rate limit"))
|
|
||||||
return ErrorCode::DockerPullRateLimit;
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -646,9 +632,6 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
||||||
vars.append({ { "$UNDERLOAD_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::underloadPacketMagicHeader).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() } });
|
vars.append({ { "$TRANSPORT_PACKET_MAGIC_HEADER", amneziaWireguarConfig.value(config_key::transportPacketMagicHeader).toString() } });
|
||||||
|
|
||||||
vars.append({ { "$COOKIE_REPLY_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::cookieReplyPacketJunkSize).toString() } });
|
|
||||||
vars.append({ { "$TRANSPORT_PACKET_JUNK_SIZE", amneziaWireguarConfig.value(config_key::transportPacketJunkSize).toString() } });
|
|
||||||
|
|
||||||
// Socks5 proxy vars
|
// Socks5 proxy vars
|
||||||
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
|
vars.append({ { "$SOCKS5_PROXY_PORT", socks5ProxyConfig.value(config_key::port).toString(protocols::socks5Proxy::defaultPort) } });
|
||||||
auto username = socks5ProxyConfig.value(config_key::userName).toString();
|
auto username = socks5ProxyConfig.value(config_key::userName).toString();
|
||||||
|
@ -835,7 +818,7 @@ ErrorCode ServerController::isServerDpkgBusy(const ServerCredentials &credential
|
||||||
|
|
||||||
if (stdOut.contains("Packet manager not found"))
|
if (stdOut.contains("Packet manager not found"))
|
||||||
return ErrorCode::ServerPacketManagerError;
|
return ErrorCode::ServerPacketManagerError;
|
||||||
if (stdOut.contains("fuser not installed") || stdOut.contains("cat not installed"))
|
if (stdOut.contains("fuser not installed"))
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
|
|
||||||
if (stdOut.isEmpty()) {
|
if (stdOut.isEmpty()) {
|
||||||
|
|
|
@ -60,7 +60,6 @@ namespace amnezia
|
||||||
ServerUserPasswordRequired = 210,
|
ServerUserPasswordRequired = 210,
|
||||||
ServerDockerOnCgroupsV2 = 211,
|
ServerDockerOnCgroupsV2 = 211,
|
||||||
ServerCgroupMountpoint = 212,
|
ServerCgroupMountpoint = 212,
|
||||||
DockerPullRateLimit = 213,
|
|
||||||
|
|
||||||
// Ssh connection errors
|
// Ssh connection errors
|
||||||
SshRequestDeniedError = 300,
|
SshRequestDeniedError = 300,
|
||||||
|
@ -118,8 +117,6 @@ namespace amnezia
|
||||||
ApiServicesMissingError = 1107,
|
ApiServicesMissingError = 1107,
|
||||||
ApiConfigLimitError = 1108,
|
ApiConfigLimitError = 1108,
|
||||||
ApiNotFoundError = 1109,
|
ApiNotFoundError = 1109,
|
||||||
ApiMigrationError = 1110,
|
|
||||||
ApiUpdateRequestError = 1111,
|
|
||||||
|
|
||||||
// QFile errors
|
// QFile errors
|
||||||
OpenError = 1200,
|
OpenError = 1200,
|
||||||
|
|
|
@ -28,7 +28,6 @@ QString errorString(ErrorCode code) {
|
||||||
case(ErrorCode::ServerUserPasswordRequired): errorMessage = QObject::tr("The user's password is required"); break;
|
case(ErrorCode::ServerUserPasswordRequired): errorMessage = QObject::tr("The user's password is required"); break;
|
||||||
case(ErrorCode::ServerDockerOnCgroupsV2): errorMessage = QObject::tr("Docker error: runc doesn't work on cgroups v2"); break;
|
case(ErrorCode::ServerDockerOnCgroupsV2): errorMessage = QObject::tr("Docker error: runc doesn't work on cgroups v2"); break;
|
||||||
case(ErrorCode::ServerCgroupMountpoint): errorMessage = QObject::tr("Server error: cgroup mountpoint does not exist"); break;
|
case(ErrorCode::ServerCgroupMountpoint): errorMessage = QObject::tr("Server error: cgroup mountpoint does not exist"); break;
|
||||||
case(ErrorCode::DockerPullRateLimit): errorMessage = QObject::tr("Docker error: The pull rate limit has been reached"); break;
|
|
||||||
|
|
||||||
// Libssh errors
|
// Libssh errors
|
||||||
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break;
|
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break;
|
||||||
|
@ -75,8 +74,6 @@ QString errorString(ErrorCode code) {
|
||||||
case (ErrorCode::ApiServicesMissingError): errorMessage = QObject::tr("Missing list of available services"); break;
|
case (ErrorCode::ApiServicesMissingError): errorMessage = QObject::tr("Missing list of available services"); break;
|
||||||
case (ErrorCode::ApiConfigLimitError): errorMessage = QObject::tr("The limit of allowed configurations per subscription has been exceeded"); break;
|
case (ErrorCode::ApiConfigLimitError): errorMessage = QObject::tr("The limit of allowed configurations per subscription has been exceeded"); break;
|
||||||
case (ErrorCode::ApiNotFoundError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break;
|
case (ErrorCode::ApiNotFoundError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break;
|
||||||
case (ErrorCode::ApiMigrationError): errorMessage = QObject::tr("A migration error has occurred. Please contact our technical support"); break;
|
|
||||||
case (ErrorCode::ApiUpdateRequestError): errorMessage = QObject::tr("Please update the application to use this feature"); break;
|
|
||||||
|
|
||||||
// QFile errors
|
// QFile errors
|
||||||
case(ErrorCode::OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break;
|
case(ErrorCode::OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break;
|
||||||
|
|
|
@ -149,7 +149,8 @@ bool Daemon::activate(const InterfaceConfig& config) {
|
||||||
// set routing
|
// set routing
|
||||||
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
|
for (const IPAddress& ip : config.m_allowedIPAddressRanges) {
|
||||||
if (!wgutils()->updateRoutePrefix(ip)) {
|
if (!wgutils()->updateRoutePrefix(ip)) {
|
||||||
logger.debug() << "Routing configuration failed for" << ip.toString();
|
logger.debug() << "Routing configuration failed for"
|
||||||
|
<< logger.sensitive(ip.toString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,14 +170,11 @@ bool Daemon::maybeUpdateResolvers(const InterfaceConfig& config) {
|
||||||
if ((config.m_hopType == InterfaceConfig::MultiHopExit) ||
|
if ((config.m_hopType == InterfaceConfig::MultiHopExit) ||
|
||||||
(config.m_hopType == InterfaceConfig::SingleHop)) {
|
(config.m_hopType == InterfaceConfig::SingleHop)) {
|
||||||
QList<QHostAddress> resolvers;
|
QList<QHostAddress> resolvers;
|
||||||
resolvers.append(QHostAddress(config.m_primaryDnsServer));
|
resolvers.append(QHostAddress(config.m_dnsServer));
|
||||||
if (!config.m_secondaryDnsServer.isEmpty()) {
|
|
||||||
resolvers.append(QHostAddress(config.m_secondaryDnsServer));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the DNS is not the Gateway, it's a user defined DNS
|
// If the DNS is not the Gateway, it's a user defined DNS
|
||||||
// thus, not add any other :)
|
// thus, not add any other :)
|
||||||
if (config.m_primaryDnsServer == config.m_serverIpv4Gateway) {
|
if (config.m_dnsServer == config.m_serverIpv4Gateway) {
|
||||||
resolvers.append(QHostAddress(config.m_serverIpv6Gateway));
|
resolvers.append(QHostAddress(config.m_serverIpv6Gateway));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,26 +280,15 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
||||||
config.m_serverIpv4Gateway = obj.value("serverIpv4Gateway").toString();
|
config.m_serverIpv4Gateway = obj.value("serverIpv4Gateway").toString();
|
||||||
config.m_serverIpv6Gateway = obj.value("serverIpv6Gateway").toString();
|
config.m_serverIpv6Gateway = obj.value("serverIpv6Gateway").toString();
|
||||||
|
|
||||||
if (!obj.contains("primaryDnsServer")) {
|
if (!obj.contains("dnsServer")) {
|
||||||
config.m_primaryDnsServer = QString();
|
config.m_dnsServer = QString();
|
||||||
} else {
|
} else {
|
||||||
QJsonValue value = obj.value("primaryDnsServer");
|
QJsonValue value = obj.value("dnsServer");
|
||||||
if (!value.isString()) {
|
if (!value.isString()) {
|
||||||
logger.error() << "dnsServer is not a string";
|
logger.error() << "dnsServer is not a string";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
config.m_primaryDnsServer = value.toString();
|
config.m_dnsServer = value.toString();
|
||||||
}
|
|
||||||
|
|
||||||
if (!obj.contains("secondaryDnsServer")) {
|
|
||||||
config.m_secondaryDnsServer = QString();
|
|
||||||
} else {
|
|
||||||
QJsonValue value = obj.value("secondaryDnsServer");
|
|
||||||
if (!value.isString()) {
|
|
||||||
logger.error() << "dnsServer is not a string";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
config.m_secondaryDnsServer = value.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj.contains("hopType")) {
|
if (!obj.contains("hopType")) {
|
||||||
|
@ -405,13 +392,6 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
||||||
if (!obj.value("S2").isNull()) {
|
if (!obj.value("S2").isNull()) {
|
||||||
config.m_responsePacketJunkSize = obj.value("S2").toString();
|
config.m_responsePacketJunkSize = obj.value("S2").toString();
|
||||||
}
|
}
|
||||||
if (!obj.value("S3").isNull()) {
|
|
||||||
config.m_cookieReplyPacketJunkSize = obj.value("S3").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("S4").isNull()) {
|
|
||||||
config.m_transportPacketJunkSize = obj.value("S4").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!obj.value("H1").isNull()) {
|
if (!obj.value("H1").isNull()) {
|
||||||
config.m_initPacketMagicHeader = obj.value("H1").toString();
|
config.m_initPacketMagicHeader = obj.value("H1").toString();
|
||||||
}
|
}
|
||||||
|
@ -425,34 +405,6 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
||||||
config.m_transportPacketMagicHeader = obj.value("H4").toString();
|
config.m_transportPacketMagicHeader = obj.value("H4").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj.value("I1").isNull()) {
|
|
||||||
config.m_specialJunk["I1"] = obj.value("I1").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("I2").isNull()) {
|
|
||||||
config.m_specialJunk["I2"] = obj.value("I2").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("I3").isNull()) {
|
|
||||||
config.m_specialJunk["I3"] = obj.value("I3").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("I4").isNull()) {
|
|
||||||
config.m_specialJunk["I4"] = obj.value("I4").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("I5").isNull()) {
|
|
||||||
config.m_specialJunk["I5"] = obj.value("I5").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("J1").isNull()) {
|
|
||||||
config.m_controlledJunk["J1"] = obj.value("J1").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("J2").isNull()) {
|
|
||||||
config.m_controlledJunk["J2"] = obj.value("J2").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("J3").isNull()) {
|
|
||||||
config.m_controlledJunk["J3"] = obj.value("J3").toString();
|
|
||||||
}
|
|
||||||
if (!obj.value("Itime").isNull()) {
|
|
||||||
config.m_specialHandshakeTimeout = obj.value("Itime").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +447,7 @@ bool Daemon::deactivate(bool emitSignals) {
|
||||||
|
|
||||||
m_connections.clear();
|
m_connections.clear();
|
||||||
// Delete the interface
|
// Delete the interface
|
||||||
return wgutils()->deleteInterface();
|
return wgutils()->deleteInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Daemon::logs() {
|
QString Daemon::logs() {
|
||||||
|
|
|
@ -28,8 +28,7 @@ QJsonObject InterfaceConfig::toJson() const {
|
||||||
(m_hopType == InterfaceConfig::SingleHop)) {
|
(m_hopType == InterfaceConfig::SingleHop)) {
|
||||||
json.insert("serverIpv4Gateway", QJsonValue(m_serverIpv4Gateway));
|
json.insert("serverIpv4Gateway", QJsonValue(m_serverIpv4Gateway));
|
||||||
json.insert("serverIpv6Gateway", QJsonValue(m_serverIpv6Gateway));
|
json.insert("serverIpv6Gateway", QJsonValue(m_serverIpv6Gateway));
|
||||||
json.insert("primaryDnsServer", QJsonValue(m_primaryDnsServer));
|
json.insert("dnsServer", QJsonValue(m_dnsServer));
|
||||||
json.insert("secondaryDnsServer", QJsonValue(m_secondaryDnsServer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray allowedIPAddesses;
|
QJsonArray allowedIPAddesses;
|
||||||
|
@ -101,15 +100,11 @@ QString InterfaceConfig::toWgConf(const QMap<QString, QString>& extra) const {
|
||||||
out << "MTU = " << m_deviceMTU << "\n";
|
out << "MTU = " << m_deviceMTU << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_primaryDnsServer.isNull()) {
|
if (!m_dnsServer.isNull()) {
|
||||||
QStringList dnsServers;
|
QStringList dnsServers(m_dnsServer);
|
||||||
dnsServers.append(m_primaryDnsServer);
|
|
||||||
if (!m_secondaryDnsServer.isNull()) {
|
|
||||||
dnsServers.append(m_secondaryDnsServer);
|
|
||||||
}
|
|
||||||
// If the DNS is not the Gateway, it's a user defined DNS
|
// If the DNS is not the Gateway, it's a user defined DNS
|
||||||
// thus, not add any other :)
|
// thus, not add any other :)
|
||||||
if (m_primaryDnsServer == m_serverIpv4Gateway) {
|
if (m_dnsServer == m_serverIpv4Gateway) {
|
||||||
dnsServers.append(m_serverIpv6Gateway);
|
dnsServers.append(m_serverIpv6Gateway);
|
||||||
}
|
}
|
||||||
out << "DNS = " << dnsServers.join(", ") << "\n";
|
out << "DNS = " << dnsServers.join(", ") << "\n";
|
||||||
|
@ -130,12 +125,6 @@ QString InterfaceConfig::toWgConf(const QMap<QString, QString>& extra) const {
|
||||||
if (!m_responsePacketJunkSize.isNull()) {
|
if (!m_responsePacketJunkSize.isNull()) {
|
||||||
out << "S2 = " << m_responsePacketJunkSize << "\n";
|
out << "S2 = " << m_responsePacketJunkSize << "\n";
|
||||||
}
|
}
|
||||||
if (!m_cookieReplyPacketJunkSize.isNull()) {
|
|
||||||
out << "S3 = " << m_cookieReplyPacketJunkSize << "\n";
|
|
||||||
}
|
|
||||||
if (!m_transportPacketJunkSize.isNull()) {
|
|
||||||
out << "S4 = " << m_transportPacketJunkSize << "\n";
|
|
||||||
}
|
|
||||||
if (!m_initPacketMagicHeader.isNull()) {
|
if (!m_initPacketMagicHeader.isNull()) {
|
||||||
out << "H1 = " << m_initPacketMagicHeader << "\n";
|
out << "H1 = " << m_initPacketMagicHeader << "\n";
|
||||||
}
|
}
|
||||||
|
@ -149,16 +138,6 @@ QString InterfaceConfig::toWgConf(const QMap<QString, QString>& extra) const {
|
||||||
out << "H4 = " << m_transportPacketMagicHeader << "\n";
|
out << "H4 = " << m_transportPacketMagicHeader << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QString& key : m_specialJunk.keys()) {
|
|
||||||
out << key << " = " << m_specialJunk[key] << "\n";
|
|
||||||
}
|
|
||||||
for (const QString& key : m_controlledJunk.keys()) {
|
|
||||||
out << key << " = " << m_controlledJunk[key] << "\n";
|
|
||||||
}
|
|
||||||
if (!m_specialHandshakeTimeout.isNull()) {
|
|
||||||
out << "Itime = " << m_specialHandshakeTimeout << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any extra config was provided, append it now.
|
// If any extra config was provided, append it now.
|
||||||
for (const QString& key : extra.keys()) {
|
for (const QString& key : extra.keys()) {
|
||||||
out << key << " = " << extra[key] << "\n";
|
out << key << " = " << extra[key] << "\n";
|
||||||
|
|
|
@ -32,8 +32,7 @@ class InterfaceConfig {
|
||||||
QString m_serverIpv4AddrIn;
|
QString m_serverIpv4AddrIn;
|
||||||
QString m_serverPskKey;
|
QString m_serverPskKey;
|
||||||
QString m_serverIpv6AddrIn;
|
QString m_serverIpv6AddrIn;
|
||||||
QString m_primaryDnsServer;
|
QString m_dnsServer;
|
||||||
QString m_secondaryDnsServer;
|
|
||||||
int m_serverPort = 0;
|
int m_serverPort = 0;
|
||||||
int m_deviceMTU = 1420;
|
int m_deviceMTU = 1420;
|
||||||
QList<IPAddress> m_allowedIPAddressRanges;
|
QList<IPAddress> m_allowedIPAddressRanges;
|
||||||
|
@ -50,15 +49,10 @@ class InterfaceConfig {
|
||||||
QString m_junkPacketMaxSize;
|
QString m_junkPacketMaxSize;
|
||||||
QString m_initPacketJunkSize;
|
QString m_initPacketJunkSize;
|
||||||
QString m_responsePacketJunkSize;
|
QString m_responsePacketJunkSize;
|
||||||
QString m_cookieReplyPacketJunkSize;
|
|
||||||
QString m_transportPacketJunkSize;
|
|
||||||
QString m_initPacketMagicHeader;
|
QString m_initPacketMagicHeader;
|
||||||
QString m_responsePacketMagicHeader;
|
QString m_responsePacketMagicHeader;
|
||||||
QString m_underloadPacketMagicHeader;
|
QString m_underloadPacketMagicHeader;
|
||||||
QString m_transportPacketMagicHeader;
|
QString m_transportPacketMagicHeader;
|
||||||
QMap<QString, QString> m_specialJunk;
|
|
||||||
QMap<QString, QString> m_controlledJunk;
|
|
||||||
QString m_specialHandshakeTimeout;
|
|
||||||
|
|
||||||
QJsonObject toJson() const;
|
QJsonObject toJson() const;
|
||||||
QString toWgConf(
|
QString toWgConf(
|
||||||
|
|
|
@ -26,21 +26,9 @@ set_target_properties(networkextension PROPERTIES
|
||||||
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
|
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
|
||||||
|
|
||||||
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../../Frameworks"
|
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../../Frameworks"
|
||||||
)
|
|
||||||
|
|
||||||
if(DEPLOY)
|
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic
|
||||||
set_target_properties(networkextension PROPERTIES
|
)
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
|
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Debug] "Apple Development"
|
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual
|
|
||||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER "distr ios.org.amnezia.AmneziaVPN"
|
|
||||||
XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER[variant=Debug] "dev ios.org.amnezia.AmneziaVPN"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
set_target_properties(networkextension PROPERTIES
|
|
||||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(networkextension PROPERTIES
|
set_target_properties(networkextension PROPERTIES
|
||||||
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
|
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
|
||||||
|
|
|
@ -38,7 +38,7 @@ LocalSocketController::LocalSocketController() {
|
||||||
m_socket = new QLocalSocket(this);
|
m_socket = new QLocalSocket(this);
|
||||||
connect(m_socket, &QLocalSocket::connected, this,
|
connect(m_socket, &QLocalSocket::connected, this,
|
||||||
&LocalSocketController::daemonConnected);
|
&LocalSocketController::daemonConnected);
|
||||||
connect(m_socket, &QLocalSocket::disconnected, this,
|
connect(m_socket, &QLocalSocket::disconnected, this,
|
||||||
[&] { errorOccurred(QLocalSocket::PeerClosedError); });
|
[&] { errorOccurred(QLocalSocket::PeerClosedError); });
|
||||||
connect(m_socket, &QLocalSocket::errorOccurred, this,
|
connect(m_socket, &QLocalSocket::errorOccurred, this,
|
||||||
&LocalSocketController::errorOccurred);
|
&LocalSocketController::errorOccurred);
|
||||||
|
@ -135,7 +135,7 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||||
|
|
||||||
// set up IPv6 unique-local-address, ULA, with "fd00::/8" prefix, not globally routable.
|
// set up IPv6 unique-local-address, ULA, with "fd00::/8" prefix, not globally routable.
|
||||||
// this will be default IPv6 gateway, OS recognizes that IPv6 link is local and switches to IPv4.
|
// this will be default IPv6 gateway, OS recognizes that IPv6 link is local and switches to IPv4.
|
||||||
// Otherwise some OSes (Linux) try IPv6 forever and hang.
|
// Otherwise some OSes (Linux) try IPv6 forever and hang.
|
||||||
// https://en.wikipedia.org/wiki/Unique_local_address (RFC 4193)
|
// https://en.wikipedia.org/wiki/Unique_local_address (RFC 4193)
|
||||||
// https://man7.org/linux/man-pages/man5/gai.conf.5.html
|
// https://man7.org/linux/man-pages/man5/gai.conf.5.html
|
||||||
json.insert("deviceIpv6Address", "fd58:baa6:dead::1"); // simply "dead::1" is globally-routable, don't use it
|
json.insert("deviceIpv6Address", "fd58:baa6:dead::1"); // simply "dead::1" is globally-routable, don't use it
|
||||||
|
@ -149,14 +149,7 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||||
json.insert("serverPort", wgConfig.value(amnezia::config_key::port).toInt());
|
json.insert("serverPort", wgConfig.value(amnezia::config_key::port).toInt());
|
||||||
json.insert("serverIpv4Gateway", wgConfig.value(amnezia::config_key::hostName));
|
json.insert("serverIpv4Gateway", wgConfig.value(amnezia::config_key::hostName));
|
||||||
// json.insert("serverIpv6Gateway", QJsonValue(hop.m_server.ipv6Gateway()));
|
// json.insert("serverIpv6Gateway", QJsonValue(hop.m_server.ipv6Gateway()));
|
||||||
|
json.insert("dnsServer", rawConfig.value(amnezia::config_key::dns1));
|
||||||
json.insert("primaryDnsServer", rawConfig.value(amnezia::config_key::dns1));
|
|
||||||
|
|
||||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
|
||||||
if (!rawConfig.value(amnezia::config_key::dns1).toString().
|
|
||||||
contains(amnezia::protocols::dns::amneziaDnsIp)) {
|
|
||||||
json.insert("secondaryDnsServer", rawConfig.value(amnezia::config_key::dns2));
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonArray jsAllowedIPAddesses;
|
QJsonArray jsAllowedIPAddesses;
|
||||||
|
|
||||||
|
@ -244,61 +237,28 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||||
json.insert(amnezia::config_key::junkPacketMaxSize, wgConfig.value(amnezia::config_key::junkPacketMaxSize));
|
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::initPacketJunkSize, wgConfig.value(amnezia::config_key::initPacketJunkSize));
|
||||||
json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize));
|
json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize));
|
||||||
json.insert(amnezia::config_key::cookieReplyPacketJunkSize, wgConfig.value(amnezia::config_key::cookieReplyPacketJunkSize));
|
|
||||||
json.insert(amnezia::config_key::transportPacketJunkSize, wgConfig.value(amnezia::config_key::transportPacketJunkSize));
|
|
||||||
json.insert(amnezia::config_key::initPacketMagicHeader, wgConfig.value(amnezia::config_key::initPacketMagicHeader));
|
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::responsePacketMagicHeader, wgConfig.value(amnezia::config_key::responsePacketMagicHeader));
|
||||||
json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader));
|
json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader));
|
||||||
json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader));
|
json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader));
|
||||||
json.insert(amnezia::config_key::specialJunk1, wgConfig.value(amnezia::config_key::specialJunk1));
|
|
||||||
json.insert(amnezia::config_key::specialJunk2, wgConfig.value(amnezia::config_key::specialJunk2));
|
|
||||||
json.insert(amnezia::config_key::specialJunk3, wgConfig.value(amnezia::config_key::specialJunk3));
|
|
||||||
json.insert(amnezia::config_key::specialJunk4, wgConfig.value(amnezia::config_key::specialJunk4));
|
|
||||||
json.insert(amnezia::config_key::specialJunk5, wgConfig.value(amnezia::config_key::specialJunk5));
|
|
||||||
json.insert(amnezia::config_key::controlledJunk1, wgConfig.value(amnezia::config_key::controlledJunk1));
|
|
||||||
json.insert(amnezia::config_key::controlledJunk2, wgConfig.value(amnezia::config_key::controlledJunk2));
|
|
||||||
json.insert(amnezia::config_key::controlledJunk3, wgConfig.value(amnezia::config_key::controlledJunk3));
|
|
||||||
json.insert(amnezia::config_key::specialHandshakeTimeout, wgConfig.value(amnezia::config_key::specialHandshakeTimeout));
|
|
||||||
} else if (!wgConfig.value(amnezia::config_key::junkPacketCount).isUndefined()
|
} else if (!wgConfig.value(amnezia::config_key::junkPacketCount).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::junkPacketMinSize).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::junkPacketMinSize).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::junkPacketMaxSize).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::junkPacketMaxSize).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::initPacketJunkSize).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::initPacketJunkSize).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::responsePacketJunkSize).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::responsePacketJunkSize).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::cookieReplyPacketJunkSize).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::transportPacketJunkSize).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::initPacketMagicHeader).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::initPacketMagicHeader).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::responsePacketMagicHeader).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::responsePacketMagicHeader).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::underloadPacketMagicHeader).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::underloadPacketMagicHeader).isUndefined()
|
||||||
&& !wgConfig.value(amnezia::config_key::transportPacketMagicHeader).isUndefined()
|
&& !wgConfig.value(amnezia::config_key::transportPacketMagicHeader).isUndefined()) {
|
||||||
&& !wgConfig.value(amnezia::config_key::specialJunk1).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::specialJunk2).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::specialJunk3).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::specialJunk4).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::specialJunk5).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::controlledJunk1).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::controlledJunk2).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::controlledJunk3).isUndefined()
|
|
||||||
&& !wgConfig.value(amnezia::config_key::specialHandshakeTimeout).isUndefined()) {
|
|
||||||
json.insert(amnezia::config_key::junkPacketCount, wgConfig.value(amnezia::config_key::junkPacketCount));
|
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::junkPacketMinSize, wgConfig.value(amnezia::config_key::junkPacketMinSize));
|
||||||
json.insert(amnezia::config_key::junkPacketMaxSize, wgConfig.value(amnezia::config_key::junkPacketMaxSize));
|
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::initPacketJunkSize, wgConfig.value(amnezia::config_key::initPacketJunkSize));
|
||||||
json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize));
|
json.insert(amnezia::config_key::responsePacketJunkSize, wgConfig.value(amnezia::config_key::responsePacketJunkSize));
|
||||||
json.insert(amnezia::config_key::cookieReplyPacketJunkSize, wgConfig.value(amnezia::config_key::cookieReplyPacketJunkSize));
|
|
||||||
json.insert(amnezia::config_key::transportPacketJunkSize, wgConfig.value(amnezia::config_key::transportPacketJunkSize));
|
|
||||||
json.insert(amnezia::config_key::initPacketMagicHeader, wgConfig.value(amnezia::config_key::initPacketMagicHeader));
|
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::responsePacketMagicHeader, wgConfig.value(amnezia::config_key::responsePacketMagicHeader));
|
||||||
json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader));
|
json.insert(amnezia::config_key::underloadPacketMagicHeader, wgConfig.value(amnezia::config_key::underloadPacketMagicHeader));
|
||||||
json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader));
|
json.insert(amnezia::config_key::transportPacketMagicHeader, wgConfig.value(amnezia::config_key::transportPacketMagicHeader));
|
||||||
json.insert(amnezia::config_key::specialJunk1, wgConfig.value(amnezia::config_key::specialJunk1));
|
|
||||||
json.insert(amnezia::config_key::specialJunk2, wgConfig.value(amnezia::config_key::specialJunk2));
|
|
||||||
json.insert(amnezia::config_key::specialJunk3, wgConfig.value(amnezia::config_key::specialJunk3));
|
|
||||||
json.insert(amnezia::config_key::specialJunk4, wgConfig.value(amnezia::config_key::specialJunk4));
|
|
||||||
json.insert(amnezia::config_key::specialJunk5, wgConfig.value(amnezia::config_key::specialJunk5));
|
|
||||||
json.insert(amnezia::config_key::controlledJunk1, wgConfig.value(amnezia::config_key::controlledJunk1));
|
|
||||||
json.insert(amnezia::config_key::controlledJunk2, wgConfig.value(amnezia::config_key::controlledJunk2));
|
|
||||||
json.insert(amnezia::config_key::controlledJunk3, wgConfig.value(amnezia::config_key::controlledJunk3));
|
|
||||||
json.insert(amnezia::config_key::specialHandshakeTimeout, wgConfig.value(amnezia::config_key::specialHandshakeTimeout));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write(json);
|
write(json);
|
||||||
|
|
|
@ -4,10 +4,7 @@ struct WGConfig: Decodable {
|
||||||
let initPacketMagicHeader, responsePacketMagicHeader: String?
|
let initPacketMagicHeader, responsePacketMagicHeader: String?
|
||||||
let underloadPacketMagicHeader, transportPacketMagicHeader: String?
|
let underloadPacketMagicHeader, transportPacketMagicHeader: String?
|
||||||
let junkPacketCount, junkPacketMinSize, junkPacketMaxSize: String?
|
let junkPacketCount, junkPacketMinSize, junkPacketMaxSize: String?
|
||||||
let initPacketJunkSize, responsePacketJunkSize, cookieReplyPacketJunkSize, transportPacketJunkSize: String?
|
let initPacketJunkSize, responsePacketJunkSize: String?
|
||||||
let specialJunk1, specialJunk2, specialJunk3, specialJunk4, specialJunk5: String?
|
|
||||||
let controlledJunk1, controlledJunk2, controlledJunk3: String?
|
|
||||||
let specialHandshakeTimeout: String?
|
|
||||||
let dns1: String
|
let dns1: String
|
||||||
let dns2: String
|
let dns2: String
|
||||||
let mtu: String
|
let mtu: String
|
||||||
|
@ -26,10 +23,7 @@ struct WGConfig: Decodable {
|
||||||
case initPacketMagicHeader = "H1", responsePacketMagicHeader = "H2"
|
case initPacketMagicHeader = "H1", responsePacketMagicHeader = "H2"
|
||||||
case underloadPacketMagicHeader = "H3", transportPacketMagicHeader = "H4"
|
case underloadPacketMagicHeader = "H3", transportPacketMagicHeader = "H4"
|
||||||
case junkPacketCount = "Jc", junkPacketMinSize = "Jmin", junkPacketMaxSize = "Jmax"
|
case junkPacketCount = "Jc", junkPacketMinSize = "Jmin", junkPacketMaxSize = "Jmax"
|
||||||
case initPacketJunkSize = "S1", responsePacketJunkSize = "S2", cookieReplyPacketJunkSize = "S3", transportPacketJunkSize = "S4"
|
case initPacketJunkSize = "S1", responsePacketJunkSize = "S2"
|
||||||
case specialJunk1 = "I1", specialJunk2 = "I2", specialJunk3 = "I3", specialJunk4 = "I4", specialJunk5 = "I5"
|
|
||||||
case controlledJunk1 = "J1", controlledJunk2 = "J2", controlledJunk3 = "J3"
|
|
||||||
case specialHandshakeTimeout = "Itime"
|
|
||||||
case dns1
|
case dns1
|
||||||
case dns2
|
case dns2
|
||||||
case mtu
|
case mtu
|
||||||
|
@ -46,59 +40,19 @@ struct WGConfig: Decodable {
|
||||||
}
|
}
|
||||||
|
|
||||||
var settings: String {
|
var settings: String {
|
||||||
guard junkPacketCount != nil else { return "" }
|
junkPacketCount == nil ? "" :
|
||||||
|
"""
|
||||||
var settingsLines: [String] = []
|
Jc = \(junkPacketCount!)
|
||||||
|
Jmin = \(junkPacketMinSize!)
|
||||||
// Required parameters when junkPacketCount is present
|
Jmax = \(junkPacketMaxSize!)
|
||||||
settingsLines.append("Jc = \(junkPacketCount!)")
|
S1 = \(initPacketJunkSize!)
|
||||||
settingsLines.append("Jmin = \(junkPacketMinSize!)")
|
S2 = \(responsePacketJunkSize!)
|
||||||
settingsLines.append("Jmax = \(junkPacketMaxSize!)")
|
H1 = \(initPacketMagicHeader!)
|
||||||
settingsLines.append("S1 = \(initPacketJunkSize!)")
|
H2 = \(responsePacketMagicHeader!)
|
||||||
settingsLines.append("S2 = \(responsePacketJunkSize!)")
|
H3 = \(underloadPacketMagicHeader!)
|
||||||
|
H4 = \(transportPacketMagicHeader!)
|
||||||
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 {
|
var str: String {
|
||||||
|
|
|
@ -507,8 +507,6 @@ bool IosController::setupWireGuard()
|
||||||
|
|
||||||
wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]);
|
wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]);
|
||||||
wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]);
|
wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]);
|
||||||
wgConfig.insert(config_key::cookieReplyPacketJunkSize, config[config_key::cookieReplyPacketJunkSize]);
|
|
||||||
wgConfig.insert(config_key::transportPacketJunkSize, config[config_key::transportPacketJunkSize]);
|
|
||||||
|
|
||||||
wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]);
|
wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]);
|
||||||
wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]);
|
wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]);
|
||||||
|
@ -607,23 +605,11 @@ bool IosController::setupAwg()
|
||||||
|
|
||||||
wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]);
|
wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]);
|
||||||
wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]);
|
wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]);
|
||||||
wgConfig.insert(config_key::cookieReplyPacketJunkSize, config[config_key::cookieReplyPacketJunkSize]);
|
|
||||||
wgConfig.insert(config_key::transportPacketJunkSize, config[config_key::transportPacketJunkSize]);
|
|
||||||
|
|
||||||
wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]);
|
wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]);
|
||||||
wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]);
|
wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]);
|
||||||
wgConfig.insert(config_key::junkPacketMaxSize, config[config_key::junkPacketMaxSize]);
|
wgConfig.insert(config_key::junkPacketMaxSize, config[config_key::junkPacketMaxSize]);
|
||||||
|
|
||||||
wgConfig.insert(config_key::specialJunk1, config[config_key::specialJunk1]);
|
|
||||||
wgConfig.insert(config_key::specialJunk2, config[config_key::specialJunk2]);
|
|
||||||
wgConfig.insert(config_key::specialJunk3, config[config_key::specialJunk3]);
|
|
||||||
wgConfig.insert(config_key::specialJunk4, config[config_key::specialJunk4]);
|
|
||||||
wgConfig.insert(config_key::specialJunk5, config[config_key::specialJunk5]);
|
|
||||||
wgConfig.insert(config_key::controlledJunk1, config[config_key::controlledJunk1]);
|
|
||||||
wgConfig.insert(config_key::controlledJunk2, config[config_key::controlledJunk2]);
|
|
||||||
wgConfig.insert(config_key::controlledJunk3, config[config_key::controlledJunk3]);
|
|
||||||
wgConfig.insert(config_key::specialHandshakeTimeout, config[config_key::specialHandshakeTimeout]);
|
|
||||||
|
|
||||||
QJsonDocument wgConfigDoc(wgConfig);
|
QJsonDocument wgConfigDoc(wgConfig);
|
||||||
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
|
@ -808,9 +794,9 @@ bool IosController::shareText(const QStringList& filesToSend) {
|
||||||
if (!qtController) return;
|
if (!qtController) return;
|
||||||
|
|
||||||
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
|
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
|
||||||
|
|
||||||
__block bool isAccepted = false;
|
__block bool isAccepted = false;
|
||||||
|
|
||||||
[activityController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
|
[activityController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
|
||||||
isAccepted = completed;
|
isAccepted = completed;
|
||||||
emit finished();
|
emit finished();
|
||||||
|
@ -822,11 +808,11 @@ bool IosController::shareText(const QStringList& filesToSend) {
|
||||||
popController.sourceView = qtController.view;
|
popController.sourceView = qtController.view;
|
||||||
popController.sourceRect = CGRectMake(100, 100, 100, 100);
|
popController.sourceRect = CGRectMake(100, 100, 100, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit);
|
QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit);
|
||||||
wait.exec();
|
wait.exec();
|
||||||
|
|
||||||
return isAccepted;
|
return isAccepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -840,7 +826,7 @@ QString IosController::openFile() {
|
||||||
if (!qtController) return;
|
if (!qtController) return;
|
||||||
|
|
||||||
[qtController presentViewController:documentPicker animated:YES completion:nil];
|
[qtController presentViewController:documentPicker animated:YES completion:nil];
|
||||||
|
|
||||||
__block QString filePath;
|
__block QString filePath;
|
||||||
|
|
||||||
documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) {
|
documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) {
|
||||||
|
@ -855,7 +841,7 @@ QString IosController::openFile() {
|
||||||
QEventLoop wait;
|
QEventLoop wait;
|
||||||
QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit);
|
QObject::connect(this, &IosController::finished, &wait, &QEventLoop::quit);
|
||||||
wait.exec();
|
wait.exec();
|
||||||
|
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ bool IPUtilsLinux::addIP4AddressToDevice(const InterfaceConfig& config) {
|
||||||
// Set ifr to interface
|
// Set ifr to interface
|
||||||
int ret = ioctl(sockfd, SIOCSIFADDR, &ifr);
|
int ret = ioctl(sockfd, SIOCSIFADDR, &ifr);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
logger.error() << "Failed to set IPv4: " << deviceAddr
|
logger.error() << "Failed to set IPv4: " << logger.sensitive(deviceAddr)
|
||||||
<< "error:" << strerror(errno);
|
<< "error:" << strerror(errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ bool IPUtilsLinux::addIP6AddressToDevice(const InterfaceConfig& config) {
|
||||||
// Set ifr6 to the interface
|
// Set ifr6 to the interface
|
||||||
ret = ioctl(sockfd, SIOCSIFADDR, &ifr6);
|
ret = ioctl(sockfd, SIOCSIFADDR, &ifr6);
|
||||||
if (ret && (errno != EEXIST)) {
|
if (ret && (errno != EEXIST)) {
|
||||||
logger.error() << "Failed to set IPv6: " << deviceAddr
|
logger.error() << "Failed to set IPv6: " << logger.sensitive(deviceAddr)
|
||||||
<< "error:" << strerror(errno);
|
<< "error:" << strerror(errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,12 +121,6 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
|
||||||
if (!config.m_responsePacketJunkSize.isEmpty()) {
|
if (!config.m_responsePacketJunkSize.isEmpty()) {
|
||||||
out << "s2=" << config.m_responsePacketJunkSize << "\n";
|
out << "s2=" << config.m_responsePacketJunkSize << "\n";
|
||||||
}
|
}
|
||||||
if (!config.m_cookieReplyPacketJunkSize.isEmpty()) {
|
|
||||||
out << "s3=" << config.m_cookieReplyPacketJunkSize << "\n";
|
|
||||||
}
|
|
||||||
if (!config.m_transportPacketJunkSize.isEmpty()) {
|
|
||||||
out << "s4=" << config.m_transportPacketJunkSize << "\n";
|
|
||||||
}
|
|
||||||
if (!config.m_initPacketMagicHeader.isEmpty()) {
|
if (!config.m_initPacketMagicHeader.isEmpty()) {
|
||||||
out << "h1=" << config.m_initPacketMagicHeader << "\n";
|
out << "h1=" << config.m_initPacketMagicHeader << "\n";
|
||||||
}
|
}
|
||||||
|
@ -140,26 +134,13 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
|
||||||
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
|
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QString& key : config.m_specialJunk.keys()) {
|
|
||||||
out << key.toLower() << "=" << config.m_specialJunk.value(key) << "\n";
|
|
||||||
}
|
|
||||||
for (const QString& key : config.m_controlledJunk.keys()) {
|
|
||||||
out << key.toLower() << "=" << config.m_controlledJunk.value(key) << "\n";
|
|
||||||
}
|
|
||||||
if (!config.m_specialHandshakeTimeout.isEmpty()) {
|
|
||||||
out << "itime=" << config.m_specialHandshakeTimeout << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = uapiErrno(uapiCommand(message));
|
int err = uapiErrno(uapiCommand(message));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
logger.error() << "Interface configuration failed:" << strerror(err);
|
logger.error() << "Interface configuration failed:" << strerror(err);
|
||||||
} else {
|
} else {
|
||||||
if (config.m_killSwitchEnabled) {
|
if (config.m_killSwitchEnabled) {
|
||||||
FirewallParams params { };
|
FirewallParams params { };
|
||||||
params.dnsServers.append(config.m_primaryDnsServer);
|
params.dnsServers.append(config.m_dnsServer);
|
||||||
if (!config.m_secondaryDnsServer.isEmpty()) {
|
|
||||||
params.dnsServers.append(config.m_secondaryDnsServer);
|
|
||||||
}
|
|
||||||
if (config.m_allowedIPAddressRanges.contains(IPAddress("0.0.0.0/0"))) {
|
if (config.m_allowedIPAddressRanges.contains(IPAddress("0.0.0.0/0"))) {
|
||||||
params.blockAll = true;
|
params.blockAll = true;
|
||||||
if (config.m_excludedAddresses.size()) {
|
if (config.m_excludedAddresses.size()) {
|
||||||
|
|
|
@ -122,7 +122,7 @@ bool IPUtilsMacos::addIP4AddressToDevice(const InterfaceConfig& config) {
|
||||||
// Set ifr to interface
|
// Set ifr to interface
|
||||||
int ret = ioctl(sockfd, SIOCAIFADDR, &ifr);
|
int ret = ioctl(sockfd, SIOCAIFADDR, &ifr);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
logger.error() << "Failed to set IPv4: " << deviceAddr
|
logger.error() << "Failed to set IPv4: " << logger.sensitive(deviceAddr)
|
||||||
<< "error:" << strerror(errno);
|
<< "error:" << strerror(errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ bool IPUtilsMacos::addIP6AddressToDevice(const InterfaceConfig& config) {
|
||||||
// Set ifr to interface
|
// Set ifr to interface
|
||||||
int ret = ioctl(sockfd, SIOCAIFADDR_IN6, &ifr6);
|
int ret = ioctl(sockfd, SIOCAIFADDR_IN6, &ifr6);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
logger.error() << "Failed to set IPv6: " << deviceAddr
|
logger.error() << "Failed to set IPv6: " << logger.sensitive(deviceAddr)
|
||||||
<< "error:" << strerror(errno);
|
<< "error:" << strerror(errno);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,16 +43,8 @@ namespace {
|
||||||
|
|
||||||
#include "macosfirewall.h"
|
#include "macosfirewall.h"
|
||||||
|
|
||||||
#include <QDir>
|
#define ResourceDir qApp->applicationDirPath() + "/pf"
|
||||||
#include <QStandardPaths>
|
#define DaemonDataDir qApp->applicationDirPath() + "/pf"
|
||||||
|
|
||||||
// Read-only rules bundled with the application.
|
|
||||||
#define ResourceDir (qApp->applicationDirPath() + "/pf")
|
|
||||||
|
|
||||||
// Writable location that does NOT live inside the signed bundle. Using a
|
|
||||||
// constant path under /Library/Application Support keeps the signature intact
|
|
||||||
// and is accessible to the root helper.
|
|
||||||
#define DaemonDataDir QStringLiteral("/Library/Application Support/AmneziaVPN/pf")
|
|
||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
|
@ -129,8 +121,6 @@ void MacOSFirewall::install()
|
||||||
logger.info() << "Installing PF root anchor";
|
logger.info() << "Installing PF root anchor";
|
||||||
|
|
||||||
installRootAnchors();
|
installRootAnchors();
|
||||||
// Ensure writable directory exists, then store the token there.
|
|
||||||
QDir().mkpath(DaemonDataDir);
|
|
||||||
execute(QStringLiteral("pfctl -E 2>&1 | grep -F 'Token : ' | cut -c9- > '%1/pf.token'").arg(DaemonDataDir));
|
execute(QStringLiteral("pfctl -E 2>&1 | grep -F 'Token : ' | cut -c9- > '%1/pf.token'").arg(DaemonDataDir));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ void MacosRouteMonitor::handleRtmDelete(const struct rt_msghdr* rtm,
|
||||||
for (const IPAddress& prefix : m_exclusionRoutes) {
|
for (const IPAddress& prefix : m_exclusionRoutes) {
|
||||||
if (prefix.address().protocol() == protocol) {
|
if (prefix.address().protocol() == protocol) {
|
||||||
logger.debug() << "Removing exclusion route to"
|
logger.debug() << "Removing exclusion route to"
|
||||||
<< prefix.toString();
|
<< logger.sensitive(prefix.toString());
|
||||||
rtmSendRoute(RTM_DELETE, prefix, rtm->rtm_index, nullptr);
|
rtmSendRoute(RTM_DELETE, prefix, rtm->rtm_index, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ void MacosRouteMonitor::handleRtmUpdate(const struct rt_msghdr* rtm,
|
||||||
for (const IPAddress& prefix : m_exclusionRoutes) {
|
for (const IPAddress& prefix : m_exclusionRoutes) {
|
||||||
if (prefix.address().protocol() == protocol) {
|
if (prefix.address().protocol() == protocol) {
|
||||||
logger.debug() << "Updating exclusion route to"
|
logger.debug() << "Updating exclusion route to"
|
||||||
<< prefix.toString();
|
<< logger.sensitive(prefix.toString());
|
||||||
rtmSendRoute(rtm_type, prefix, ifindex, addrlist[1].constData());
|
rtmSendRoute(rtm_type, prefix, ifindex, addrlist[1].constData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,7 +510,8 @@ bool MacosRouteMonitor::deleteRoute(const IPAddress& prefix, int flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacosRouteMonitor::addExclusionRoute(const IPAddress& prefix) {
|
bool MacosRouteMonitor::addExclusionRoute(const IPAddress& prefix) {
|
||||||
logger.debug() << "Adding exclusion route for" << prefix.toString();
|
logger.debug() << "Adding exclusion route for"
|
||||||
|
<< logger.sensitive(prefix.toString());
|
||||||
|
|
||||||
if (m_exclusionRoutes.contains(prefix)) {
|
if (m_exclusionRoutes.contains(prefix)) {
|
||||||
logger.warning() << "Exclusion route already exists";
|
logger.warning() << "Exclusion route already exists";
|
||||||
|
@ -535,7 +536,8 @@ bool MacosRouteMonitor::addExclusionRoute(const IPAddress& prefix) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacosRouteMonitor::deleteExclusionRoute(const IPAddress& prefix) {
|
bool MacosRouteMonitor::deleteExclusionRoute(const IPAddress& prefix) {
|
||||||
logger.debug() << "Deleting exclusion route for" << prefix.toString();
|
logger.debug() << "Deleting exclusion route for"
|
||||||
|
<< logger.sensitive(prefix.toString());
|
||||||
|
|
||||||
m_exclusionRoutes.removeAll(prefix);
|
m_exclusionRoutes.removeAll(prefix);
|
||||||
if (prefix.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
if (prefix.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||||
|
|
|
@ -119,12 +119,6 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
|
||||||
if (!config.m_responsePacketJunkSize.isEmpty()) {
|
if (!config.m_responsePacketJunkSize.isEmpty()) {
|
||||||
out << "s2=" << config.m_responsePacketJunkSize << "\n";
|
out << "s2=" << config.m_responsePacketJunkSize << "\n";
|
||||||
}
|
}
|
||||||
if (!config.m_cookieReplyPacketJunkSize.isEmpty()) {
|
|
||||||
out << "s3=" << config.m_cookieReplyPacketJunkSize << "\n";
|
|
||||||
}
|
|
||||||
if (!config.m_transportPacketJunkSize.isEmpty()) {
|
|
||||||
out << "s4=" << config.m_transportPacketJunkSize << "\n";
|
|
||||||
}
|
|
||||||
if (!config.m_initPacketMagicHeader.isEmpty()) {
|
if (!config.m_initPacketMagicHeader.isEmpty()) {
|
||||||
out << "h1=" << config.m_initPacketMagicHeader << "\n";
|
out << "h1=" << config.m_initPacketMagicHeader << "\n";
|
||||||
}
|
}
|
||||||
|
@ -138,43 +132,30 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
|
||||||
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
|
out << "h4=" << config.m_transportPacketMagicHeader << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QString& key : config.m_specialJunk.keys()) {
|
|
||||||
out << key.toLower() << "=" << config.m_specialJunk.value(key) << "\n";
|
|
||||||
}
|
|
||||||
for (const QString& key : config.m_controlledJunk.keys()) {
|
|
||||||
out << key.toLower() << "=" << config.m_controlledJunk.value(key) << "\n";
|
|
||||||
}
|
|
||||||
if (!config.m_specialHandshakeTimeout.isEmpty()) {
|
|
||||||
out << "itime=" << config.m_specialHandshakeTimeout << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = uapiErrno(uapiCommand(message));
|
int err = uapiErrno(uapiCommand(message));
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
logger.error() << "Interface configuration failed:" << strerror(err);
|
logger.error() << "Interface configuration failed:" << strerror(err);
|
||||||
} else {
|
} else {
|
||||||
if (config.m_killSwitchEnabled) {
|
if (config.m_killSwitchEnabled) {
|
||||||
FirewallParams params { };
|
FirewallParams params { };
|
||||||
params.dnsServers.append(config.m_primaryDnsServer);
|
params.dnsServers.append(config.m_dnsServer);
|
||||||
if (!config.m_secondaryDnsServer.isEmpty()) {
|
|
||||||
params.dnsServers.append(config.m_secondaryDnsServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.m_allowedIPAddressRanges.contains(IPAddress("0.0.0.0/0"))) {
|
if (config.m_allowedIPAddressRanges.contains(IPAddress("0.0.0.0/0"))) {
|
||||||
params.blockAll = true;
|
params.blockAll = true;
|
||||||
if (config.m_excludedAddresses.size()) {
|
if (config.m_excludedAddresses.size()) {
|
||||||
params.allowNets = true;
|
params.allowNets = true;
|
||||||
foreach (auto net, config.m_excludedAddresses) {
|
foreach (auto net, config.m_excludedAddresses) {
|
||||||
params.allowAddrs.append(net.toUtf8());
|
params.allowAddrs.append(net.toUtf8());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
params.blockNets = true;
|
params.blockNets = true;
|
||||||
foreach (auto net, config.m_allowedIPAddressRanges) {
|
foreach (auto net, config.m_allowedIPAddressRanges) {
|
||||||
params.blockAddrs.append(net.toString());
|
params.blockAddrs.append(net.toString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
applyFirewallRules(params);
|
||||||
}
|
}
|
||||||
applyFirewallRules(params);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (err == 0);
|
return (err == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ bool WindowsFirewall::allowTrafficRange(const QStringList& ranges) {
|
||||||
|
|
||||||
for (const QString& addr : ranges) {
|
for (const QString& addr : ranges) {
|
||||||
logger.debug() << "Allow killswitch exclude: " << addr;
|
logger.debug() << "Allow killswitch exclude: " << addr;
|
||||||
if (!allowTrafficTo(QHostAddress(addr), HIGH_WEIGHT, "Allow killswitch bypass traffic")) {
|
if (!allowTrafficTo(QHostAddress(addr), LOW_WEIGHT + 1, "Allow killswitch bypass traffic")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,32 +291,15 @@ bool WindowsFirewall::enablePeerTraffic(const InterfaceConfig& config) {
|
||||||
"Block Internet", config.m_serverPublicKey)) {
|
"Block Internet", config.m_serverPublicKey)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!config.m_primaryDnsServer.isEmpty()) {
|
if (!config.m_dnsServer.isEmpty()) {
|
||||||
if (!allowTrafficTo(QHostAddress(config.m_primaryDnsServer), 53, HIGH_WEIGHT,
|
if (!allowTrafficTo(QHostAddress(config.m_dnsServer), 53, HIGH_WEIGHT,
|
||||||
"Allow DNS-Server", config.m_serverPublicKey)) {
|
"Allow DNS-Server", config.m_serverPublicKey)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// In some cases, we might configure a 2nd DNS server for IPv6, however
|
// In some cases, we might configure a 2nd DNS server for IPv6, however
|
||||||
// this should probably be cleaned up by converting m_dnsServer into
|
// this should probably be cleaned up by converting m_dnsServer into
|
||||||
// a QStringList instead.
|
// a QStringList instead.
|
||||||
if (config.m_primaryDnsServer == config.m_serverIpv4Gateway) {
|
if (config.m_dnsServer == config.m_serverIpv4Gateway) {
|
||||||
if (!allowTrafficTo(QHostAddress(config.m_serverIpv6Gateway), 53,
|
|
||||||
HIGH_WEIGHT, "Allow extra IPv6 DNS-Server",
|
|
||||||
config.m_serverPublicKey)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.m_secondaryDnsServer.isEmpty()) {
|
|
||||||
if (!allowTrafficTo(QHostAddress(config.m_secondaryDnsServer), 53, HIGH_WEIGHT,
|
|
||||||
"Allow DNS-Server", config.m_serverPublicKey)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// In some cases, we might configure a 2nd DNS server for IPv6, however
|
|
||||||
// this should probably be cleaned up by converting m_dnsServer into
|
|
||||||
// a QStringList instead.
|
|
||||||
if (config.m_secondaryDnsServer == config.m_serverIpv4Gateway) {
|
|
||||||
if (!allowTrafficTo(QHostAddress(config.m_serverIpv6Gateway), 53,
|
if (!allowTrafficTo(QHostAddress(config.m_serverIpv6Gateway), 53,
|
||||||
HIGH_WEIGHT, "Allow extra IPv6 DNS-Server",
|
HIGH_WEIGHT, "Allow extra IPv6 DNS-Server",
|
||||||
config.m_serverPublicKey)) {
|
config.m_serverPublicKey)) {
|
||||||
|
|
|
@ -303,7 +303,8 @@ void WindowsRouteMonitor::updateCapturedRoutes(int family, void* ptable) {
|
||||||
data->Age++;
|
data->Age++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
logger.debug() << "Capturing route to" << prefix.toString();
|
logger.debug() << "Capturing route to"
|
||||||
|
<< logger.sensitive(prefix.toString());
|
||||||
|
|
||||||
// Clone the route and direct it into the VPN tunnel.
|
// Clone the route and direct it into the VPN tunnel.
|
||||||
data = new MIB_IPFORWARD_ROW2;
|
data = new MIB_IPFORWARD_ROW2;
|
||||||
|
@ -353,7 +354,8 @@ void WindowsRouteMonitor::updateCapturedRoutes(int family, void* ptable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug() << "Removing route capture for" << i.key().toString();
|
logger.debug() << "Removing route capture for"
|
||||||
|
<< logger.sensitive(i.key().toString());
|
||||||
|
|
||||||
// Otherwise, this route is no longer in use.
|
// Otherwise, this route is no longer in use.
|
||||||
DWORD result = DeleteIpForwardEntry2(data);
|
DWORD result = DeleteIpForwardEntry2(data);
|
||||||
|
@ -366,7 +368,8 @@ void WindowsRouteMonitor::updateCapturedRoutes(int family, void* ptable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowsRouteMonitor::addExclusionRoute(const IPAddress& prefix) {
|
bool WindowsRouteMonitor::addExclusionRoute(const IPAddress& prefix) {
|
||||||
logger.debug() << "Adding exclusion route for" << prefix.toString();
|
logger.debug() << "Adding exclusion route for"
|
||||||
|
<< logger.sensitive(prefix.toString());
|
||||||
|
|
||||||
// Silently ignore non-routeable addresses.
|
// Silently ignore non-routeable addresses.
|
||||||
QHostAddress addr = prefix.address();
|
QHostAddress addr = prefix.address();
|
||||||
|
@ -434,7 +437,7 @@ bool WindowsRouteMonitor::addExclusionRoute(const IPAddress& prefix) {
|
||||||
|
|
||||||
bool WindowsRouteMonitor::deleteExclusionRoute(const IPAddress& prefix) {
|
bool WindowsRouteMonitor::deleteExclusionRoute(const IPAddress& prefix) {
|
||||||
logger.debug() << "Deleting exclusion route for"
|
logger.debug() << "Deleting exclusion route for"
|
||||||
<< prefix.address().toString();
|
<< logger.sensitive(prefix.address().toString());
|
||||||
|
|
||||||
MIB_IPFORWARD_ROW2* data = m_exclusionRoutes.take(prefix);
|
MIB_IPFORWARD_ROW2* data = m_exclusionRoutes.take(prefix);
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
|
@ -444,7 +447,7 @@ bool WindowsRouteMonitor::deleteExclusionRoute(const IPAddress& prefix) {
|
||||||
DWORD result = DeleteIpForwardEntry2(data);
|
DWORD result = DeleteIpForwardEntry2(data);
|
||||||
if ((result != ERROR_NOT_FOUND) && (result != NO_ERROR)) {
|
if ((result != ERROR_NOT_FOUND) && (result != NO_ERROR)) {
|
||||||
logger.error() << "Failed to delete route to"
|
logger.error() << "Failed to delete route to"
|
||||||
<< prefix.toString()
|
<< logger.sensitive(prefix.toString())
|
||||||
<< "result:" << result;
|
<< "result:" << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +465,7 @@ void WindowsRouteMonitor::flushRouteTable(
|
||||||
DWORD result = DeleteIpForwardEntry2(data);
|
DWORD result = DeleteIpForwardEntry2(data);
|
||||||
if ((result != ERROR_NOT_FOUND) && (result != NO_ERROR)) {
|
if ((result != ERROR_NOT_FOUND) && (result != NO_ERROR)) {
|
||||||
logger.error() << "Failed to delete route to"
|
logger.error() << "Failed to delete route to"
|
||||||
<< i.key().toString()
|
<< logger.sensitive(i.key().toString())
|
||||||
<< "result:" << result;
|
<< "result:" << result;
|
||||||
}
|
}
|
||||||
delete data;
|
delete data;
|
||||||
|
|
|
@ -130,7 +130,6 @@ bool WireguardUtilsWindows::addInterface(const InterfaceConfig& config) {
|
||||||
// Enable the windows firewall
|
// Enable the windows firewall
|
||||||
NET_IFINDEX ifindex;
|
NET_IFINDEX ifindex;
|
||||||
ConvertInterfaceLuidToIndex(&luid, &ifindex);
|
ConvertInterfaceLuidToIndex(&luid, &ifindex);
|
||||||
m_firewall->allowAllTraffic();
|
|
||||||
m_firewall->enableInterface(ifindex);
|
m_firewall->enableInterface(ifindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ ErrorCode OpenVpnProtocol::start()
|
||||||
return lastError();
|
return lastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
||||||
IpcClient::Interface()->addKillSwitchAllowedRange(QStringList(NetworkUtilities::getIPAddress(
|
IpcClient::Interface()->addKillSwitchAllowedRange(QStringList(NetworkUtilities::getIPAddress(
|
||||||
m_configData.value(amnezia::config_key::hostName).toString())));
|
m_configData.value(amnezia::config_key::hostName).toString())));
|
||||||
#endif
|
#endif
|
||||||
|
@ -343,7 +343,7 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
|
||||||
// killSwitch toggle
|
// killSwitch toggle
|
||||||
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
|
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
|
||||||
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
||||||
IpcClient::Interface()->enableKillSwitch(m_configData, netInterfaces.at(i).index());
|
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
|
||||||
}
|
}
|
||||||
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
|
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
|
||||||
m_configData.insert("vpnGateway", m_vpnGateway);
|
m_configData.insert("vpnGateway", m_vpnGateway);
|
||||||
|
|
|
@ -72,21 +72,10 @@ namespace amnezia
|
||||||
constexpr char junkPacketMaxSize[] = "Jmax";
|
constexpr char junkPacketMaxSize[] = "Jmax";
|
||||||
constexpr char initPacketJunkSize[] = "S1";
|
constexpr char initPacketJunkSize[] = "S1";
|
||||||
constexpr char responsePacketJunkSize[] = "S2";
|
constexpr char responsePacketJunkSize[] = "S2";
|
||||||
constexpr char cookieReplyPacketJunkSize[] = "S3";
|
|
||||||
constexpr char transportPacketJunkSize[] = "S4";
|
|
||||||
constexpr char initPacketMagicHeader[] = "H1";
|
constexpr char initPacketMagicHeader[] = "H1";
|
||||||
constexpr char responsePacketMagicHeader[] = "H2";
|
constexpr char responsePacketMagicHeader[] = "H2";
|
||||||
constexpr char underloadPacketMagicHeader[] = "H3";
|
constexpr char underloadPacketMagicHeader[] = "H3";
|
||||||
constexpr char transportPacketMagicHeader[] = "H4";
|
constexpr char transportPacketMagicHeader[] = "H4";
|
||||||
constexpr char specialJunk1[] = "I1";
|
|
||||||
constexpr char specialJunk2[] = "I2";
|
|
||||||
constexpr char specialJunk3[] = "I3";
|
|
||||||
constexpr char specialJunk4[] = "I4";
|
|
||||||
constexpr char specialJunk5[] = "I5";
|
|
||||||
constexpr char controlledJunk1[] = "J1";
|
|
||||||
constexpr char controlledJunk2[] = "J2";
|
|
||||||
constexpr char controlledJunk3[] = "J3";
|
|
||||||
constexpr char specialHandshakeTimeout[] = "Itime";
|
|
||||||
|
|
||||||
constexpr char openvpn[] = "openvpn";
|
constexpr char openvpn[] = "openvpn";
|
||||||
constexpr char wireguard[] = "wireguard";
|
constexpr char wireguard[] = "wireguard";
|
||||||
|
@ -114,8 +103,6 @@ namespace amnezia
|
||||||
|
|
||||||
constexpr char clientId[] = "clientId";
|
constexpr char clientId[] = "clientId";
|
||||||
|
|
||||||
constexpr char nameOverriddenByUser[] = "nameOverriddenByUser";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace protocols
|
namespace protocols
|
||||||
|
@ -227,22 +214,10 @@ namespace amnezia
|
||||||
constexpr char defaultJunkPacketMaxSize[] = "30";
|
constexpr char defaultJunkPacketMaxSize[] = "30";
|
||||||
constexpr char defaultInitPacketJunkSize[] = "15";
|
constexpr char defaultInitPacketJunkSize[] = "15";
|
||||||
constexpr char defaultResponsePacketJunkSize[] = "18";
|
constexpr char defaultResponsePacketJunkSize[] = "18";
|
||||||
constexpr char defaultCookieReplyPacketJunkSize[] = "20";
|
|
||||||
constexpr char defaultTransportPacketJunkSize[] = "23";
|
|
||||||
|
|
||||||
constexpr char defaultInitPacketMagicHeader[] = "1020325451";
|
constexpr char defaultInitPacketMagicHeader[] = "1020325451";
|
||||||
constexpr char defaultResponsePacketMagicHeader[] = "3288052141";
|
constexpr char defaultResponsePacketMagicHeader[] = "3288052141";
|
||||||
constexpr char defaultTransportPacketMagicHeader[] = "2528465083";
|
constexpr char defaultTransportPacketMagicHeader[] = "2528465083";
|
||||||
constexpr char defaultUnderloadPacketMagicHeader[] = "1766607858";
|
constexpr char defaultUnderloadPacketMagicHeader[] = "1766607858";
|
||||||
constexpr char defaultSpecialJunk1[] = "";
|
|
||||||
constexpr char defaultSpecialJunk2[] = "";
|
|
||||||
constexpr char defaultSpecialJunk3[] = "";
|
|
||||||
constexpr char defaultSpecialJunk4[] = "";
|
|
||||||
constexpr char defaultSpecialJunk5[] = "";
|
|
||||||
constexpr char defaultControlledJunk1[] = "";
|
|
||||||
constexpr char defaultControlledJunk2[] = "";
|
|
||||||
constexpr char defaultControlledJunk3[] = "";
|
|
||||||
constexpr char defaultSpecialHandshakeTimeout[] = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace socks5Proxy
|
namespace socks5Proxy
|
||||||
|
|
|
@ -98,13 +98,8 @@ ErrorCode XrayProtocol::startTun2Sock()
|
||||||
if (vpnState == Vpn::ConnectionState::Connected) {
|
if (vpnState == Vpn::ConnectionState::Connected) {
|
||||||
setConnectionState(Vpn::ConnectionState::Connecting);
|
setConnectionState(Vpn::ConnectionState::Connecting);
|
||||||
QList<QHostAddress> dnsAddr;
|
QList<QHostAddress> dnsAddr;
|
||||||
|
|
||||||
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
|
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
|
||||||
// We don't use secondary DNS if primary DNS is AmneziaDNS
|
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
|
||||||
if (!m_configData.value(amnezia::config_key::dns1).toString().
|
|
||||||
contains(amnezia::protocols::dns::amneziaDnsIp)) {
|
|
||||||
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
|
|
||||||
}
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
QThread::msleep(8000);
|
QThread::msleep(8000);
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,7 +134,7 @@ ErrorCode XrayProtocol::startTun2Sock()
|
||||||
// killSwitch toggle
|
// killSwitch toggle
|
||||||
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
|
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
|
||||||
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
|
||||||
IpcClient::Interface()->enableKillSwitch(m_configData, netInterfaces.at(i).index());
|
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
|
||||||
}
|
}
|
||||||
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
|
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
|
||||||
m_configData.insert("vpnGateway", m_vpnGateway);
|
m_configData.insert("vpnGateway", m_vpnGateway);
|
||||||
|
|
|
@ -236,10 +236,6 @@
|
||||||
<file>ui/qml/Pages2/PageSettingsApiNativeConfigs.qml</file>
|
<file>ui/qml/Pages2/PageSettingsApiNativeConfigs.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSettingsApiDevices.qml</file>
|
<file>ui/qml/Pages2/PageSettingsApiDevices.qml</file>
|
||||||
<file>images/controls/monitor.svg</file>
|
<file>images/controls/monitor.svg</file>
|
||||||
<file>ui/qml/Components/ApiPremV1MigrationDrawer.qml</file>
|
|
||||||
<file>ui/qml/Components/ApiPremV1SubListDrawer.qml</file>
|
|
||||||
<file>ui/qml/Components/OtpCodeDrawer.qml</file>
|
|
||||||
<file>ui/qml/Components/AwgTextField.qml</file>
|
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/countriesFlags">
|
<qresource prefix="/countriesFlags">
|
||||||
<file>images/flagKit/ZW.svg</file>
|
<file>images/flagKit/ZW.svg</file>
|
||||||
|
|
|
@ -10,7 +10,7 @@ RUN mkdir -p /opt/amnezia
|
||||||
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
||||||
RUN chmod a+x /opt/amnezia/start.sh
|
RUN chmod a+x /opt/amnezia/start.sh
|
||||||
|
|
||||||
# Tune network
|
# Tune network
|
||||||
RUN echo -e " \n\
|
RUN echo -e " \n\
|
||||||
fs.file-max = 51200 \n\
|
fs.file-max = 51200 \n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -40,8 +40,7 @@ RUN echo -e " \n\
|
||||||
echo -e " \n\
|
echo -e " \n\
|
||||||
* soft nofile 51200 \n\
|
* soft nofile 51200 \n\
|
||||||
* hard nofile 51200 \n\
|
* hard nofile 51200 \n\
|
||||||
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
||||||
|
|
||||||
ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ]
|
ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ]
|
||||||
CMD [ "" ]
|
CMD [ "" ]
|
||||||
|
|
||||||
|
|
|
@ -23,5 +23,4 @@ H1 = $INIT_PACKET_MAGIC_HEADER
|
||||||
H2 = $RESPONSE_PACKET_MAGIC_HEADER
|
H2 = $RESPONSE_PACKET_MAGIC_HEADER
|
||||||
H3 = $UNDERLOAD_PACKET_MAGIC_HEADER
|
H3 = $UNDERLOAD_PACKET_MAGIC_HEADER
|
||||||
H4 = $TRANSPORT_PACKET_MAGIC_HEADER
|
H4 = $TRANSPORT_PACKET_MAGIC_HEADER
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
if which apt-get > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/lib/dpkg/lock-frontend";\
|
if which apt-get > /dev/null 2>&1; then LOCK_FILE="/var/lib/dpkg/lock-frontend";\
|
||||||
elif which dnf > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/cache/dnf/* /var/run/dnf/* /var/lib/dnf/* /var/lib/rpm/*";\
|
elif which dnf > /dev/null 2>&1; then LOCK_FILE="/var/run/dnf.pid";\
|
||||||
elif which yum > /dev/null 2>&1; then LOCK_CMD="cat"; LOCK_FILE="/var/run/yum.pid";\
|
elif which yum > /dev/null 2>&1; then LOCK_FILE="/var/run/yum.pid";\
|
||||||
elif which zypper > /dev/null 2>&1; then LOCK_CMD="cat"; LOCK_FILE="/var/run/zypp.pid";\
|
elif which pacman > /dev/null 2>&1; then LOCK_FILE="/var/lib/pacman/db.lck";\
|
||||||
elif which pacman > /dev/null 2>&1; then LOCK_CMD="fuser"; LOCK_FILE="/var/lib/pacman/db.lck";\
|
|
||||||
else echo "Packet manager not found"; echo "Internal error"; exit 1; fi;\
|
else echo "Packet manager not found"; echo "Internal error"; exit 1; fi;\
|
||||||
if command -v $LOCK_CMD > /dev/null 2>&1; then sudo $LOCK_CMD $LOCK_FILE 2>/dev/null; else echo "$LOCK_CMD not installed"; fi
|
if command -v fuser > /dev/null 2>&1; then sudo fuser $LOCK_FILE 2>/dev/null; else echo "fuser not installed"; fi
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); opt="--version";\
|
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); opt="--version";\
|
||||||
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); opt="--version";\
|
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); opt="--version";\
|
||||||
elif which yum > /dev/null 2>&1; then pm=$(which yum); opt="--version";\
|
elif which yum > /dev/null 2>&1; then pm=$(which yum); opt="--version";\
|
||||||
elif which zypper > /dev/null 2>&1; then pm=$(which zypper); opt="--version";\
|
|
||||||
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); opt="--version";\
|
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); opt="--version";\
|
||||||
else pm="uname"; opt="-a";\
|
else pm="uname"; opt="-a";\
|
||||||
fi;\
|
fi;\
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); silent_inst="-yq install"; check_pkgs="-yq update"; docker_pkg="docker.io"; dist="debian";\
|
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); silent_inst="-yq install"; check_pkgs="-yq update"; docker_pkg="docker.io"; dist="debian";\
|
||||||
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); silent_inst="-yq install"; check_pkgs="-yq check-update"; docker_pkg="docker"; dist="fedora";\
|
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); silent_inst="-yq install"; check_pkgs="-yq check-update"; docker_pkg="docker"; dist="fedora";\
|
||||||
elif which yum > /dev/null 2>&1; then pm=$(which yum); silent_inst="-y -q install"; check_pkgs="-y -q check-update"; docker_pkg="docker"; dist="centos";\
|
elif which yum > /dev/null 2>&1; then pm=$(which yum); silent_inst="-y -q install"; check_pkgs="-y -q check-update"; docker_pkg="docker"; dist="centos";\
|
||||||
elif which zypper > /dev/null 2>&1; then pm=$(which zypper); silent_inst="-nq install"; check_pkgs="-nq refresh"; docker_pkg="docker"; dist="opensuse";\
|
|
||||||
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); silent_inst="-S --noconfirm --noprogressbar --quiet"; check_pkgs="-Sup"; docker_pkg="docker"; dist="archlinux";\
|
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); silent_inst="-S --noconfirm --noprogressbar --quiet"; check_pkgs="-Sup"; docker_pkg="docker"; dist="archlinux";\
|
||||||
else echo "Packet manager not found"; exit 1; fi;\
|
else echo "Packet manager not found"; exit 1; fi;\
|
||||||
echo "Dist: $dist, Packet manager: $pm, Install command: $silent_inst, Check pkgs command: $check_pkgs, Docker pkg: $docker_pkg";\
|
echo "Dist: $dist, Packet manager: $pm, Install command: $silent_inst, Check pkgs command: $check_pkgs, Docker pkg: $docker_pkg";\
|
||||||
|
|
|
@ -559,16 +559,6 @@ void Settings::disableHomeAdLabel()
|
||||||
setValue("Conf/homeAdLabelVisible", false);
|
setValue("Conf/homeAdLabelVisible", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::isPremV1MigrationReminderActive()
|
|
||||||
{
|
|
||||||
return value("Conf/premV1MigrationReminderActive", true).toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Settings::disablePremV1MigrationReminder()
|
|
||||||
{
|
|
||||||
setValue("Conf/premV1MigrationReminderActive", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList Settings::allowedDnsServers() const
|
QStringList Settings::allowedDnsServers() const
|
||||||
{
|
{
|
||||||
return value("Conf/allowedDnsServers").toStringList();
|
return value("Conf/allowedDnsServers").toStringList();
|
||||||
|
|
|
@ -174,12 +174,11 @@ public:
|
||||||
|
|
||||||
QLocale getAppLanguage()
|
QLocale getAppLanguage()
|
||||||
{
|
{
|
||||||
QString localeStr = m_settings.value("Conf/appLanguage").toString();
|
return value("Conf/appLanguage", QLocale()).toLocale();
|
||||||
return QLocale(localeStr);
|
|
||||||
};
|
};
|
||||||
void setAppLanguage(QLocale locale)
|
void setAppLanguage(QLocale locale)
|
||||||
{
|
{
|
||||||
setValue("Conf/appLanguage", locale.name());
|
setValue("Conf/appLanguage", locale);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isScreenshotsEnabled() const
|
bool isScreenshotsEnabled() const
|
||||||
|
@ -230,9 +229,6 @@ public:
|
||||||
bool isHomeAdLabelVisible();
|
bool isHomeAdLabelVisible();
|
||||||
void disableHomeAdLabel();
|
void disableHomeAdLabel();
|
||||||
|
|
||||||
bool isPremV1MigrationReminderActive();
|
|
||||||
void disablePremV1MigrationReminder();
|
|
||||||
|
|
||||||
QStringList allowedDnsServers() const;
|
QStringList allowedDnsServers() const;
|
||||||
void setAllowedDnsServers(const QStringList &servers);
|
void setAllowedDnsServers(const QStringList &servers);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
34
client/ui/Controls2
Normal file
34
client/ui/Controls2
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
topPadding: 16
|
||||||
|
leftPadding: 16
|
||||||
|
|
||||||
|
color: "#D7D8DB"
|
||||||
|
selectionColor: "#412102"
|
||||||
|
selectedTextColor: "#D7D8DB"
|
||||||
|
placeholderTextColor: "#878B91"
|
||||||
|
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.family: "PT Root UI VF"
|
||||||
|
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.RightButton
|
||||||
|
onClicked: contextMenu.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextMenuType {
|
||||||
|
id: contextMenu
|
||||||
|
textObj: textField
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,6 @@ namespace
|
||||||
{
|
{
|
||||||
constexpr char cloak[] = "cloak";
|
constexpr char cloak[] = "cloak";
|
||||||
constexpr char awg[] = "awg";
|
constexpr char awg[] = "awg";
|
||||||
constexpr char vless[] = "vless";
|
|
||||||
|
|
||||||
constexpr char apiEndpoint[] = "api_endpoint";
|
constexpr char apiEndpoint[] = "api_endpoint";
|
||||||
constexpr char accessToken[] = "api_key";
|
constexpr char accessToken[] = "api_key";
|
||||||
|
@ -36,6 +35,10 @@ namespace
|
||||||
constexpr char serviceInfo[] = "service_info";
|
constexpr char serviceInfo[] = "service_info";
|
||||||
constexpr char serviceProtocol[] = "service_protocol";
|
constexpr char serviceProtocol[] = "service_protocol";
|
||||||
|
|
||||||
|
constexpr char aesKey[] = "aes_key";
|
||||||
|
constexpr char aesIv[] = "aes_iv";
|
||||||
|
constexpr char aesSalt[] = "aes_salt";
|
||||||
|
|
||||||
constexpr char apiPayload[] = "api_payload";
|
constexpr char apiPayload[] = "api_payload";
|
||||||
constexpr char keyPayload[] = "key_payload";
|
constexpr char keyPayload[] = "key_payload";
|
||||||
|
|
||||||
|
@ -44,185 +47,6 @@ namespace
|
||||||
|
|
||||||
constexpr char config[] = "config";
|
constexpr char config[] = "config";
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProtocolData
|
|
||||||
{
|
|
||||||
OpenVpnConfigurator::ConnectionData certRequest;
|
|
||||||
|
|
||||||
QString wireGuardClientPrivKey;
|
|
||||||
QString wireGuardClientPubKey;
|
|
||||||
|
|
||||||
QString xrayUuid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GatewayRequestData
|
|
||||||
{
|
|
||||||
QString osVersion;
|
|
||||||
QString appVersion;
|
|
||||||
|
|
||||||
QString installationUuid;
|
|
||||||
|
|
||||||
QString userCountryCode;
|
|
||||||
QString serverCountryCode;
|
|
||||||
QString serviceType;
|
|
||||||
QString serviceProtocol;
|
|
||||||
|
|
||||||
QJsonObject authData;
|
|
||||||
|
|
||||||
QJsonObject toJsonObject() const
|
|
||||||
{
|
|
||||||
QJsonObject obj;
|
|
||||||
if (!osVersion.isEmpty()) {
|
|
||||||
obj[configKey::osVersion] = osVersion;
|
|
||||||
}
|
|
||||||
if (!appVersion.isEmpty()) {
|
|
||||||
obj[configKey::appVersion] = appVersion;
|
|
||||||
}
|
|
||||||
if (!installationUuid.isEmpty()) {
|
|
||||||
obj[configKey::uuid] = installationUuid;
|
|
||||||
}
|
|
||||||
if (!userCountryCode.isEmpty()) {
|
|
||||||
obj[configKey::userCountryCode] = userCountryCode;
|
|
||||||
}
|
|
||||||
if (!serverCountryCode.isEmpty()) {
|
|
||||||
obj[configKey::serverCountryCode] = serverCountryCode;
|
|
||||||
}
|
|
||||||
if (!serviceType.isEmpty()) {
|
|
||||||
obj[configKey::serviceType] = serviceType;
|
|
||||||
}
|
|
||||||
if (!serviceProtocol.isEmpty()) {
|
|
||||||
obj[configKey::serviceProtocol] = serviceProtocol;
|
|
||||||
}
|
|
||||||
if (!authData.isEmpty()) {
|
|
||||||
obj[configKey::authData] = authData;
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ProtocolData generateProtocolData(const QString &protocol)
|
|
||||||
{
|
|
||||||
ProtocolData protocolData;
|
|
||||||
if (protocol == configKey::cloak) {
|
|
||||||
protocolData.certRequest = OpenVpnConfigurator::createCertRequest();
|
|
||||||
} else if (protocol == configKey::awg) {
|
|
||||||
auto connData = WireguardConfigurator::genClientKeys();
|
|
||||||
protocolData.wireGuardClientPubKey = connData.clientPubKey;
|
|
||||||
protocolData.wireGuardClientPrivKey = connData.clientPrivKey;
|
|
||||||
} else if (protocol == configKey::vless) {
|
|
||||||
protocolData.xrayUuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
|
||||||
}
|
|
||||||
|
|
||||||
return protocolData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendProtocolDataToApiPayload(const QString &protocol, const ProtocolData &protocolData, QJsonObject &apiPayload)
|
|
||||||
{
|
|
||||||
if (protocol == configKey::cloak) {
|
|
||||||
apiPayload[configKey::certificate] = protocolData.certRequest.request;
|
|
||||||
} else if (protocol == configKey::awg) {
|
|
||||||
apiPayload[configKey::publicKey] = protocolData.wireGuardClientPubKey;
|
|
||||||
} else if (protocol == configKey::vless) {
|
|
||||||
apiPayload[configKey::publicKey] = protocolData.xrayUuid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorCode fillServerConfig(const QString &protocol, const ProtocolData &apiPayloadData, const QByteArray &apiResponseBody,
|
|
||||||
QJsonObject &serverConfig)
|
|
||||||
{
|
|
||||||
QString data = QJsonDocument::fromJson(apiResponseBody).object().value(config_key::config).toString();
|
|
||||||
|
|
||||||
data.replace("vpn://", "");
|
|
||||||
QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
|
||||||
|
|
||||||
if (ba.isEmpty()) {
|
|
||||||
qDebug() << "empty vpn key";
|
|
||||||
return ErrorCode::ApiConfigEmptyError;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray ba_uncompressed = qUncompress(ba);
|
|
||||||
if (!ba_uncompressed.isEmpty()) {
|
|
||||||
ba = ba_uncompressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString configStr = ba;
|
|
||||||
if (protocol == configKey::cloak) {
|
|
||||||
configStr.replace("<key>", "<key>\n");
|
|
||||||
configStr.replace("$OPENVPN_PRIV_KEY", apiPayloadData.certRequest.privKey);
|
|
||||||
} else if (protocol == configKey::awg) {
|
|
||||||
configStr.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", apiPayloadData.wireGuardClientPrivKey);
|
|
||||||
auto newServerConfig = QJsonDocument::fromJson(configStr.toUtf8()).object();
|
|
||||||
auto containers = newServerConfig.value(config_key::containers).toArray();
|
|
||||||
if (containers.isEmpty()) {
|
|
||||||
qDebug() << "missing containers field";
|
|
||||||
return ErrorCode::ApiConfigEmptyError;
|
|
||||||
}
|
|
||||||
auto container = containers.at(0).toObject();
|
|
||||||
QString containerName = ContainerProps::containerTypeToString(DockerContainer::Awg);
|
|
||||||
auto serverProtocolConfig = container.value(containerName).toObject();
|
|
||||||
auto clientProtocolConfig =
|
|
||||||
QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object();
|
|
||||||
|
|
||||||
//TODO looks like this block can be removed after v1 configs EOL
|
|
||||||
|
|
||||||
serverProtocolConfig[config_key::junkPacketCount] = clientProtocolConfig.value(config_key::junkPacketCount);
|
|
||||||
serverProtocolConfig[config_key::junkPacketMinSize] = clientProtocolConfig.value(config_key::junkPacketMinSize);
|
|
||||||
serverProtocolConfig[config_key::junkPacketMaxSize] = clientProtocolConfig.value(config_key::junkPacketMaxSize);
|
|
||||||
serverProtocolConfig[config_key::initPacketJunkSize] = clientProtocolConfig.value(config_key::initPacketJunkSize);
|
|
||||||
serverProtocolConfig[config_key::responsePacketJunkSize] = clientProtocolConfig.value(config_key::responsePacketJunkSize);
|
|
||||||
serverProtocolConfig[config_key::initPacketMagicHeader] = clientProtocolConfig.value(config_key::initPacketMagicHeader);
|
|
||||||
serverProtocolConfig[config_key::responsePacketMagicHeader] = clientProtocolConfig.value(config_key::responsePacketMagicHeader);
|
|
||||||
serverProtocolConfig[config_key::underloadPacketMagicHeader] = clientProtocolConfig.value(config_key::underloadPacketMagicHeader);
|
|
||||||
serverProtocolConfig[config_key::transportPacketMagicHeader] = clientProtocolConfig.value(config_key::transportPacketMagicHeader);
|
|
||||||
|
|
||||||
serverProtocolConfig[config_key::cookieReplyPacketJunkSize] = clientProtocolConfig.value(config_key::cookieReplyPacketJunkSize);
|
|
||||||
serverProtocolConfig[config_key::transportPacketJunkSize] = clientProtocolConfig.value(config_key::transportPacketJunkSize);
|
|
||||||
serverProtocolConfig[config_key::specialJunk1] = clientProtocolConfig.value(config_key::specialJunk1);
|
|
||||||
serverProtocolConfig[config_key::specialJunk2] = clientProtocolConfig.value(config_key::specialJunk2);
|
|
||||||
serverProtocolConfig[config_key::specialJunk3] = clientProtocolConfig.value(config_key::specialJunk3);
|
|
||||||
serverProtocolConfig[config_key::specialJunk4] = clientProtocolConfig.value(config_key::specialJunk4);
|
|
||||||
serverProtocolConfig[config_key::specialJunk5] = clientProtocolConfig.value(config_key::specialJunk5);
|
|
||||||
serverProtocolConfig[config_key::controlledJunk1] = clientProtocolConfig.value(config_key::controlledJunk1);
|
|
||||||
serverProtocolConfig[config_key::controlledJunk2] = clientProtocolConfig.value(config_key::controlledJunk2);
|
|
||||||
serverProtocolConfig[config_key::controlledJunk3] = clientProtocolConfig.value(config_key::controlledJunk3);
|
|
||||||
serverProtocolConfig[config_key::specialHandshakeTimeout] = clientProtocolConfig.value(config_key::specialHandshakeTimeout);
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
container[containerName] = serverProtocolConfig;
|
|
||||||
containers.replace(0, container);
|
|
||||||
newServerConfig[config_key::containers] = containers;
|
|
||||||
configStr = QString(QJsonDocument(newServerConfig).toJson());
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject newServerConfig = QJsonDocument::fromJson(configStr.toUtf8()).object();
|
|
||||||
serverConfig[config_key::dns1] = newServerConfig.value(config_key::dns1);
|
|
||||||
serverConfig[config_key::dns2] = newServerConfig.value(config_key::dns2);
|
|
||||||
serverConfig[config_key::containers] = newServerConfig.value(config_key::containers);
|
|
||||||
serverConfig[config_key::hostName] = newServerConfig.value(config_key::hostName);
|
|
||||||
|
|
||||||
if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) {
|
|
||||||
serverConfig[config_key::configVersion] = newServerConfig.value(config_key::configVersion);
|
|
||||||
serverConfig[config_key::description] = newServerConfig.value(config_key::description);
|
|
||||||
serverConfig[config_key::name] = newServerConfig.value(config_key::name);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto defaultContainer = newServerConfig.value(config_key::defaultContainer).toString();
|
|
||||||
serverConfig[config_key::defaultContainer] = defaultContainer;
|
|
||||||
|
|
||||||
QVariantMap map = serverConfig.value(configKey::apiConfig).toObject().toVariantMap();
|
|
||||||
map.insert(newServerConfig.value(configKey::apiConfig).toObject().toVariantMap());
|
|
||||||
auto apiConfig = QJsonObject::fromVariantMap(map);
|
|
||||||
|
|
||||||
if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) {
|
|
||||||
apiConfig.insert(apiDefs::key::supportedProtocols,
|
|
||||||
QJsonDocument::fromJson(apiResponseBody).object().value(apiDefs::key::supportedProtocols).toArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
serverConfig[configKey::apiConfig] = apiConfig;
|
|
||||||
|
|
||||||
return ErrorCode::NoError;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiConfigsController::ApiConfigsController(const QSharedPointer<ServersModel> &serversModel,
|
ApiConfigsController::ApiConfigsController(const QSharedPointer<ServersModel> &serversModel,
|
||||||
|
@ -239,26 +63,22 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
|
|
||||||
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
|
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
|
||||||
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
||||||
|
|
||||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
|
||||||
QString(APP_VERSION),
|
|
||||||
m_settings->getInstallationUuid(true),
|
|
||||||
apiConfigObject.value(configKey::userCountryCode).toString(),
|
|
||||||
serverCountryCode,
|
|
||||||
apiConfigObject.value(configKey::serviceType).toString(),
|
|
||||||
m_apiServicesModel->getSelectedServiceProtocol(),
|
|
||||||
serverConfigObject.value(configKey::authData).toObject() };
|
|
||||||
|
|
||||||
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
|
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
|
||||||
ProtocolData protocolData = generateProtocolData(protocol);
|
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
|
||||||
|
|
||||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
|
||||||
appendProtocolDataToApiPayload(gatewayRequestData.serviceProtocol, protocolData, apiPayload);
|
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
|
||||||
|
apiPayload[configKey::serverCountryCode] = serverCountryCode;
|
||||||
|
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
|
||||||
|
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = executeRequest(QString("%1v1/native_config"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/native_config"), apiPayload, responseBody);
|
||||||
if (errorCode != ErrorCode::NoError) {
|
if (errorCode != ErrorCode::NoError) {
|
||||||
emit errorOccurred(errorCode);
|
emit errorOccurred(errorCode);
|
||||||
return false;
|
return false;
|
||||||
|
@ -266,7 +86,7 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
|
||||||
|
|
||||||
QJsonObject jsonConfig = QJsonDocument::fromJson(responseBody).object();
|
QJsonObject jsonConfig = QJsonDocument::fromJson(responseBody).object();
|
||||||
QString nativeConfig = jsonConfig.value(configKey::config).toString();
|
QString nativeConfig = jsonConfig.value(configKey::config).toString();
|
||||||
nativeConfig.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", protocolData.wireGuardClientPrivKey);
|
nativeConfig.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", apiPayloadData.wireGuardClientPrivKey);
|
||||||
|
|
||||||
SystemController::saveFile(fileName, nativeConfig);
|
SystemController::saveFile(fileName, nativeConfig);
|
||||||
return true;
|
return true;
|
||||||
|
@ -274,22 +94,22 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
|
||||||
|
|
||||||
bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode)
|
bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode)
|
||||||
{
|
{
|
||||||
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
|
|
||||||
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
|
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
|
||||||
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
||||||
|
|
||||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
|
||||||
QString(APP_VERSION),
|
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
|
||||||
m_settings->getInstallationUuid(true),
|
|
||||||
apiConfigObject.value(configKey::userCountryCode).toString(),
|
|
||||||
serverCountryCode,
|
|
||||||
apiConfigObject.value(configKey::serviceType).toString(),
|
|
||||||
m_apiServicesModel->getSelectedServiceProtocol(),
|
|
||||||
serverConfigObject.value(configKey::authData).toObject() };
|
|
||||||
|
|
||||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
|
||||||
|
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
|
||||||
|
apiPayload[configKey::serverCountryCode] = serverCountryCode;
|
||||||
|
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
|
||||||
|
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = executeRequest(QString("%1v1/revoke_native_config"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_native_config"), apiPayload, responseBody);
|
||||||
if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) {
|
if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) {
|
||||||
emit errorOccurred(errorCode);
|
emit errorOccurred(errorCode);
|
||||||
return false;
|
return false;
|
||||||
|
@ -320,11 +140,13 @@ void ApiConfigsController::copyVpnKeyToClipboard()
|
||||||
|
|
||||||
bool ApiConfigsController::fillAvailableServices()
|
bool ApiConfigsController::fillAvailableServices()
|
||||||
{
|
{
|
||||||
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
|
|
||||||
QJsonObject apiPayload;
|
QJsonObject apiPayload;
|
||||||
apiPayload[configKey::osVersion] = QSysInfo::productType();
|
apiPayload[configKey::osVersion] = QSysInfo::productType();
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = executeRequest(QString("%1v1/services"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/services"), apiPayload, responseBody);
|
||||||
if (errorCode == ErrorCode::NoError) {
|
if (errorCode == ErrorCode::NoError) {
|
||||||
if (!responseBody.contains("services")) {
|
if (!responseBody.contains("services")) {
|
||||||
errorCode = ErrorCode::ApiServicesMissingError;
|
errorCode = ErrorCode::ApiServicesMissingError;
|
||||||
|
@ -343,36 +165,32 @@ bool ApiConfigsController::fillAvailableServices()
|
||||||
|
|
||||||
bool ApiConfigsController::importServiceFromGateway()
|
bool ApiConfigsController::importServiceFromGateway()
|
||||||
{
|
{
|
||||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
if (m_serversModel->isServerFromApiAlreadyExists(m_apiServicesModel->getCountryCode(), m_apiServicesModel->getSelectedServiceType(),
|
||||||
QString(APP_VERSION),
|
m_apiServicesModel->getSelectedServiceProtocol())) {
|
||||||
m_settings->getInstallationUuid(true),
|
|
||||||
m_apiServicesModel->getCountryCode(),
|
|
||||||
"",
|
|
||||||
m_apiServicesModel->getSelectedServiceType(),
|
|
||||||
m_apiServicesModel->getSelectedServiceProtocol(),
|
|
||||||
QJsonObject() };
|
|
||||||
|
|
||||||
if (m_serversModel->isServerFromApiAlreadyExists(gatewayRequestData.userCountryCode, gatewayRequestData.serviceType,
|
|
||||||
gatewayRequestData.serviceProtocol)) {
|
|
||||||
emit errorOccurred(ErrorCode::ApiConfigAlreadyAdded);
|
emit errorOccurred(ErrorCode::ApiConfigAlreadyAdded);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolData protocolData = generateProtocolData(gatewayRequestData.serviceProtocol);
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
|
|
||||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
auto installationUuid = m_settings->getInstallationUuid(true);
|
||||||
appendProtocolDataToApiPayload(gatewayRequestData.serviceProtocol, protocolData, apiPayload);
|
auto userCountryCode = m_apiServicesModel->getCountryCode();
|
||||||
|
auto serviceType = m_apiServicesModel->getSelectedServiceType();
|
||||||
|
auto serviceProtocol = m_apiServicesModel->getSelectedServiceProtocol();
|
||||||
|
|
||||||
|
ApiPayloadData apiPayloadData = generateApiPayloadData(serviceProtocol);
|
||||||
|
|
||||||
|
QJsonObject apiPayload = fillApiPayload(serviceProtocol, apiPayloadData);
|
||||||
|
apiPayload[configKey::userCountryCode] = userCountryCode;
|
||||||
|
apiPayload[configKey::serviceType] = serviceType;
|
||||||
|
apiPayload[configKey::uuid] = installationUuid;
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/config"), apiPayload, responseBody);
|
||||||
|
|
||||||
QJsonObject serverConfig;
|
QJsonObject serverConfig;
|
||||||
if (errorCode == ErrorCode::NoError) {
|
if (errorCode == ErrorCode::NoError) {
|
||||||
errorCode = fillServerConfig(gatewayRequestData.serviceProtocol, protocolData, responseBody, serverConfig);
|
fillServerConfig(serviceProtocol, apiPayloadData, responseBody, serverConfig);
|
||||||
if (errorCode != ErrorCode::NoError) {
|
|
||||||
emit errorOccurred(errorCode);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
QJsonObject apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
||||||
apiConfig.insert(configKey::userCountryCode, m_apiServicesModel->getCountryCode());
|
apiConfig.insert(configKey::userCountryCode, m_apiServicesModel->getCountryCode());
|
||||||
|
@ -393,33 +211,37 @@ bool ApiConfigsController::importServiceFromGateway()
|
||||||
bool ApiConfigsController::updateServiceFromGateway(const int serverIndex, const QString &newCountryCode, const QString &newCountryName,
|
bool ApiConfigsController::updateServiceFromGateway(const int serverIndex, const QString &newCountryCode, const QString &newCountryName,
|
||||||
bool reloadServiceConfig)
|
bool reloadServiceConfig)
|
||||||
{
|
{
|
||||||
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||||
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
||||||
|
auto authData = serverConfig.value(configKey::authData).toObject();
|
||||||
|
|
||||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
auto installationUuid = m_settings->getInstallationUuid(true);
|
||||||
QString(APP_VERSION),
|
auto userCountryCode = apiConfig.value(configKey::userCountryCode).toString();
|
||||||
m_settings->getInstallationUuid(true),
|
auto serviceType = apiConfig.value(configKey::serviceType).toString();
|
||||||
apiConfig.value(configKey::userCountryCode).toString(),
|
auto serviceProtocol = apiConfig.value(configKey::serviceProtocol).toString();
|
||||||
newCountryCode,
|
|
||||||
apiConfig.value(configKey::serviceType).toString(),
|
|
||||||
apiConfig.value(configKey::serviceProtocol).toString(),
|
|
||||||
serverConfig.value(configKey::authData).toObject() };
|
|
||||||
|
|
||||||
ProtocolData protocolData = generateProtocolData(gatewayRequestData.serviceProtocol);
|
ApiPayloadData apiPayloadData = generateApiPayloadData(serviceProtocol);
|
||||||
|
|
||||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
QJsonObject apiPayload = fillApiPayload(serviceProtocol, apiPayloadData);
|
||||||
appendProtocolDataToApiPayload(gatewayRequestData.serviceProtocol, protocolData, apiPayload);
|
apiPayload[configKey::userCountryCode] = userCountryCode;
|
||||||
|
apiPayload[configKey::serviceType] = serviceType;
|
||||||
|
apiPayload[configKey::uuid] = installationUuid;
|
||||||
|
|
||||||
|
if (!newCountryCode.isEmpty()) {
|
||||||
|
apiPayload[configKey::serverCountryCode] = newCountryCode;
|
||||||
|
}
|
||||||
|
if (!authData.isEmpty()) {
|
||||||
|
apiPayload[configKey::authData] = authData;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = executeRequest(QString("%1v1/config"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/config"), apiPayload, responseBody);
|
||||||
|
|
||||||
QJsonObject newServerConfig;
|
QJsonObject newServerConfig;
|
||||||
if (errorCode == ErrorCode::NoError) {
|
if (errorCode == ErrorCode::NoError) {
|
||||||
errorCode = fillServerConfig(gatewayRequestData.serviceProtocol, protocolData, responseBody, newServerConfig);
|
fillServerConfig(serviceProtocol, apiPayloadData, responseBody, newServerConfig);
|
||||||
if (errorCode != ErrorCode::NoError) {
|
|
||||||
emit errorOccurred(errorCode);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject newApiConfig = newServerConfig.value(configKey::apiConfig).toObject();
|
QJsonObject newApiConfig = newServerConfig.value(configKey::apiConfig).toObject();
|
||||||
newApiConfig.insert(configKey::userCountryCode, apiConfig.value(configKey::userCountryCode));
|
newApiConfig.insert(configKey::userCountryCode, apiConfig.value(configKey::userCountryCode));
|
||||||
|
@ -428,12 +250,8 @@ bool ApiConfigsController::updateServiceFromGateway(const int serverIndex, const
|
||||||
newApiConfig.insert(apiDefs::key::vpnKey, apiConfig.value(apiDefs::key::vpnKey));
|
newApiConfig.insert(apiDefs::key::vpnKey, apiConfig.value(apiDefs::key::vpnKey));
|
||||||
|
|
||||||
newServerConfig.insert(configKey::apiConfig, newApiConfig);
|
newServerConfig.insert(configKey::apiConfig, newApiConfig);
|
||||||
newServerConfig.insert(configKey::authData, gatewayRequestData.authData);
|
newServerConfig.insert(configKey::authData, authData);
|
||||||
|
|
||||||
if (serverConfig.value(config_key::nameOverriddenByUser).toBool()) {
|
|
||||||
newServerConfig.insert(config_key::name, serverConfig.value(config_key::name));
|
|
||||||
newServerConfig.insert(config_key::nameOverriddenByUser, true);
|
|
||||||
}
|
|
||||||
m_serversModel->editServer(newServerConfig, serverIndex);
|
m_serversModel->editServer(newServerConfig, serverIndex);
|
||||||
if (reloadServiceConfig) {
|
if (reloadServiceConfig) {
|
||||||
emit reloadServerFromApiFinished(tr("API config reloaded"));
|
emit reloadServerFromApiFinished(tr("API config reloaded"));
|
||||||
|
@ -456,20 +274,16 @@ bool ApiConfigsController::updateServiceFromTelegram(const int serverIndex)
|
||||||
QThread::msleep(10);
|
QThread::msleep(10);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfig = m_serversModel->getServerConfig(serverIndex);
|
||||||
auto installationUuid = m_settings->getInstallationUuid(true);
|
auto installationUuid = m_settings->getInstallationUuid(true);
|
||||||
|
|
||||||
QString serviceProtocol = serverConfig.value(configKey::protocol).toString();
|
QString serviceProtocol = serverConfig.value(configKey::protocol).toString();
|
||||||
ProtocolData protocolData = generateProtocolData(serviceProtocol);
|
ApiPayloadData apiPayloadData = generateApiPayloadData(serviceProtocol);
|
||||||
|
|
||||||
QJsonObject apiPayload;
|
QJsonObject apiPayload = fillApiPayload(serviceProtocol, apiPayloadData);
|
||||||
appendProtocolDataToApiPayload(serviceProtocol, protocolData, apiPayload);
|
|
||||||
apiPayload[configKey::uuid] = installationUuid;
|
apiPayload[configKey::uuid] = installationUuid;
|
||||||
apiPayload[configKey::osVersion] = QSysInfo::productType();
|
|
||||||
apiPayload[configKey::appVersion] = QString(APP_VERSION);
|
|
||||||
apiPayload[configKey::accessToken] = serverConfig.value(configKey::accessToken).toString();
|
apiPayload[configKey::accessToken] = serverConfig.value(configKey::accessToken).toString();
|
||||||
apiPayload[configKey::apiEndpoint] = serverConfig.value(configKey::apiEndpoint).toString();
|
apiPayload[configKey::apiEndpoint] = serverConfig.value(configKey::apiEndpoint).toString();
|
||||||
|
|
||||||
|
@ -477,11 +291,7 @@ bool ApiConfigsController::updateServiceFromTelegram(const int serverIndex)
|
||||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/proxy_config"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/proxy_config"), apiPayload, responseBody);
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
if (errorCode == ErrorCode::NoError) {
|
||||||
errorCode = fillServerConfig(serviceProtocol, protocolData, responseBody, serverConfig);
|
fillServerConfig(serviceProtocol, apiPayloadData, responseBody, serverConfig);
|
||||||
if (errorCode != ErrorCode::NoError) {
|
|
||||||
emit errorOccurred(errorCode);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_serversModel->editServer(serverConfig, serverIndex);
|
m_serversModel->editServer(serverConfig, serverIndex);
|
||||||
emit updateServerFromApiFinished();
|
emit updateServerFromApiFinished();
|
||||||
|
@ -494,6 +304,8 @@ bool ApiConfigsController::updateServiceFromTelegram(const int serverIndex)
|
||||||
|
|
||||||
bool ApiConfigsController::deactivateDevice()
|
bool ApiConfigsController::deactivateDevice()
|
||||||
{
|
{
|
||||||
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
|
|
||||||
auto serverIndex = m_serversModel->getProcessedServerIndex();
|
auto serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
auto serverConfigObject = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfigObject = m_serversModel->getServerConfig(serverIndex);
|
||||||
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
||||||
|
@ -502,19 +314,18 @@ bool ApiConfigsController::deactivateDevice()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
|
||||||
QString(APP_VERSION),
|
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
|
||||||
m_settings->getInstallationUuid(true),
|
|
||||||
apiConfigObject.value(configKey::userCountryCode).toString(),
|
|
||||||
apiConfigObject.value(configKey::serverCountryCode).toString(),
|
|
||||||
apiConfigObject.value(configKey::serviceType).toString(),
|
|
||||||
"",
|
|
||||||
serverConfigObject.value(configKey::authData).toObject() };
|
|
||||||
|
|
||||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
|
||||||
|
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
|
||||||
|
apiPayload[configKey::serverCountryCode] = apiConfigObject.value(configKey::serverCountryCode);
|
||||||
|
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
|
||||||
|
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
|
||||||
|
apiPayload[configKey::uuid] = m_settings->getInstallationUuid(true);
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = executeRequest(QString("%1v1/revoke_config"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_config"), apiPayload, responseBody);
|
||||||
if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) {
|
if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) {
|
||||||
emit errorOccurred(errorCode);
|
emit errorOccurred(errorCode);
|
||||||
return false;
|
return false;
|
||||||
|
@ -528,6 +339,8 @@ bool ApiConfigsController::deactivateDevice()
|
||||||
|
|
||||||
bool ApiConfigsController::deactivateExternalDevice(const QString &uuid, const QString &serverCountryCode)
|
bool ApiConfigsController::deactivateExternalDevice(const QString &uuid, const QString &serverCountryCode)
|
||||||
{
|
{
|
||||||
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||||
|
|
||||||
auto serverIndex = m_serversModel->getProcessedServerIndex();
|
auto serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
auto serverConfigObject = m_serversModel->getServerConfig(serverIndex);
|
auto serverConfigObject = m_serversModel->getServerConfig(serverIndex);
|
||||||
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
||||||
|
@ -536,19 +349,18 @@ bool ApiConfigsController::deactivateExternalDevice(const QString &uuid, const Q
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
|
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
|
||||||
QString(APP_VERSION),
|
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
|
||||||
uuid,
|
|
||||||
apiConfigObject.value(configKey::userCountryCode).toString(),
|
|
||||||
serverCountryCode,
|
|
||||||
apiConfigObject.value(configKey::serviceType).toString(),
|
|
||||||
"",
|
|
||||||
serverConfigObject.value(configKey::authData).toObject() };
|
|
||||||
|
|
||||||
QJsonObject apiPayload = gatewayRequestData.toJsonObject();
|
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
|
||||||
|
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
|
||||||
|
apiPayload[configKey::serverCountryCode] = serverCountryCode;
|
||||||
|
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
|
||||||
|
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
|
||||||
|
apiPayload[configKey::uuid] = uuid;
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
ErrorCode errorCode = executeRequest(QString("%1v1/revoke_config"), apiPayload, responseBody);
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/revoke_config"), apiPayload, responseBody);
|
||||||
if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) {
|
if (errorCode != ErrorCode::NoError && errorCode != ErrorCode::ApiNotFoundError) {
|
||||||
emit errorOccurred(errorCode);
|
emit errorOccurred(errorCode);
|
||||||
return false;
|
return false;
|
||||||
|
@ -587,29 +399,108 @@ bool ApiConfigsController::isConfigValid()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiConfigsController::setCurrentProtocol(const QString &protocolName)
|
ApiConfigsController::ApiPayloadData ApiConfigsController::generateApiPayloadData(const QString &protocol)
|
||||||
{
|
{
|
||||||
auto serverIndex = m_serversModel->getProcessedServerIndex();
|
ApiConfigsController::ApiPayloadData apiPayload;
|
||||||
auto serverConfigObject = m_serversModel->getServerConfig(serverIndex);
|
if (protocol == configKey::cloak) {
|
||||||
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
apiPayload.certRequest = OpenVpnConfigurator::createCertRequest();
|
||||||
|
} else if (protocol == configKey::awg) {
|
||||||
apiConfigObject[configKey::serviceProtocol] = protocolName;
|
auto connData = WireguardConfigurator::genClientKeys();
|
||||||
|
apiPayload.wireGuardClientPubKey = connData.clientPubKey;
|
||||||
serverConfigObject.insert(configKey::apiConfig, apiConfigObject);
|
apiPayload.wireGuardClientPrivKey = connData.clientPrivKey;
|
||||||
|
}
|
||||||
m_serversModel->editServer(serverConfigObject, serverIndex);
|
return apiPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ApiConfigsController::isVlessProtocol()
|
QJsonObject ApiConfigsController::fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData)
|
||||||
{
|
{
|
||||||
auto serverIndex = m_serversModel->getProcessedServerIndex();
|
QJsonObject obj;
|
||||||
auto serverConfigObject = m_serversModel->getServerConfig(serverIndex);
|
if (protocol == configKey::cloak) {
|
||||||
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
obj[configKey::certificate] = apiPayloadData.certRequest.request;
|
||||||
|
} else if (protocol == configKey::awg) {
|
||||||
if (apiConfigObject[configKey::serviceProtocol].toString() == "vless") {
|
obj[configKey::publicKey] = apiPayloadData.wireGuardClientPubKey;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
obj[configKey::osVersion] = QSysInfo::productType();
|
||||||
|
obj[configKey::appVersion] = QString(APP_VERSION);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiConfigsController::fillServerConfig(const QString &protocol, const ApiPayloadData &apiPayloadData,
|
||||||
|
const QByteArray &apiResponseBody, QJsonObject &serverConfig)
|
||||||
|
{
|
||||||
|
QString data = QJsonDocument::fromJson(apiResponseBody).object().value(config_key::config).toString();
|
||||||
|
|
||||||
|
data.replace("vpn://", "");
|
||||||
|
QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||||
|
|
||||||
|
if (ba.isEmpty()) {
|
||||||
|
emit errorOccurred(ErrorCode::ApiConfigEmptyError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray ba_uncompressed = qUncompress(ba);
|
||||||
|
if (!ba_uncompressed.isEmpty()) {
|
||||||
|
ba = ba_uncompressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString configStr = ba;
|
||||||
|
if (protocol == configKey::cloak) {
|
||||||
|
configStr.replace("<key>", "<key>\n");
|
||||||
|
configStr.replace("$OPENVPN_PRIV_KEY", apiPayloadData.certRequest.privKey);
|
||||||
|
} else if (protocol == configKey::awg) {
|
||||||
|
configStr.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", apiPayloadData.wireGuardClientPrivKey);
|
||||||
|
auto newServerConfig = QJsonDocument::fromJson(configStr.toUtf8()).object();
|
||||||
|
auto containers = newServerConfig.value(config_key::containers).toArray();
|
||||||
|
if (containers.isEmpty()) {
|
||||||
|
return; // todo process error
|
||||||
|
}
|
||||||
|
auto container = containers.at(0).toObject();
|
||||||
|
QString containerName = ContainerProps::containerTypeToString(DockerContainer::Awg);
|
||||||
|
auto containerConfig = container.value(containerName).toObject();
|
||||||
|
auto protocolConfig = QJsonDocument::fromJson(containerConfig.value(config_key::last_config).toString().toUtf8()).object();
|
||||||
|
containerConfig[config_key::junkPacketCount] = protocolConfig.value(config_key::junkPacketCount);
|
||||||
|
containerConfig[config_key::junkPacketMinSize] = protocolConfig.value(config_key::junkPacketMinSize);
|
||||||
|
containerConfig[config_key::junkPacketMaxSize] = protocolConfig.value(config_key::junkPacketMaxSize);
|
||||||
|
containerConfig[config_key::initPacketJunkSize] = protocolConfig.value(config_key::initPacketJunkSize);
|
||||||
|
containerConfig[config_key::responsePacketJunkSize] = protocolConfig.value(config_key::responsePacketJunkSize);
|
||||||
|
containerConfig[config_key::initPacketMagicHeader] = protocolConfig.value(config_key::initPacketMagicHeader);
|
||||||
|
containerConfig[config_key::responsePacketMagicHeader] = protocolConfig.value(config_key::responsePacketMagicHeader);
|
||||||
|
containerConfig[config_key::underloadPacketMagicHeader] = protocolConfig.value(config_key::underloadPacketMagicHeader);
|
||||||
|
containerConfig[config_key::transportPacketMagicHeader] = protocolConfig.value(config_key::transportPacketMagicHeader);
|
||||||
|
container[containerName] = containerConfig;
|
||||||
|
containers.replace(0, container);
|
||||||
|
newServerConfig[config_key::containers] = containers;
|
||||||
|
configStr = QString(QJsonDocument(newServerConfig).toJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject newServerConfig = QJsonDocument::fromJson(configStr.toUtf8()).object();
|
||||||
|
serverConfig[config_key::dns1] = newServerConfig.value(config_key::dns1);
|
||||||
|
serverConfig[config_key::dns2] = newServerConfig.value(config_key::dns2);
|
||||||
|
serverConfig[config_key::containers] = newServerConfig.value(config_key::containers);
|
||||||
|
serverConfig[config_key::hostName] = newServerConfig.value(config_key::hostName);
|
||||||
|
|
||||||
|
if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) {
|
||||||
|
serverConfig[config_key::configVersion] = newServerConfig.value(config_key::configVersion);
|
||||||
|
serverConfig[config_key::description] = newServerConfig.value(config_key::description);
|
||||||
|
serverConfig[config_key::name] = newServerConfig.value(config_key::name);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto defaultContainer = newServerConfig.value(config_key::defaultContainer).toString();
|
||||||
|
serverConfig[config_key::defaultContainer] = defaultContainer;
|
||||||
|
|
||||||
|
QVariantMap map = serverConfig.value(configKey::apiConfig).toObject().toVariantMap();
|
||||||
|
map.insert(newServerConfig.value(configKey::apiConfig).toObject().toVariantMap());
|
||||||
|
auto apiConfig = QJsonObject::fromVariantMap(map);
|
||||||
|
|
||||||
|
if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) {
|
||||||
|
apiConfig.insert(configKey::serviceInfo, QJsonDocument::fromJson(apiResponseBody).object().value(configKey::serviceInfo).toObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
serverConfig[configKey::apiConfig] = apiConfig;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QString> ApiConfigsController::getQrCodes()
|
QList<QString> ApiConfigsController::getQrCodes()
|
||||||
|
@ -626,10 +517,3 @@ QString ApiConfigsController::getVpnKey()
|
||||||
{
|
{
|
||||||
return m_vpnKey;
|
return m_vpnKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode ApiConfigsController::executeRequest(const QString &endpoint, const QJsonObject &apiPayload, QByteArray &responseBody)
|
|
||||||
{
|
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
|
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
|
||||||
return gatewayController.post(endpoint, apiPayload, responseBody);
|
|
||||||
}
|
|
||||||
|
|
|
@ -35,9 +35,6 @@ public slots:
|
||||||
|
|
||||||
bool isConfigValid();
|
bool isConfigValid();
|
||||||
|
|
||||||
void setCurrentProtocol(const QString &protocolName);
|
|
||||||
bool isVlessProtocol();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void errorOccurred(ErrorCode errorCode);
|
void errorOccurred(ErrorCode errorCode);
|
||||||
|
|
||||||
|
@ -49,12 +46,23 @@ signals:
|
||||||
void vpnKeyExportReady();
|
void vpnKeyExportReady();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct ApiPayloadData
|
||||||
|
{
|
||||||
|
OpenVpnConfigurator::ConnectionData certRequest;
|
||||||
|
|
||||||
|
QString wireGuardClientPrivKey;
|
||||||
|
QString wireGuardClientPubKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
ApiPayloadData generateApiPayloadData(const QString &protocol);
|
||||||
|
QJsonObject fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData);
|
||||||
|
void fillServerConfig(const QString &protocol, const ApiPayloadData &apiPayloadData, const QByteArray &apiResponseBody,
|
||||||
|
QJsonObject &serverConfig);
|
||||||
|
|
||||||
QList<QString> getQrCodes();
|
QList<QString> getQrCodes();
|
||||||
int getQrCodesCount();
|
int getQrCodesCount();
|
||||||
QString getVpnKey();
|
QString getVpnKey();
|
||||||
|
|
||||||
ErrorCode executeRequest(const QString &endpoint, const QJsonObject &apiPayload, QByteArray &responseBody);
|
|
||||||
|
|
||||||
QList<QString> m_qrCodes;
|
QList<QString> m_qrCodes;
|
||||||
QString m_vpnKey;
|
QString m_vpnKey;
|
||||||
|
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
#include "apiPremV1MigrationController.h"
|
|
||||||
|
|
||||||
#include <QEventLoop>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include "core/api/apiDefs.h"
|
|
||||||
#include "core/api/apiUtils.h"
|
|
||||||
#include "core/controllers/gatewayController.h"
|
|
||||||
|
|
||||||
ApiPremV1MigrationController::ApiPremV1MigrationController(const QSharedPointer<ServersModel> &serversModel,
|
|
||||||
const std::shared_ptr<Settings> &settings, QObject *parent)
|
|
||||||
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ApiPremV1MigrationController::hasConfigsToMigration()
|
|
||||||
{
|
|
||||||
QJsonArray vpnKeys;
|
|
||||||
|
|
||||||
auto serversCount = m_serversModel->getServersCount();
|
|
||||||
for (size_t i = 0; i < serversCount; i++) {
|
|
||||||
auto serverConfigObject = m_serversModel->getServerConfig(i);
|
|
||||||
|
|
||||||
if (apiUtils::getConfigType(serverConfigObject) != apiDefs::ConfigType::AmneziaPremiumV1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString vpnKey = apiUtils::getPremiumV1VpnKey(serverConfigObject);
|
|
||||||
vpnKeys.append(vpnKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vpnKeys.isEmpty()) {
|
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
|
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
|
||||||
QJsonObject apiPayload;
|
|
||||||
|
|
||||||
apiPayload["configs"] = vpnKeys;
|
|
||||||
QByteArray responseBody;
|
|
||||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/prem-v1/is-active-subscription"), apiPayload, responseBody);
|
|
||||||
|
|
||||||
auto migrationsStatus = QJsonDocument::fromJson(responseBody).object();
|
|
||||||
for (const auto &migrationStatus : migrationsStatus) {
|
|
||||||
if (migrationStatus == "not_found") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApiPremV1MigrationController::getSubscriptionList(const QString &email)
|
|
||||||
{
|
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
|
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
|
||||||
QJsonObject apiPayload;
|
|
||||||
|
|
||||||
apiPayload[apiDefs::key::email] = email;
|
|
||||||
QByteArray responseBody;
|
|
||||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/prem-v1/subscription-list"), apiPayload, responseBody);
|
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
|
||||||
m_email = email;
|
|
||||||
m_subscriptionsModel = QJsonDocument::fromJson(responseBody).array();
|
|
||||||
if (m_subscriptionsModel.isEmpty()) {
|
|
||||||
emit noSubscriptionToMigrate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit subscriptionsModelChanged();
|
|
||||||
} else {
|
|
||||||
emit errorOccurred(ErrorCode::ApiMigrationError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonArray ApiPremV1MigrationController::getSubscriptionModel()
|
|
||||||
{
|
|
||||||
return m_subscriptionsModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApiPremV1MigrationController::sendMigrationCode(const int subscriptionIndex)
|
|
||||||
{
|
|
||||||
QEventLoop wait;
|
|
||||||
QTimer::singleShot(1000, &wait, &QEventLoop::quit);
|
|
||||||
wait.exec();
|
|
||||||
|
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
|
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
|
||||||
QJsonObject apiPayload;
|
|
||||||
|
|
||||||
apiPayload[apiDefs::key::email] = m_email;
|
|
||||||
QByteArray responseBody;
|
|
||||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/prem-v1/migration-code"), apiPayload, responseBody);
|
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
|
||||||
m_subscriptionIndex = subscriptionIndex;
|
|
||||||
emit otpSuccessfullySent();
|
|
||||||
} else {
|
|
||||||
emit errorOccurred(ErrorCode::ApiMigrationError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApiPremV1MigrationController::migrate(const QString &migrationCode)
|
|
||||||
{
|
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
|
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
|
||||||
QJsonObject apiPayload;
|
|
||||||
|
|
||||||
apiPayload[apiDefs::key::email] = m_email;
|
|
||||||
apiPayload[apiDefs::key::orderId] = m_subscriptionsModel.at(m_subscriptionIndex).toObject().value(apiDefs::key::id).toString();
|
|
||||||
apiPayload[apiDefs::key::migrationCode] = migrationCode;
|
|
||||||
QByteArray responseBody;
|
|
||||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/prem-v1/migrate"), apiPayload, responseBody);
|
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
|
||||||
auto responseObject = QJsonDocument::fromJson(responseBody).object();
|
|
||||||
QString premiumV2VpnKey = responseObject.value(apiDefs::key::config).toString();
|
|
||||||
|
|
||||||
emit importPremiumV2VpnKey(premiumV2VpnKey);
|
|
||||||
} else {
|
|
||||||
emit errorOccurred(ErrorCode::ApiMigrationError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ApiPremV1MigrationController::isPremV1MigrationReminderActive()
|
|
||||||
{
|
|
||||||
return m_settings->isPremV1MigrationReminderActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApiPremV1MigrationController::disablePremV1MigrationReminder()
|
|
||||||
{
|
|
||||||
m_settings->disablePremV1MigrationReminder();
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
#ifndef APIPREMV1MIGRATIONCONTROLLER_H
|
|
||||||
#define APIPREMV1MIGRATIONCONTROLLER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#include "ui/models/servers_model.h"
|
|
||||||
|
|
||||||
class ApiPremV1MigrationController : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
ApiPremV1MigrationController(const QSharedPointer<ServersModel> &serversModel, const std::shared_ptr<Settings> &settings,
|
|
||||||
QObject *parent = nullptr);
|
|
||||||
|
|
||||||
Q_PROPERTY(QJsonArray subscriptionsModel READ getSubscriptionModel NOTIFY subscriptionsModelChanged)
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
bool hasConfigsToMigration();
|
|
||||||
void getSubscriptionList(const QString &email);
|
|
||||||
QJsonArray getSubscriptionModel();
|
|
||||||
void sendMigrationCode(const int subscriptionIndex);
|
|
||||||
void migrate(const QString &migrationCode);
|
|
||||||
|
|
||||||
bool isPremV1MigrationReminderActive();
|
|
||||||
void disablePremV1MigrationReminder();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void subscriptionsModelChanged();
|
|
||||||
|
|
||||||
void otpSuccessfullySent();
|
|
||||||
|
|
||||||
void importPremiumV2VpnKey(const QString &vpnKey);
|
|
||||||
|
|
||||||
void errorOccurred(ErrorCode errorCode);
|
|
||||||
|
|
||||||
void showMigrationDrawer();
|
|
||||||
void migrationFinished();
|
|
||||||
|
|
||||||
void noSubscriptionToMigrate();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
|
||||||
std::shared_ptr<Settings> m_settings;
|
|
||||||
|
|
||||||
QJsonArray m_subscriptionsModel;
|
|
||||||
int m_subscriptionIndex;
|
|
||||||
QString m_email;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // APIPREMV1MIGRATIONCONTROLLER_H
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include "core/api/apiUtils.h"
|
#include "core/api/apiUtils.h"
|
||||||
#include "core/controllers/gatewayController.h"
|
#include "core/controllers/gatewayController.h"
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -49,8 +48,7 @@ bool ApiSettingsController::getAccountInfo(bool reload)
|
||||||
wait.exec();
|
wait.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), requestTimeoutMsecs,
|
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), requestTimeoutMsecs);
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
|
||||||
|
|
||||||
auto processedIndex = m_serversModel->getProcessedServerIndex();
|
auto processedIndex = m_serversModel->getProcessedServerIndex();
|
||||||
auto serverConfig = m_serversModel->getServerConfig(processedIndex);
|
auto serverConfig = m_serversModel->getServerConfig(processedIndex);
|
||||||
|
@ -61,14 +59,15 @@ bool ApiSettingsController::getAccountInfo(bool reload)
|
||||||
apiPayload[configKey::userCountryCode] = apiConfig.value(configKey::userCountryCode).toString();
|
apiPayload[configKey::userCountryCode] = apiConfig.value(configKey::userCountryCode).toString();
|
||||||
apiPayload[configKey::serviceType] = apiConfig.value(configKey::serviceType).toString();
|
apiPayload[configKey::serviceType] = apiConfig.value(configKey::serviceType).toString();
|
||||||
apiPayload[configKey::authData] = authData;
|
apiPayload[configKey::authData] = authData;
|
||||||
apiPayload[apiDefs::key::cliVersion] = QString(APP_VERSION);
|
|
||||||
|
|
||||||
QByteArray responseBody;
|
QByteArray responseBody;
|
||||||
|
|
||||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/account_info"), apiPayload, responseBody);
|
if (apiUtils::isPremiumServer(serverConfig)) {
|
||||||
if (errorCode != ErrorCode::NoError) {
|
ErrorCode errorCode = gatewayController.post(QString("%1v1/account_info"), apiPayload, responseBody);
|
||||||
emit errorOccurred(errorCode);
|
if (errorCode != ErrorCode::NoError) {
|
||||||
return false;
|
emit errorOccurred(errorCode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject accountInfo = QJsonDocument::fromJson(responseBody).object();
|
QJsonObject accountInfo = QJsonDocument::fromJson(responseBody).object();
|
||||||
|
|
|
@ -145,7 +145,7 @@ void ExportController::generateOpenVpnConfig(const QString &clientName)
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
|
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
|
||||||
for (const QString &line : std::as_const(lines)) {
|
for (const QString &line : lines) {
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
|
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
|
||||||
for (const QString &line : std::as_const(lines)) {
|
for (const QString &line : lines) {
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ void ExportController::generateAwgConfig(const QString &clientName)
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
|
QStringList lines = nativeConfig.value(config_key::config).toString().replace("\r", "").split("\n");
|
||||||
for (const QString &line : std::as_const(lines)) {
|
for (const QString &line : lines) {
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ void ExportController::generateShadowSocksConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
|
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
|
||||||
for (const QString &line : std::as_const(lines)) {
|
for (const QString &line : lines) {
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ void ExportController::generateCloakConfig()
|
||||||
nativeConfig.insert("ProxyMethod", "shadowsocks");
|
nativeConfig.insert("ProxyMethod", "shadowsocks");
|
||||||
|
|
||||||
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
|
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
|
||||||
for (const QString &line : std::as_const(lines)) {
|
for (const QString &line : lines) {
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ void ExportController::generateXrayConfig(const QString &clientName)
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
|
QStringList lines = QString(QJsonDocument(nativeConfig).toJson()).replace("\r", "").split("\n");
|
||||||
for (const QString &line : std::as_const(lines)) {
|
for (const QString &line : lines) {
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "core/errorstrings.h"
|
#include "core/errorstrings.h"
|
||||||
#include "core/qrCodeUtils.h"
|
#include "core/qrCodeUtils.h"
|
||||||
#include "core/serialization/serialization.h"
|
#include "core/serialization/serialization.h"
|
||||||
#include "protocols/protocols_defs.h"
|
|
||||||
#include "systemController.h"
|
#include "systemController.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
|
@ -287,19 +286,6 @@ void ImportController::processNativeWireGuardConfig()
|
||||||
clientProtocolConfig[config_key::underloadPacketMagicHeader] = "3";
|
clientProtocolConfig[config_key::underloadPacketMagicHeader] = "3";
|
||||||
clientProtocolConfig[config_key::transportPacketMagicHeader] = "4";
|
clientProtocolConfig[config_key::transportPacketMagicHeader] = "4";
|
||||||
|
|
||||||
// clientProtocolConfig[config_key::cookieReplyPacketJunkSize] = "0";
|
|
||||||
// clientProtocolConfig[config_key::transportPacketJunkSize] = "0";
|
|
||||||
|
|
||||||
// clientProtocolConfig[config_key::specialJunk1] = "";
|
|
||||||
// clientProtocolConfig[config_key::specialJunk2] = "";
|
|
||||||
// clientProtocolConfig[config_key::specialJunk3] = "";
|
|
||||||
// clientProtocolConfig[config_key::specialJunk4] = "";
|
|
||||||
// clientProtocolConfig[config_key::specialJunk5] = "";
|
|
||||||
// clientProtocolConfig[config_key::controlledJunk1] = "";
|
|
||||||
// clientProtocolConfig[config_key::controlledJunk2] = "";
|
|
||||||
// clientProtocolConfig[config_key::controlledJunk3] = "";
|
|
||||||
// clientProtocolConfig[config_key::specialHandshakeTimeout] = "0";
|
|
||||||
|
|
||||||
clientProtocolConfig[config_key::isObfuscationEnabled] = true;
|
clientProtocolConfig[config_key::isObfuscationEnabled] = true;
|
||||||
|
|
||||||
serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(clientProtocolConfig).toJson());
|
serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(clientProtocolConfig).toJson());
|
||||||
|
@ -452,33 +438,21 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||||
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
|
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
|
||||||
|
|
||||||
QString protocolName = "wireguard";
|
QString protocolName = "wireguard";
|
||||||
|
if (!configMap.value(config_key::junkPacketCount).isEmpty() && !configMap.value(config_key::junkPacketMinSize).isEmpty()
|
||||||
const QStringList requiredJunkFields = { config_key::junkPacketCount, config_key::junkPacketMinSize,
|
&& !configMap.value(config_key::junkPacketMaxSize).isEmpty() && !configMap.value(config_key::initPacketJunkSize).isEmpty()
|
||||||
config_key::junkPacketMaxSize, config_key::initPacketJunkSize,
|
&& !configMap.value(config_key::responsePacketJunkSize).isEmpty() && !configMap.value(config_key::initPacketMagicHeader).isEmpty()
|
||||||
config_key::responsePacketJunkSize, config_key::initPacketMagicHeader,
|
&& !configMap.value(config_key::responsePacketMagicHeader).isEmpty()
|
||||||
config_key::responsePacketMagicHeader, config_key::underloadPacketMagicHeader,
|
&& !configMap.value(config_key::underloadPacketMagicHeader).isEmpty()
|
||||||
config_key::transportPacketMagicHeader };
|
&& !configMap.value(config_key::transportPacketMagicHeader).isEmpty()) {
|
||||||
|
lastConfig[config_key::junkPacketCount] = configMap.value(config_key::junkPacketCount);
|
||||||
const QStringList optionalJunkFields = { // config_key::cookieReplyPacketJunkSize,
|
lastConfig[config_key::junkPacketMinSize] = configMap.value(config_key::junkPacketMinSize);
|
||||||
// config_key::transportPacketJunkSize,
|
lastConfig[config_key::junkPacketMaxSize] = configMap.value(config_key::junkPacketMaxSize);
|
||||||
config_key::specialJunk1, config_key::specialJunk2, config_key::specialJunk3,
|
lastConfig[config_key::initPacketJunkSize] = configMap.value(config_key::initPacketJunkSize);
|
||||||
config_key::specialJunk4, config_key::specialJunk5, config_key::controlledJunk1,
|
lastConfig[config_key::responsePacketJunkSize] = configMap.value(config_key::responsePacketJunkSize);
|
||||||
config_key::controlledJunk2, config_key::controlledJunk3, config_key::specialHandshakeTimeout
|
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);
|
||||||
bool hasAllRequiredFields = std::all_of(requiredJunkFields.begin(), requiredJunkFields.end(),
|
lastConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader);
|
||||||
[&configMap](const QString &field) { return !configMap.value(field).isEmpty(); });
|
|
||||||
if (hasAllRequiredFields) {
|
|
||||||
for (const QString &field : requiredJunkFields) {
|
|
||||||
lastConfig[field] = configMap.value(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const QString &field : optionalJunkFields) {
|
|
||||||
if (!configMap.value(field).isEmpty()) {
|
|
||||||
lastConfig[field] = configMap.value(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protocolName = "awg";
|
protocolName = "awg";
|
||||||
m_configType = ConfigTypes::Awg;
|
m_configType = ConfigTypes::Awg;
|
||||||
}
|
}
|
||||||
|
@ -682,39 +656,47 @@ void ImportController::checkForMaliciousStrings(const QJsonObject &serverConfig)
|
||||||
const QJsonArray &containers = serverConfig[config_key::containers].toArray();
|
const QJsonArray &containers = serverConfig[config_key::containers].toArray();
|
||||||
for (const QJsonValue &container : containers) {
|
for (const QJsonValue &container : containers) {
|
||||||
auto containerConfig = container.toObject();
|
auto containerConfig = container.toObject();
|
||||||
auto containerName = containerConfig[config_key::container].toString();
|
QString containerName = containerConfig[config_key::container].toString();
|
||||||
if ((containerName == ContainerProps::containerToString(DockerContainer::OpenVpn))
|
|
||||||
|| (containerName == ContainerProps::containerToString(DockerContainer::Cloak))
|
|
||||||
|| (containerName == ContainerProps::containerToString(DockerContainer::ShadowSocks))) {
|
|
||||||
|
|
||||||
QString protocolConfig =
|
if (containerName == ContainerProps::containerToString(DockerContainer::OpenVpn)
|
||||||
containerConfig[ProtocolProps::protoToString(Proto::OpenVpn)].toObject()[config_key::last_config].toString();
|
|| containerName == ContainerProps::containerToString(DockerContainer::Cloak)
|
||||||
QString protocolConfigJson = QJsonDocument::fromJson(protocolConfig.toUtf8()).object()[config_key::config].toString();
|
|| containerName == ContainerProps::containerToString(DockerContainer::ShadowSocks))
|
||||||
|
{
|
||||||
|
QString protoCfgB64 = containerConfig[ProtocolProps::protoToString(Proto::OpenVpn)]
|
||||||
|
.toObject()[config_key::last_config].toString();
|
||||||
|
QString cfgJson = QJsonDocument::fromJson(protoCfgB64.toUtf8())
|
||||||
|
.object()[config_key::config].toString();
|
||||||
|
|
||||||
|
QStringList lines = cfgJson.replace("\r", "").split('\n');
|
||||||
|
|
||||||
|
const size_t dangerousTagsMaxCount = 1;
|
||||||
|
|
||||||
// https://github.com/OpenVPN/openvpn/blob/master/doc/man-sections/script-options.rst
|
// https://github.com/OpenVPN/openvpn/blob/master/doc/man-sections/script-options.rst
|
||||||
QStringList dangerousTags {
|
const QStringList dangerousTags {
|
||||||
"up", "tls-verify", "ipchange", "client-connect", "route-up", "route-pre-down", "client-disconnect", "down", "learn-address", "auth-user-pass-verify"
|
"up", "tls-verify", "ipchange", "client-connect",
|
||||||
|
"route-up", "route-pre-down", "client-disconnect",
|
||||||
|
"down", "learn-address", "auth-user-pass-verify"
|
||||||
};
|
};
|
||||||
|
const QStringList allowedTags { "up", "down" };
|
||||||
|
|
||||||
QStringList maliciousStrings;
|
QStringList found;
|
||||||
QStringList lines = protocolConfigJson.split('\n', Qt::SkipEmptyParts);
|
for (QString line : lines) {
|
||||||
|
line = line.trimmed();
|
||||||
for (const QString &rawLine : lines) {
|
if (line.isEmpty() || line.startsWith('#') || line.startsWith(';'))
|
||||||
QString line = rawLine.trimmed();
|
continue;
|
||||||
|
QString tag = line.section(QRegularExpression("\\s+"), 0, 0);
|
||||||
QString command = line.section(' ', 0, 0, QString::SectionSkipEmpty);
|
if (dangerousTags.contains(tag) && !allowedTags.contains(tag)) {
|
||||||
if (dangerousTags.contains(command, Qt::CaseInsensitive)) {
|
found << line;
|
||||||
maliciousStrings << rawLine;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_maliciousWarningText = tr("This configuration contains an OpenVPN setup. OpenVPN configurations can include malicious "
|
m_maliciousWarningText = tr("This configuration contains an OpenVPN setup. OpenVPN configurations can include malicious "
|
||||||
"scripts, so only add it if you fully trust the provider of this config. ");
|
"scripts, so only add it if you fully trust the provider of this config. ");
|
||||||
|
|
||||||
if (!maliciousStrings.isEmpty()) {
|
if (found.size() >= dangerousTagsMaxCount) {
|
||||||
m_maliciousWarningText.push_back(tr("<br>In the imported configuration, potentially dangerous lines were found:"));
|
m_maliciousWarningText += tr("<br>Potentially dangerous directives found:");
|
||||||
for (const auto &string : maliciousStrings) {
|
for (auto &l : found) {
|
||||||
m_maliciousWarningText.push_back(QString("<br><i>%1</i>").arg(string));
|
m_maliciousWarningText += QString("<br><i>%1</i>").arg(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
|
|
||||||
#include "core/api/apiUtils.h"
|
|
||||||
#include "core/controllers/serverController.h"
|
#include "core/controllers/serverController.h"
|
||||||
#include "core/controllers/vpnConfigurationController.h"
|
#include "core/controllers/vpnConfigurationController.h"
|
||||||
#include "core/networkUtilities.h"
|
#include "core/networkUtilities.h"
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
#include "ui/models/protocols/awgConfigModel.h"
|
#include "ui/models/protocols/awgConfigModel.h"
|
||||||
#include "ui/models/protocols/wireguardConfigModel.h"
|
#include "ui/models/protocols/wireguardConfigModel.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
#include "core/api/apiUtils.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -79,36 +79,12 @@ void InstallController::install(DockerContainer container, int port, TransportPr
|
||||||
|
|
||||||
int s1 = QRandomGenerator::global()->bounded(15, 150);
|
int s1 = QRandomGenerator::global()->bounded(15, 150);
|
||||||
int s2 = QRandomGenerator::global()->bounded(15, 150);
|
int s2 = QRandomGenerator::global()->bounded(15, 150);
|
||||||
// int s3 = QRandomGenerator::global()->bounded(15, 150);
|
while (s1 + AwgConstant::messageInitiationSize == s2 + AwgConstant::messageResponseSize) {
|
||||||
// int s4 = QRandomGenerator::global()->bounded(15, 150);
|
|
||||||
|
|
||||||
// Ensure all values are unique and don't create equal packet sizes
|
|
||||||
QSet<int> usedValues;
|
|
||||||
usedValues.insert(s1);
|
|
||||||
|
|
||||||
while (usedValues.contains(s2) || s1 + AwgConstant::messageInitiationSize == s2 + AwgConstant::messageResponseSize) {
|
|
||||||
s2 = QRandomGenerator::global()->bounded(15, 150);
|
s2 = QRandomGenerator::global()->bounded(15, 150);
|
||||||
}
|
}
|
||||||
usedValues.insert(s2);
|
|
||||||
|
|
||||||
// while (usedValues.contains(s3)
|
|
||||||
// || s1 + AwgConstant::messageInitiationSize == s3 + AwgConstant::messageCookieReplySize
|
|
||||||
// || s2 + AwgConstant::messageResponseSize == s3 + AwgConstant::messageCookieReplySize) {
|
|
||||||
// s3 = QRandomGenerator::global()->bounded(15, 150);
|
|
||||||
// }
|
|
||||||
// usedValues.insert(s3);
|
|
||||||
|
|
||||||
// while (usedValues.contains(s4)
|
|
||||||
// || s1 + AwgConstant::messageInitiationSize == s4 + AwgConstant::messageTransportSize
|
|
||||||
// || s2 + AwgConstant::messageResponseSize == s4 + AwgConstant::messageTransportSize
|
|
||||||
// || s3 + AwgConstant::messageCookieReplySize == s4 + AwgConstant::messageTransportSize) {
|
|
||||||
// s4 = QRandomGenerator::global()->bounded(15, 150);
|
|
||||||
// }
|
|
||||||
|
|
||||||
QString initPacketJunkSize = QString::number(s1);
|
QString initPacketJunkSize = QString::number(s1);
|
||||||
QString responsePacketJunkSize = QString::number(s2);
|
QString responsePacketJunkSize = QString::number(s2);
|
||||||
// QString cookieReplyPacketJunkSize = QString::number(s3);
|
|
||||||
// QString transportPacketJunkSize = QString::number(s4);
|
|
||||||
|
|
||||||
QSet<QString> headersValue;
|
QSet<QString> headersValue;
|
||||||
while (headersValue.size() != 4) {
|
while (headersValue.size() != 4) {
|
||||||
|
@ -132,21 +108,6 @@ void InstallController::install(DockerContainer container, int port, TransportPr
|
||||||
containerConfig[config_key::responsePacketMagicHeader] = responsePacketMagicHeader;
|
containerConfig[config_key::responsePacketMagicHeader] = responsePacketMagicHeader;
|
||||||
containerConfig[config_key::underloadPacketMagicHeader] = underloadPacketMagicHeader;
|
containerConfig[config_key::underloadPacketMagicHeader] = underloadPacketMagicHeader;
|
||||||
containerConfig[config_key::transportPacketMagicHeader] = transportPacketMagicHeader;
|
containerConfig[config_key::transportPacketMagicHeader] = transportPacketMagicHeader;
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// containerConfig[config_key::cookieReplyPacketJunkSize] = cookieReplyPacketJunkSize;
|
|
||||||
// containerConfig[config_key::transportPacketJunkSize] = transportPacketJunkSize;
|
|
||||||
|
|
||||||
// containerConfig[config_key::specialJunk1] = specialJunk1;
|
|
||||||
// containerConfig[config_key::specialJunk2] = specialJunk2;
|
|
||||||
// containerConfig[config_key::specialJunk3] = specialJunk3;
|
|
||||||
// containerConfig[config_key::specialJunk4] = specialJunk4;
|
|
||||||
// containerConfig[config_key::specialJunk5] = specialJunk5;
|
|
||||||
// containerConfig[config_key::controlledJunk1] = controlledJunk1;
|
|
||||||
// containerConfig[config_key::controlledJunk2] = controlledJunk2;
|
|
||||||
// containerConfig[config_key::controlledJunk3] = controlledJunk3;
|
|
||||||
// containerConfig[config_key::specialHandshakeTimeout] = specialHandshakeTimeout;
|
|
||||||
|
|
||||||
} else if (container == DockerContainer::Sftp) {
|
} else if (container == DockerContainer::Sftp) {
|
||||||
containerConfig.insert(config_key::userName, protocols::sftp::defaultUserName);
|
containerConfig.insert(config_key::userName, protocols::sftp::defaultUserName);
|
||||||
containerConfig.insert(config_key::password, Utils::getRandomString(16));
|
containerConfig.insert(config_key::password, Utils::getRandomString(16));
|
||||||
|
@ -402,8 +363,7 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
|
||||||
|
|
||||||
QJsonObject config;
|
QJsonObject config;
|
||||||
Proto mainProto = ContainerProps::defaultProtocol(container);
|
Proto mainProto = ContainerProps::defaultProtocol(container);
|
||||||
const auto &protocols = ContainerProps::protocolsForContainer(container);
|
for (auto protocol : ContainerProps::protocolsForContainer(container)) {
|
||||||
for (const auto &protocol : protocols) {
|
|
||||||
QJsonObject containerConfig;
|
QJsonObject containerConfig;
|
||||||
if (protocol == mainProto) {
|
if (protocol == mainProto) {
|
||||||
containerConfig.insert(config_key::port, port);
|
containerConfig.insert(config_key::port, port);
|
||||||
|
@ -427,7 +387,6 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
containerConfig[config_key::subnet_address] = serverConfigMap.value("Address").remove("/24");
|
|
||||||
containerConfig[config_key::junkPacketCount] = serverConfigMap.value(config_key::junkPacketCount);
|
containerConfig[config_key::junkPacketCount] = serverConfigMap.value(config_key::junkPacketCount);
|
||||||
containerConfig[config_key::junkPacketMinSize] = serverConfigMap.value(config_key::junkPacketMinSize);
|
containerConfig[config_key::junkPacketMinSize] = serverConfigMap.value(config_key::junkPacketMinSize);
|
||||||
containerConfig[config_key::junkPacketMaxSize] = serverConfigMap.value(config_key::junkPacketMaxSize);
|
containerConfig[config_key::junkPacketMaxSize] = serverConfigMap.value(config_key::junkPacketMaxSize);
|
||||||
|
@ -439,38 +398,6 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
|
||||||
serverConfigMap.value(config_key::underloadPacketMagicHeader);
|
serverConfigMap.value(config_key::underloadPacketMagicHeader);
|
||||||
containerConfig[config_key::transportPacketMagicHeader] =
|
containerConfig[config_key::transportPacketMagicHeader] =
|
||||||
serverConfigMap.value(config_key::transportPacketMagicHeader);
|
serverConfigMap.value(config_key::transportPacketMagicHeader);
|
||||||
|
|
||||||
// containerConfig[config_key::cookieReplyPacketJunkSize] = serverConfigMap.value(config_key::cookieReplyPacketJunkSize);
|
|
||||||
// containerConfig[config_key::transportPacketJunkSize] = serverConfigMap.value(config_key::transportPacketJunkSize);
|
|
||||||
|
|
||||||
// containerConfig[config_key::specialJunk1] = serverConfigMap.value(config_key::specialJunk1);
|
|
||||||
// containerConfig[config_key::specialJunk2] = serverConfigMap.value(config_key::specialJunk2);
|
|
||||||
// containerConfig[config_key::specialJunk3] = serverConfigMap.value(config_key::specialJunk3);
|
|
||||||
// containerConfig[config_key::specialJunk4] = serverConfigMap.value(config_key::specialJunk4);
|
|
||||||
// containerConfig[config_key::specialJunk5] = serverConfigMap.value(config_key::specialJunk5);
|
|
||||||
// containerConfig[config_key::controlledJunk1] = serverConfigMap.value(config_key::controlledJunk1);
|
|
||||||
// containerConfig[config_key::controlledJunk2] = serverConfigMap.value(config_key::controlledJunk2);
|
|
||||||
// containerConfig[config_key::controlledJunk3] = serverConfigMap.value(config_key::controlledJunk3);
|
|
||||||
// containerConfig[config_key::specialHandshakeTimeout] = serverConfigMap.value(config_key::specialHandshakeTimeout);
|
|
||||||
|
|
||||||
} else if (protocol == Proto::WireGuard) {
|
|
||||||
QString serverConfig = serverController->getTextFileFromContainer(container, credentials,
|
|
||||||
protocols::wireguard::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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
containerConfig[config_key::subnet_address] = serverConfigMap.value("Address").remove("/24");
|
|
||||||
} else if (protocol == Proto::Sftp) {
|
} else if (protocol == Proto::Sftp) {
|
||||||
stdOut.clear();
|
stdOut.clear();
|
||||||
script = QString("sudo docker inspect --format '{{.Config.Cmd}}' %1").arg(name);
|
script = QString("sudo docker inspect --format '{{.Config.Cmd}}' %1").arg(name);
|
||||||
|
@ -505,51 +432,6 @@ ErrorCode InstallController::getAlreadyInstalledContainers(const ServerCredentia
|
||||||
containerConfig.insert(config_key::userName, userName);
|
containerConfig.insert(config_key::userName, userName);
|
||||||
containerConfig.insert(config_key::password, password);
|
containerConfig.insert(config_key::password, password);
|
||||||
}
|
}
|
||||||
} else if (protocol == Proto::Xray) {
|
|
||||||
QString currentConfig = serverController->getTextFileFromContainer(
|
|
||||||
container, credentials, amnezia::protocols::xray::serverConfigPath, errorCode);
|
|
||||||
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(currentConfig.toUtf8());
|
|
||||||
qDebug() << doc;
|
|
||||||
if (doc.isNull() || !doc.isObject()) {
|
|
||||||
logger.error() << "Failed to parse server config JSON";
|
|
||||||
errorCode = ErrorCode::InternalError;
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
QJsonObject serverConfig = doc.object();
|
|
||||||
|
|
||||||
if (!serverConfig.contains("inbounds")) {
|
|
||||||
logger.error() << "Server config missing 'inbounds' field";
|
|
||||||
errorCode = ErrorCode::InternalError;
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonArray inbounds = serverConfig["inbounds"].toArray();
|
|
||||||
if (inbounds.isEmpty()) {
|
|
||||||
logger.error() << "Server config has empty 'inbounds' array";
|
|
||||||
errorCode = ErrorCode::InternalError;
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject inbound = inbounds[0].toObject();
|
|
||||||
if (!inbound.contains("streamSettings")) {
|
|
||||||
logger.error() << "Inbound missing 'streamSettings' field";
|
|
||||||
errorCode = ErrorCode::InternalError;
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject streamSettings = inbound["streamSettings"].toObject();
|
|
||||||
QJsonObject realitySettings = streamSettings["realitySettings"].toObject();
|
|
||||||
if (!realitySettings.contains("serverNames")) {
|
|
||||||
logger.error() << "Settings missing 'clients' field";
|
|
||||||
errorCode = ErrorCode::InternalError;
|
|
||||||
return errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString siteName = realitySettings["serverNames"][0].toString();
|
|
||||||
qDebug() << siteName;
|
|
||||||
|
|
||||||
containerConfig.insert(config_key::site, siteName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config.insert(config_key::container, ContainerProps::containerToString(container));
|
config.insert(config_key::container, ContainerProps::containerToString(container));
|
||||||
|
|
|
@ -126,13 +126,7 @@ void SettingsController::clearLogs()
|
||||||
|
|
||||||
void SettingsController::backupAppConfig(const QString &fileName)
|
void SettingsController::backupAppConfig(const QString &fileName)
|
||||||
{
|
{
|
||||||
QByteArray data = m_settings->backupAppConfig();
|
SystemController::saveFile(fileName, m_settings->backupAppConfig());
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
|
||||||
QJsonObject config = doc.object();
|
|
||||||
|
|
||||||
config["Conf/autoStart"] = Autostart::isAutostart();
|
|
||||||
|
|
||||||
SystemController::saveFile(fileName, QJsonDocument(config).toJson());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsController::restoreAppConfig(const QString &fileName)
|
void SettingsController::restoreAppConfig(const QString &fileName)
|
||||||
|
@ -146,30 +140,9 @@ void SettingsController::restoreAppConfigFromData(const QByteArray &data)
|
||||||
{
|
{
|
||||||
bool ok = m_settings->restoreAppConfig(data);
|
bool ok = m_settings->restoreAppConfig(data);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
QJsonObject newConfigData = QJsonDocument::fromJson(data).object();
|
|
||||||
|
|
||||||
#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_MACX)
|
|
||||||
bool autoStart = false;
|
|
||||||
if (newConfigData.contains("Conf/autoStart")) {
|
|
||||||
autoStart = newConfigData["Conf/autoStart"].toBool();
|
|
||||||
}
|
|
||||||
toggleAutoStart(autoStart);
|
|
||||||
#endif
|
|
||||||
m_serversModel->resetModel();
|
m_serversModel->resetModel();
|
||||||
m_languageModel->changeLanguage(
|
m_languageModel->changeLanguage(
|
||||||
static_cast<LanguageSettings::AvailableLanguageEnum>(m_languageModel->getCurrentLanguageIndex()));
|
static_cast<LanguageSettings::AvailableLanguageEnum>(m_languageModel->getCurrentLanguageIndex()));
|
||||||
|
|
||||||
#if defined(Q_OS_WINDOWS) || defined(Q_OS_ANDROID)
|
|
||||||
int appSplitTunnelingRouteMode = newConfigData.value("Conf/appsRouteMode").toInt();
|
|
||||||
bool appSplittunnelingEnabled = newConfigData.value("Conf/appsSplitTunnelingEnabled").toBool();
|
|
||||||
m_appSplitTunnelingModel->setRouteMode(appSplitTunnelingRouteMode);
|
|
||||||
m_appSplitTunnelingModel->toggleSplitTunneling(appSplittunnelingEnabled);
|
|
||||||
#endif
|
|
||||||
int siteSplitTunnelingRouteMode = newConfigData.value("Conf/routeMode").toInt();
|
|
||||||
bool siteSplittunnelingEnabled = newConfigData.value("Conf/sitesSplitTunnelingEnabled").toBool();
|
|
||||||
m_sitesModel->setRouteMode(siteSplitTunnelingRouteMode);
|
|
||||||
m_sitesModel->toggleSplitTunneling(siteSplittunnelingEnabled);
|
|
||||||
|
|
||||||
emit restoreBackupFinished();
|
emit restoreBackupFinished();
|
||||||
} else {
|
} else {
|
||||||
emit changeSettingsErrorOccurred(tr("Backup file is corrupted"));
|
emit changeSettingsErrorOccurred(tr("Backup file is corrupted"));
|
||||||
|
@ -194,8 +167,6 @@ void SettingsController::clearSettings()
|
||||||
m_appSplitTunnelingModel->setRouteMode(Settings::AppsRouteMode::VpnAllExceptApps);
|
m_appSplitTunnelingModel->setRouteMode(Settings::AppsRouteMode::VpnAllExceptApps);
|
||||||
m_appSplitTunnelingModel->toggleSplitTunneling(false);
|
m_appSplitTunnelingModel->toggleSplitTunneling(false);
|
||||||
|
|
||||||
toggleAutoStart(false);
|
|
||||||
|
|
||||||
emit changeSettingsFinished(tr("All settings have been reset to default values"));
|
emit changeSettingsFinished(tr("All settings have been reset to default values"));
|
||||||
|
|
||||||
#ifdef Q_OS_IOS
|
#ifdef Q_OS_IOS
|
||||||
|
|
|
@ -75,12 +75,6 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case IsProtocolSelectionSupportedRole: {
|
|
||||||
if (m_accountInfoData.supportedProtocols.size() > 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
@ -101,10 +95,6 @@ void ApiAccountInfoModel::updateModel(const QJsonObject &accountInfoObject, cons
|
||||||
|
|
||||||
accountInfoData.configType = apiUtils::getConfigType(serverConfig);
|
accountInfoData.configType = apiUtils::getConfigType(serverConfig);
|
||||||
|
|
||||||
for (const auto &protocol : accountInfoObject.value(apiDefs::key::supportedProtocols).toArray()) {
|
|
||||||
accountInfoData.supportedProtocols.push_back(protocol.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_accountInfoData = accountInfoData;
|
m_accountInfoData = accountInfoData;
|
||||||
|
|
||||||
m_supportInfo = accountInfoObject.value(apiDefs::key::supportInfo).toObject();
|
m_supportInfo = accountInfoObject.value(apiDefs::key::supportInfo).toObject();
|
||||||
|
@ -169,7 +159,6 @@ QHash<int, QByteArray> ApiAccountInfoModel::roleNames() const
|
||||||
roles[ServiceDescriptionRole] = "serviceDescription";
|
roles[ServiceDescriptionRole] = "serviceDescription";
|
||||||
roles[IsComponentVisibleRole] = "isComponentVisible";
|
roles[IsComponentVisibleRole] = "isComponentVisible";
|
||||||
roles[HasExpiredWorkerRole] = "hasExpiredWorker";
|
roles[HasExpiredWorkerRole] = "hasExpiredWorker";
|
||||||
roles[IsProtocolSelectionSupportedRole] = "isProtocolSelectionSupported";
|
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,7 @@ public:
|
||||||
ServiceDescriptionRole,
|
ServiceDescriptionRole,
|
||||||
EndDateRole,
|
EndDateRole,
|
||||||
IsComponentVisibleRole,
|
IsComponentVisibleRole,
|
||||||
HasExpiredWorkerRole,
|
HasExpiredWorkerRole
|
||||||
IsProtocolSelectionSupportedRole
|
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ApiAccountInfoModel(QObject *parent = nullptr);
|
explicit ApiAccountInfoModel(QObject *parent = nullptr);
|
||||||
|
@ -52,8 +51,6 @@ private:
|
||||||
int maxDeviceCount;
|
int maxDeviceCount;
|
||||||
|
|
||||||
apiDefs::ConfigType configType;
|
apiDefs::ConfigType configType;
|
||||||
|
|
||||||
QStringList supportedProtocols;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
AccountInfoData m_accountInfoData;
|
AccountInfoData m_accountInfoData;
|
||||||
|
|
|
@ -69,7 +69,7 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
||||||
"Access all websites and online resources. Speeds up to %1 Mbps.")
|
"Access all websites and online resources. Speeds up to %1 Mbps.")
|
||||||
.arg(speed);
|
.arg(speed);
|
||||||
} else if (serviceType == serviceType::amneziaFree) {
|
} else if (serviceType == serviceType::amneziaFree) {
|
||||||
QString description = tr("Amnezia Free provides unlimited, free access to a basic set of websites and apps, including Facebook, Instagram, Twitter (X), Discord, Telegram, and more. YouTube is not included in the free plan.");
|
QString description = tr("AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan.");
|
||||||
if (!isServiceAvailable) {
|
if (!isServiceAvailable) {
|
||||||
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, "
|
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, "
|
||||||
"return to the previous screen, and try again.</a>");
|
"return to the previous screen, and try again.</a>");
|
||||||
|
@ -82,7 +82,7 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
||||||
return tr("Amnezia Premium is classic VPN for for seamless work, downloading large files, and watching videos. "
|
return tr("Amnezia Premium is classic VPN for for seamless work, downloading large files, and watching videos. "
|
||||||
"Access all websites and online resources.");
|
"Access all websites and online resources.");
|
||||||
} else {
|
} else {
|
||||||
return tr("Amnezia Free provides unlimited, free access to a basic set of websites and apps, including Facebook, Instagram, Twitter (X), Discord, Telegram, and more. YouTube is not included in the free plan.");
|
return tr("AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case IsServiceAvailableRole: {
|
case IsServiceAvailableRole: {
|
||||||
|
|
|
@ -28,17 +28,7 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
|
||||||
case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||||
case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||||
case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||||
case Roles::ClientSpecialJunk1Role: m_clientProtocolConfig.insert(config_key::specialJunk1, value.toString()); break;
|
|
||||||
case Roles::ClientSpecialJunk2Role: m_clientProtocolConfig.insert(config_key::specialJunk2, value.toString()); break;
|
|
||||||
case Roles::ClientSpecialJunk3Role: m_clientProtocolConfig.insert(config_key::specialJunk3, value.toString()); break;
|
|
||||||
case Roles::ClientSpecialJunk4Role: m_clientProtocolConfig.insert(config_key::specialJunk4, value.toString()); break;
|
|
||||||
case Roles::ClientSpecialJunk5Role: m_clientProtocolConfig.insert(config_key::specialJunk5, value.toString()); break;
|
|
||||||
case Roles::ClientControlledJunk1Role: m_clientProtocolConfig.insert(config_key::controlledJunk1, value.toString()); break;
|
|
||||||
case Roles::ClientControlledJunk2Role: m_clientProtocolConfig.insert(config_key::controlledJunk2, value.toString()); break;
|
|
||||||
case Roles::ClientControlledJunk3Role: m_clientProtocolConfig.insert(config_key::controlledJunk3, value.toString()); break;
|
|
||||||
case Roles::ClientSpecialHandshakeTimeoutRole:
|
|
||||||
m_clientProtocolConfig.insert(config_key::specialHandshakeTimeout, value.toString());
|
|
||||||
break;
|
|
||||||
case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||||
case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||||
case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||||
|
@ -46,12 +36,6 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
|
||||||
case Roles::ServerResponsePacketJunkSizeRole:
|
case Roles::ServerResponsePacketJunkSizeRole:
|
||||||
m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
|
m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
|
||||||
break;
|
break;
|
||||||
// case Roles::ServerCookieReplyPacketJunkSizeRole:
|
|
||||||
// m_serverProtocolConfig.insert(config_key::cookieReplyPacketJunkSize, value.toString());
|
|
||||||
// break;
|
|
||||||
// case Roles::ServerTransportPacketJunkSizeRole:
|
|
||||||
// m_serverProtocolConfig.insert(config_key::transportPacketJunkSize, value.toString());
|
|
||||||
// break;
|
|
||||||
case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
|
case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
|
||||||
case Roles::ServerResponsePacketMagicHeaderRole:
|
case Roles::ServerResponsePacketMagicHeaderRole:
|
||||||
m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
|
m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
|
||||||
|
@ -82,23 +66,12 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
|
||||||
case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount);
|
case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount);
|
||||||
case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize);
|
case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize);
|
||||||
case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize);
|
case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize);
|
||||||
case Roles::ClientSpecialJunk1Role: return m_clientProtocolConfig.value(config_key::specialJunk1);
|
|
||||||
case Roles::ClientSpecialJunk2Role: return m_clientProtocolConfig.value(config_key::specialJunk2);
|
|
||||||
case Roles::ClientSpecialJunk3Role: return m_clientProtocolConfig.value(config_key::specialJunk3);
|
|
||||||
case Roles::ClientSpecialJunk4Role: return m_clientProtocolConfig.value(config_key::specialJunk4);
|
|
||||||
case Roles::ClientSpecialJunk5Role: return m_clientProtocolConfig.value(config_key::specialJunk5);
|
|
||||||
case Roles::ClientControlledJunk1Role: return m_clientProtocolConfig.value(config_key::controlledJunk1);
|
|
||||||
case Roles::ClientControlledJunk2Role: return m_clientProtocolConfig.value(config_key::controlledJunk2);
|
|
||||||
case Roles::ClientControlledJunk3Role: return m_clientProtocolConfig.value(config_key::controlledJunk3);
|
|
||||||
case Roles::ClientSpecialHandshakeTimeoutRole: return m_clientProtocolConfig.value(config_key::specialHandshakeTimeout);
|
|
||||||
|
|
||||||
case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount);
|
case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount);
|
||||||
case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize);
|
case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize);
|
||||||
case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize);
|
case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize);
|
||||||
case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize);
|
case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize);
|
||||||
case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize);
|
case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize);
|
||||||
// case Roles::ServerCookieReplyPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::cookieReplyPacketJunkSize);
|
|
||||||
// case Roles::ServerTransportPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::transportPacketJunkSize);
|
|
||||||
case Roles::ServerInitPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::initPacketMagicHeader);
|
case Roles::ServerInitPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::initPacketMagicHeader);
|
||||||
case Roles::ServerResponsePacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::responsePacketMagicHeader);
|
case Roles::ServerResponsePacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::responsePacketMagicHeader);
|
||||||
case Roles::ServerUnderloadPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::underloadPacketMagicHeader);
|
case Roles::ServerUnderloadPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::underloadPacketMagicHeader);
|
||||||
|
@ -121,8 +94,7 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
|
||||||
m_serverProtocolConfig.insert(config_key::transport_proto,
|
m_serverProtocolConfig.insert(config_key::transport_proto,
|
||||||
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||||
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
||||||
m_serverProtocolConfig[config_key::subnet_address] =
|
m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
||||||
serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
|
||||||
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||||
m_serverProtocolConfig[config_key::junkPacketCount] =
|
m_serverProtocolConfig[config_key::junkPacketCount] =
|
||||||
serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||||
|
@ -134,10 +106,6 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
|
||||||
serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||||
m_serverProtocolConfig[config_key::responsePacketJunkSize] =
|
m_serverProtocolConfig[config_key::responsePacketJunkSize] =
|
||||||
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||||
// m_serverProtocolConfig[config_key::cookieReplyPacketJunkSize] =
|
|
||||||
// serverProtocolConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize);
|
|
||||||
// m_serverProtocolConfig[config_key::transportPacketJunkSize] =
|
|
||||||
// serverProtocolConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize);
|
|
||||||
m_serverProtocolConfig[config_key::initPacketMagicHeader] =
|
m_serverProtocolConfig[config_key::initPacketMagicHeader] =
|
||||||
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||||
m_serverProtocolConfig[config_key::responsePacketMagicHeader] =
|
m_serverProtocolConfig[config_key::responsePacketMagicHeader] =
|
||||||
|
@ -156,24 +124,6 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
|
||||||
clientProtocolConfig.value(config_key::junkPacketMinSize).toString(m_serverProtocolConfig[config_key::junkPacketMinSize].toString());
|
clientProtocolConfig.value(config_key::junkPacketMinSize).toString(m_serverProtocolConfig[config_key::junkPacketMinSize].toString());
|
||||||
m_clientProtocolConfig[config_key::junkPacketMaxSize] =
|
m_clientProtocolConfig[config_key::junkPacketMaxSize] =
|
||||||
clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(m_serverProtocolConfig[config_key::junkPacketMaxSize].toString());
|
clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(m_serverProtocolConfig[config_key::junkPacketMaxSize].toString());
|
||||||
m_clientProtocolConfig[config_key::specialJunk1] =
|
|
||||||
clientProtocolConfig.value(config_key::specialJunk1).toString(protocols::awg::defaultSpecialJunk1);
|
|
||||||
m_clientProtocolConfig[config_key::specialJunk2] =
|
|
||||||
clientProtocolConfig.value(config_key::specialJunk2).toString(protocols::awg::defaultSpecialJunk2);
|
|
||||||
m_clientProtocolConfig[config_key::specialJunk3] =
|
|
||||||
clientProtocolConfig.value(config_key::specialJunk3).toString(protocols::awg::defaultSpecialJunk3);
|
|
||||||
m_clientProtocolConfig[config_key::specialJunk4] =
|
|
||||||
clientProtocolConfig.value(config_key::specialJunk4).toString(protocols::awg::defaultSpecialJunk4);
|
|
||||||
m_clientProtocolConfig[config_key::specialJunk5] =
|
|
||||||
clientProtocolConfig.value(config_key::specialJunk5).toString(protocols::awg::defaultSpecialJunk5);
|
|
||||||
m_clientProtocolConfig[config_key::controlledJunk1] =
|
|
||||||
clientProtocolConfig.value(config_key::controlledJunk1).toString(protocols::awg::defaultControlledJunk1);
|
|
||||||
m_clientProtocolConfig[config_key::controlledJunk2] =
|
|
||||||
clientProtocolConfig.value(config_key::controlledJunk2).toString(protocols::awg::defaultControlledJunk2);
|
|
||||||
m_clientProtocolConfig[config_key::controlledJunk3] =
|
|
||||||
clientProtocolConfig.value(config_key::controlledJunk3).toString(protocols::awg::defaultControlledJunk3);
|
|
||||||
m_clientProtocolConfig[config_key::specialHandshakeTimeout] =
|
|
||||||
clientProtocolConfig.value(config_key::specialHandshakeTimeout).toString(protocols::awg::defaultSpecialHandshakeTimeout);
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,15 +141,6 @@ QJsonObject AwgConfigModel::getConfig()
|
||||||
jsonConfig[config_key::junkPacketCount] = m_clientProtocolConfig[config_key::junkPacketCount];
|
jsonConfig[config_key::junkPacketCount] = m_clientProtocolConfig[config_key::junkPacketCount];
|
||||||
jsonConfig[config_key::junkPacketMinSize] = m_clientProtocolConfig[config_key::junkPacketMinSize];
|
jsonConfig[config_key::junkPacketMinSize] = m_clientProtocolConfig[config_key::junkPacketMinSize];
|
||||||
jsonConfig[config_key::junkPacketMaxSize] = m_clientProtocolConfig[config_key::junkPacketMaxSize];
|
jsonConfig[config_key::junkPacketMaxSize] = m_clientProtocolConfig[config_key::junkPacketMaxSize];
|
||||||
jsonConfig[config_key::specialJunk1] = m_clientProtocolConfig[config_key::specialJunk1];
|
|
||||||
jsonConfig[config_key::specialJunk2] = m_clientProtocolConfig[config_key::specialJunk2];
|
|
||||||
jsonConfig[config_key::specialJunk3] = m_clientProtocolConfig[config_key::specialJunk3];
|
|
||||||
jsonConfig[config_key::specialJunk4] = m_clientProtocolConfig[config_key::specialJunk4];
|
|
||||||
jsonConfig[config_key::specialJunk5] = m_clientProtocolConfig[config_key::specialJunk5];
|
|
||||||
jsonConfig[config_key::controlledJunk1] = m_clientProtocolConfig[config_key::controlledJunk1];
|
|
||||||
jsonConfig[config_key::controlledJunk2] = m_clientProtocolConfig[config_key::controlledJunk2];
|
|
||||||
jsonConfig[config_key::controlledJunk3] = m_clientProtocolConfig[config_key::controlledJunk3];
|
|
||||||
jsonConfig[config_key::specialHandshakeTimeout] = m_clientProtocolConfig[config_key::specialHandshakeTimeout];
|
|
||||||
|
|
||||||
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||||
}
|
}
|
||||||
|
@ -218,17 +159,6 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2)
|
||||||
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
|
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2, const int s3, const int s4)
|
|
||||||
// {
|
|
||||||
// int initSize = AwgConstant::messageInitiationSize + s1;
|
|
||||||
// int responseSize = AwgConstant::messageResponseSize + s2;
|
|
||||||
// int cookieSize = AwgConstant::messageCookieReplySize + s3;
|
|
||||||
// int transportSize = AwgConstant::messageTransportSize + s4;
|
|
||||||
|
|
||||||
// return (initSize == responseSize || initSize == cookieSize || initSize == transportSize || responseSize == cookieSize
|
|
||||||
// || responseSize == transportSize || cookieSize == transportSize);
|
|
||||||
// }
|
|
||||||
|
|
||||||
bool AwgConfigModel::isServerSettingsEqual()
|
bool AwgConfigModel::isServerSettingsEqual()
|
||||||
{
|
{
|
||||||
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
||||||
|
@ -248,24 +178,12 @@ QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
||||||
roles[ClientJunkPacketCountRole] = "clientJunkPacketCount";
|
roles[ClientJunkPacketCountRole] = "clientJunkPacketCount";
|
||||||
roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize";
|
roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize";
|
||||||
roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize";
|
roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize";
|
||||||
roles[ClientSpecialJunk1Role] = "clientSpecialJunk1";
|
|
||||||
roles[ClientSpecialJunk2Role] = "clientSpecialJunk2";
|
|
||||||
roles[ClientSpecialJunk3Role] = "clientSpecialJunk3";
|
|
||||||
roles[ClientSpecialJunk4Role] = "clientSpecialJunk4";
|
|
||||||
roles[ClientSpecialJunk5Role] = "clientSpecialJunk5";
|
|
||||||
roles[ClientControlledJunk1Role] = "clientControlledJunk1";
|
|
||||||
roles[ClientControlledJunk2Role] = "clientControlledJunk2";
|
|
||||||
roles[ClientControlledJunk3Role] = "clientControlledJunk3";
|
|
||||||
roles[ClientSpecialHandshakeTimeoutRole] = "clientSpecialHandshakeTimeout";
|
|
||||||
|
|
||||||
roles[ServerJunkPacketCountRole] = "serverJunkPacketCount";
|
roles[ServerJunkPacketCountRole] = "serverJunkPacketCount";
|
||||||
roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize";
|
roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize";
|
||||||
roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize";
|
roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize";
|
||||||
roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize";
|
roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize";
|
||||||
roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize";
|
roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize";
|
||||||
roles[ServerCookieReplyPacketJunkSizeRole] = "serverCookieReplyPacketJunkSize";
|
|
||||||
roles[ServerTransportPacketJunkSizeRole] = "serverTransportPacketJunkSize";
|
|
||||||
|
|
||||||
roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader";
|
roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader";
|
||||||
roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader";
|
roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader";
|
||||||
roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader";
|
roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader";
|
||||||
|
@ -282,16 +200,6 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
|
||||||
clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||||
clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||||
clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||||
clientSpecialJunk1 = clientProtocolConfig.value(config_key::specialJunk1).toString(protocols::awg::defaultSpecialJunk1);
|
|
||||||
clientSpecialJunk2 = clientProtocolConfig.value(config_key::specialJunk2).toString(protocols::awg::defaultSpecialJunk2);
|
|
||||||
clientSpecialJunk3 = clientProtocolConfig.value(config_key::specialJunk3).toString(protocols::awg::defaultSpecialJunk3);
|
|
||||||
clientSpecialJunk4 = clientProtocolConfig.value(config_key::specialJunk4).toString(protocols::awg::defaultSpecialJunk4);
|
|
||||||
clientSpecialJunk5 = clientProtocolConfig.value(config_key::specialJunk5).toString(protocols::awg::defaultSpecialJunk5);
|
|
||||||
clientControlledJunk1 = clientProtocolConfig.value(config_key::controlledJunk1).toString(protocols::awg::defaultControlledJunk1);
|
|
||||||
clientControlledJunk2 = clientProtocolConfig.value(config_key::controlledJunk2).toString(protocols::awg::defaultControlledJunk2);
|
|
||||||
clientControlledJunk3 = clientProtocolConfig.value(config_key::controlledJunk3).toString(protocols::awg::defaultControlledJunk3);
|
|
||||||
clientSpecialHandshakeTimeout =
|
|
||||||
clientProtocolConfig.value(config_key::specialHandshakeTimeout).toString(protocols::awg::defaultSpecialHandshakeTimeout);
|
|
||||||
|
|
||||||
subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
||||||
port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||||
|
@ -301,10 +209,6 @@ AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
|
||||||
serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||||
serverResponsePacketJunkSize =
|
serverResponsePacketJunkSize =
|
||||||
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||||
// serverCookieReplyPacketJunkSize =
|
|
||||||
// serverProtocolConfig.value(config_key::cookieReplyPacketJunkSize).toString(protocols::awg::defaultCookieReplyPacketJunkSize);
|
|
||||||
// serverTransportPacketJunkSize =
|
|
||||||
// serverProtocolConfig.value(config_key::transportPacketJunkSize).toString(protocols::awg::defaultTransportPacketJunkSize);
|
|
||||||
serverInitPacketMagicHeader =
|
serverInitPacketMagicHeader =
|
||||||
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||||
serverResponsePacketMagicHeader =
|
serverResponsePacketMagicHeader =
|
||||||
|
@ -320,8 +224,6 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
||||||
if (subnetAddress != other.subnetAddress || port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|
if (subnetAddress != other.subnetAddress || port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|
||||||
|| serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|
|| serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|
||||||
|| serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|
|| serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|
||||||
// || serverCookieReplyPacketJunkSize != other.serverCookieReplyPacketJunkSize
|
|
||||||
// || serverTransportPacketJunkSize != other.serverTransportPacketJunkSize
|
|
||||||
|| serverInitPacketMagicHeader != other.serverInitPacketMagicHeader
|
|| serverInitPacketMagicHeader != other.serverInitPacketMagicHeader
|
||||||
|| serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader
|
|| serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader
|
||||||
|| serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader
|
|| serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader
|
||||||
|
@ -334,12 +236,7 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
||||||
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
|
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
|
||||||
{
|
{
|
||||||
if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount
|
if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount
|
||||||
|| clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize
|
|| clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) {
|
||||||
|| clientSpecialJunk1 != other.clientSpecialJunk1 || clientSpecialJunk2 != other.clientSpecialJunk2
|
|
||||||
|| clientSpecialJunk3 != other.clientSpecialJunk3 || clientSpecialJunk4 != other.clientSpecialJunk4
|
|
||||||
|| clientSpecialJunk5 != other.clientSpecialJunk5 || clientControlledJunk1 != other.clientControlledJunk1
|
|
||||||
|| clientControlledJunk2 != other.clientControlledJunk2 || clientControlledJunk3 != other.clientControlledJunk3
|
|
||||||
|| clientSpecialHandshakeTimeout != other.clientSpecialHandshakeTimeout) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -6,12 +6,9 @@
|
||||||
|
|
||||||
#include "containers/containers_defs.h"
|
#include "containers/containers_defs.h"
|
||||||
|
|
||||||
namespace AwgConstant
|
namespace AwgConstant {
|
||||||
{
|
|
||||||
const int messageInitiationSize = 148;
|
const int messageInitiationSize = 148;
|
||||||
const int messageResponseSize = 92;
|
const int messageResponseSize = 92;
|
||||||
const int messageCookieReplySize = 64;
|
|
||||||
const int messageTransportSize = 32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AwgConfig
|
struct AwgConfig
|
||||||
|
@ -25,23 +22,12 @@ struct AwgConfig
|
||||||
QString clientJunkPacketCount;
|
QString clientJunkPacketCount;
|
||||||
QString clientJunkPacketMinSize;
|
QString clientJunkPacketMinSize;
|
||||||
QString clientJunkPacketMaxSize;
|
QString clientJunkPacketMaxSize;
|
||||||
QString clientSpecialJunk1;
|
|
||||||
QString clientSpecialJunk2;
|
|
||||||
QString clientSpecialJunk3;
|
|
||||||
QString clientSpecialJunk4;
|
|
||||||
QString clientSpecialJunk5;
|
|
||||||
QString clientControlledJunk1;
|
|
||||||
QString clientControlledJunk2;
|
|
||||||
QString clientControlledJunk3;
|
|
||||||
QString clientSpecialHandshakeTimeout;
|
|
||||||
|
|
||||||
QString serverJunkPacketCount;
|
QString serverJunkPacketCount;
|
||||||
QString serverJunkPacketMinSize;
|
QString serverJunkPacketMinSize;
|
||||||
QString serverJunkPacketMaxSize;
|
QString serverJunkPacketMaxSize;
|
||||||
QString serverInitPacketJunkSize;
|
QString serverInitPacketJunkSize;
|
||||||
QString serverResponsePacketJunkSize;
|
QString serverResponsePacketJunkSize;
|
||||||
QString serverCookieReplyPacketJunkSize;
|
|
||||||
QString serverTransportPacketJunkSize;
|
|
||||||
QString serverInitPacketMagicHeader;
|
QString serverInitPacketMagicHeader;
|
||||||
QString serverResponsePacketMagicHeader;
|
QString serverResponsePacketMagicHeader;
|
||||||
QString serverUnderloadPacketMagicHeader;
|
QString serverUnderloadPacketMagicHeader;
|
||||||
|
@ -49,6 +35,7 @@ struct AwgConfig
|
||||||
|
|
||||||
bool hasEqualServerSettings(const AwgConfig &other) const;
|
bool hasEqualServerSettings(const AwgConfig &other) const;
|
||||||
bool hasEqualClientSettings(const AwgConfig &other) const;
|
bool hasEqualClientSettings(const AwgConfig &other) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AwgConfigModel : public QAbstractListModel
|
class AwgConfigModel : public QAbstractListModel
|
||||||
|
@ -64,28 +51,16 @@ public:
|
||||||
ClientJunkPacketCountRole,
|
ClientJunkPacketCountRole,
|
||||||
ClientJunkPacketMinSizeRole,
|
ClientJunkPacketMinSizeRole,
|
||||||
ClientJunkPacketMaxSizeRole,
|
ClientJunkPacketMaxSizeRole,
|
||||||
ClientSpecialJunk1Role,
|
|
||||||
ClientSpecialJunk2Role,
|
|
||||||
ClientSpecialJunk3Role,
|
|
||||||
ClientSpecialJunk4Role,
|
|
||||||
ClientSpecialJunk5Role,
|
|
||||||
ClientControlledJunk1Role,
|
|
||||||
ClientControlledJunk2Role,
|
|
||||||
ClientControlledJunk3Role,
|
|
||||||
ClientSpecialHandshakeTimeoutRole,
|
|
||||||
|
|
||||||
ServerJunkPacketCountRole,
|
ServerJunkPacketCountRole,
|
||||||
ServerJunkPacketMinSizeRole,
|
ServerJunkPacketMinSizeRole,
|
||||||
ServerJunkPacketMaxSizeRole,
|
ServerJunkPacketMaxSizeRole,
|
||||||
ServerInitPacketJunkSizeRole,
|
ServerInitPacketJunkSizeRole,
|
||||||
ServerResponsePacketJunkSizeRole,
|
ServerResponsePacketJunkSizeRole,
|
||||||
ServerCookieReplyPacketJunkSizeRole,
|
|
||||||
ServerTransportPacketJunkSizeRole,
|
|
||||||
|
|
||||||
ServerInitPacketMagicHeaderRole,
|
ServerInitPacketMagicHeaderRole,
|
||||||
ServerResponsePacketMagicHeaderRole,
|
ServerResponsePacketMagicHeaderRole,
|
||||||
ServerUnderloadPacketMagicHeaderRole,
|
ServerUnderloadPacketMagicHeaderRole,
|
||||||
ServerTransportPacketMagicHeaderRole,
|
ServerTransportPacketMagicHeaderRole
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit AwgConfigModel(QObject *parent = nullptr);
|
explicit AwgConfigModel(QObject *parent = nullptr);
|
||||||
|
@ -100,7 +75,7 @@ public slots:
|
||||||
QJsonObject getConfig();
|
QJsonObject getConfig();
|
||||||
|
|
||||||
bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
|
bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
|
||||||
bool isPacketSizeEqual(const int s1, const int s2/*, const int s3, const int s4*/);
|
bool isPacketSizeEqual(const int s1, const int s2);
|
||||||
|
|
||||||
bool isServerSettingsEqual();
|
bool isServerSettingsEqual();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ bool XrayConfigModel::setData(const QModelIndex &index, const QVariant &value, i
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::SiteRole: m_protocolConfig.insert(config_key::site, value.toString()); break;
|
case Roles::SiteRole: m_protocolConfig.insert(config_key::site, value.toString()); break;
|
||||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dataChanged(index, index, QList { role });
|
emit dataChanged(index, index, QList { role });
|
||||||
|
@ -35,7 +34,6 @@ QVariant XrayConfigModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Roles::SiteRole: return m_protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite);
|
case Roles::SiteRole: return m_protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite);
|
||||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::xray::defaultPort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
@ -69,7 +67,6 @@ QHash<int, QByteArray> XrayConfigModel::roleNames() const
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
roles[SiteRole] = "site";
|
roles[SiteRole] = "site";
|
||||||
roles[PortRole] = "port";
|
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@ class XrayConfigModel : public QAbstractListModel
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
SiteRole,
|
SiteRole
|
||||||
PortRole
|
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit XrayConfigModel(QObject *parent = nullptr);
|
explicit XrayConfigModel(QObject *parent = nullptr);
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#include <AmneziaVPN-Swift.h>
|
#include <AmneziaVPN-Swift.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "core/api/apiUtils.h"
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
namespace configKey
|
namespace configKey
|
||||||
|
@ -68,7 +66,6 @@ bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int
|
||||||
} else {
|
} else {
|
||||||
server.insert(config_key::description, value.toString());
|
server.insert(config_key::description, value.toString());
|
||||||
}
|
}
|
||||||
server.insert(config_key::nameOverriddenByUser, true);
|
|
||||||
m_settings->editServer(index.row(), server);
|
m_settings->editServer(index.row(), server);
|
||||||
m_servers.replace(index.row(), server);
|
m_servers.replace(index.row(), server);
|
||||||
if (index.row() == m_defaultServerIndex) {
|
if (index.row() == m_defaultServerIndex) {
|
||||||
|
@ -351,25 +348,6 @@ void ServersModel::removeServer()
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::removeServer(const int serverIndex)
|
|
||||||
{
|
|
||||||
beginResetModel();
|
|
||||||
m_settings->removeServer(serverIndex);
|
|
||||||
m_servers = m_settings->serversArray();
|
|
||||||
|
|
||||||
if (m_settings->defaultServerIndex() == serverIndex) {
|
|
||||||
setDefaultServerIndex(0);
|
|
||||||
} else if (m_settings->defaultServerIndex() > serverIndex) {
|
|
||||||
setDefaultServerIndex(m_settings->defaultServerIndex() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_settings->serversCount() == 0) {
|
|
||||||
setDefaultServerIndex(-1);
|
|
||||||
}
|
|
||||||
setProcessedServerIndex(m_defaultServerIndex);
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray> ServersModel::roleNames() const
|
QHash<int, QByteArray> ServersModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
@ -429,7 +407,7 @@ void ServersModel::updateDefaultServerContainersModel()
|
||||||
emit defaultServerContainersUpdated(containers);
|
emit defaultServerContainersUpdated(containers);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ServersModel::getServerConfig(const int serverIndex) const
|
QJsonObject ServersModel::getServerConfig(const int serverIndex)
|
||||||
{
|
{
|
||||||
return m_servers.at(serverIndex).toObject();
|
return m_servers.at(serverIndex).toObject();
|
||||||
}
|
}
|
||||||
|
@ -816,8 +794,3 @@ const QString ServersModel::getDefaultServerImagePathCollapsed()
|
||||||
}
|
}
|
||||||
return QString("qrc:/countriesFlags/images/flagKit/%1.svg").arg(countryCode.toUpper());
|
return QString("qrc:/countriesFlags/images/flagKit/%1.svg").arg(countryCode.toUpper());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServersModel::processedServerIsPremium() const
|
|
||||||
{
|
|
||||||
return apiUtils::isPremiumServer(getServerConfig(m_processedServerIndex));
|
|
||||||
}
|
|
||||||
|
|
|
@ -63,9 +63,6 @@ public:
|
||||||
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged)
|
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged)
|
||||||
|
|
||||||
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
|
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
|
||||||
Q_PROPERTY(bool processedServerIsPremium READ processedServerIsPremium NOTIFY processedServerChanged)
|
|
||||||
|
|
||||||
bool processedServerIsPremium() const;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setDefaultServerIndex(const int index);
|
void setDefaultServerIndex(const int index);
|
||||||
|
@ -93,9 +90,8 @@ public slots:
|
||||||
void addServer(const QJsonObject &server);
|
void addServer(const QJsonObject &server);
|
||||||
void editServer(const QJsonObject &server, const int serverIndex);
|
void editServer(const QJsonObject &server, const int serverIndex);
|
||||||
void removeServer();
|
void removeServer();
|
||||||
void removeServer(const int serverIndex);
|
|
||||||
|
|
||||||
QJsonObject getServerConfig(const int serverIndex) const;
|
QJsonObject getServerConfig(const int serverIndex);
|
||||||
|
|
||||||
void reloadDefaultServerContainerConfig();
|
void reloadDefaultServerContainerConfig();
|
||||||
void updateContainerConfig(const int containerIndex, const QJsonObject config);
|
void updateContainerConfig(const int containerIndex, const QJsonObject config);
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
|
|
||||||
import QtCore
|
|
||||||
|
|
||||||
import PageEnum 1.0
|
|
||||||
import Style 1.0
|
|
||||||
|
|
||||||
import "./"
|
|
||||||
import "../Controls2"
|
|
||||||
import "../Controls2/TextTypes"
|
|
||||||
import "../Config"
|
|
||||||
import "../Components"
|
|
||||||
|
|
||||||
DrawerType2 {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
expandedHeight: parent.height * 0.9
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ApiPremV1MigrationController
|
|
||||||
|
|
||||||
function onErrorOccurred(error, goToPageHome) {
|
|
||||||
PageController.showErrorMessage(error)
|
|
||||||
root.closeTriggered()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expandedStateContent: Item {
|
|
||||||
implicitHeight: root.expandedHeight
|
|
||||||
|
|
||||||
ListViewType {
|
|
||||||
id: listView
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
model: 1 // fake model to force the ListView to be created without a model
|
|
||||||
snapMode: ListView.NoSnap
|
|
||||||
|
|
||||||
header: ColumnLayout {
|
|
||||||
width: listView.width
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
id: header
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 20
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Switch to the new Amnezia Premium subscription")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: ColumnLayout {
|
|
||||||
width: listView.width
|
|
||||||
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
|
|
||||||
ParagraphTextType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 24
|
|
||||||
Layout.bottomMargin: 24
|
|
||||||
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
textFormat: Text.RichText
|
|
||||||
text: {
|
|
||||||
var str = qsTr("We'll preserve all remaining days of your current subscription and give you an extra month as a thank you. ")
|
|
||||||
str += qsTr("This new subscription type will be actively developed with more locations and features added regularly. Currently available:")
|
|
||||||
str += "<ul style='margin-left: -16px;'>"
|
|
||||||
str += qsTr("<li>13 locations (with more coming soon)</li>")
|
|
||||||
str += qsTr("<li>Easier switching between countries in the app</li>")
|
|
||||||
str += qsTr("<li>Personal dashboard to manage your subscription</li>")
|
|
||||||
str += "</ul>"
|
|
||||||
str += qsTr("Old keys will be deactivated after switching.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: emailLabel
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
borderColor: AmneziaStyle.color.mutedGray
|
|
||||||
headerTextColor: AmneziaStyle.color.paleGray
|
|
||||||
|
|
||||||
headerText: qsTr("Email")
|
|
||||||
textField.placeholderText: qsTr("mail@example.com")
|
|
||||||
|
|
||||||
|
|
||||||
textField.onFocusChanged: {
|
|
||||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ApiPremV1MigrationController
|
|
||||||
|
|
||||||
function onNoSubscriptionToMigrate() {
|
|
||||||
emailLabel.errorText = qsTr("No old format subscriptions for a given email")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CaptionTextType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
color: AmneziaStyle.color.mutedGray
|
|
||||||
|
|
||||||
text: qsTr("Enter the email you used for your current subscription")
|
|
||||||
}
|
|
||||||
|
|
||||||
ApiPremV1SubListDrawer {
|
|
||||||
id: apiPremV1SubListDrawer
|
|
||||||
parent: root
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
OtpCodeDrawer {
|
|
||||||
id: otpCodeDrawer
|
|
||||||
parent: root
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
|
||||||
id: yesButton
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 32
|
|
||||||
|
|
||||||
text: qsTr("Continue")
|
|
||||||
|
|
||||||
clickedFunc: function() {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
ApiPremV1MigrationController.getSubscriptionList(emailLabel.textField.text)
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
|
||||||
id: noButton
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
defaultColor: AmneziaStyle.color.transparent
|
|
||||||
hoveredColor: AmneziaStyle.color.translucentWhite
|
|
||||||
pressedColor: AmneziaStyle.color.sheerWhite
|
|
||||||
disabledColor: AmneziaStyle.color.mutedGray
|
|
||||||
textColor: AmneziaStyle.color.paleGray
|
|
||||||
borderWidth: 1
|
|
||||||
|
|
||||||
text: qsTr("Remind me later")
|
|
||||||
|
|
||||||
clickedFunc: function() {
|
|
||||||
root.closeTriggered()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
Layout.topMargin: 32
|
|
||||||
Layout.bottomMargin: 32
|
|
||||||
implicitHeight: 32
|
|
||||||
|
|
||||||
defaultColor: "transparent"
|
|
||||||
hoveredColor: AmneziaStyle.color.translucentWhite
|
|
||||||
pressedColor: AmneziaStyle.color.sheerWhite
|
|
||||||
textColor: AmneziaStyle.color.vibrantRed
|
|
||||||
|
|
||||||
text: qsTr("Don't remind me again")
|
|
||||||
|
|
||||||
clickedFunc: function() {
|
|
||||||
var headerText = qsTr("No more reminders? You can always switch to the new format in the server settings")
|
|
||||||
var yesButtonText = qsTr("Continue")
|
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
ApiPremV1MigrationController.disablePremV1MigrationReminder()
|
|
||||||
root.closeTriggered()
|
|
||||||
}
|
|
||||||
var noButtonFunction = function() {
|
|
||||||
}
|
|
||||||
|
|
||||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
|
|
||||||
import Style 1.0
|
|
||||||
|
|
||||||
import "../Controls2"
|
|
||||||
import "../Controls2/TextTypes"
|
|
||||||
import "../Config"
|
|
||||||
|
|
||||||
DrawerType2 {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ApiPremV1MigrationController
|
|
||||||
|
|
||||||
function onSubscriptionsModelChanged() {
|
|
||||||
if (ApiPremV1MigrationController.subscriptionsModel.length > 1) {
|
|
||||||
root.openTriggered()
|
|
||||||
} else {
|
|
||||||
sendMigrationCode(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendMigrationCode(index) {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
ApiPremV1MigrationController.sendMigrationCode(index)
|
|
||||||
root.closeTriggered()
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
expandedHeight: parent.height * 0.9
|
|
||||||
|
|
||||||
expandedStateContent: Item {
|
|
||||||
implicitHeight: root.expandedHeight
|
|
||||||
|
|
||||||
ListViewType {
|
|
||||||
id: listView
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
model: ApiPremV1MigrationController.subscriptionsModel
|
|
||||||
|
|
||||||
header: ColumnLayout {
|
|
||||||
width: listView.width
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
id: header
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 20
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Choose Subscription")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
implicitWidth: listView.width
|
|
||||||
implicitHeight: delegateContent.implicitHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: delegateContent
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
id: server
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: qsTr("Order ID: ") + modelData.id
|
|
||||||
|
|
||||||
descriptionText: qsTr("Purchase Date: ") + Qt.formatDateTime(new Date(modelData.created_at), "dd.MM.yyyy hh:mm")
|
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
sendMigrationCode(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
|
|
||||||
import "../Controls2"
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
textField.validator: IntValidator { bottom: 0 }
|
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
import QtQuick.Layouts
|
|
||||||
|
|
||||||
import Style 1.0
|
|
||||||
|
|
||||||
import "../Controls2"
|
|
||||||
import "../Controls2/TextTypes"
|
|
||||||
|
|
||||||
import "../Config"
|
|
||||||
|
|
||||||
DrawerType2 {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ApiPremV1MigrationController
|
|
||||||
|
|
||||||
function onOtpSuccessfullySent() {
|
|
||||||
root.openTriggered()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expandedHeight: parent.height * 0.6
|
|
||||||
|
|
||||||
expandedStateContent: Item {
|
|
||||||
implicitHeight: root.expandedHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
id: header
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 20
|
|
||||||
|
|
||||||
headerText: qsTr("OTP code was sent to your email")
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: otpFiled
|
|
||||||
|
|
||||||
borderColor: AmneziaStyle.color.mutedGray
|
|
||||||
headerTextColor: AmneziaStyle.color.paleGray
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
headerText: qsTr("OTP Code")
|
|
||||||
textField.maximumLength: 30
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
|
||||||
id: saveButton
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
text: qsTr("Continue")
|
|
||||||
|
|
||||||
clickedFunc: function() {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
ApiPremV1MigrationController.migrate(otpFiled.textField.text)
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
root.closeTriggered()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
@ -41,7 +39,7 @@ DrawerType2 {
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: root.headerText
|
text: headerText
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
|
@ -50,7 +48,7 @@ DrawerType2 {
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: root.descriptionText
|
text: descriptionText
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
@ -60,11 +58,11 @@ DrawerType2 {
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: root.yesButtonText
|
text: yesButtonText
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
if (root.yesButtonFunction && typeof root.yesButtonFunction === "function") {
|
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
||||||
root.yesButtonFunction()
|
yesButtonFunction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,13 +80,11 @@ DrawerType2 {
|
||||||
textColor: AmneziaStyle.color.paleGray
|
textColor: AmneziaStyle.color.paleGray
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
|
|
||||||
visible: root.noButtonText !== ""
|
text: noButtonText
|
||||||
|
|
||||||
text: root.noButtonText
|
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
if (root.noButtonFunction && typeof root.noButtonFunction === "function") {
|
if (noButtonFunction && typeof noButtonFunction === "function") {
|
||||||
root.noButtonFunction()
|
noButtonFunction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,31 +33,6 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
|
|
||||||
target: ApiPremV1MigrationController
|
|
||||||
|
|
||||||
function onMigrationFinished() {
|
|
||||||
apiPremV1MigrationDrawer.closeTriggered()
|
|
||||||
|
|
||||||
var headerText = qsTr("You've successfully switched to the new Amnezia Premium subscription!")
|
|
||||||
var descriptionText = qsTr("Old keys will no longer work. Please use your new subscription key to connect. \nThank you for staying with us!")
|
|
||||||
var yesButtonText = qsTr("Continue")
|
|
||||||
var noButtonText = ""
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
}
|
|
||||||
var noButtonFunction = function() {
|
|
||||||
}
|
|
||||||
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
|
||||||
|
|
||||||
function onShowMigrationDrawer() {
|
|
||||||
apiPremV1MigrationDrawer.openTriggered()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
objectName: "homeColumnItem"
|
objectName: "homeColumnItem"
|
||||||
|
|
||||||
|
@ -454,9 +429,4 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiPremV1MigrationDrawer {
|
|
||||||
id: apiPremV1MigrationDrawer
|
|
||||||
anchors.fill: parent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,10 +115,14 @@ PageType {
|
||||||
KeyNavigation.tab: junkPacketCountTextField.textField
|
KeyNavigation.tab: junkPacketCountTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: junkPacketCountTextField
|
id: junkPacketCountTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: "Jc - Junk packet count"
|
headerText: "Jc - Junk packet count"
|
||||||
textField.text: clientJunkPacketCount
|
textField.text: clientJunkPacketCount
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== clientJunkPacketCount) {
|
if (textField.text !== clientJunkPacketCount) {
|
||||||
|
@ -126,13 +130,19 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
|
|
||||||
KeyNavigation.tab: junkPacketMinSizeTextField.textField
|
KeyNavigation.tab: junkPacketMinSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: junkPacketMinSizeTextField
|
id: junkPacketMinSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: "Jmin - Junk packet minimum size"
|
headerText: "Jmin - Junk packet minimum size"
|
||||||
textField.text: clientJunkPacketMinSize
|
textField.text: clientJunkPacketMinSize
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== clientJunkPacketMinSize) {
|
if (textField.text !== clientJunkPacketMinSize) {
|
||||||
|
@ -140,144 +150,28 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
|
|
||||||
KeyNavigation.tab: junkPacketMaxSizeTextField.textField
|
KeyNavigation.tab: junkPacketMaxSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: junkPacketMaxSizeTextField
|
id: junkPacketMaxSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: "Jmax - Junk packet maximum size"
|
headerText: "Jmax - Junk packet maximum size"
|
||||||
textField.text: clientJunkPacketMaxSize
|
textField.text: clientJunkPacketMaxSize
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== clientJunkPacketMaxSize) {
|
if (textField.text !== clientJunkPacketMaxSize) {
|
||||||
clientJunkPacketMaxSize = textField.text
|
clientJunkPacketMaxSize = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
checkEmptyText: true
|
||||||
id: specialJunk1TextField
|
|
||||||
headerText: qsTr("I1 - First special junk packet")
|
|
||||||
textField.text: clientSpecialJunk1
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientSpecialJunk1) {
|
|
||||||
clientSpecialJunk1 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: specialJunk2TextField
|
|
||||||
headerText: qsTr("I2 - Second special junk packet")
|
|
||||||
textField.text: clientSpecialJunk2
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientSpecialJunk2) {
|
|
||||||
clientSpecialJunk2 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: specialJunk3TextField
|
|
||||||
headerText: qsTr("I3 - Third special junk packet")
|
|
||||||
textField.text: clientSpecialJunk3
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientSpecialJunk3) {
|
|
||||||
clientSpecialJunk3 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: specialJunk4TextField
|
|
||||||
headerText: qsTr("I4 - Fourth special junk packet")
|
|
||||||
textField.text: clientSpecialJunk4
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientSpecialJunk4) {
|
|
||||||
clientSpecialJunk4 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: specialJunk5TextField
|
|
||||||
headerText: qsTr("I5 - Fifth special junk packet")
|
|
||||||
textField.text: clientSpecialJunk5
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientSpecialJunk5 ) {
|
|
||||||
clientSpecialJunk5 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: controlledJunk1TextField
|
|
||||||
headerText: qsTr("J1 - First controlled junk packet")
|
|
||||||
textField.text: clientControlledJunk1
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientControlledJunk1) {
|
|
||||||
clientControlledJunk1 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: controlledJunk2TextField
|
|
||||||
headerText: qsTr("J2 - Second controlled junk packet")
|
|
||||||
textField.text: clientControlledJunk2
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientControlledJunk2) {
|
|
||||||
clientControlledJunk2 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: controlledJunk3TextField
|
|
||||||
headerText: qsTr("J3 - Third controlled junk packet")
|
|
||||||
textField.text: clientControlledJunk3
|
|
||||||
textField.validator: null
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientControlledJunk3) {
|
|
||||||
clientControlledJunk3 = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: iTimeTextField
|
|
||||||
headerText: qsTr("Itime - Special handshake timeout")
|
|
||||||
textField.text: clientSpecialHandshakeTimeout
|
|
||||||
checkEmptyText: false
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== clientSpecialHandshakeTimeout) {
|
|
||||||
clientSpecialHandshakeTimeout = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Header2TextType {
|
Header2TextType {
|
||||||
|
@ -287,78 +181,82 @@ PageType {
|
||||||
text: qsTr("Server settings")
|
text: qsTr("Server settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: portTextField
|
id: portTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 8
|
||||||
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textField.text: port
|
textField.text: port
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: initPacketJunkSizeTextField
|
id: initPacketJunkSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
headerText: "S1 - Init packet junk size"
|
headerText: "S1 - Init packet junk size"
|
||||||
textField.text: serverInitPacketJunkSize
|
textField.text: serverInitPacketJunkSize
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: responsePacketJunkSizeTextField
|
id: responsePacketJunkSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
headerText: "S2 - Response packet junk size"
|
headerText: "S2 - Response packet junk size"
|
||||||
textField.text: serverResponsePacketJunkSize
|
textField.text: serverResponsePacketJunkSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
// id: cookieReplyPacketJunkSizeTextField
|
|
||||||
// enabled: false
|
|
||||||
|
|
||||||
// headerText: "S3 - Cookie Reply packet junk size"
|
|
||||||
// textField.text: serverCookieReplyPacketJunkSize
|
|
||||||
// }
|
|
||||||
|
|
||||||
// AwgTextField {
|
|
||||||
// id: transportPacketJunkSizeTextField
|
|
||||||
// enabled: false
|
|
||||||
|
|
||||||
// headerText: "S4 - Transport packet junk size"
|
|
||||||
// textField.text: serverTransportPacketJunkSize
|
|
||||||
// }
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: initPacketMagicHeaderTextField
|
id: initPacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
headerText: "H1 - Init packet magic header"
|
headerText: "H1 - Init packet magic header"
|
||||||
textField.text: serverInitPacketMagicHeader
|
textField.text: serverInitPacketMagicHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: responsePacketMagicHeaderTextField
|
id: responsePacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
headerText: "H2 - Response packet magic header"
|
headerText: "H2 - Response packet magic header"
|
||||||
textField.text: serverResponsePacketMagicHeader
|
textField.text: serverResponsePacketMagicHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: underloadPacketMagicHeaderTextField
|
id: underloadPacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
headerText: "H3 - Underload packet magic header"
|
headerText: "H3 - Underload packet magic header"
|
||||||
textField.text: serverUnderloadPacketMagicHeader
|
textField.text: serverUnderloadPacketMagicHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: transportPacketMagicHeaderTextField
|
id: transportPacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
headerText: "H4 - Transport packet magic header"
|
headerText: "H4 - Transport packet magic header"
|
||||||
textField.text: serverTransportPacketMagicHeader
|
textField.text: serverTransportPacketMagicHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,138 +138,183 @@ PageType {
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: junkPacketCountTextField
|
id: junkPacketCountTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("Jc - Junk packet count")
|
headerText: qsTr("Jc - Junk packet count")
|
||||||
textField.text: serverJunkPacketCount
|
textField.text: serverJunkPacketCount
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
|
if (textField.text === "") {
|
||||||
|
textField.text = "0"
|
||||||
|
}
|
||||||
|
|
||||||
if (textField.text !== serverJunkPacketCount) {
|
if (textField.text !== serverJunkPacketCount) {
|
||||||
serverJunkPacketCount = textField.text
|
serverJunkPacketCount = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: junkPacketMinSizeTextField
|
id: junkPacketMinSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("Jmin - Junk packet minimum size")
|
headerText: qsTr("Jmin - Junk packet minimum size")
|
||||||
textField.text: serverJunkPacketMinSize
|
textField.text: serverJunkPacketMinSize
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== serverJunkPacketMinSize) {
|
if (textField.text !== serverJunkPacketMinSize) {
|
||||||
serverJunkPacketMinSize = textField.text
|
serverJunkPacketMinSize = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: junkPacketMaxSizeTextField
|
id: junkPacketMaxSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("Jmax - Junk packet maximum size")
|
headerText: qsTr("Jmax - Junk packet maximum size")
|
||||||
textField.text: serverJunkPacketMaxSize
|
textField.text: serverJunkPacketMaxSize
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== serverJunkPacketMaxSize) {
|
if (textField.text !== serverJunkPacketMaxSize) {
|
||||||
serverJunkPacketMaxSize = textField.text
|
serverJunkPacketMaxSize = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: initPacketJunkSizeTextField
|
id: initPacketJunkSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("S1 - Init packet junk size")
|
headerText: qsTr("S1 - Init packet junk size")
|
||||||
textField.text: serverInitPacketJunkSize
|
textField.text: serverInitPacketJunkSize
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== serverInitPacketJunkSize) {
|
if (textField.text !== serverInitPacketJunkSize) {
|
||||||
serverInitPacketJunkSize = textField.text
|
serverInitPacketJunkSize = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
|
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
if(activeFocus) {
|
||||||
|
listview.positionViewAtEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: responsePacketJunkSizeTextField
|
id: responsePacketJunkSizeTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("S2 - Response packet junk size")
|
headerText: qsTr("S2 - Response packet junk size")
|
||||||
textField.text: serverResponsePacketJunkSize
|
textField.text: serverResponsePacketJunkSize
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== serverResponsePacketJunkSize) {
|
if (textField.text !== serverResponsePacketJunkSize) {
|
||||||
serverResponsePacketJunkSize = textField.text
|
serverResponsePacketJunkSize = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
|
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
if(activeFocus) {
|
||||||
|
listview.positionViewAtEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
// id: cookieReplyPacketJunkSizeTextField
|
|
||||||
// headerText: qsTr("S3 - Cookie reply packet junk size")
|
|
||||||
// textField.text: serverCookieReplyPacketJunkSize
|
|
||||||
|
|
||||||
// textField.onEditingFinished: {
|
|
||||||
// if (textField.text !== serverCookieReplyPacketJunkSize) {
|
|
||||||
// serverCookieReplyPacketJunkSize = textField.text
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// AwgTextField {
|
|
||||||
// id: transportPacketJunkSizeTextField
|
|
||||||
// headerText: qsTr("S4 - Transport packet junk size")
|
|
||||||
// textField.text: serverTransportPacketJunkSize
|
|
||||||
|
|
||||||
// textField.onEditingFinished: {
|
|
||||||
// if (textField.text !== serverTransportPacketJunkSize) {
|
|
||||||
// serverTransportPacketJunkSize = textField.text
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: initPacketMagicHeaderTextField
|
id: initPacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("H1 - Init packet magic header")
|
headerText: qsTr("H1 - Init packet magic header")
|
||||||
textField.text: serverInitPacketMagicHeader
|
textField.text: serverInitPacketMagicHeader
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== serverInitPacketMagicHeader) {
|
if (textField.text !== serverInitPacketMagicHeader) {
|
||||||
serverInitPacketMagicHeader = textField.text
|
serverInitPacketMagicHeader = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: responsePacketMagicHeaderTextField
|
id: responsePacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("H2 - Response packet magic header")
|
headerText: qsTr("H2 - Response packet magic header")
|
||||||
textField.text: serverResponsePacketMagicHeader
|
textField.text: serverResponsePacketMagicHeader
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== serverResponsePacketMagicHeader) {
|
if (textField.text !== serverResponsePacketMagicHeader) {
|
||||||
serverResponsePacketMagicHeader = textField.text
|
serverResponsePacketMagicHeader = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
AwgTextField {
|
TextFieldWithHeaderType {
|
||||||
id: underloadPacketMagicHeaderTextField
|
|
||||||
headerText: qsTr("H3 - Underload packet magic header")
|
|
||||||
textField.text: serverUnderloadPacketMagicHeader
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== serverUnderloadPacketMagicHeader) {
|
|
||||||
serverUnderloadPacketMagicHeader = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AwgTextField {
|
|
||||||
id: transportPacketMagicHeaderTextField
|
id: transportPacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("H4 - Transport packet magic header")
|
headerText: qsTr("H4 - Transport packet magic header")
|
||||||
textField.text: serverTransportPacketMagicHeader
|
textField.text: serverTransportPacketMagicHeader
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
textField.onEditingFinished: {
|
||||||
if (textField.text !== serverTransportPacketMagicHeader) {
|
if (textField.text !== serverTransportPacketMagicHeader) {
|
||||||
serverTransportPacketMagicHeader = textField.text
|
serverTransportPacketMagicHeader = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextFieldWithHeaderType {
|
||||||
|
id: underloadPacketMagicHeaderTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
headerText: qsTr("H3 - Underload packet magic header")
|
||||||
|
textField.text: serverUnderloadPacketMagicHeader
|
||||||
|
textField.validator: IntValidator { bottom: 0 }
|
||||||
|
|
||||||
|
textField.onEditingFinished: {
|
||||||
|
if (textField.text !== serverUnderloadPacketMagicHeader) {
|
||||||
|
serverUnderloadPacketMagicHeader = textField.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkEmptyText: true
|
||||||
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
id: saveRestartButton
|
id: saveRestartButton
|
||||||
|
@ -283,8 +328,6 @@ PageType {
|
||||||
responsePacketMagicHeaderTextField.errorText === "" &&
|
responsePacketMagicHeaderTextField.errorText === "" &&
|
||||||
initPacketMagicHeaderTextField.errorText === "" &&
|
initPacketMagicHeaderTextField.errorText === "" &&
|
||||||
responsePacketJunkSizeTextField.errorText === "" &&
|
responsePacketJunkSizeTextField.errorText === "" &&
|
||||||
// cookieReplyHeaderJunkTextField.errorText === "" &&
|
|
||||||
// transportHeaderJunkTextField.errorText === "" &&
|
|
||||||
initPacketJunkSizeTextField.errorText === "" &&
|
initPacketJunkSizeTextField.errorText === "" &&
|
||||||
junkPacketMaxSizeTextField.errorText === "" &&
|
junkPacketMaxSizeTextField.errorText === "" &&
|
||||||
junkPacketMinSizeTextField.errorText === "" &&
|
junkPacketMinSizeTextField.errorText === "" &&
|
||||||
|
@ -317,13 +360,6 @@ PageType {
|
||||||
PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)"))
|
PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92)"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// if (AwgConfigModel.isPacketSizeEqual(parseInt(initPacketJunkSizeTextField.textField.text),
|
|
||||||
// parseInt(responsePacketJunkSizeTextField.textField.text),
|
|
||||||
// parseInt(cookieReplyPacketJunkSizeTextField.textField.text),
|
|
||||||
// parseInt(transportPacketJunkSizeTextField.textField.text))) {
|
|
||||||
// PageController.showErrorMessage(qsTr("The value of the field S1 + message initiation size (148) must not equal S2 + message response size (92) + S3 + cookie reply size (64) + S4 + transport packet size (32)"))
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var headerText = qsTr("Save settings?")
|
var headerText = qsTr("Save settings?")
|
||||||
|
|
|
@ -59,14 +59,11 @@ PageType {
|
||||||
model: CloakConfigModel
|
model: CloakConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
|
||||||
|
|
||||||
property alias trafficFromField: trafficFromField
|
|
||||||
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
|
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias trafficFromField: trafficFromField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
|
@ -81,6 +78,7 @@ PageType {
|
||||||
|
|
||||||
BaseHeaderType {
|
BaseHeaderType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
headerText: qsTr("Cloak settings")
|
headerText: qsTr("Cloak settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +88,6 @@ PageType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
headerText: qsTr("Disguised as traffic from")
|
headerText: qsTr("Disguised as traffic from")
|
||||||
textField.text: site
|
textField.text: site
|
||||||
|
|
||||||
|
@ -108,8 +104,6 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
@ -118,8 +112,6 @@ PageType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textField.text: port
|
textField.text: port
|
||||||
textField.maximumLength: 5
|
textField.maximumLength: 5
|
||||||
|
@ -130,8 +122,6 @@ PageType {
|
||||||
port = textField.text
|
port = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
|
@ -139,8 +129,6 @@ PageType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
|
||||||
|
@ -178,46 +166,25 @@ PageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
id: saveButton
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
enabled: trafficFromField.errorText === "" &&
|
|
||||||
portTextField.errorText === ""
|
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
|
|
||||||
var headerText = qsTr("Save settings?")
|
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
||||||
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
||||||
var yesButtonText = qsTr("Continue")
|
return
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
|
||||||
InstallController.updateContainer(CloakConfigModel.getConfig())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var noButtonFunction = function() {
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
if (!GC.isMobile()) {
|
InstallController.updateContainer(CloakConfigModel.getConfig())
|
||||||
saveButton.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEnterPressed: saveButton.clicked()
|
|
||||||
Keys.onReturnPressed: saveButton.clicked()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,14 +58,11 @@ PageType {
|
||||||
model: OpenVpnConfigModel
|
model: OpenVpnConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
|
||||||
|
|
||||||
property alias vpnAddressSubnetTextField: vpnAddressSubnetTextField
|
|
||||||
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
|
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias vpnAddressSubnetTextField: vpnAddressSubnetTextField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
|
@ -80,6 +77,7 @@ PageType {
|
||||||
|
|
||||||
BaseHeaderType {
|
BaseHeaderType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
headerText: qsTr("OpenVPN settings")
|
headerText: qsTr("OpenVPN settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +87,6 @@ PageType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
headerText: qsTr("VPN address subnet")
|
headerText: qsTr("VPN address subnet")
|
||||||
textField.text: subnetAddress
|
textField.text: subnetAddress
|
||||||
|
|
||||||
|
@ -101,8 +97,6 @@ PageType {
|
||||||
subnetAddress = textField.text
|
subnetAddress = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
|
@ -140,7 +134,7 @@ PageType {
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
enabled: isPortEditable
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textField.text: port
|
textField.text: port
|
||||||
|
@ -152,8 +146,6 @@ PageType {
|
||||||
port = textField.text
|
port = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitcherType {
|
SwitcherType {
|
||||||
|
@ -396,45 +388,26 @@ PageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
id: saveButton
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
enabled: vpnAddressSubnetTextField.errorText === "" &&
|
|
||||||
portTextField.errorText === ""
|
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
parentFlickable: fl
|
parentFlickable: fl
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
|
|
||||||
var headerText = qsTr("Save settings?")
|
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
||||||
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
||||||
var yesButtonText = qsTr("Continue")
|
return
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
|
||||||
InstallController.updateContainer(OpenVpnConfigModel.getConfig())
|
|
||||||
}
|
}
|
||||||
var noButtonFunction = function() {
|
|
||||||
if (!GC.isMobile()) {
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
saveButton.forceActiveFocus()
|
InstallController.updateContainer(OpenVpnConfigModel.getConfig())
|
||||||
}
|
|
||||||
}
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEnterPressed: saveButton.clicked()
|
|
||||||
Keys.onReturnPressed: saveButton.clicked()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,13 +57,15 @@ PageType {
|
||||||
model: ShadowSocksConfigModel
|
model: ShadowSocksConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
|
||||||
|
|
||||||
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
|
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property var focusItemId: portTextField.enabled ?
|
||||||
|
portTextField :
|
||||||
|
cipherDropDown.enabled ?
|
||||||
|
cipherDropDown :
|
||||||
|
saveRestartButton
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
|
@ -78,6 +80,7 @@ PageType {
|
||||||
|
|
||||||
BaseHeaderType {
|
BaseHeaderType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
headerText: qsTr("Shadowsocks settings")
|
headerText: qsTr("Shadowsocks settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +90,7 @@ PageType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
enabled: isPortEditable
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textField.text: port
|
textField.text: port
|
||||||
|
@ -99,8 +102,6 @@ PageType {
|
||||||
port = textField.text
|
port = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
|
@ -108,7 +109,7 @@ PageType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 20
|
Layout.topMargin: 20
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
enabled: isCipherEditable
|
||||||
|
|
||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
@ -148,43 +149,27 @@ PageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
id: saveButton
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
enabled: portTextField.errorText === ""
|
enabled: isPortEditable | isCipherEditable
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
|
|
||||||
var headerText = qsTr("Save settings?")
|
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
||||||
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
||||||
var yesButtonText = qsTr("Continue")
|
return
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
|
||||||
InstallController.updateContainer(ShadowSocksConfigModel.getConfig())
|
|
||||||
}
|
}
|
||||||
var noButtonFunction = function() {
|
|
||||||
if (!GC.isMobile()) {
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
saveButton.forceActiveFocus()
|
InstallController.updateContainer(ShadowSocksConfigModel.getConfig())
|
||||||
}
|
|
||||||
}
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEnterPressed: saveButton.clicked()
|
|
||||||
Keys.onReturnPressed: saveButton.clicked()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ PageType {
|
||||||
}
|
}
|
||||||
var noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
if (!GC.isMobile()) {
|
if (!GC.isMobile()) {
|
||||||
saveButton.forceActiveFocus()
|
saveRestartButton.forceActiveFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
|
|
|
@ -58,10 +58,7 @@ PageType {
|
||||||
model: XrayConfigModel
|
model: XrayConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
id: delegateItem
|
|
||||||
|
|
||||||
property alias focusItemId: textFieldWithHeaderType.textField
|
property alias focusItemId: textFieldWithHeaderType.textField
|
||||||
property bool isEnabled: ServersModel.isProcessedServerHasWriteAccess()
|
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
@ -88,8 +85,6 @@ PageType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
headerText: qsTr("Disguised as traffic from")
|
headerText: qsTr("Disguised as traffic from")
|
||||||
textField.text: site
|
textField.text: site
|
||||||
|
|
||||||
|
@ -98,77 +93,39 @@ PageType {
|
||||||
var tmpText = textField.text
|
var tmpText = textField.text
|
||||||
tmpText = tmpText.toLocaleLowerCase()
|
tmpText = tmpText.toLocaleLowerCase()
|
||||||
|
|
||||||
if (tmpText.startsWith("https://")) {
|
var indexHttps = tmpText.indexOf("https://")
|
||||||
|
if (indexHttps === 0) {
|
||||||
tmpText = textField.text.substring(8)
|
tmpText = textField.text.substring(8)
|
||||||
site = tmpText
|
|
||||||
} else {
|
} else {
|
||||||
site = textField.text
|
site = textField.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
|
||||||
id: portTextField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
enabled: delegateItem.isEnabled
|
|
||||||
|
|
||||||
headerText: qsTr("Port")
|
|
||||||
textField.text: port
|
|
||||||
textField.maximumLength: 5
|
|
||||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
|
||||||
|
|
||||||
textField.onEditingFinished: {
|
|
||||||
if (textField.text !== port) {
|
|
||||||
port = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkEmptyText: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
id: saveButton
|
id: basicButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
enabled: portTextField.errorText === ""
|
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: function() {
|
onClicked: {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
|
|
||||||
var headerText = qsTr("Save settings?")
|
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
||||||
var descriptionText = qsTr("All users with whom you shared a connection with will no longer be able to connect to it.")
|
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
||||||
var yesButtonText = qsTr("Continue")
|
return
|
||||||
var noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
var yesButtonFunction = function() {
|
|
||||||
if (ConnectionController.isConnected && ServersModel.getDefaultServerData("defaultContainer") === ContainersModel.getProcessedContainerIndex()) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change settings while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
|
||||||
InstallController.updateContainer(XrayConfigModel.getConfig())
|
|
||||||
//focusItem.forceActiveFocus()
|
|
||||||
}
|
}
|
||||||
var noButtonFunction = function() {
|
|
||||||
if (!GC.isMobile()) {
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
saveButton.forceActiveFocus()
|
InstallController.updateContainer(XrayConfigModel.getConfig())
|
||||||
}
|
focusItem.forceActiveFocus()
|
||||||
}
|
|
||||||
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Keys.onEnterPressed: saveButton.clicked()
|
Keys.onEnterPressed: basicButton.clicked()
|
||||||
Keys.onReturnPressed: saveButton.clicked()
|
Keys.onReturnPressed: basicButton.clicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ PageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
var headerText = qsTr("Are you sure you want to unlink this device?")
|
var headerText = qsTr("Are you sure you want to unlink this device?")
|
||||||
var descriptionText = qsTr("This will unlink the device from your subscription. You can reconnect it anytime by pressing \"Reload API config\" in subscription settings on device.")
|
var descriptionText = qsTr("This will unlink the device from your subscription. You can reconnect it anytime by pressing Connect.")
|
||||||
var yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
var noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
|
|
|
@ -158,32 +158,6 @@ PageType {
|
||||||
|
|
||||||
readonly property bool isVisibleForAmneziaFree: ApiAccountInfoModel.data("isComponentVisible")
|
readonly property bool isVisibleForAmneziaFree: ApiAccountInfoModel.data("isComponentVisible")
|
||||||
|
|
||||||
SwitcherType {
|
|
||||||
id: switcher
|
|
||||||
|
|
||||||
readonly property bool isVlessProtocol: ApiConfigsController.isVlessProtocol()
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 24
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
|
|
||||||
visible: ApiAccountInfoModel.data("isProtocolSelectionSupported")
|
|
||||||
|
|
||||||
text: qsTr("Use VLESS protocol")
|
|
||||||
checked: switcher.isVlessProtocol
|
|
||||||
onToggled: function() {
|
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Cannot change protocol during active connection"))
|
|
||||||
} else {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
ApiConfigsController.setCurrentProtocol(switcher.isVlessProtocol ? "awg" : "vless")
|
|
||||||
ApiConfigsController.updateServiceFromGateway(ServersModel.processedIndex, "", "", true)
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WarningType {
|
WarningType {
|
||||||
id: warning
|
id: warning
|
||||||
|
|
||||||
|
@ -359,7 +333,7 @@ PageType {
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
var headerText = qsTr("Are you sure you want to unlink this device?")
|
var headerText = qsTr("Are you sure you want to unlink this device?")
|
||||||
var descriptionText = qsTr("This will unlink the device from your subscription. You can reconnect it anytime by pressing \"Reload API config\" in subscription settings on device.")
|
var descriptionText = qsTr("This will unlink the device from your subscription. You can reconnect it anytime by pressing Connect.")
|
||||||
var yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
var noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,6 @@ PageType {
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
visible: link !== ""
|
|
||||||
text: title
|
text: title
|
||||||
descriptionText: description
|
descriptionText: description
|
||||||
rightImageSource: "qrc:/images/controls/external-link.svg"
|
rightImageSource: "qrc:/images/controls/external-link.svg"
|
||||||
|
|
|
@ -49,7 +49,7 @@ PageType {
|
||||||
if (!ConnectionController.isConnected) {
|
if (!ConnectionController.isConnected) {
|
||||||
SettingsController.isKillSwitchEnabled = checked
|
SettingsController.isKillSwitchEnabled = checked
|
||||||
} else {
|
} else {
|
||||||
PageController.showNotificationMessage(qsTr("KillSwitch settings cannot be changed during an active connection"))
|
PageController.showNotificationMessage(qsTr("Cannot change killSwitch settings during active connection"))
|
||||||
switcher.checked = SettingsController.isKillSwitchEnabled
|
switcher.checked = SettingsController.isKillSwitchEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ PageType {
|
||||||
checked: !SettingsController.strictKillSwitchEnabled
|
checked: !SettingsController.strictKillSwitchEnabled
|
||||||
|
|
||||||
text: qsTr("Soft KillSwitch")
|
text: qsTr("Soft KillSwitch")
|
||||||
descriptionText: qsTr("Internet access is blocked if the VPN disconnects unexpectedly")
|
descriptionText: qsTr("Internet connection is blocked if VPN connection drops accidentally")
|
||||||
|
|
||||||
onClicked: function() {
|
onClicked: function() {
|
||||||
SettingsController.strictKillSwitchEnabled = false
|
SettingsController.strictKillSwitchEnabled = false
|
||||||
|
@ -81,17 +81,15 @@ PageType {
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
visible: false
|
enabled: SettingsController.isKillSwitchEnabled && !ConnectionController.isConnected
|
||||||
enabled: false
|
|
||||||
// enabled: SettingsController.isKillSwitchEnabled && !ConnectionController.isConnected
|
|
||||||
checked: SettingsController.strictKillSwitchEnabled
|
checked: SettingsController.strictKillSwitchEnabled
|
||||||
|
|
||||||
text: qsTr("Strict KillSwitch")
|
text: qsTr("Strict KillSwitch")
|
||||||
descriptionText: qsTr("Internet connection is blocked even when VPN is turned off manually or hasn't started")
|
descriptionText: qsTr("Internet connection is blocked even if VPN was turned off manually or not started")
|
||||||
|
|
||||||
onClicked: function() {
|
onClicked: function() {
|
||||||
var headerText = qsTr("Just a little heads-up")
|
var headerText = qsTr("Just a little heads-up")
|
||||||
var descriptionText = qsTr("If the VPN disconnects or drops while Strict KillSwitch is enabled, internet access will be blocked. To restore access, reconnect VPN or disable/change the KillSwitch.")
|
var descriptionText = qsTr("If you disconnect from VPN or the VPN connection drops while the Strict Kill Switch is turned on, your internet access will be disabled. To restore it, connect to VPN, change the Kill Switch mode or turn the Kill Switch off.")
|
||||||
var yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
var noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
|
@ -105,9 +103,7 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {}
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
@ -115,7 +111,7 @@ PageType {
|
||||||
|
|
||||||
enabled: true
|
enabled: true
|
||||||
text: qsTr("DNS Exceptions")
|
text: qsTr("DNS Exceptions")
|
||||||
descriptionText: qsTr("DNS servers listed here will remain accessible when KillSwitch is active.")
|
descriptionText: qsTr("DNS servers from the list will remain accessible when Kill Switch is triggered")
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
|
|
|
@ -43,7 +43,7 @@ PageType {
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
headerText: qsTr("DNS Exceptions")
|
headerText: qsTr("DNS Exceptions")
|
||||||
descriptionText: qsTr("DNS servers listed here will remain accessible when KillSwitch is active")
|
descriptionText: qsTr("DNS servers from the list will remain accessible when Kill Switch is triggered")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,24 +257,6 @@ PageType {
|
||||||
DividerType {
|
DividerType {
|
||||||
visible: ServersModel.getProcessedServerData("isServerFromTelegramApi")
|
visible: ServersModel.getProcessedServerData("isServerFromTelegramApi")
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
id: labelWithButton6
|
|
||||||
visible: ServersModel.getProcessedServerData("isServerFromTelegramApi") && ServersModel.processedServerIsPremium
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: qsTr("Switch to the new Amnezia Premium subscription")
|
|
||||||
textColor: AmneziaStyle.color.vibrantRed
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
PageController.goToPageHome()
|
|
||||||
ApiPremV1MigrationController.showMigrationDrawer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
visible: ServersModel.getProcessedServerData("isServerFromTelegramApi") && ServersModel.processedServerIsPremium
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -429,11 +429,6 @@ PageType {
|
||||||
|
|
||||||
fillConnectionTypeModel()
|
fillConnectionTypeModel()
|
||||||
|
|
||||||
if (exportTypeSelector.currentIndex >= root.connectionTypesModel.length) {
|
|
||||||
exportTypeSelector.currentIndex = 0
|
|
||||||
exportTypeSelector.text = root.connectionTypesModel[0].name
|
|
||||||
}
|
|
||||||
|
|
||||||
if (accessTypeSelector.currentIndex === 1) {
|
if (accessTypeSelector.currentIndex === 1) {
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ExportController.updateClientManagementModel(ContainersModel.getProcessedContainerIndex(),
|
ExportController.updateClientManagementModel(ContainersModel.getProcessedContainerIndex(),
|
||||||
|
|
Binary file not shown.
258
deploy/build_macos.sh
Normal file → Executable file
258
deploy/build_macos.sh
Normal file → Executable file
|
@ -1,15 +1,4 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
# Usage:
|
|
||||||
# Export the required signing credentials before running this script, e.g.:
|
|
||||||
# export MAC_APP_CERT_PW='pw-for-DeveloperID-Application'
|
|
||||||
# export MAC_INSTALL_CERT_PW='pw-for-DeveloperID-Installer'
|
|
||||||
# export MAC_SIGNER_ID='Developer ID Application: Some Company Name (XXXXXXXXXX)'
|
|
||||||
# export MAC_INSTALLER_SIGNER_ID='Developer ID Installer: Some Company Name (XXXXXXXXXX)'
|
|
||||||
# export APPLE_DEV_EMAIL='your@email.com'
|
|
||||||
# export APPLE_DEV_PASSWORD='<your-password>'
|
|
||||||
# bash deploy/build_macos.sh [-n]
|
|
||||||
# -----------------------------------------------------------------------------
|
|
||||||
echo "Build script started ..."
|
echo "Build script started ..."
|
||||||
|
|
||||||
set -o errexit -o nounset
|
set -o errexit -o nounset
|
||||||
|
@ -25,10 +14,10 @@ done
|
||||||
PROJECT_DIR=$(pwd)
|
PROJECT_DIR=$(pwd)
|
||||||
DEPLOY_DIR=$PROJECT_DIR/deploy
|
DEPLOY_DIR=$PROJECT_DIR/deploy
|
||||||
|
|
||||||
mkdir -p "$DEPLOY_DIR/build"
|
mkdir -p $DEPLOY_DIR/build
|
||||||
BUILD_DIR="$DEPLOY_DIR/build"
|
BUILD_DIR=$DEPLOY_DIR/build
|
||||||
|
|
||||||
echo "Project dir: ${PROJECT_DIR}"
|
echo "Project dir: ${PROJECT_DIR}"
|
||||||
echo "Build dir: ${BUILD_DIR}"
|
echo "Build dir: ${BUILD_DIR}"
|
||||||
|
|
||||||
APP_NAME=AmneziaVPN
|
APP_NAME=AmneziaVPN
|
||||||
|
@ -39,45 +28,39 @@ PLIST_NAME=$APP_NAME.plist
|
||||||
OUT_APP_DIR=$BUILD_DIR/client
|
OUT_APP_DIR=$BUILD_DIR/client
|
||||||
BUNDLE_DIR=$OUT_APP_DIR/$APP_FILENAME
|
BUNDLE_DIR=$OUT_APP_DIR/$APP_FILENAME
|
||||||
|
|
||||||
# Prebuilt deployment assets are available via the symlink under deploy/data
|
|
||||||
PREBUILT_DEPLOY_DATA_DIR=$PROJECT_DIR/deploy/data/deploy-prebuilt/macos
|
PREBUILT_DEPLOY_DATA_DIR=$PROJECT_DIR/deploy/data/deploy-prebuilt/macos
|
||||||
DEPLOY_DATA_DIR=$PROJECT_DIR/deploy/data/macos
|
DEPLOY_DATA_DIR=$PROJECT_DIR/deploy/data/macos
|
||||||
|
|
||||||
|
INSTALLER_DATA_DIR=$BUILD_DIR/installer/packages/$APP_DOMAIN/data
|
||||||
|
INSTALLER_BUNDLE_DIR=$BUILD_DIR/installer/$APP_FILENAME
|
||||||
|
DMG_FILENAME=$PROJECT_DIR/${APP_NAME}.dmg
|
||||||
|
|
||||||
# Search Qt
|
# Search Qt
|
||||||
if [ -z "${QT_VERSION+x}" ]; then
|
if [ -z "${QT_VERSION+x}" ]; then
|
||||||
QT_VERSION=6.8.3;
|
QT_VERSION=6.4.3;
|
||||||
|
QIF_VERSION=4.6
|
||||||
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/macos/bin
|
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/macos/bin
|
||||||
|
QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Using Qt in $QT_BIN_DIR"
|
echo "Using Qt in $QT_BIN_DIR"
|
||||||
|
echo "Using QIF in $QIF_BIN_DIR"
|
||||||
|
|
||||||
|
|
||||||
# Checking env
|
# Checking env
|
||||||
"$QT_BIN_DIR/qt-cmake" --version
|
$QT_BIN_DIR/qt-cmake --version
|
||||||
cmake --version
|
cmake --version
|
||||||
clang -v
|
clang -v
|
||||||
|
|
||||||
# Build App
|
# Build App
|
||||||
echo "Building App..."
|
echo "Building App..."
|
||||||
cd "$BUILD_DIR"
|
cd $BUILD_DIR
|
||||||
|
|
||||||
"$QT_BIN_DIR/qt-cmake" -S "$PROJECT_DIR" -B "$BUILD_DIR"
|
$QT_BIN_DIR/qt-cmake -S $PROJECT_DIR -B $BUILD_DIR
|
||||||
cmake --build . --config release --target all
|
cmake --build . --config release --target all
|
||||||
|
|
||||||
# Build and run tests here
|
# Build and run tests here
|
||||||
|
|
||||||
# Create a temporary keychain and import certificates
|
|
||||||
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
|
|
||||||
security import "$DEPLOY_DIR/DeveloperIDG2CA.cer" -k "$KEYCHAIN_PATH" -T /usr/bin/codesign
|
|
||||||
security list-keychains -d user -s "$KEYCHAIN_PATH"
|
|
||||||
|
|
||||||
echo "____________________________________"
|
echo "____________________________________"
|
||||||
echo "............Deploy.................."
|
echo "............Deploy.................."
|
||||||
echo "____________________________________"
|
echo "____________________________________"
|
||||||
|
@ -86,159 +69,102 @@ echo "____________________________________"
|
||||||
echo "Packaging ..."
|
echo "Packaging ..."
|
||||||
|
|
||||||
|
|
||||||
cp -Rv "$PREBUILT_DEPLOY_DATA_DIR"/* "$BUNDLE_DIR/Contents/macOS"
|
cp -Rv $PREBUILT_DEPLOY_DATA_DIR/* $BUNDLE_DIR/Contents/macOS
|
||||||
"$QT_BIN_DIR/macdeployqt" "$OUT_APP_DIR/$APP_FILENAME" -always-overwrite -qmldir="$PROJECT_DIR"
|
$QT_BIN_DIR/macdeployqt $OUT_APP_DIR/$APP_FILENAME -always-overwrite -qmldir=$PROJECT_DIR
|
||||||
cp -av "$BUILD_DIR/service/server/$APP_NAME-service" "$BUNDLE_DIR/Contents/macOS"
|
cp -av $BUILD_DIR/service/server/$APP_NAME-service $BUNDLE_DIR/Contents/macOS
|
||||||
rsync -av --exclude="$PLIST_NAME" --exclude=post_install.sh --exclude=post_uninstall.sh "$DEPLOY_DATA_DIR/" "$BUNDLE_DIR/Contents/macOS/"
|
cp -Rv $PROJECT_DIR/deploy/data/macos/* $BUNDLE_DIR/Contents/macOS
|
||||||
|
rm -f $BUNDLE_DIR/Contents/macOS/post_install.sh $BUNDLE_DIR/Contents/macOS/post_uninstall.sh
|
||||||
|
|
||||||
if [ "${MAC_APP_CERT_PW+x}" ]; then
|
if [ "${MAC_CERT_PW+x}" ]; then
|
||||||
|
|
||||||
# Path to the p12 that contains the Developer ID *Application* certificate
|
CERTIFICATE_P12=$DEPLOY_DIR/PrivacyTechAppleCertDeveloperId.p12
|
||||||
CERTIFICATE_P12=$DEPLOY_DIR/DeveloperIdApplicationCertificate.p12
|
WWDRCA=$DEPLOY_DIR/WWDRCA.cer
|
||||||
|
KEYCHAIN=amnezia.build.macos.keychain
|
||||||
|
TEMP_PASS=tmp_pass
|
||||||
|
|
||||||
# Ensure launchd plist is bundled, but place it inside Resources so that
|
security create-keychain -p $TEMP_PASS $KEYCHAIN || true
|
||||||
# the bundle keeps a valid structure (nothing but `Contents` at the root).
|
security default-keychain -s $KEYCHAIN
|
||||||
mkdir -p "$BUNDLE_DIR/Contents/Resources"
|
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||||
cp "$DEPLOY_DATA_DIR/$PLIST_NAME" "$BUNDLE_DIR/Contents/Resources/$PLIST_NAME"
|
|
||||||
|
|
||||||
# Show available signing identities (useful for debugging)
|
security default-keychain
|
||||||
security find-identity -p codesigning || true
|
security list-keychains
|
||||||
|
|
||||||
|
security import $WWDRCA -k $KEYCHAIN -T /usr/bin/codesign || true
|
||||||
|
security import $CERTIFICATE_P12 -k $KEYCHAIN -P $MAC_CERT_PW -T /usr/bin/codesign || true
|
||||||
|
|
||||||
|
security set-key-partition-list -S apple-tool:,apple: -k $TEMP_PASS $KEYCHAIN
|
||||||
|
security find-identity -p codesigning
|
||||||
|
|
||||||
echo "Signing App bundle..."
|
echo "Signing App bundle..."
|
||||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --keychain "$KEYCHAIN_PATH" --sign "$MAC_SIGNER_ID" "$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
|
/usr/bin/codesign --verify -vvvv $BUNDLE_DIR || true
|
||||||
spctl -a -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 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 300
|
||||||
|
xcrun stapler staple $BUNDLE_DIR
|
||||||
|
xcrun stapler validate $BUNDLE_DIR
|
||||||
|
spctl -a -vvvv $BUNDLE_DIR || true
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Packaging installer..."
|
echo "Packaging installer..."
|
||||||
PKG_DIR=$BUILD_DIR/pkg
|
mkdir -p $INSTALLER_DATA_DIR
|
||||||
# Remove any stale packaging data from previous runs
|
cp -av $PROJECT_DIR/deploy/installer $BUILD_DIR
|
||||||
rm -rf "$PKG_DIR"
|
cp -av $DEPLOY_DATA_DIR/post_install.sh $INSTALLER_DATA_DIR/post_install.sh
|
||||||
PKG_ROOT=$PKG_DIR/root
|
cp -av $DEPLOY_DATA_DIR/post_uninstall.sh $INSTALLER_DATA_DIR/post_uninstall.sh
|
||||||
SCRIPTS_DIR=$PKG_DIR/scripts
|
cp -av $DEPLOY_DATA_DIR/$PLIST_NAME $INSTALLER_DATA_DIR/$PLIST_NAME
|
||||||
RESOURCES_DIR=$PKG_DIR/resources
|
|
||||||
INSTALL_PKG=$PKG_DIR/${APP_NAME}_install.pkg
|
|
||||||
UNINSTALL_PKG=$PKG_DIR/${APP_NAME}_uninstall.pkg
|
|
||||||
FINAL_PKG=$PKG_DIR/${APP_NAME}.pkg
|
|
||||||
UNINSTALL_SCRIPTS_DIR=$PKG_DIR/uninstall_scripts
|
|
||||||
|
|
||||||
mkdir -p "$PKG_ROOT/Applications" "$SCRIPTS_DIR" "$RESOURCES_DIR" "$UNINSTALL_SCRIPTS_DIR"
|
chmod a+x $INSTALLER_DATA_DIR/post_install.sh $INSTALLER_DATA_DIR/post_uninstall.sh
|
||||||
|
|
||||||
cp -R "$BUNDLE_DIR" "$PKG_ROOT/Applications"
|
cd $BUNDLE_DIR
|
||||||
# launchd plist is already inside the bundle; no need to add it again after signing
|
tar czf $INSTALLER_DATA_DIR/$APP_NAME.tar.gz ./
|
||||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --keychain "$KEYCHAIN_PATH" --sign "$MAC_SIGNER_ID" "$PKG_ROOT/Applications/$APP_FILENAME"
|
|
||||||
/usr/bin/codesign --verify --deep --strict --verbose=4 "$PKG_ROOT/Applications/$APP_FILENAME" || true
|
|
||||||
cp "$DEPLOY_DATA_DIR/post_install.sh" "$SCRIPTS_DIR/post_install.sh"
|
|
||||||
cp "$DEPLOY_DATA_DIR/post_uninstall.sh" "$UNINSTALL_SCRIPTS_DIR/postinstall"
|
|
||||||
mkdir -p "$RESOURCES_DIR/scripts"
|
|
||||||
cp "$DEPLOY_DATA_DIR/check_install.sh" "$RESOURCES_DIR/scripts/check_install.sh"
|
|
||||||
cp "$DEPLOY_DATA_DIR/check_uninstall.sh" "$RESOURCES_DIR/scripts/check_uninstall.sh"
|
|
||||||
|
|
||||||
cat > "$SCRIPTS_DIR/postinstall" <<'EOS'
|
echo "Building installer..."
|
||||||
#!/bin/bash
|
$QIF_BIN_DIR/binarycreator --offline-only -v -c $BUILD_DIR/installer/config/macos.xml -p $BUILD_DIR/installer/packages -f $INSTALLER_BUNDLE_DIR
|
||||||
SCRIPT_DIR="$(dirname "$0")"
|
|
||||||
bash "$SCRIPT_DIR/post_install.sh"
|
|
||||||
exit 0
|
|
||||||
EOS
|
|
||||||
|
|
||||||
chmod +x "$SCRIPTS_DIR"/*
|
if [ "${MAC_CERT_PW+x}" ]; then
|
||||||
chmod +x "$UNINSTALL_SCRIPTS_DIR"/*
|
echo "Signing installer bundle..."
|
||||||
chmod +x "$RESOURCES_DIR/scripts"/*
|
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||||
cp "$PROJECT_DIR/LICENSE" "$RESOURCES_DIR/LICENSE"
|
/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
|
||||||
|
|
||||||
APP_VERSION=$(grep -m1 -E 'project\(' "$PROJECT_DIR/CMakeLists.txt" | sed -E 's/.*VERSION ([0-9.]+).*/\1/')
|
if [ "${NOTARIZE_APP+x}" ]; then
|
||||||
echo "Building component package $INSTALL_PKG ..."
|
echo "Notarizing installer bundle..."
|
||||||
|
/usr/bin/ditto -c -k --keepParent $INSTALLER_BUNDLE_DIR $PROJECT_DIR/Installer_bundle_to_notarize.zip
|
||||||
# Disable bundle relocation so the app always ends up in /Applications even if
|
xcrun notarytool submit $PROJECT_DIR/Installer_bundle_to_notarize.zip --apple-id $APPLE_DEV_EMAIL --team-id $MAC_TEAM_ID --password $APPLE_DEV_PASSWORD
|
||||||
# another copy is lying around somewhere. We do this by letting pkgbuild
|
rm $PROJECT_DIR/Installer_bundle_to_notarize.zip
|
||||||
# analyse the contents, flipping the BundleIsRelocatable flag to false for every
|
sleep 300
|
||||||
# bundle it discovers and then feeding that plist back to pkgbuild.
|
xcrun stapler staple $INSTALLER_BUNDLE_DIR
|
||||||
|
xcrun stapler validate $INSTALLER_BUNDLE_DIR
|
||||||
COMPONENT_PLIST="$PKG_DIR/component.plist"
|
spctl -a -vvvv $INSTALLER_BUNDLE_DIR || true
|
||||||
# Create the component description plist first
|
fi
|
||||||
pkgbuild --analyze --root "$PKG_ROOT" "$COMPONENT_PLIST"
|
|
||||||
|
|
||||||
# Turn all `BundleIsRelocatable` keys to false (PlistBuddy is available on all
|
|
||||||
# macOS systems). We first convert to xml1 to ensure predictable formatting.
|
|
||||||
|
|
||||||
# Turn relocation off for every bundle entry in the plist. PlistBuddy cannot
|
|
||||||
# address keys that contain slashes without quoting, so we iterate through the
|
|
||||||
# top-level keys it prints.
|
|
||||||
plutil -convert xml1 "$COMPONENT_PLIST"
|
|
||||||
for bundle_key in $(/usr/libexec/PlistBuddy -c "Print" "$COMPONENT_PLIST" | awk '/^[ \t]*[A-Za-z0-9].*\.app/ {print $1}'); do
|
|
||||||
/usr/libexec/PlistBuddy -c "Set :'${bundle_key}':BundleIsRelocatable false" "$COMPONENT_PLIST" || true
|
|
||||||
done
|
|
||||||
|
|
||||||
# Now build the real payload package with the edited plist so that the final
|
|
||||||
# PackageInfo contains relocatable="false".
|
|
||||||
pkgbuild --root "$PKG_ROOT" \
|
|
||||||
--identifier "$APP_DOMAIN" \
|
|
||||||
--version "$APP_VERSION" \
|
|
||||||
--install-location "/" \
|
|
||||||
--scripts "$SCRIPTS_DIR" \
|
|
||||||
--component-plist "$COMPONENT_PLIST" \
|
|
||||||
--sign "$MAC_INSTALLER_SIGNER_ID" \
|
|
||||||
"$INSTALL_PKG"
|
|
||||||
|
|
||||||
# Build uninstaller component package
|
|
||||||
UNINSTALL_COMPONENT_PKG=$PKG_DIR/${APP_NAME}_uninstall_component.pkg
|
|
||||||
echo "Building uninstaller component package $UNINSTALL_COMPONENT_PKG ..."
|
|
||||||
pkgbuild --nopayload \
|
|
||||||
--identifier "$APP_DOMAIN.uninstall" \
|
|
||||||
--version "$APP_VERSION" \
|
|
||||||
--scripts "$UNINSTALL_SCRIPTS_DIR" \
|
|
||||||
--sign "$MAC_INSTALLER_SIGNER_ID" \
|
|
||||||
"$UNINSTALL_COMPONENT_PKG"
|
|
||||||
|
|
||||||
# Wrap uninstaller component in a distribution package for clearer UI
|
|
||||||
echo "Building uninstaller distribution package $UNINSTALL_PKG ..."
|
|
||||||
UNINSTALL_RESOURCES=$PKG_DIR/uninstall_resources
|
|
||||||
rm -rf "$UNINSTALL_RESOURCES"
|
|
||||||
mkdir -p "$UNINSTALL_RESOURCES"
|
|
||||||
cp "$DEPLOY_DATA_DIR/uninstall_welcome.html" "$UNINSTALL_RESOURCES"
|
|
||||||
cp "$DEPLOY_DATA_DIR/uninstall_conclusion.html" "$UNINSTALL_RESOURCES"
|
|
||||||
productbuild \
|
|
||||||
--distribution "$DEPLOY_DATA_DIR/distribution_uninstall.xml" \
|
|
||||||
--package-path "$PKG_DIR" \
|
|
||||||
--resources "$UNINSTALL_RESOURCES" \
|
|
||||||
--sign "$MAC_INSTALLER_SIGNER_ID" \
|
|
||||||
"$UNINSTALL_PKG"
|
|
||||||
|
|
||||||
cp "$PROJECT_DIR/deploy/data/macos/distribution.xml" "$PKG_DIR/distribution.xml"
|
|
||||||
|
|
||||||
echo "Creating final installer $FINAL_PKG ..."
|
|
||||||
productbuild --distribution "$PKG_DIR/distribution.xml" \
|
|
||||||
--package-path "$PKG_DIR" \
|
|
||||||
--resources "$RESOURCES_DIR" \
|
|
||||||
--sign "$MAC_INSTALLER_SIGNER_ID" \
|
|
||||||
"$FINAL_PKG"
|
|
||||||
|
|
||||||
if [ "${MAC_INSTALL_CERT_PW+x}" ] && [ "${NOTARIZE_APP+x}" ]; then
|
|
||||||
echo "Notarizing installer package..."
|
|
||||||
xcrun notarytool submit "$FINAL_PKG" \
|
|
||||||
--apple-id "$APPLE_DEV_EMAIL" \
|
|
||||||
--team-id "$MAC_TEAM_ID" \
|
|
||||||
--password "$APPLE_DEV_PASSWORD" \
|
|
||||||
--wait
|
|
||||||
|
|
||||||
echo "Stapling ticket..."
|
|
||||||
xcrun stapler staple "$FINAL_PKG"
|
|
||||||
xcrun stapler validate "$FINAL_PKG"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${MAC_INSTALL_CERT_PW+x}" ]; then
|
echo "Building DMG installer..."
|
||||||
/usr/bin/codesign --verify -vvvv "$FINAL_PKG" || true
|
# Allow Terminal to make changes in Privacy & Security > App Management
|
||||||
spctl -a -vvvv "$FINAL_PKG" || true
|
hdiutil create -size 256mb -volname AmneziaVPN -srcfolder $BUILD_DIR/installer/$APP_NAME.app -ov -format UDZO $DMG_FILENAME
|
||||||
|
|
||||||
|
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 "$MAC_SIGNER_ID" $DMG_FILENAME
|
||||||
|
/usr/bin/codesign --verify -vvvv $DMG_FILENAME || true
|
||||||
|
|
||||||
|
if [ "${NOTARIZE_APP+x}" ]; then
|
||||||
|
echo "Notarizing DMG installer..."
|
||||||
|
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
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Sign app bundle
|
echo "Finished, artifact is $DMG_FILENAME"
|
||||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --keychain "$KEYCHAIN_PATH" --sign "$MAC_SIGNER_ID" "$BUNDLE_DIR"
|
|
||||||
spctl -a -vvvv "$BUNDLE_DIR" || true
|
|
||||||
|
|
||||||
# Restore login keychain as the only user keychain and delete the temporary keychain
|
# restore keychain
|
||||||
KEYCHAIN="$HOME/Library/Keychains/login.keychain-db"
|
security default-keychain -s login.keychain
|
||||||
security list-keychains -d user -s "$KEYCHAIN"
|
|
||||||
security delete-keychain "$KEYCHAIN_PATH"
|
|
||||||
|
|
||||||
echo "Finished, artifact is $FINAL_PKG"
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
if [ -d "/Applications/AmneziaVPN.app" ] || pgrep -x "AmneziaVPN-service" >/dev/null; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
exit 0
|
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
if [ -d "/Applications/AmneziaVPN.app" ] || pgrep -x "AmneziaVPN-service" >/dev/null; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
exit 1
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<installer-gui-script minSpecVersion="1">
|
|
||||||
<title>AmneziaVPN Installer</title>
|
|
||||||
<license file="LICENSE"/>
|
|
||||||
<choices-outline>
|
|
||||||
<line choice="install"/>
|
|
||||||
<line choice="uninstall"/>
|
|
||||||
</choices-outline>
|
|
||||||
<choice id="install" title="Install AmneziaVPN" start_selected="true">
|
|
||||||
<pkg-ref id="org.amneziavpn.package"/>
|
|
||||||
</choice>
|
|
||||||
<choice id="uninstall" title="Uninstall AmneziaVPN" start_selected="false">
|
|
||||||
<pkg-ref id="org.amneziavpn.uninstall"/>
|
|
||||||
</choice>
|
|
||||||
<pkg-ref id="org.amneziavpn.package" auth="Root" install-check="scripts/check_install.sh">AmneziaVPN_install.pkg</pkg-ref>
|
|
||||||
<pkg-ref id="org.amneziavpn.uninstall" auth="Root" install-check="scripts/check_uninstall.sh">AmneziaVPN_uninstall_component.pkg</pkg-ref>
|
|
||||||
</installer-gui-script>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<installer-gui-script minSpecVersion="1">
|
|
||||||
<title>Uninstall AmneziaVPN</title>
|
|
||||||
<options customize-install-button="always"/>
|
|
||||||
<welcome file="uninstall_welcome.html"/>
|
|
||||||
<conclusion file="uninstall_conclusion.html"/>
|
|
||||||
<choices-outline>
|
|
||||||
<line choice="uninstall"/>
|
|
||||||
</choices-outline>
|
|
||||||
<choice id="uninstall" title="Uninstall AmneziaVPN" start_selected="true">
|
|
||||||
<pkg-ref id="org.amneziavpn.uninstall"/>
|
|
||||||
</choice>
|
|
||||||
<pkg-ref id="org.amneziavpn.uninstall" auth="Root">AmneziaVPN_uninstall_component.pkg</pkg-ref>
|
|
||||||
</installer-gui-script>
|
|
|
@ -7,42 +7,29 @@ LOG_FOLDER=/var/log/$APP_NAME
|
||||||
LOG_FILE="$LOG_FOLDER/post-install.log"
|
LOG_FILE="$LOG_FOLDER/post-install.log"
|
||||||
APP_PATH=/Applications/$APP_NAME.app
|
APP_PATH=/Applications/$APP_NAME.app
|
||||||
|
|
||||||
# Handle new installations unpacked into localized folder
|
|
||||||
if [ -d "/Applications/${APP_NAME}.localized" ]; then
|
|
||||||
echo "`date` Detected ${APP_NAME}.localized, migrating to standard path" >> $LOG_FILE
|
|
||||||
sudo rm -rf "$APP_PATH"
|
|
||||||
sudo mv "/Applications/${APP_NAME}.localized/${APP_NAME}.app" "$APP_PATH"
|
|
||||||
sudo rm -rf "/Applications/${APP_NAME}.localized"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if launchctl list "$APP_NAME-service" &> /dev/null; then
|
if launchctl list "$APP_NAME-service" &> /dev/null; then
|
||||||
launchctl unload "$LAUNCH_DAEMONS_PLIST_NAME"
|
launchctl unload $LAUNCH_DAEMONS_PLIST_NAME
|
||||||
rm -f "$LAUNCH_DAEMONS_PLIST_NAME"
|
rm -f $LAUNCH_DAEMONS_PLIST_NAME
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo chmod -R a-w "$APP_PATH/"
|
tar xzf $APP_PATH/$APP_NAME.tar.gz -C $APP_PATH
|
||||||
sudo chown -R root "$APP_PATH/"
|
rm -f $APP_PATH/$APP_NAME.tar.gz
|
||||||
sudo chgrp -R wheel "$APP_PATH/"
|
sudo chmod -R a-w $APP_PATH/
|
||||||
|
sudo chown -R root $APP_PATH/
|
||||||
|
sudo chgrp -R wheel $APP_PATH/
|
||||||
|
|
||||||
rm -rf $LOG_FOLDER
|
rm -rf $LOG_FOLDER
|
||||||
mkdir -p $LOG_FOLDER
|
mkdir -p $LOG_FOLDER
|
||||||
|
|
||||||
echo "`date` Script started" > $LOG_FILE
|
echo "`date` Script started" > $LOG_FILE
|
||||||
|
|
||||||
echo "Requesting ${APP_NAME} to quit gracefully" >> "$LOG_FILE"
|
killall -9 $APP_NAME-service 2>> $LOG_FILE
|
||||||
osascript -e 'tell application "AmneziaVPN" to quit'
|
|
||||||
|
|
||||||
PLIST_SOURCE="$APP_PATH/Contents/Resources/$PLIST_NAME"
|
mv -f $APP_PATH/$PLIST_NAME $LAUNCH_DAEMONS_PLIST_NAME 2>> $LOG_FILE
|
||||||
if [ -f "$PLIST_SOURCE" ]; then
|
chown root:wheel $LAUNCH_DAEMONS_PLIST_NAME
|
||||||
mv -f "$PLIST_SOURCE" "$LAUNCH_DAEMONS_PLIST_NAME" 2>> $LOG_FILE
|
launchctl load $LAUNCH_DAEMONS_PLIST_NAME
|
||||||
else
|
|
||||||
echo "`date` ERROR: service plist not found at $PLIST_SOURCE" >> $LOG_FILE
|
|
||||||
fi
|
|
||||||
|
|
||||||
chown root:wheel "$LAUNCH_DAEMONS_PLIST_NAME"
|
|
||||||
launchctl load "$LAUNCH_DAEMONS_PLIST_NAME"
|
|
||||||
echo "`date` Launching ${APP_NAME} application" >> $LOG_FILE
|
|
||||||
open -a "$APP_PATH" 2>> $LOG_FILE || true
|
|
||||||
|
|
||||||
echo "`date` Service status: $?" >> $LOG_FILE
|
echo "`date` Service status: $?" >> $LOG_FILE
|
||||||
echo "`date` Script finished" >> $LOG_FILE
|
echo "`date` Script finished" >> $LOG_FILE
|
||||||
|
|
||||||
|
#rm -- "$0"
|
||||||
|
|
|
@ -9,19 +9,6 @@ SYSTEM_APP_SUPPORT="/Library/Application Support/$APP_NAME"
|
||||||
LOG_FOLDER="/var/log/$APP_NAME"
|
LOG_FOLDER="/var/log/$APP_NAME"
|
||||||
CACHES_FOLDER="$HOME/Library/Caches/$APP_NAME"
|
CACHES_FOLDER="$HOME/Library/Caches/$APP_NAME"
|
||||||
|
|
||||||
# Attempt to quit the GUI application if it's currently running
|
|
||||||
if pgrep -x "$APP_NAME" > /dev/null; then
|
|
||||||
echo "Quitting $APP_NAME..."
|
|
||||||
osascript -e 'tell application "'"$APP_NAME"'" to quit' || true
|
|
||||||
# Wait up to 10 seconds for the app to terminate gracefully
|
|
||||||
for i in {1..10}; do
|
|
||||||
if ! pgrep -x "$APP_NAME" > /dev/null; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Stop the running service if it exists
|
# Stop the running service if it exists
|
||||||
if pgrep -x "${APP_NAME}-service" > /dev/null; then
|
if pgrep -x "${APP_NAME}-service" > /dev/null; then
|
||||||
sudo killall -9 "${APP_NAME}-service"
|
sudo killall -9 "${APP_NAME}-service"
|
||||||
|
@ -45,40 +32,3 @@ sudo rm -rf "$LOG_FOLDER"
|
||||||
|
|
||||||
# Remove any caches left behind
|
# Remove any caches left behind
|
||||||
rm -rf "$CACHES_FOLDER"
|
rm -rf "$CACHES_FOLDER"
|
||||||
|
|
||||||
# Remove PF data directory created by firewall helper, if present
|
|
||||||
sudo rm -rf "/Library/Application Support/${APP_NAME}/pf"
|
|
||||||
|
|
||||||
# ---------------- PF firewall cleanup ----------------------
|
|
||||||
# Rules are loaded under the anchor "amn" (see macosfirewall.cpp)
|
|
||||||
# Flush only that anchor to avoid destroying user/system rules.
|
|
||||||
|
|
||||||
PF_ANCHOR="amn"
|
|
||||||
|
|
||||||
### Flush all PF rules, NATs, and tables under our anchor and sub-anchors ###
|
|
||||||
anchors=$(sudo pfctl -s Anchors 2>/dev/null | awk '/^'"${PF_ANCHOR}"'/ {sub(/\*$/, "", $1); print $1}')
|
|
||||||
for anc in $anchors; do
|
|
||||||
echo "Flushing PF anchor $anc"
|
|
||||||
sudo pfctl -a "$anc" -F all 2>/dev/null || true
|
|
||||||
# flush tables under this anchor
|
|
||||||
tables=$(sudo pfctl -s Tables 2>/dev/null | awk '/^'"$anc"'/ {print}')
|
|
||||||
for tbl in $tables; do
|
|
||||||
echo "Killing PF table $tbl"
|
|
||||||
sudo pfctl -t "$tbl" -T kill 2>/dev/null || true
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
### Reload default PF config to restore system rules ###
|
|
||||||
if [ -f /etc/pf.conf ]; then
|
|
||||||
echo "Restoring system PF config"
|
|
||||||
sudo pfctl -f /etc/pf.conf 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
### Disable PF if no rules remain ###
|
|
||||||
if sudo pfctl -s info 2>/dev/null | grep -q '^Status: Enabled' && \
|
|
||||||
! sudo pfctl -sr 2>/dev/null | grep -q .; then
|
|
||||||
echo "Disabling PF"
|
|
||||||
sudo pfctl -d 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
<html>
|
|
||||||
<head><title>Uninstall Complete</title></head>
|
|
||||||
<body>
|
|
||||||
<h1>AmneziaVPN has been uninstalled</h1>
|
|
||||||
<p>Thank you for using AmneziaVPN. The application and its components have been removed.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue