Compare commits

...

44 Commits

Author SHA1 Message Date
pokamest 49e58c25f2 Installer version bump 2022-02-05 16:08:53 +03:00
pokamest ac6000a2ae Svg icons, dns ui fix 2022-02-05 15:52:14 +03:00
pokamest 6d1c9edc24 Log panel added 2022-02-04 17:49:48 +03:00
pokamest 1a7fa3746d DNS service fixes for all containers 2022-02-02 02:12:29 +03:00
pokamest f7a57ffeb4 Cloak container arm support, ss updated 2022-02-02 01:52:37 +03:00
pokamest ad9d45a154 Dns selection implemented 2022-02-01 19:48:59 +03:00
pokamest 5fffb2afe3 Dns container to internal network 2022-01-31 16:08:22 +03:00
pokamest 1269114074 Cleanup berfore uninstall, post-uninstall refactoring 2022-01-31 00:10:51 +03:00
pokamest d24f6ae064 Logs functions fixes 2022-01-30 17:35:57 +03:00
pokamest 95fe09489c Vpn and wizard pages fixes 2022-01-28 16:03:21 +03:00
pokamest 1a144da36d SFTP fixes for Macos 2022-01-24 14:29:37 -08:00
pokamest 8e26da1759 Macos build fixes 2022-01-23 15:25:53 -08:00
pokamest daf53226c3 SFTP fixes 2022-01-24 02:01:56 +03:00
pokamest 2b9e615e51 Various fixes 2022-01-23 19:16:40 +03:00
pokamest 02acbecef5 Re-resolve sites after VPN Connected 2022-01-22 20:00:06 +03:00
pokamest 8f28964ce2 Tiny ui fixes 2022-01-22 18:19:57 +03:00
pokamest 495e74e2f0 Sites page fix 2022-01-22 18:19:38 +03:00
pokamest 8f23970ccc Gradle build bump 2022-01-04 17:12:32 +03:00
pokamest 9ec39658fe DNS container with EmerCoin DNS support 2022-01-03 18:30:53 +03:00
pokamest 9943e081d9 RegExp validators fix 2021-12-25 23:01:53 +03:00
pokamest 68a51c9c63 WireGuard protocol fix 2021-12-25 21:14:55 +03:00
pokamest e7dd964825 ServerController fix 2021-12-22 13:41:09 +03:00
pokamest f20134415e IKEv2 class file renamed 2021-12-21 02:57:23 +03:00
pokamest bd9b9600c1 Release 2.0.6 2021-12-21 00:35:18 +03:00
pokamest 5ae9873455 Destructor crash fix 2021-12-20 15:43:36 +03:00
pokamest 5776ca0384 Merge pull request #47 from amnezia-vpn/qr_rework
Qr rework
2021-12-20 03:23:48 +03:00
pokamest f8f4b39965 qzxing submodule 2021-12-20 02:42:16 +03:00
pokamest 1d51419a11 QR codes rework 2021-12-20 02:29:23 +03:00
pokamest 5e1ca0c19f iOS icons asset 2021-12-16 11:54:07 -08:00
pokamest b341224c92 AppStore icon fix 2021-12-16 15:04:59 +03:00
pokamest 3861f23af3 iOS icon fixed 2021-12-16 14:45:08 +03:00
pokamest e7beff79d0 iOS icons 2021-12-16 14:38:41 +03:00
pokamest 2380875cbf Merge branch 'ios-wireguard' into dev 2021-12-15 06:06:08 -08:00
pokamest 343e6a50df resetIpStack added 2021-12-15 14:53:07 +03:00
pokamest 5aa47d35e7 Version to main screen 2021-12-14 12:50:57 +03:00
pokamest 313ceed1d0 StartPageLogic fix 2021-12-12 14:42:25 +03:00
pokamest ac07d62344 ui fixes 2021-12-11 14:44:24 +03:00
pokamest 2db1bbae4b WireGuard server script fix 2021-12-10 15:43:43 +03:00
Alex Kh 090e50e936 [WIP] protocol switching and relaunch crash issues (possibly) fixed 2021-12-09 12:59:56 +04:00
Alex Kh b6bab0c723 [WIP] seamless protocol switching without leaving the app 2021-12-08 19:40:43 +04:00
Alex Kh 1a333f7968 [WIP] move connection state call to main thread 2021-12-08 17:10:15 +04:00
Alex Kh 87c00b3804 Merge branch 'ios-wireguard' of https://github.com/amnezia-vpn/desktop-client into ios-wireguard 2021-12-08 15:57:16 +04:00
Alex Kh eba71469a4 [WIP] OpenVPN tunnel implementation 2021-12-08 15:55:36 +04:00
pokamest 4eef127744 VPN modes ui fix 2021-12-04 19:48:47 +03:00
176 changed files with 3660 additions and 3126 deletions
+1
View File
@@ -47,6 +47,7 @@ client/amneziavpn_qml_plugin_import.cpp
client/qmlcache_loader.cpp
client/rep_ipc_interface_replica.h
client/resources_qmlcache.qrc
client/3rd/OpenVPNAdpter/build/
# QtCreator
+6
View File
@@ -7,3 +7,9 @@
[submodule "client/3rd/wireguard-apple"]
path = client/3rd/wireguard-apple
url = https://github.com/WireGuard/wireguard-apple
[submodule "client/3rd/OpenVPNAdapter"]
path = client/3rd/OpenVPNAdapter
url = https://github.com/ss-abramchuk/OpenVPNAdapter.git
[submodule "client/3rd/qzxing"]
path = client/3rd/qzxing
url = https://github.com/ftylitak/qzxing.git
+1 -1
View File
@@ -2,5 +2,5 @@ TEMPLATE = subdirs
SUBDIRS = client
!ios:!android {
SUBDIRS += service platform
SUBDIRS += service
}
File diff suppressed because it is too large Load Diff
@@ -1,129 +0,0 @@
#if !defined(AFX_QR_ENCODE_H__AC886DF7_C0AE_4C9F_AC7A_FCDA8CB1DD37__INCLUDED_)
#define AFX_QR_ENCODE_H__AC886DF7_C0AE_4C9F_AC7A_FCDA8CB1DD37__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
//
#define QR_LEVEL_L 0
#define QR_LEVEL_M 1
#define QR_LEVEL_Q 2
#define QR_LEVEL_H 3
//
#define QR_MODE_NUMERAL 0
#define QR_MODE_ALPHABET 1
#define QR_MODE_8BIT 2
#define QR_MODE_KANJI 3
//
#define QR_VRESION_S 0
#define QR_VRESION_M 1
#define QR_VRESION_L 2
#define MAX_ALLCODEWORD 3706
#define MAX_DATACODEWORD 2956
#define MAX_CODEBLOCK 153
#define MAX_MODULESIZE 177
#define QR_MARGIN 0
/////////////////////////////////////////////////////////////////////////////
typedef struct tagRS_BLOCKINFO
{
int ncRSBlock;
int ncAllCodeWord;
int ncDataCodeWord;
} RS_BLOCKINFO, *LPRS_BLOCKINFO;
/////////////////////////////////////////////////////////////////////////////
typedef struct tagQR_VERSIONINFO
{
int nVersionNo;
int ncAllCodeWord;
int ncDataCodeWord[4];
int ncAlignPoint;
int nAlignPoint[6];
RS_BLOCKINFO RS_BlockInfo1[4];
RS_BLOCKINFO RS_BlockInfo2[4];
} QR_VERSIONINFO, *LPQR_VERSIONINFO;
/////////////////////////////////////////////////////////////////////////////
class CQR_Encode
{
public:
CQR_Encode();
~CQR_Encode();
public:
int m_nLevel;
int m_nVersion;
bool m_bAutoExtent;
int m_nMaskingNo;
public:
int m_nSymbleSize;
unsigned char m_byModuleData[MAX_MODULESIZE][MAX_MODULESIZE]; // [x][y]
private:
int m_ncDataCodeWordBit;
unsigned char m_byDataCodeWord[MAX_DATACODEWORD];
int m_ncDataBlock;
unsigned char m_byBlockMode[MAX_DATACODEWORD];
int m_nBlockLength[MAX_DATACODEWORD];
int m_ncAllCodeWord;
unsigned char m_byAllCodeWord[MAX_ALLCODEWORD];
unsigned char m_byRSWork[MAX_CODEBLOCK];
public:
bool EncodeData(int nLevel, int nVersion, bool bAutoExtent, int nMaskingNo, const char* lpsSource, int ncSource = 0);
private:
int GetEncodeVersion(int nVersion, const char* lpsSource, int ncLength);
bool EncodeSourceData(const char* lpsSource, int ncLength, int nVerGroup);
int GetBitLength(unsigned char nMode, int ncData, int nVerGroup);
int SetBitStream(int nIndex, unsigned short wData, int ncData);
bool IsNumeralData(unsigned char c);
bool IsAlphabetData(unsigned char c);
bool IsKanjiData(unsigned char c1, unsigned char c2);
unsigned char AlphabetToBinaly(unsigned char c);
unsigned short KanjiToBinaly(unsigned short wc);
void GetRSCodeWord(unsigned char * lpbyRSWork, int ncDataCodeWord, int ncRSCodeWord);
private:
void FormatModule();
void SetFunctionModule();
void SetFinderPattern(int x, int y);
void SetAlignmentPattern(int x, int y);
void SetVersionPattern();
void SetCodeWordPattern();
void SetMaskingPattern(int nPatternNo);
void SetFormatInfoPattern(int nPatternNo);
int CountPenalty();
};
/////////////////////////////////////////////////////////////////////////////
#endif // !defined(AFX_QR_ENCODE_H__AC886DF7_C0AE_4C9F_AC7A_FCDA8CB1DD37__INCLUDED_)
@@ -1,5 +0,0 @@
HEADERS += \
3rd/QRCodeGenerator/QRCodeGenerator.h \
SOURCES += \
3rd/QRCodeGenerator/QRCodeGenerator.cpp \
+1 -1
View File
@@ -11,7 +11,7 @@ win32 {
-lcrypt32 \
!contains(QMAKE_TARGET.arch, x86_64) {
INCLUDEPATH += $$PWD/windows/x86_64
INCLUDEPATH += $$PWD/windows/x86
HEADERS += $$PWD/windows/x86/botan_all.h
SOURCES += $$PWD/windows/x86/botan_all.cpp
}
+2 -2
View File
@@ -940,8 +940,8 @@ void SshConnectionPrivate::connectToHost()
this, &SshConnectionPrivate::handleSocketConnected);
connect(m_socket, &QIODevice::readyRead,
this, &SshConnectionPrivate::handleIncomingData);
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
SLOT(handleSocketError()));
connect(m_socket, &QAbstractSocket::errorOccurred,
this, &SshConnectionPrivate::handleSocketError);
connect(m_socket, &QAbstractSocket::disconnected,
this, &SshConnectionPrivate::handleSocketDisconnected);
connect(&m_timeoutTimer, &QTimer::timeout, this, &SshConnectionPrivate::handleTimeout);
+1
Submodule client/3rd/qzxing added at 2fd4dd60c0
+2 -2
View File
@@ -217,7 +217,9 @@ enum ConnectionState : NSInteger;
SWIFT_CLASS("_TtC10AmneziaVPN18IOSVpnProtocolImpl")
@interface IOSVpnProtocolImpl : NSObject
- (nonnull instancetype)initWithBundleID:(NSString * _Nonnull)bundleID privateKey:(NSData * _Nonnull)privateKey deviceIpv4Address:(NSString * _Nonnull)deviceIpv4Address deviceIpv6Address:(NSString * _Nonnull)deviceIpv6Address closure:(void (^ _Nonnull)(enum ConnectionState, NSDate * _Nullable))closure callback:(void (^ _Nonnull)(BOOL))callback OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)initWithBundleID:(NSString * _Nonnull)bundleID config:(NSString * _Nonnull)config closure:(void (^ _Nonnull)(enum ConnectionState, NSDate * _Nullable))closure callback:(void (^ _Nonnull)(BOOL))callback;
- (void)connectWithDnsServer:(NSString * _Nonnull)dnsServer serverIpv6Gateway:(NSString * _Nonnull)serverIpv6Gateway serverPublicKey:(NSString * _Nonnull)serverPublicKey presharedKey:(NSString * _Nonnull)presharedKey serverIpv4AddrIn:(NSString * _Nonnull)serverIpv4AddrIn serverPort:(NSInteger)serverPort allowedIPAddressRanges:(NSArray<VPNIPAddressRange *> * _Nonnull)allowedIPAddressRanges ipv6Enabled:(Boolean)enabled reason:(NSInteger)reason failureCallback:(void (^ _Nonnull)(void))failureCallback;
- (void)connectWithOvpnConfig:(NSString * _Nonnull)ovpnConfig failureCallback:(void (^ _Nonnull)(void))failureCallback;
- (void)disconnect;
- (void)checkStatusWithCallback:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull, NSString * _Nonnull))callback;
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
@@ -230,8 +232,6 @@ typedef SWIFT_ENUM(NSInteger, ConnectionState, closed) {
ConnectionStateDisconnected = 2,
};
SWIFT_CLASS("_TtC10AmneziaVPN17VPNIPAddressRange")
@interface VPNIPAddressRange : NSObject
- (nonnull instancetype)initWithAddress:(NSString * _Nonnull)address networkPrefixLength:(uint8_t)networkPrefixLength isIpv6:(BOOL)isIpv6 OBJC_DESIGNATED_INITIALIZER;
+2 -1
View File
@@ -2,12 +2,13 @@
<manifest package="org.amnezia.vpn" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-permission android:name="android.permission.CAMERA"/>
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
+2 -6
View File
@@ -38,13 +38,9 @@ apply plugin: 'kotlinx-serialization'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'com.android.installreferrer:installreferrer:2.2'
implementation 'com.android.billingclient:billing-ktx:4.0.0'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0-alpha02"
implementation "androidx.security:security-crypto:1.1.0-alpha03"
implementation "androidx.security:security-identity-credential:1.0.0-alpha02"
implementation 'com.adjust.sdk:adjust-android:4.28.2'
implementation 'com.google.android.gms:play-services-ads-identifier:17.0.1'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.0.10"
}
@@ -106,8 +102,8 @@ android {
resConfig "en"
minSdkVersion = 24
targetSdkVersion = 30
versionCode 2 // Change to a higher number
versionName "2.0.1" // Change to a higher number
versionCode 8 // Change to a higher number
versionName "2.0.8" // Change to a higher number
}
buildTypes {
@@ -0,0 +1,6 @@
package org.ftylitak.qzxing;
public class NativeFunctions {
public static native void onPermissionsGranted();
public static native void onPermissionsDenied();
}
@@ -0,0 +1,25 @@
package org.ftylitak.qzxing;
import android.Manifest;
import android.content.pm.PackageManager;
import org.qtproject.qt5.android.bindings.QtActivity;
import static org.ftylitak.qzxing.Utilities.REQUEST_CAMERA;
public class QZXingLiveActivity extends QtActivity {
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CAMERA: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
NativeFunctions.onPermissionsGranted();
} else {
NativeFunctions.onPermissionsDenied();
}
return;
}
}
}
}
@@ -0,0 +1,42 @@
package org.ftylitak.qzxing;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
public class Utilities {
public static final int REQUEST_CAMERA = 0;
public static final String[] requiredPermissionsModifyPhoneState = {
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public static void checkAndRequestPermissionList(Activity activity, String[] permissions) {
ArrayList<String> permissionsToRequest = new ArrayList<>();
for (int i = 0; i < permissions.length; i++) {
if (ContextCompat.checkSelfPermission(activity, permissions[i])
!= PackageManager.PERMISSION_GRANTED)
permissionsToRequest.add(permissions[i]);
}
if (permissionsToRequest.size() != 0)
ActivityCompat.requestPermissions(activity,
permissionsToRequest.toArray(new String[0]),
REQUEST_CAMERA);
else
NativeFunctions.onPermissionsGranted();
}
public static void requestQZXingPermissions(Activity activity) {
checkAndRequestPermissionList(activity, requiredPermissionsModifyPhoneState);
}
}
+19 -6
View File
@@ -5,14 +5,17 @@ TEMPLATE = app
#CONFIG += console
CONFIG += qtquickcompiler
CONFIG += qzxing_multimedia \
enable_decoder_qr_code \
enable_encoder_qr_code
DEFINES += QT_DEPRECATED_WARNINGS
include("3rd/QtSsh/src/ssh/qssh.pri")
include("3rd/QtSsh/src/botan/botan.pri")
!android:!ios:include("3rd/SingleApplication/singleapplication.pri")
include("3rd/QRCodeGenerator/QRCodeGenerator.pri")
include ("3rd/SortFilterProxyModel/SortFilterProxyModel.pri")
include("3rd/QZXing/src/QZXing-components.pri")
INCLUDEPATH += $$PWD/3rd/OpenSSL/include
DEPENDPATH += $$PWD/3rd/OpenSSL/include
@@ -48,6 +51,7 @@ HEADERS += \
ui/pages_logic/NetworkSettingsLogic.h \
ui/pages_logic/NewServerProtocolsLogic.h \
ui/pages_logic/PageLogicBase.h \
ui/pages_logic/QrDecoderLogic.h \
ui/pages_logic/ServerConfiguringProgressLogic.h \
ui/pages_logic/ServerContainersLogic.h \
ui/pages_logic/ServerListLogic.h \
@@ -103,6 +107,7 @@ SOURCES += \
ui/pages_logic/NetworkSettingsLogic.cpp \
ui/pages_logic/NewServerProtocolsLogic.cpp \
ui/pages_logic/PageLogicBase.cpp \
ui/pages_logic/QrDecoderLogic.cpp \
ui/pages_logic/ServerConfiguringProgressLogic.cpp \
ui/pages_logic/ServerContainersLogic.cpp \
ui/pages_logic/ServerListLogic.cpp \
@@ -141,12 +146,14 @@ win32 {
RC_FILE = platform_win/vpnclient.rc
HEADERS += \
ui/framelesswindow.h \
protocols/ikev2_vpn_protocol_windows.h \
ui/framelesswindow.h
SOURCES += \
protocols/ikev2_vpn_protocol_windows.cpp \
ui/framelesswindow.cpp
VERSION = 1.0.0.0
VERSION = 2.0.0.0
QMAKE_TARGET_COMPANY = "AmneziaVPN"
QMAKE_TARGET_PRODUCT = "AmneziaVPN"
@@ -193,11 +200,11 @@ linux:!android {
}
win32|macx|linux:!android {
DEFINES += AMNEZIA_DESKTOP
HEADERS += \
ui/systemtray_notificationhandler.h \
protocols/openvpnprotocol.h \
protocols/ikev2_vpn_protocol.h \
protocols/openvpnovercloakprotocol.h \
protocols/shadowsocksvpnprotocol.h \
protocols/wireguardprotocol.h \
@@ -205,7 +212,6 @@ win32|macx|linux:!android {
SOURCES += \
ui/systemtray_notificationhandler.cpp \
protocols/openvpnprotocol.cpp \
protocols/ikev2_vpn_protocol.cpp \
protocols/openvpnovercloakprotocol.cpp \
protocols/shadowsocksvpnprotocol.cpp \
protocols/wireguardprotocol.cpp \
@@ -218,11 +224,13 @@ android {
INCLUDEPATH += platforms/android
HEADERS += \
platforms/android/native.h \
platforms/android/android_controller.h \
platforms/android/android_notificationhandler.h \
protocols/android_vpnprotocol.h
SOURCES += \
platforms/android/native.cpp \
platforms/android/android_controller.cpp \
platforms/android/android_notificationhandler.cpp \
protocols/android_vpnprotocol.cpp
@@ -276,6 +284,11 @@ ios {
LIBS += -framework StoreKit
LIBS += -framework UserNotifications
# LIBS += $$PWD/3rd/OpenVPNAdapter/build/Debug-iphoneos/LZ4.framework
# LIBS += $$PWD/3rd/OpenVPNAdapter/build/Debug-iphoneos/mbedTLS.framework
# LIBS += $$PWD/3rd/OpenVPNAdapter/build/Debug-iphoneos/OpenVPNClient.framework
# LIBS += $$PWD/3rd/OpenVPNAdapter/build/Debug-iphoneos/OpenVPNAdapter.framework
DEFINES += MVPN_IOS
HEADERS += \
@@ -309,7 +322,7 @@ ios {
QMAKE_DEVELOPMENT_TEAM = X7UJ388FXK
QMAKE_PROVISIONING_PROFILE = f2fefb59-14aa-4aa9-ac14-1d5531b06dcc
QMAKE_XCODE_CODE_SIGN_IDENTITY = "Apple Distribution"
QMAKE_INFO_PLIST= $$PWD/ios/app/Info.plist
QMAKE_INFO_PLIST = $$PWD/ios/app/Info.plist
XCODEBUILD_FLAGS += -allowProvisioningUpdates
+44 -8
View File
@@ -10,6 +10,7 @@
#include <QJsonDocument>
#include "containers/containers_defs.h"
#include "utils.h"
Settings &VpnConfigurator::m_settings()
{
@@ -41,24 +42,59 @@ QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentia
}
}
QString VpnConfigurator::processConfigWithLocalSettings(DockerContainer container, Proto proto, QString config)
QPair<QString, QString> VpnConfigurator::getDnsForConfig(int serverIndex)
{
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
QPair<QString, QString> dns;
bool useAmneziaDns = m_settings().useAmneziaDns();
const QJsonObject &server = m_settings().server(serverIndex);
dns.first = server.value(config_key::dns1).toString();
dns.second = server.value(config_key::dns2).toString();
if (dns.first.isEmpty() || !Utils::checkIPv4Format(dns.first)) {
if (useAmneziaDns && m_settings().containers(serverIndex).contains(DockerContainer::Dns)) {
dns.first = protocols::dns::amneziaDnsIp;
}
else dns.first = m_settings().primaryDns();
}
if (dns.second.isEmpty() || !Utils::checkIPv4Format(dns.second)) {
dns.second = m_settings().secondaryDns();
}
qDebug() << "VpnConfigurator::getDnsForConfig" << dns.first << dns.second;
return dns;
}
QString &VpnConfigurator::processConfigWithDnsSettings(int serverIndex, DockerContainer container,
Proto proto, QString &config)
{
auto dns = getDnsForConfig(serverIndex);
config.replace("$PRIMARY_DNS", dns.first);
config.replace("$SECONDARY_DNS", dns.second);
return config;
}
QString &VpnConfigurator::processConfigWithLocalSettings(int serverIndex, DockerContainer container,
Proto proto, QString &config)
{
processConfigWithDnsSettings(serverIndex, container, proto, config);
if (proto == Proto::OpenVpn) {
return OpenVpnConfigurator::processConfigWithLocalSettings(config);
config = OpenVpnConfigurator::processConfigWithLocalSettings(config);
}
return config;
}
QString VpnConfigurator::processConfigWithExportSettings(DockerContainer container, Proto proto, QString config)
QString &VpnConfigurator::processConfigWithExportSettings(int serverIndex, DockerContainer container,
Proto proto, QString &config)
{
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
processConfigWithDnsSettings(serverIndex, container, proto, config);
if (proto == Proto::OpenVpn) {
return OpenVpnConfigurator::processConfigWithExportSettings(config);
config = OpenVpnConfigurator::processConfigWithExportSettings(config);
}
return config;
}
+5 -2
View File
@@ -15,8 +15,11 @@ public:
static QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr);
static QString processConfigWithLocalSettings(DockerContainer container, Proto proto, QString config);
static QString processConfigWithExportSettings(DockerContainer container, Proto proto, QString config);
static QPair<QString, QString> getDnsForConfig(int serverIndex);
static QString &processConfigWithDnsSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
static QString &processConfigWithLocalSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
static QString &processConfigWithExportSettings(int serverIndex, DockerContainer container, Proto proto, QString &config);
// workaround for containers which is not support normal configaration
static void updateContainerConfigAfterInstallation(DockerContainer container,
@@ -50,7 +50,7 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
}
WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials,
DockerContainer container, ErrorCode *errorCode)
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
{
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
connData.host = credentials.hostName;
@@ -61,6 +61,49 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
}
ErrorCode e = ErrorCode::NoError;
// Get list of already created clients (only IP addreses)
QString nextIpNumber;
{
QString script = QString("cat %1 | grep AllowedIPs").arg(amnezia::protocols::wireguard::serverConfigPath);
QString stdOut;
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
stdOut += data + "\n";
};
ServerController::runContainerScript(credentials, container, script, cbReadStdOut);
stdOut.replace("AllowedIPs = ", "");
stdOut.replace("/32", "");
QStringList ips = stdOut.split("\n", Qt::SkipEmptyParts);
// Calc next IP address
if (ips.isEmpty()) {
nextIpNumber = "2";
}
else {
int next = ips.last().split(".").last().toInt() + 1;
if (next > 254) {
if (errorCode) *errorCode = ErrorCode::AddressPoolError;
return connData;
}
nextIpNumber = QString::number(next);
}
}
QString subnetIp = containerConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
{
QStringList l = subnetIp.split(".", Qt::SkipEmptyParts);
if (l.isEmpty()) {
if (errorCode) *errorCode = ErrorCode::AddressPoolError;
return connData;
}
l.removeLast();
l.append(nextIpNumber);
connData.clientIP = l.join(".");
}
// Get keys
connData.serverPubKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e);
connData.serverPubKey.replace("\n", "");
if (e) {
@@ -76,18 +119,15 @@ WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardCon
return connData;
}
// Add client to config
QString configPart = QString(
"[Peer]\n"
"PublicKey = %1\n"
"PresharedKey = %2\n"
"AllowedIPs = $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR\n\n").
"AllowedIPs = %3/32\n\n").
arg(connData.clientPubKey).
arg(connData.pskKey);
configPart = ServerController::replaceVars(configPart, ServerController::genVarsForScript(credentials, container));
qDebug().noquote() << "Adding wg conf part to server" << configPart;
arg(connData.pskKey).
arg(connData.clientIP);
e = ServerController::uploadTextFileToContainer(container, credentials, configPart,
protocols::wireguard::serverConfigPath, QSsh::SftpOverwriteMode::SftpAppendToExisting);
@@ -116,12 +156,13 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede
QString config = ServerController::replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
ServerController::genVarsForScript(credentials, container, containerConfig));
ConnectionData connData = prepareWireguardConfig(credentials, container, errorCode);
ConnectionData connData = prepareWireguardConfig(credentials, container, containerConfig, errorCode);
if (errorCode && *errorCode) {
return "";
}
config.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", connData.clientPrivKey);
config.replace("$WIREGUARD_CLIENT_IP", connData.clientIP);
config.replace("$WIREGUARD_SERVER_PUBLIC_KEY", connData.serverPubKey);
config.replace("$WIREGUARD_PSK", connData.pskKey);
@@ -130,6 +171,7 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede
jConfig[config_key::hostName] = connData.host;
jConfig[config_key::client_priv_key] = connData.clientPrivKey;
jConfig[config_key::client_ip] = connData.clientIP;
jConfig[config_key::client_pub_key] = connData.clientPubKey;
jConfig[config_key::psk_key] = connData.pskKey;
jConfig[config_key::server_pub_key] = connData.serverPubKey;
@@ -15,6 +15,7 @@ public:
struct ConnectionData {
QString clientPrivKey; // client private key
QString clientPubKey; // client public key
QString clientIP; // internal client IP address
QString serverPubKey; // tls-auth key
QString pskKey; // preshared key
QString host; // host ip
@@ -29,7 +30,7 @@ public:
private:
static ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
DockerContainer container, ErrorCode *errorCode = nullptr);
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
static ConnectionData genClientKeys();
+5 -1
View File
@@ -148,7 +148,11 @@ bool ContainerProps::isWorkingOnPlatform(DockerContainer c)
default: return false;
}
#elif defined (Q_OS_MAC)
return false;
switch (c) {
case DockerContainer::WireGuard: return false;
case DockerContainer::Ipsec: return false;
default: return true;
}
#elif defined (Q_OS_ANDROID)
switch (c) {
+3
View File
@@ -6,6 +6,8 @@
namespace amnezia {
constexpr const qint16 qrMagicCode = 1984;
struct ServerCredentials
{
QString hostName;
@@ -58,6 +60,7 @@ enum ErrorCode
OpenVpnAdaptersInUseError,
OpenVpnUnknownError,
OpenVpnTapAdapterError,
AddressPoolError,
// 3rd party utils errors
OpenSslFailed,
+1
View File
@@ -45,6 +45,7 @@ QString errorString(ErrorCode code){
// VPN errors
case (OpenVpnAdaptersInUseError): return QObject::tr("Can't connect: another VPN connection is active");
case (OpenVpnTapAdapterError): return QObject::tr("Can't setup OpenVPN TAP network adapter");
case (AddressPoolError): return QObject::tr("VPN pool error: no available addresses");
case(InternalError):
default:
+16 -7
View File
@@ -79,6 +79,8 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
}
qDebug().noquote() << "EXEC" << lineToExec;
Debug::appendSshLog("Run command:" + lineToExec);
QSharedPointer<SshRemoteProcess> proc = client->createRemoteProcess(lineToExec.toUtf8());
if (!proc) {
@@ -101,7 +103,9 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, &wait, [proc, cbReadStdOut](){
QString s = proc->readAllStandardOutput();
if (s != "." && !s.isEmpty()) {
Debug::appendSshLog("Output: " + s);
qDebug().noquote() << "stdout" << s;
}
if (cbReadStdOut) cbReadStdOut(s, proc);
@@ -110,6 +114,7 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, &wait, [proc, cbReadStdErr](){
QString s = proc->readAllStandardError();
if (s != "." && !s.isEmpty()) {
Debug::appendSshLog("Output: " + s);
qDebug().noquote() << "stderr" << s;
}
if (cbReadStdErr) cbReadStdErr(s, proc);
@@ -135,6 +140,7 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
const std::function<void (const QString &, QSharedPointer<QSsh::SshRemoteProcess>)> &cbReadStdErr)
{
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
Debug::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + ":\n" + script);
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
if (e) return e;
@@ -165,8 +171,9 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
};
// mkdir
QFileInfo fi(path);
QString mkdir = "sudo docker exec -i $CONTAINER_NAME mkdir -p " + fi.absoluteDir().absolutePath();
QString mkdir = QString("sudo docker exec -i $CONTAINER_NAME mkdir -p \"$(dirname %1)\"")
.arg(path);
e = runScript(credentials,
replaceVars(mkdir, genVarsForScript(credentials, container)));
if (e) return e;
@@ -477,8 +484,10 @@ QJsonObject ServerController::createContainerInitialConfig(DockerContainer conta
bool ServerController::isReinstallContainerRequred(DockerContainer container, const QJsonObject &oldConfig, const QJsonObject &newConfig)
{
const QJsonObject &oldProtoConfig = oldConfig[ContainerProps::containerToString(container)].toObject();
const QJsonObject &newProtoConfig = newConfig[ContainerProps::containerToString(container)].toObject();
Proto mainProto = ContainerProps::defaultProtocol(container);
const QJsonObject &oldProtoConfig = oldConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
const QJsonObject &newProtoConfig = newConfig.value(ProtocolProps::protoToString(mainProto)).toObject();
if (container == DockerContainer::OpenVpn) {
if (oldProtoConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) !=
@@ -666,9 +675,9 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
vars.append({{"$FAKE_WEB_SITE_ADDRESS", cloakConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite) }});
// Wireguard vars
vars.append({{"$WIREGUARD_SUBNET_IP", openvpnConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) }});
vars.append({{"$WIREGUARD_SUBNET_CIDR", openvpnConfig.value(config_key::subnet_cidr).toString(protocols::wireguard::defaultSubnetCidr) }});
vars.append({{"$WIREGUARD_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(protocols::wireguard::defaultSubnetMask) }});
vars.append({{"$WIREGUARD_SUBNET_IP", wireguarConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress) }});
vars.append({{"$WIREGUARD_SUBNET_CIDR", wireguarConfig.value(config_key::subnet_cidr).toString(protocols::wireguard::defaultSubnetCidr) }});
vars.append({{"$WIREGUARD_SUBNET_MASK", wireguarConfig.value(config_key::subnet_mask).toString(protocols::wireguard::defaultSubnetMask) }});
vars.append({{"$WIREGUARD_SERVER_PORT", wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) }});
+1
View File
@@ -5,6 +5,7 @@
#include <QObject>
#include "sshconnection.h"
#include "sshremoteprocess.h"
#include "debug.h"
#include "defs.h"
#include "settings.h"
+83 -5
View File
@@ -6,13 +6,15 @@
#include <iostream>
#include <core/ipcclient.h>
#include "debug.h"
#include "defines.h"
#include "utils.h"
QFile Debug::m_file;
QTextStream Debug::m_textStream;
QString Debug::m_logFileName;
QString Debug::m_logFileName = QString("%1.log").arg(APPLICATION_NAME);
void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
@@ -26,10 +28,30 @@ void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
}
Debug::m_textStream << qFormatLogMessage(type, context, msg) << endl << flush;
Debug::appendAllLog(qFormatLogMessage(type, context, msg));
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush;
}
Debug &Debug::Instance()
{
static Debug s;
return s;
}
void Debug::appendSshLog(const QString &log)
{
QString dt = QDateTime::currentDateTime().toString();
Instance().m_sshLog.append(dt + ": " + log + "\n");
emit Instance().sshLogChanged(Instance().sshLog());
}
void Debug::appendAllLog(const QString &log)
{
Instance().m_allLog.append(log + "\n");
emit Instance().allLogChanged(Instance().allLog());
}
bool Debug::init()
{
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
@@ -40,11 +62,8 @@ bool Debug::init()
return false;
}
m_logFileName = QString("%1.log").arg(APPLICATION_NAME);
m_file.setFileName(appDir.filePath(m_logFileName));
if (!m_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
if (!m_file.open(QIODevice::Append)) {
qWarning() << "Cannot open log file:" << m_logFileName;
return false;
}
@@ -63,6 +82,20 @@ QString Debug::userLogsDir()
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/log";
}
QString Debug::userLogsFilePath()
{
return userLogsDir() + QDir::separator() + m_logFileName;
}
QString Debug::getLogFile()
{
m_file.flush();
QFile file(userLogsFilePath());
file.open(QIODevice::ReadOnly);
return file.readAll();
}
bool Debug::openLogsFolder()
{
QString path = userLogsDir();
@@ -88,3 +121,48 @@ QString Debug::appLogFileNamePath()
{
return m_file.fileName();
}
void Debug::clearLogs()
{
bool isLogActive = m_file.isOpen();
m_file.close();
QFile file(userLogsFilePath());
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
file.resize(0);
file.close();
if (isLogActive) {
init();
}
}
void Debug::clearServiceLogs()
{
IpcClient *m_IpcClient = new IpcClient;
if (!m_IpcClient->isSocketConnected()) {
if (!IpcClient::init(m_IpcClient)) {
qWarning() << "Error occured when init IPC client";
return;
}
}
if (m_IpcClient->Interface()) {
m_IpcClient->Interface()->setLogsEnabled(false);
m_IpcClient->Interface()->cleanUp();
}
else {
qWarning() << "Error occured cleaning up service logs";
}
}
void Debug::cleanUp()
{
clearLogs();
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
dir.removeRecursively();
clearServiceLogs();
}
+23 -1
View File
@@ -7,15 +7,37 @@
#include <QString>
#include <QTextStream>
class Debug
#include "ui/property_helper.h"
class Debug : public QObject
{
Q_OBJECT
AUTO_PROPERTY(QString, sshLog)
AUTO_PROPERTY(QString, allLog)
public:
static Debug& Instance();
static void appendSshLog(const QString &log);
static void appendAllLog(const QString &log);
static bool init();
static bool openLogsFolder();
static bool openServiceLogsFolder();
static QString appLogFileNamePath();
static void clearLogs();
static void clearServiceLogs();
static void cleanUp();
static QString userLogsFilePath();
static QString getLogFile();
private:
Debug() {}
Debug(Debug const &) = delete;
Debug& operator= (Debug const&) = delete;
static QString userLogsDir();
static QFile m_file;
+2 -2
View File
@@ -4,7 +4,7 @@
#define APPLICATION_NAME "AmneziaVPN"
#define SERVICE_NAME "AmneziaVPN-service"
#define ORGANIZATION_NAME "AmneziaVPN.ORG"
#define APP_MAJOR_VERSION "2.0.1"
#define APP_VERSION "2.0.1.0"
#define APP_MAJOR_VERSION "2.0.8"
#define APP_VERSION "2.0.8.0"
#endif // DEFINES_H
Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>

After

Width:  |  Height:  |  Size: 268 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>

After

Width:  |  Height:  |  Size: 317 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z"/></svg>

After

Width:  |  Height:  |  Size: 252 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><rect height="2" width="18" x="3" y="2"/><rect height="2" width="18" x="3" y="20"/><rect height="2" width="18" x="3" y="14"/><rect height="2" width="18" x="3" y="8"/></g></g></svg>

After

Width:  |  Height:  |  Size: 371 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/></svg>

After

Width:  |  Height:  |  Size: 209 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.68-1.5 1.5s.68 1.5 1.5 1.5 1.5-.68 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z"/></svg>

After

Width:  |  Height:  |  Size: 430 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><path d="M12,2L4,5v6.09c0,5.05,3.41,9.76,8,10.91c4.59-1.15,8-5.86,8-10.91V5L12,2z M18,11.09c0,4-2.55,7.7-6,8.83 c-3.45-1.13-6-4.82-6-8.83V6.31l6-2.12l6,2.12V11.09z M8.82,10.59L7.4,12l3.54,3.54l5.66-5.66l-1.41-1.41l-4.24,4.24L8.82,10.59z"/></g></svg>

After

Width:  |  Height:  |  Size: 434 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><g><path d="M12,2L4,5v6.09c0,5.05,3.41,9.76,8,10.91c4.59-1.15,8-5.86,8-10.91V5L12,2z M18,11.09c0,4-2.55,7.7-6,8.83 c-3.45-1.13-6-4.82-6-8.83v-4.7l6-2.25l6,2.25V11.09z"/><rect height="2" width="2" x="11" y="14"/><rect height="5" width="2" x="11" y="7"/></g></g></svg>

After

Width:  |  Height:  |  Size: 451 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24v24H0V0z" fill="none"/></g><g><path d="M17,8l-1.41,1.41L17.17,11H9v2h8.17l-1.58,1.58L17,16l4-4L17,8z M5,5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h7v-2H5V5z"/></g></svg>

After

Width:  |  Height:  |  Size: 324 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M14.17,13.71l1.4-2.42c0.09-0.15,0.05-0.34-0.08-0.45l-1.48-1.16c0.03-0.22,0.05-0.45,0.05-0.68s-0.02-0.46-0.05-0.69 l1.48-1.16c0.13-0.11,0.17-0.3,0.08-0.45l-1.4-2.42c-0.09-0.15-0.27-0.21-0.43-0.15L12,4.83c-0.36-0.28-0.75-0.51-1.18-0.69 l-0.26-1.85C10.53,2.13,10.38,2,10.21,2h-2.8C7.24,2,7.09,2.13,7.06,2.3L6.8,4.15C6.38,4.33,5.98,4.56,5.62,4.84l-1.74-0.7 c-0.16-0.06-0.34,0-0.43,0.15l-1.4,2.42C1.96,6.86,2,7.05,2.13,7.16l1.48,1.16C3.58,8.54,3.56,8.77,3.56,9s0.02,0.46,0.05,0.69 l-1.48,1.16C2,10.96,1.96,11.15,2.05,11.3l1.4,2.42c0.09,0.15,0.27,0.21,0.43,0.15l1.74-0.7c0.36,0.28,0.75,0.51,1.18,0.69 l0.26,1.85C7.09,15.87,7.24,16,7.41,16h2.8c0.17,0,0.32-0.13,0.35-0.3l0.26-1.85c0.42-0.18,0.82-0.41,1.18-0.69l1.74,0.7 C13.9,13.92,14.08,13.86,14.17,13.71z M8.81,11c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2s2,0.9,2,2C10.81,10.1,9.91,11,8.81,11z"/><path d="M21.92,18.67l-0.96-0.74c0.02-0.14,0.04-0.29,0.04-0.44c0-0.15-0.01-0.3-0.04-0.44l0.95-0.74 c0.08-0.07,0.11-0.19,0.05-0.29l-0.9-1.55c-0.05-0.1-0.17-0.13-0.28-0.1l-1.11,0.45c-0.23-0.18-0.48-0.33-0.76-0.44l-0.17-1.18 C18.73,13.08,18.63,13,18.53,13h-1.79c-0.11,0-0.21,0.08-0.22,0.19l-0.17,1.18c-0.27,0.12-0.53,0.26-0.76,0.44l-1.11-0.45 c-0.1-0.04-0.22,0-0.28,0.1l-0.9,1.55c-0.05,0.1-0.04,0.22,0.05,0.29l0.95,0.74c-0.02,0.14-0.03,0.29-0.03,0.44 c0,0.15,0.01,0.3,0.03,0.44l-0.95,0.74c-0.08,0.07-0.11,0.19-0.05,0.29l0.9,1.55c0.05,0.1,0.17,0.13,0.28,0.1l1.11-0.45 c0.23,0.18,0.48,0.33,0.76,0.44l0.17,1.18c0.02,0.11,0.11,0.19,0.22,0.19h1.79c0.11,0,0.21-0.08,0.22-0.19l0.17-1.18 c0.27-0.12,0.53-0.26,0.75-0.44l1.12,0.45c0.1,0.04,0.22,0,0.28-0.1l0.9-1.55C22.03,18.86,22,18.74,21.92,18.67z M17.63,18.83 c-0.74,0-1.35-0.6-1.35-1.35s0.6-1.35,1.35-1.35s1.35,0.6,1.35,1.35S18.37,18.83,17.63,18.83z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>

After

Width:  |  Height:  |  Size: 361 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19.43 12.98c.04-.32.07-.64.07-.98 0-.34-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.09-.16-.26-.25-.44-.25-.06 0-.12.01-.17.03l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.06-.02-.12-.03-.18-.03-.17 0-.34.09-.43.25l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98 0 .33.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.09.16.26.25.44.25.06 0 .12-.01.17-.03l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.06.02.12.03.18.03.17 0 .34-.09.43-.25l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zm-1.98-1.71c.04.31.05.52.05.73 0 .21-.02.43-.05.73l-.14 1.13.89.7 1.08.84-.7 1.21-1.27-.51-1.04-.42-.9.68c-.43.32-.84.56-1.25.73l-1.06.43-.16 1.13-.2 1.35h-1.4l-.19-1.35-.16-1.13-1.06-.43c-.43-.18-.83-.41-1.23-.71l-.91-.7-1.06.43-1.27.51-.7-1.21 1.08-.84.89-.7-.14-1.13c-.03-.31-.05-.54-.05-.74s.02-.43.05-.73l.14-1.13-.89-.7-1.08-.84.7-1.21 1.27.51 1.04.42.9-.68c.43-.32.84-.56 1.25-.73l1.06-.43.16-1.13.2-1.35h1.39l.19 1.35.16 1.13 1.06.43c.43.18.83.41 1.23.71l.91.7 1.06-.43 1.27-.51.7 1.21-1.07.85-.89.7.14 1.13zM12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><rect fill="none" height="24" width="24"/><path d="M10,13c0.55,0,1,0.45,1,1s-0.45,1-1,1s-1-0.45-1-1S9.45,13,10,13 M10,11c-1.66,0-3,1.34-3,3s1.34,3,3,3s3-1.34,3-3 S11.66,11,10,11L10,11z M18.5,9l1.09-2.41L22,5.5l-2.41-1.09L18.5,2l-1.09,2.41L15,5.5l2.41,1.09L18.5,9z M21.28,12.72L20.5,11 l-0.78,1.72L18,13.5l1.72,0.78L20.5,16l0.78-1.72L23,13.5L21.28,12.72z M16.25,14c0-0.12,0-0.25-0.01-0.37l1.94-1.47l-2.5-4.33 l-2.24,0.94c-0.2-0.13-0.42-0.26-0.64-0.37L12.5,6h-5L7.2,8.41C6.98,8.52,6.77,8.65,6.56,8.78L4.32,7.83l-2.5,4.33l1.94,1.47 C3.75,13.75,3.75,13.88,3.75,14s0,0.25,0.01,0.37l-1.94,1.47l2.5,4.33l2.24-0.94c0.2,0.13,0.42,0.26,0.64,0.37L7.5,22h5l0.3-2.41 c0.22-0.11,0.43-0.23,0.64-0.37l2.24,0.94l2.5-4.33l-1.94-1.47C16.25,14.25,16.25,14.12,16.25,14z M14.83,17.64l-1.73-0.73 c-0.56,0.6-1.3,1.04-2.13,1.23L10.73,20H9.27l-0.23-1.86c-0.83-0.19-1.57-0.63-2.13-1.23l-1.73,0.73l-0.73-1.27l1.49-1.13 c-0.12-0.39-0.18-0.8-0.18-1.23c0-0.43,0.06-0.84,0.18-1.23l-1.49-1.13l0.73-1.27l1.73,0.73c0.56-0.6,1.3-1.04,2.13-1.23L9.27,8 h1.47l0.23,1.86c0.83,0.19,1.57,0.63,2.13,1.23l1.73-0.73l0.73,1.27l-1.49,1.13c0.12,0.39,0.18,0.8,0.18,1.23 c0,0.43-0.06,0.84-0.18,1.23l1.49,1.13L14.83,17.64z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92s2.92-1.31 2.92-2.92c0-1.61-1.31-2.92-2.92-2.92zM18 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM6 13c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm12 7.02c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></svg>

After

Width:  |  Height:  |  Size: 679 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M22 19h-6v-4h-2.68c-1.14 2.42-3.6 4-6.32 4-3.86 0-7-3.14-7-7s3.14-7 7-7c2.72 0 5.17 1.58 6.32 4H24v6h-2v4zm-4-2h2v-4h2v-2H11.94l-.23-.67C11.01 8.34 9.11 7 7 7c-2.76 0-5 2.24-5 5s2.24 5 5 5c2.11 0 4.01-1.34 4.71-3.33l.23-.67H18v4zM7 15c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3zm0-4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z"/></svg>

After

Width:  |  Height:  |  Size: 498 B

@@ -0,0 +1,62 @@
{
"images" : [
{
"filename" : "icon_40x40.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "icon_60x60.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "icon_58x58.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "icon_87x87.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "icon_80x80.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "icon_120x120.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "icon_120x120-1.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "icon_180x180.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "icon_1024x1024.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+6
View File
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
+53 -23
View File
@@ -16,8 +16,9 @@
#include "ui/pages_logic/AppSettingsLogic.h"
#include "ui/pages_logic/GeneralSettingsLogic.h"
#include "ui/pages_logic/NetworkSettingsLogic.h"
#include "ui/pages_logic/ServerConfiguringProgressLogic.h"
#include "ui/pages_logic/NewServerProtocolsLogic.h"
#include "ui/pages_logic/QrDecoderLogic.h"
#include "ui/pages_logic/ServerConfiguringProgressLogic.h"
#include "ui/pages_logic/ServerContainersLogic.h"
#include "ui/pages_logic/ServerListLogic.h"
#include "ui/pages_logic/ServerSettingsLogic.h"
@@ -34,6 +35,8 @@
#include "ui/uilogic.h"
#include "QZXing.h"
#include "debug.h"
#include "defines.h"
@@ -48,6 +51,10 @@
#include "Windows.h"
#endif
#if defined(Q_OS_ANDROID)
#include "native.h"
#endif
static void loadTranslator()
{
QTranslator* translator = new QTranslator;
@@ -79,10 +86,15 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
#endif
#ifdef Q_OS_WIN
AllowSetForegroundWindow(0);
#endif
#if defined(Q_OS_ANDROID)
NativeHelpers::registerApplicationInstance(&app);
#endif
loadTranslator();
QFontDatabase::addApplicationFont(":/fonts/Lato-Black.ttf");
@@ -108,14 +120,32 @@ int main(int argc, char *argv[])
QCommandLineOption c_autostart {{"a", "autostart"}, "System autostart"};
parser.addOption(c_autostart);
QCommandLineOption c_cleanup {{"c", "cleanup"}, "Cleanup logs"};
parser.addOption(c_cleanup);
parser.process(app);
if (!Debug::init()) {
qWarning() << "Initialization of debug subsystem failed";
if (parser.isSet(c_cleanup)) {
Debug::cleanUp();
QTimer::singleShot(100,[&app]{
app.quit();
});
app.exec();
return 0;
}
Settings settings;
if (settings.isSaveLogs()) {
if (!Debug::init()) {
qWarning() << "Initialization of debug subsystem failed";
}
}
app.setQuitOnLastWindowClosed(false);
QZXing::registerQMLTypes();
qRegisterMetaType<VpnProtocol::VpnConnectionState>("VpnProtocol::VpnConnectionState");
qRegisterMetaType<ServerCredentials>("ServerCredentials");
@@ -151,13 +181,16 @@ int main(int argc, char *argv[])
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine->rootContext()->setContextProperty("Debug", &Debug::Instance());
engine->rootContext()->setContextProperty("UiLogic", uiLogic);
engine->rootContext()->setContextProperty("AppSettingsLogic", uiLogic->appSettingsLogic());
engine->rootContext()->setContextProperty("GeneralSettingsLogic", uiLogic->generalSettingsLogic());
engine->rootContext()->setContextProperty("NetworkSettingsLogic", uiLogic->networkSettingsLogic());
engine->rootContext()->setContextProperty("ServerConfiguringProgressLogic", uiLogic->serverConfiguringProgressLogic());
engine->rootContext()->setContextProperty("NewServerProtocolsLogic", uiLogic->newServerProtocolsLogic());
engine->rootContext()->setContextProperty("QrDecoderLogic", uiLogic->qrDecoderLogic());
engine->rootContext()->setContextProperty("ServerConfiguringProgressLogic", uiLogic->serverConfiguringProgressLogic());
engine->rootContext()->setContextProperty("ServerListLogic", uiLogic->serverListLogic());
engine->rootContext()->setContextProperty("ServerSettingsLogic", uiLogic->serverSettingsLogic());
engine->rootContext()->setContextProperty("ServerContainersLogic", uiLogic->serverprotocolsLogic());
@@ -181,26 +214,23 @@ int main(int argc, char *argv[])
uiLogic->setQmlRoot(engine->rootObjects().at(0));
}
#ifdef Q_OS_WIN
if (parser.isSet("a")) uiLogic->showOnStartup();
else emit uiLogic->show();
#else
uiLogic->showOnStartup();
#endif
// TODO - fix
//#ifdef Q_OS_WIN
// if (parser.isSet("a")) mainWindow.showOnStartup();
// else mainWindow.show();
//#else
// mainWindow.showOnStartup();
//#endif
// TODO - fix
//#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
// if (app.isPrimary()) {
// QObject::connect(&app, &SingleApplication::instanceStarted, &mainWindow, [&](){
// qDebug() << "Secondary instance started, showing this window instead";
// mainWindow.show();
// mainWindow.showNormal();
// mainWindow.raise();
// });
// }
//#endif
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
if (app.isPrimary()) {
QObject::connect(&app, &SingleApplication::instanceStarted, uiLogic, [&](){
qDebug() << "Secondary instance started, showing this window instead";
emit uiLogic->show();
emit uiLogic->raise();
});
}
#endif
return app.exec();
}
+54
View File
@@ -0,0 +1,54 @@
#include "native.h"
#include <QMetaObject>
#if defined(Q_OS_ANDROID)
#include <jni.h>
#endif // Q_OS_ANDROID
QObject *NativeHelpers::application_p_ = 0;
#if defined(Q_OS_ANDROID)
// define our native static functions
// these are the functions that Java part will call directly from Android UI thread
static void onPermissionsGranted(JNIEnv * /*env*/, jobject /*obj*/)
{
QMetaObject::invokeMethod(NativeHelpers::getApplicationInstance(), "onPermissionsGranted"
, Qt::QueuedConnection);
}
static void onPermissionsDenied(JNIEnv * /*env*/, jobject /*obj*/)
{
QMetaObject::invokeMethod(NativeHelpers::getApplicationInstance(), "onPermissionsDenied"
, Qt::QueuedConnection);
}
//create a vector with all our JNINativeMethod(s)
static JNINativeMethod methods[] = {
{"onPermissionsGranted", "()V", (void *)onPermissionsGranted},
{"onPermissionsDenied", "()V", (void *)onPermissionsDenied},
};
// this method is called automatically by Java after the .so file is loaded
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
{
JNIEnv* env;
// get the JNIEnv pointer.
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
return JNI_ERR;
// search for Java class which declares the native methods
jclass javaClass = env->FindClass("org/ftylitak/qzxing/NativeFunctions");
if (!javaClass)
return JNI_ERR;
// register our native methods
if (env->RegisterNatives(javaClass, methods,
sizeof(methods) / sizeof(methods[0])) < 0) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
#endif // Q_OS_ANDROID
+20
View File
@@ -0,0 +1,20 @@
#ifndef NATIVE_H
#define NATIVE_H
#include <QObject>
class NativeHelpers {
public:
static void registerApplicationInstance(QObject *app_p) {
application_p_ = app_p;
}
static QObject* getApplicationInstance() {
return application_p_;
}
private:
static QObject *application_p_;
};
#endif // NATIVE_H
+260 -85
View File
@@ -4,94 +4,72 @@
import Foundation
import NetworkExtension
import os
import OpenVPNAdapter
enum TunnelProtoType: String {
case wireguard, openvpn, none
}
class PacketTunnelProvider: NEPacketTunnelProvider {
private lazy var wgAdapter: WireGuardAdapter = {
return WireGuardAdapter(with: self) { logLevel, message in
wg_log(logLevel.osLogLevel, message: message)
}
}()
private lazy var ovpnAdapter: OpenVPNAdapter = {
let adapter = OpenVPNAdapter()
adapter.delegate = self
return adapter
}()
let vpnReachability = OpenVPNReachability()
var startHandler: ((Error?) -> Void)?
var stopHandler: (() -> Void)?
var protoType: TunnelProtoType = .wireguard
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
let activationAttemptId = options?["activationAttemptId"] as? String
let errorNotifier = ErrorNotifier(activationAttemptId: activationAttemptId)
Logger.configureGlobal(tagged: "NET", withFilePath: FileManager.logFileURL?.path)
wg_log(.info, message: "Starting tunnel from the " + (activationAttemptId == nil ? "OS directly, rather than the app" : "app"))
guard let tunnelProviderProtocol = self.protocolConfiguration as? NETunnelProviderProtocol,
let tunnelConfiguration = tunnelProviderProtocol.asTunnelConfiguration() else {
errorNotifier.notify(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
completionHandler(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
return
if let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
let providerConfiguration = protocolConfiguration.providerConfiguration,
let _: Data = providerConfiguration["ovpn"] as? Data {
protoType = .openvpn
} else {
protoType = .wireguard
}
// Start the tunnel
wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
guard let adapterError = adapterError else {
let interfaceName = self.wgAdapter.interfaceName ?? "unknown"
wg_log(.info, message: "Tunnel interface is \(interfaceName)")
completionHandler(nil)
return
}
switch adapterError {
case .cannotLocateTunnelFileDescriptor:
wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor")
errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
case .dnsResolution(let dnsErrors):
let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address }
.joined(separator: ", ")
wg_log(.error, message: "DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)")
errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure)
completionHandler(PacketTunnelProviderError.dnsResolutionFailure)
case .setNetworkSettings(let error):
wg_log(.error, message: "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
case .startWireGuardBackend(let errorCode):
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)")
errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
completionHandler(PacketTunnelProviderError.couldNotStartBackend)
case .invalidState:
// Must never happen
fatalError()
}
switch protoType {
case .wireguard:
startWireguard(activationAttemptId: activationAttemptId,
errorNotifier: errorNotifier,
completionHandler: completionHandler)
case .openvpn:
startOpenVPN(completionHandler: completionHandler)
case .none:
break
}
}
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
wg_log(.info, staticMessage: "Stopping tunnel")
wgAdapter.stop { error in
ErrorNotifier.removeLastErrorFile()
if let error = error {
wg_log(.error, message: "Failed to stop WireGuard adapter: \(error.localizedDescription)")
}
completionHandler()
#if os(macOS)
// HACK: This is a filthy hack to work around Apple bug 32073323 (dup'd by us as 47526107).
// Remove it when they finally fix this upstream and the fix has been rolled out to
// sufficient quantities of users.
exit(0)
#endif
switch protoType {
case .wireguard:
stopWireguard(with: reason, completionHandler: completionHandler)
case .openvpn:
stopOpenVPN(with: reason, completionHandler: completionHandler)
case .none:
break
}
}
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
guard let completionHandler = completionHandler else { return }
if messageData.count == 1 && messageData[0] == 0 {
wgAdapter.getRuntimeConfiguration { settings in
var data: Data?
@@ -108,31 +86,144 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
completionHandler(nil)
return
}
do {
let tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: configString)
wgAdapter.update(tunnelConfiguration: tunnelConfiguration) { error in
if let error = error {
wg_log(.error, message: "Failed to switch tunnel configuration: \(error.localizedDescription)")
completionHandler(nil)
return
let tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: configString)
wgAdapter.update(tunnelConfiguration: tunnelConfiguration) { error in
if let error = error {
wg_log(.error, message: "Failed to switch tunnel configuration: \(error.localizedDescription)")
completionHandler(nil)
return
}
self.wgAdapter.getRuntimeConfiguration { settings in
var data: Data?
if let settings = settings {
data = settings.data(using: .utf8)!
}
completionHandler(data)
}
}
self.wgAdapter.getRuntimeConfiguration { settings in
var data: Data?
if let settings = settings {
data = settings.data(using: .utf8)!
}
completionHandler(data)
}
}
} catch {
completionHandler(nil)
completionHandler(nil)
}
} else {
completionHandler(nil)
}
}
// MARK: Private methods
private func startWireguard(activationAttemptId: String?,
errorNotifier: ErrorNotifier,
completionHandler: @escaping (Error?) -> Void) {
guard let tunnelProviderProtocol = self.protocolConfiguration as? NETunnelProviderProtocol,
let tunnelConfiguration = tunnelProviderProtocol.asTunnelConfiguration() else {
errorNotifier.notify(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
completionHandler(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
return
}
wg_log(.info, message: "Starting wireguard tunnel from the " + (activationAttemptId == nil ? "OS directly, rather than the app" : "app"))
// Start the tunnel
wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
guard let adapterError = adapterError else {
let interfaceName = self.wgAdapter.interfaceName ?? "unknown"
wg_log(.info, message: "Tunnel interface is \(interfaceName)")
completionHandler(nil)
return
}
switch adapterError {
case .cannotLocateTunnelFileDescriptor:
wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor")
errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
case .dnsResolution(let dnsErrors):
let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address }
.joined(separator: ", ")
wg_log(.error, message: "DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)")
errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure)
completionHandler(PacketTunnelProviderError.dnsResolutionFailure)
case .setNetworkSettings(let error):
wg_log(.error, message: "Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
case .startWireGuardBackend(let errorCode):
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)")
errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
completionHandler(PacketTunnelProviderError.couldNotStartBackend)
case .invalidState:
// Must never happen
fatalError()
}
}
}
private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) {
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
let providerConfiguration = protocolConfiguration.providerConfiguration,
let ovpnConfiguration: Data = providerConfiguration["ovpn"] as? Data else {
return
}
let configuration = OpenVPNConfiguration()
configuration.fileContent = ovpnConfiguration
// configuration.settings = [] // Additional setting if needed any
// configuration.tunPersist = true // keep tun active during pauses/reconections
let evaluation: OpenVPNConfigurationEvaluation
do {
evaluation = try ovpnAdapter.apply(configuration: configuration)
} catch {
completionHandler(error)
return
}
if !evaluation.autologin {
print("Implement login with user credentials")
}
vpnReachability.startTracking { [weak self] status in
guard status == .reachableViaWiFi else { return }
self?.ovpnAdapter.reconnect(afterTimeInterval: 5)
}
startHandler = completionHandler
ovpnAdapter.connect(using: packetFlow)
}
private func stopWireguard(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
wg_log(.info, staticMessage: "Stopping tunnel")
wgAdapter.stop { error in
ErrorNotifier.removeLastErrorFile()
if let error = error {
wg_log(.error, message: "Failed to stop WireGuard adapter: \(error.localizedDescription)")
}
completionHandler()
#if os(macOS)
// HACK: This is a filthy hack to work around Apple bug 32073323 (dup'd by us as 47526107).
// Remove it when they finally fix this upstream and the fix has been rolled out to
// sufficient quantities of users.
exit(0)
#endif
}
}
private func stopOpenVPN(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
stopHandler = completionHandler
if vpnReachability.isTracking {
vpnReachability.stopTracking()
}
ovpnAdapter.disconnect()
}
}
extension WireGuardLogLevel {
@@ -145,3 +236,87 @@ extension WireGuardLogLevel {
}
}
}
extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {}
extension PacketTunnelProvider: OpenVPNAdapterDelegate {
// OpenVPNAdapter calls this delegate method to configure a VPN tunnel.
// `completionHandler` callback requires an object conforming to `OpenVPNAdapterPacketFlow`
// protocol if the tunnel is configured without errors. Otherwise send nil.
// `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so
// you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and
// send `self.packetFlow` to `completionHandler` callback.
func openVPNAdapter(
_ openVPNAdapter: OpenVPNAdapter,
configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?,
completionHandler: @escaping (Error?) -> Void
) {
// In order to direct all DNS queries first to the VPN DNS servers before the primary DNS servers
// send empty string to NEDNSSettings.matchDomains
networkSettings?.dnsSettings?.matchDomains = [""]
// Set the network settings for the current tunneling session.
setTunnelNetworkSettings(networkSettings, completionHandler: completionHandler)
}
// Process events returned by the OpenVPN library
func openVPNAdapter(
_ openVPNAdapter: OpenVPNAdapter,
handleEvent event:
OpenVPNAdapterEvent, message: String?
) {
switch event {
case .connected:
if reasserting {
reasserting = false
}
guard let startHandler = startHandler else { return }
startHandler(nil)
self.startHandler = nil
case .disconnected:
guard let stopHandler = stopHandler else { return }
if vpnReachability.isTracking {
vpnReachability.stopTracking()
}
stopHandler()
self.stopHandler = nil
case .reconnecting:
reasserting = true
default:
break
}
}
// Handle errors thrown by the OpenVPN library
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) {
// Handle only fatal errors
guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool,
fatal == true else { return }
if vpnReachability.isTracking {
vpnReachability.stopTracking()
}
if let startHandler = startHandler {
startHandler(error)
self.startHandler = nil
} else {
cancelTunnelWithError(error)
}
}
// Use this method to process any log message returned by OpenVPN library.
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) {
// Handle log messages
}
}
+271 -15
View File
@@ -5,7 +5,7 @@
import Foundation
import NetworkExtension
let vpnName = "AmneziaVPN"
let vpnName = "Amnezia WireguardVPN"
var vpnBundleID = "";
@objc class VPNIPAddressRange : NSObject {
@@ -30,27 +30,32 @@ public class IOSVpnProtocolImpl : NSObject {
private var deviceIpv4Address: String? = nil
private var deviceIpv6Address: String? = nil
@objc enum IOSConnectionState: Int { case Error, Connected, Disconnected }
@objc init(bundleID: String, privateKey: Data, deviceIpv4Address: String, deviceIpv6Address: String, closure: @escaping (IOSConnectionState, Date?) -> Void, callback: @escaping (Bool) -> Void) {
@objc enum ConnectionState: Int { case Error, Connected, Disconnected }
@objc init(bundleID: String,
config: String,
closure: @escaping (ConnectionState, Date?) -> Void,
callback: @escaping (Bool) -> Void) {
super.init()
Logger.configureGlobal(tagged: "APP", withFilePath: "")
print("Config from caller: \(config)")
vpnBundleID = bundleID;
precondition(!vpnBundleID.isEmpty)
stateChangeCallback = callback
self.privateKey = PrivateKey(rawValue: privateKey)
self.deviceIpv4Address = deviceIpv4Address
self.deviceIpv6Address = deviceIpv6Address
NotificationCenter.default.addObserver(self, selector: #selector(self.vpnStatusDidChange(notification:)), name: Notification.Name.NEVPNStatusDidChange, object: nil)
NotificationCenter.default.removeObserver(self)
NotificationCenter.default.addObserver(self,
selector: #selector(self.vpnStatusDidChange(notification:)),
name: Notification.Name.NEVPNStatusDidChange,
object: nil)
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
if let error = error {
Logger.global?.log(message: "Loading from preference failed: \(error)")
closure(IOSConnectionState.Error, nil)
closure(ConnectionState.Error, nil)
return
}
@@ -64,11 +69,22 @@ public class IOSVpnProtocolImpl : NSObject {
print("We have received \(nsManagers.count) managers.")
let tunnel = nsManagers.first(where: IOSVpnProtocolImpl.isOurManager(_:))
// if let name = tunnel?.localizedDescription, name == vpnName {
// tunnel?.removeFromPreferences(completionHandler: { removeError in
// if let error = removeError {
// Logger.global?.log(message: "WireguardVPN Tunnel Remove from Prefs Error: \(error)")
// closure(ConnectionState.Error, nil)
// return
// }
// })
// }
if tunnel == nil {
Logger.global?.log(message: "Creating the tunnel")
print("Creating the tunnel")
self!.tunnel = NETunnelProviderManager()
closure(IOSConnectionState.Disconnected, nil)
closure(ConnectionState.Disconnected, nil)
return
}
@@ -77,9 +93,80 @@ public class IOSVpnProtocolImpl : NSObject {
self!.tunnel = tunnel
if tunnel?.connection.status == .connected {
closure(IOSConnectionState.Connected, tunnel?.connection.connectedDate)
closure(ConnectionState.Connected, tunnel?.connection.connectedDate)
} else {
closure(IOSConnectionState.Disconnected, nil)
closure(ConnectionState.Disconnected, nil)
}
}
}
@objc init(bundleID: String,
privateKey: Data,
deviceIpv4Address: String,
deviceIpv6Address: String,
closure: @escaping (ConnectionState, Date?) -> Void,
callback: @escaping (Bool) -> Void) {
super.init()
Logger.configureGlobal(tagged: "APP", withFilePath: "")
vpnBundleID = bundleID;
precondition(!vpnBundleID.isEmpty)
stateChangeCallback = callback
self.privateKey = PrivateKey(rawValue: privateKey)
self.deviceIpv4Address = deviceIpv4Address
self.deviceIpv6Address = deviceIpv6Address
NotificationCenter.default.removeObserver(self)
NotificationCenter.default.addObserver(self, selector: #selector(self.vpnStatusDidChange(notification:)), name: Notification.Name.NEVPNStatusDidChange, object: nil)
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
if let error = error {
Logger.global?.log(message: "Loading from preference failed: \(error)")
closure(ConnectionState.Error, nil)
return
}
if self == nil {
Logger.global?.log(message: "We are shutting down.")
return
}
let nsManagers = managers ?? []
Logger.global?.log(message: "We have received \(nsManagers.count) managers.")
print("We have received \(nsManagers.count) managers.")
let tunnel = nsManagers.first(where: IOSVpnProtocolImpl.isOurManager(_:))
// if let name = tunnel?.localizedDescription, name != vpnName {
// tunnel?.removeFromPreferences(completionHandler: { removeError in
// if let error = removeError {
// Logger.global?.log(message: "OpenVpn Tunnel Remove from Prefs Error: \(error)")
// closure(ConnectionState.Error, nil)
// return
// }
// })
// }
if tunnel == nil {
Logger.global?.log(message: "Creating the tunnel")
print("Creating the tunnel")
self!.tunnel = NETunnelProviderManager()
closure(ConnectionState.Disconnected, nil)
return
}
Logger.global?.log(message: "Tunnel already exists")
print("Tunnel already exists")
self!.tunnel = tunnel
if tunnel?.connection.status == .connected {
closure(ConnectionState.Connected, tunnel?.connection.connectedDate)
} else {
closure(ConnectionState.Disconnected, nil)
}
}
}
@@ -142,6 +229,22 @@ public class IOSVpnProtocolImpl : NSObject {
print("Found the manager with the correct bundle identifier: \(tunnelProto.providerBundleIdentifier!)")
return true
}
@objc func connect(ovpnConfig: String, failureCallback: @escaping () -> Void) {
Logger.global?.log(message: "Connecting")
assert(tunnel != nil)
let addr: String = ovpnConfig
.splitToArray(separator: "\n", trimmingCharacters: nil)
.first { $0.starts(with: "remote ") }
.splitToArray(separator: " ", trimmingCharacters: nil)[1]
print("server: \(addr)")
// Let's remove the previous config if it exists.
(tunnel?.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
self.configureOpenVPNTunnel(serverAddress: addr, config: ovpnConfig, failureCallback: failureCallback)
}
@objc func connect(dnsServer: String, serverIpv6Gateway: String, serverPublicKey: String, presharedKey: String, serverIpv4AddrIn: String, serverPort: Int, allowedIPAddressRanges: Array<VPNIPAddressRange>, ipv6Enabled: Bool, reason: Int, failureCallback: @escaping () -> Void) {
Logger.global?.log(message: "Connecting")
@@ -247,6 +350,46 @@ public class IOSVpnProtocolImpl : NSObject {
}
}
}
func configureOpenVPNTunnel(serverAddress: String, config: String, failureCallback: @escaping () -> Void) {
let tunnelProtocol = NETunnelProviderProtocol()
tunnelProtocol.serverAddress = serverAddress
tunnelProtocol.providerBundleIdentifier = vpnBundleID
tunnelProtocol.providerConfiguration = ["ovpn": Data(config.utf8)]
tunnel?.protocolConfiguration = tunnelProtocol
tunnel?.localizedDescription = "Amnezia OpenVPN"
tunnel?.isEnabled = true
tunnel?.saveToPreferences { [unowned self] saveError in
if let error = saveError {
Logger.global?.log(message: "Connect OpenVPN Tunnel Save Error: \(error)")
failureCallback()
return
}
Logger.global?.log(message: "Saving the OpenVPN tunnel succeeded")
self.tunnel?.loadFromPreferences { error in
if let error = error {
Logger.global?.log(message: "Connect OpenVPN Tunnel Load Error: \(error)")
failureCallback()
return
}
Logger.global?.log(message: "Loading the OpenVPN tunnel succeeded")
print("Loading the openvpn tunnel succeeded")
do {
print("starting openvpn tunnel")
try self.tunnel?.connection.startVPNTunnel()
} catch let error {
Logger.global?.log(message: "Something went wrong: \(error)")
failureCallback()
return
}
}
}
}
@objc func disconnect() {
Logger.global?.log(message: "Disconnecting")
@@ -257,7 +400,74 @@ public class IOSVpnProtocolImpl : NSObject {
@objc func checkStatus(callback: @escaping (String, String, String) -> Void) {
Logger.global?.log(message: "Check status")
assert(tunnel != nil)
let protoType = (tunnel!.localizedDescription ?? "").toTunnelType
switch protoType {
case .wireguard:
checkWireguardStatus(callback: callback)
case .openvpn:
checkOVPNStatus(callback: callback)
case .empty:
break
}
}
private func checkOVPNStatus(callback: @escaping (String, String, String) -> Void) {
Logger.global?.log(message: "Check OpenVPN")
guard let proto = tunnel?.protocolConfiguration as? NETunnelProviderProtocol else {
callback("", "", "")
return
}
guard let configData = proto.providerConfiguration?["ovpn"] as? Data,
let ovpnConfig = String(data: configData, encoding: .utf8) else {
callback("", "", "")
return
}
let serverIpv4Gateway: String = ovpnConfig
.splitToArray(separator: "\n", trimmingCharacters: nil)
.first { $0.starts(with: "remote ") }
.splitToArray(separator: " ", trimmingCharacters: nil)[1]
print("server IP: \(serverIpv4Gateway)")
let deviceIpv4Address = getTunIPAddress()
print("device IP: \(serverIpv4Gateway)")
if deviceIpv4Address == nil {
callback("", "", "")
return
}
guard let session = tunnel?.connection as? NETunnelProviderSession else {
callback("", "", "")
return
}
do {
try session.sendProviderMessage(Data([UInt8(0)])) { [callback] data in
guard let data = data,
let configString = String(data: data, encoding: .utf8)
else {
Logger.global?.log(message: "Failed to convert data to string")
callback("", "", "")
return
}
callback("\(serverIpv4Gateway)", "\(deviceIpv4Address!)", configString)
}
} catch {
Logger.global?.log(message: "Failed to retrieve data from session")
callback("", "", "")
}
}
private func checkWireguardStatus(callback: @escaping (String, String, String) -> Void) {
Logger.global?.log(message: "Check Wireguard")
let proto = tunnel!.protocolConfiguration as? NETunnelProviderProtocol
if proto == nil {
callback("", "", "")
@@ -305,4 +515,50 @@ public class IOSVpnProtocolImpl : NSObject {
callback("", "", "")
}
}
private func getTunIPAddress() -> String? {
var address: String? = nil
var interfaces: UnsafeMutablePointer<ifaddrs>? = nil
var temp_addr: UnsafeMutablePointer<ifaddrs>? = nil
var success: Int = 0
// retrieve the current interfaces - returns 0 on success
success = Int(getifaddrs(&interfaces))
if success == 0 {
// Loop through linked list of interfaces
temp_addr = interfaces
while temp_addr != nil {
if temp_addr?.pointee.ifa_addr == nil {
continue
}
if temp_addr?.pointee.ifa_addr.pointee.sa_family == UInt8(AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if let name = temp_addr?.pointee.ifa_name, ((String(utf8String: name)?.contains("tun")) != nil) {
// Get NSString from C String
if let value = temp_addr?.pointee.ifa_addr as? sockaddr_in {
address = String(utf8String: inet_ntoa(value.sin_addr))
}
}
}
temp_addr = temp_addr?.pointee.ifa_next
}
}
freeifaddrs(interfaces)
return address
}
}
enum TunnelType: String {
case wireguard, openvpn, empty
}
extension String {
var toTunnelType: TunnelType {
switch self {
case "wireguard": return .wireguard
case "openvpn": return .openvpn
default:
return .empty
}
}
}
@@ -1,14 +1,13 @@
#include <QCoreApplication>
#include <QFileInfo>
#include <QProcess>
//#include <QRegularExpression>
//#include <QTcpSocket>
#include <QThread>
#include <chrono>
#include "debug.h"
#include "ikev2_vpn_protocol.h"
#include "ikev2_vpn_protocol_windows.h"
#include "utils.h"
static Ikev2Protocol* self = nullptr;
@@ -24,23 +23,19 @@ Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent)
VpnProtocol(configuration, parent)
{
self = this;
//m_configFile.setFileTemplate(QDir::tempPath() + QDir::separator() + serviceName() + ".conf");
readIkev2Configuration(configuration);
}
Ikev2Protocol::~Ikev2Protocol()
{
qDebug() << "IpsecProtocol::~IpsecProtocol()";
#ifdef Q_OS_WIN
disconnect_vpn();
#endif
Ikev2Protocol::stop();
}
void Ikev2Protocol::stop()
{
setConnectionState(VpnProtocol::Disconnecting);
#ifdef Q_OS_WINDOWS
{
if (! disconnect_vpn() ){
qDebug()<<"We don't disconnect";
@@ -50,7 +45,6 @@ void Ikev2Protocol::stop()
setConnectionState(VpnProtocol::Disconnected);
}
}
#endif
}
void Ikev2Protocol::newConnectionStateEventReceived(UINT unMsg, tagRASCONNSTATE rasconnstate, DWORD dwError)
@@ -60,181 +54,117 @@ void Ikev2Protocol::newConnectionStateEventReceived(UINT unMsg, tagRASCONNSTATE
switch (rasconnstate)
{
case RASCS_OpenPort:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
setConnectionState(Preparing);
//printf ("RASCS_OpenPort = %d\n", _connection_state);
//printf ("Opening port...\n");
break;
case RASCS_PortOpened:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
setConnectionState(Preparing);
//printf ("RASCS_PortOpened = %d\n", _connection_state);
//printf ("Port opened.\n");
break;
case RASCS_ConnectDevice:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
setConnectionState(Preparing);
//printf ("RASCS_ConnectDevice = %d\n", _connection_state);
//printf ("Connecting device...\n");
break;
case RASCS_DeviceConnected:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
setConnectionState(Preparing);
//printf ("RASCS_DeviceConnected = %d\n", _connection_state);
//printf ("Device connected.\n");
break;
case RASCS_AllDevicesConnected:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
setConnectionState(Preparing);
//printf ("RASCS_AllDevicesConnected = %d\n", _connection_state);
//printf ("All devices connected.\n");
break;
case RASCS_Authenticate:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
setConnectionState(Preparing);
//printf ("RASCS_Authenticate = %d\n", _connection_state);
// printf ("Authenticating...\n");
break;
case RASCS_AuthNotify:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
if (dwError != 0) {
qDebug() << "have error" << dwError;
//qDebug() << "have error" << dwError;
setConnectionState(Disconnected);
} else {
qDebug() << "RASCS_AuthNotify but no error" << dwError;
//qDebug() << "RASCS_AuthNotify but no error" << dwError;
}
//printf ("RASCS_AuthNotify = %d\n", _connection_state);
// printf ("Authentication notify.\n");
break;
case RASCS_AuthRetry:
qDebug()<<__FUNCTION__ << __LINE__;
//qDebug()<<__FUNCTION__ << __LINE__;
setConnectionState(Preparing);
//printf ("RASCS_AuthRetry = %d\n", _connection_state);
//printf ("Retrying authentication...\n");
break;
case RASCS_AuthCallback:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_AuthCallback = %d\n", _connection_state);
//printf ("Authentication callback...\n");
break;
case RASCS_AuthChangePassword:
qDebug()<<__FUNCTION__ << __LINE__;
// printf ("RASCS_AuthChangePassword = %d\n", _connection_state);
//printf ("Change password...\n");
break;
case RASCS_AuthProject:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_AuthProject = %d\n", _connection_state);
//printf ("Projection phase started...\n");
break;
case RASCS_AuthLinkSpeed:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_AuthLinkSpeed = %d\n", _connection_state);
//printf ("Negoting speed...\n");
break;
case RASCS_AuthAck:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_AuthAck = %d\n", _connection_state);
//printf ("Authentication acknowledge...\n");
break;
case RASCS_ReAuthenticate:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_ReAuthenticate = %d\n", _connection_state);
//printf ("Retrying Authentication...\n");
//qDebug()<<__FUNCTION__ << __LINE__;
break;
case RASCS_Authenticated:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_Authenticated = %d\n", _connection_state);
//printf ("Authentication complete.\n");
//qDebug()<<__FUNCTION__ << __LINE__;
break;
case RASCS_PrepareForCallback:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_PrepareForCallback = %d\n", _connection_state);
//printf ("Preparing for callback...\n");
break;
case RASCS_WaitForModemReset:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_WaitForModemReset = %d\n", _connection_state);
// printf ("Waiting for modem reset...\n");
break;
case RASCS_WaitForCallback:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_WaitForCallback = %d\n", _connection_state);
//printf ("Waiting for callback...\n");
break;
case RASCS_Projected:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_Projected = %d\n", _connection_state);
//printf ("Projection completed.\n");
break;
#if (WINVER >= 0x400)
case RASCS_StartAuthentication: // Windows 95 only
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_StartAuthentication = %d\n", _connection_state);
//printf ("Starting authentication...\n");
break;
case RASCS_CallbackComplete: // Windows 95 only
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_CallbackComplete = %d\n", rasconnstate);
//printf ("Callback complete.\n");
break;
case RASCS_LogonNetwork: // Windows 95 only
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_LogonNetwork = %d\n", _connection_state);
//printf ("Login to the network.\n");
break;
#endif
case RASCS_SubEntryConnected:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_SubEntryConnected = %d\n", _connection_state);
//printf ("Subentry connected.\n");
break;
case RASCS_SubEntryDisconnected:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_SubEntryDisconnected = %d\n", _connection_state);
//printf ("Subentry disconnected.\n");
break;
//PAUSED STATES:
case RASCS_Interactive:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_Interactive = %d\n", _connection_state);
//printf ("In Paused state: Interactive mode.\n");
break;
case RASCS_RetryAuthentication:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_RetryAuthentication = %d\n", _connection_state);
//printf ("In Paused state: Retry Authentication...\n");
break;
case RASCS_CallbackSetByCaller:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_CallbackSetByCaller = %d\n", _connection_state);
//printf ("In Paused state: Callback set by Caller.\n");
break;
case RASCS_PasswordExpired:
setConnectionState(Error);
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_PasswordExpired = %d\n", _connection_state);
//printf ("In Paused state: Password has expired...\n");
break;
case RASCS_Connected: // = RASCS_DONE:
setConnectionState(Connected);
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_Connected = %d\n", _connection_state);
//printf ("Connection completed.\n");
//SetEvent(gEvent_handle);
//qDebug()<<__FUNCTION__ << __LINE__;
break;
case RASCS_Disconnected:
setConnectionState(Disconnected);
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("RASCS_Disconnected = %d\n", _connection_state);
//printf ("Disconnecting...\n");
//qDebug()<<__FUNCTION__ << __LINE__;
break;
default:
qDebug()<<__FUNCTION__ << __LINE__;
//printf ("Unknown Status = %d\n", _connection_state);
//printf ("What are you going to do about it?\n");
//qDebug()<<__FUNCTION__ << __LINE__;
break;
}
}
@@ -246,7 +176,6 @@ void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration)
ErrorCode Ikev2Protocol::start()
{
#ifdef Q_OS_WINDOWS
QByteArray cert = QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8());
setConnectionState(Connecting);
@@ -277,34 +206,10 @@ ErrorCode Ikev2Protocol::start()
});
certInstallProcess->setArguments(arguments);
// qDebug() << arguments.join(" ");
// connect(certInstallProcess.data(), &PrivilegedProcess::errorOccurred, [certInstallProcess](QProcess::ProcessError error) {
// qDebug() << "PrivilegedProcess errorOccurred" << error;
// });
// connect(certInstallProcess.data(), &PrivilegedProcess::stateChanged, [certInstallProcess](QProcess::ProcessState newState) {
// qDebug() << "PrivilegedProcess stateChanged" << newState;
// });
// connect(certInstallProcess.data(), &PrivilegedProcess::readyRead, [certInstallProcess]() {
// auto req = certInstallProcess->readAll();
// req.waitForFinished();
// qDebug() << "PrivilegedProcess readyRead" << req.returnValue();
// });
certInstallProcess->start();
}
// /*
{
// auto adapterRemoveProcess = new QProcess;
// adapterRemoveProcess->setProgram("powershell");
// QString arguments = QString("-command \"Remove-VpnConnection -Name '%1' -Force\"").arg(tunnelName());
// adapterRemoveProcess->setNativeArguments(arguments);
// adapterRemoveProcess->start();
// adapterRemoveProcess->waitForFinished(5000);
if ( disconnect_vpn()){
qDebug()<<"VPN was disconnected";
}
@@ -319,21 +224,6 @@ ErrorCode Ikev2Protocol::start()
qDebug() <<"Can't create the VPN connect";
}
}
// auto adapterInstallProcess = new QProcess;
// adapterInstallProcess->setProgram("powershell");
// QString arguments = QString("-command \"Add-VpnConnection "
// "-ServerAddress '%1' "
// "-Name '%2' "
// "-TunnelType IKEv2 "
// "-AuthenticationMethod MachineCertificate "
// "-EncryptionLevel Required "
// "-PassThru\"")
// .arg(m_config[config_key::hostName].toString())
// .arg(tunnelName());
// adapterInstallProcess->setNativeArguments(arguments);
// adapterInstallProcess->start();
// adapterInstallProcess->waitForFinished(5000);
}
{
@@ -352,10 +242,6 @@ ErrorCode Ikev2Protocol::start()
.arg(tunnelName());
adapterConfigProcess->setNativeArguments(arguments);
// connect(adapterConfigProcess, &QProcess::readyRead, [adapterConfigProcess]() {
// qDebug().noquote() << "adapterConfigProcess readyRead" << adapterConfigProcess->readAll();
// });
adapterConfigProcess->start();
adapterConfigProcess->waitForFinished(5000);
}
@@ -367,13 +253,8 @@ ErrorCode Ikev2Protocol::start()
}
//setConnectionState(Connecting);
return ErrorCode::NoError;
#else
return ErrorCode::NoError;
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifdef Q_OS_WINDOWS
bool Ikev2Protocol::create_new_vpn(const QString & vpn_name,
const QString & serv_addr){
@@ -442,5 +323,3 @@ void WINAPI RasDialFuncCallback(UINT unMsg,
self->newConnectionStateEventReceived(unMsg, rasconnstate, dwError);
}
}
#endif
@@ -1,5 +1,5 @@
#ifndef IPSEC_PROTOCOL_H
#define IPSEC_PROTOCOL_H
#ifndef IKEV2_VPN_PROTOCOL_WINDOWS_H
#define IKEV2_VPN_PROTOCOL_WINDOWS_H
#include <QObject>
#include <QProcess>
@@ -10,7 +10,6 @@
#include "vpnprotocol.h"
#include "core/ipcclient.h"
#ifdef Q_OS_WIN
#include <string>
#include <memory>
#include <atomic>
@@ -31,8 +30,6 @@
#pragma comment(lib, "rasapi32.lib")
#pragma comment(lib, "Crypt32.lib")
#endif
class Ikev2Protocol : public VpnProtocol
{
Q_OBJECT
@@ -54,14 +51,9 @@ public:
private:
void readIkev2Configuration(const QJsonObject &configuration);
#ifdef Q_OS_WIN
//certificates variables
#endif
private:
QJsonObject m_config;
#ifdef Q_OS_WIN
//RAS functions and parametrs
HRASCONN hRasConn{nullptr};
bool create_new_vpn(const QString & vpn_name,
@@ -70,12 +62,8 @@ private:
bool connect_to_vpn(const QString & vpn_name);
bool disconnect_vpn();
#endif
};
#ifdef Q_OS_WIN
DWORD CALLBACK rasCallback(UINT msg, RASCONNSTATE rascs, DWORD err);
#endif
#endif // IPSEC_PROTOCOL_H
#endif // IKEV2_VPN_PROTOCOL_WINDOWS_H
+7
View File
@@ -3,6 +3,7 @@
#include "vpnprotocol.h"
#include "protocols/protocols_defs.h"
#include "json.h"
using namespace amnezia;
@@ -45,6 +46,12 @@ private:
bool m_serviceConnected = false;
bool m_checkingStatus = false;
std::function<void(const QString&)> m_logCallback;
void setupWireguardProtocol(const QtJson::JsonObject& result);
void setupOpenVPNProtocol(const QtJson::JsonObject& result);
void launchWireguardTunnel(const QtJson::JsonObject &result);
void launchOpenVPNTunnel(const QtJson::JsonObject &result);
};
+282 -125
View File
@@ -10,8 +10,6 @@
#include <QByteArray>
#include "json.h"
#include "ipaddressrange.h"
#include "ios_vpnprotocol.h"
#include "core/errorstrings.h"
@@ -21,6 +19,7 @@ namespace
{
IOSVpnProtocol* s_instance = nullptr;
IOSVpnProtocolImpl* m_controller = nullptr;
Proto currentProto = amnezia::Proto::Any;
}
IOSVpnProtocol::IOSVpnProtocol(Proto proto, const QJsonObject &configuration, QObject* parent)
@@ -35,10 +34,9 @@ bool IOSVpnProtocol::initialize()
{
qDebug() << "Initializing Swift Controller";
static bool creating = false;
// No nested creation!
Q_ASSERT(creating == false);
creating = true;
// qDebug() << "config =>";
// qDebug() << QJsonDocument(m_rawConfig).toJson();
if (!m_controller) {
bool ok;
@@ -49,142 +47,69 @@ bool IOSVpnProtocol::initialize()
return false;
}
QString vpnProto = result["protocol"].toString();
qDebug() << "protocol: " << vpnProto;
qDebug() << "config data => ";
QtJson::JsonObject config = result["wireguard_config_data"].toMap();
QString privateKey = config["client_priv_key"].toString();
QByteArray key = QByteArray::fromBase64(privateKey.toLocal8Bit());
qDebug() << " - " << "client_priv_key: " << config["client_priv_key"].toString();
qDebug() << " - " << "client_pub_key: " << config["client_pub_key"].toString();
qDebug() << " - " << "interface config: " << config["config"].toString();
QString addr = config["config"].toString().split("\n").takeAt(1).split(" = ").takeLast();
QString dns = config["config"].toString().split("\n").takeAt(2).split(" = ").takeLast();
QString privkey = config["config"].toString().split("\n").takeAt(3).split(" = ").takeLast();
QString pubkey = config["config"].toString().split("\n").takeAt(6).split(" = ").takeLast();
QString presharedkey = config["config"].toString().split("\n").takeAt(7).split(" = ").takeLast();
QString allowedips = config["config"].toString().split("\n").takeAt(8).split(" = ").takeLast();
QString endpoint = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast();
QString keepalive = config["config"].toString().split("\n").takeAt(10).split(" = ").takeLast();
qDebug() << " - " << "[Interface] address: " << addr;
qDebug() << " - " << "[Interface] dns: " << dns;
qDebug() << " - " << "[Interface] private key: " << privkey;
qDebug() << " - " << "[Peer] public key: " << pubkey;
qDebug() << " - " << "[Peer] preshared key: " << presharedkey;
qDebug() << " - " << "[Peer] allowed ips: " << allowedips;
qDebug() << " - " << "[Peer] endpoint: " << endpoint;
qDebug() << " - " << "[Peer] keepalive: " << keepalive;
qDebug() << " - " << "hostName: " << config["hostName"].toString();
qDebug() << " - " << "psk_key: " << config["psk_key"].toString();
qDebug() << " - " << "server_pub_key: " << config["server_pub_key"].toString();
m_controller = [[IOSVpnProtocolImpl alloc] initWithBundleID:@VPN_NE_BUNDLEID
privateKey:key.toNSData()
deviceIpv4Address:addr.toNSString()
deviceIpv6Address:@"::/0"
closure:^(ConnectionState state, NSDate* date) {
qDebug() << "Creation completed with connection state:" << state;
creating = false;
switch (state) {
case ConnectionStateError: {
[m_controller dealloc];
m_controller = nullptr;
emit connectionStateChanged(VpnConnectionState::Error);
return;
}
case ConnectionStateConnected: {
Q_ASSERT(date);
QDateTime qtDate(QDateTime::fromNSDate(date));
emit connectionStateChanged(VpnConnectionState::Connected);
return;
}
case ConnectionStateDisconnected:
// Just in case we are connecting, let's call disconnect.
[m_controller disconnect];
emit connectionStateChanged(VpnConnectionState::Disconnected);
return;
}
QString protoName = result["protocol"].toString();
qDebug() << "protocol: " << protoName;
if (protoName == "wireguard") {
setupWireguardProtocol(result);
currentProto = amnezia::Proto::WireGuard;
} else if (protoName == "openvpn") {
setupOpenVPNProtocol(result);
currentProto = amnezia::Proto::OpenVpn;
} else {
return false;
}
callback:^(BOOL a_connected) {
qDebug() << "State changed: " << a_connected;
if (a_connected) {
emit connectionStateChanged(Connected);
return;
}
// emit connectionStateChanged(Disconnected);
}];
}
return true;
}
ErrorCode IOSVpnProtocol::start()
{
bool ok;
QtJson::JsonObject result = QtJson::parse(QJsonDocument(m_rawConfig).toJson(), ok).toMap();
qDebug() << "current protocol: " << currentProto;
qDebug() << "new protocol: " << m_protocol;
qDebug() << "config: " << result;
if(!ok) {
qDebug() << QString("An error occurred during config parsing");
return InternalError;
}
QString protocol = result["protocol"].toString();
QtJson::JsonObject config = result["wireguard_config_data"].toMap();
QString clientPrivateKey = config["client_priv_key"].toString();
QByteArray key = QByteArray::fromBase64(clientPrivateKey.toLocal8Bit());
QString clientPubKey = config["client_pub_key"].toString();
QString addr = config["config"].toString().split("\n").takeAt(1).split(" = ").takeLast();
QStringList dnsServersList = config["config"].toString().split("\n").takeAt(2).split(" = ").takeLast().split(", ");
QString privkey = config["config"].toString().split("\n").takeAt(3).split(" = ").takeLast();
QString pubkey = config["config"].toString().split("\n").takeAt(6).split(" = ").takeLast();
QString presharedkey = config["config"].toString().split("\n").takeAt(7).split(" = ").takeLast();
QStringList allowedIPList = config["config"].toString().split("\n").takeAt(8).split(" = ").takeLast().split(", ");
QString endpoint = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast();
QString serverAddr = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast().split(":").takeFirst();
QString port = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast().split(":").takeLast();
QString keepalive = config["config"].toString().split("\n").takeAt(10).split(" = ").takeLast();
QString hostname = config["hostName"].toString();
QString pskKey = config["psk_key"].toString();
QString serverPubKey = config["server_pub_key"].toString();
qDebug() << "IOSVPNProtocol starts for" << hostname;
qDebug() << "DNS:" << dnsServersList.takeFirst().toNSString();
qDebug() << "serverPublicKey:" << serverPubKey.toNSString();
qDebug() << "serverIpv4AddrIn:" << serverAddr.toNSString();
qDebug() << "serverPort:" << (uint32_t)port.toInt();
qDebug() << "allowed ip list" << allowedIPList;
NSMutableArray<VPNIPAddressRange*>* allowedIPAddressRangesNS =
[NSMutableArray<VPNIPAddressRange*> arrayWithCapacity:allowedIPList.length()];
for (const IPAddressRange item : allowedIPList) {
VPNIPAddressRange* range =
[[VPNIPAddressRange alloc] initWithAddress:item.ipAddress().toNSString()
networkPrefixLength:item.range()
isIpv6:item.type() == IPAddressRange::IPv6];
[allowedIPAddressRangesNS addObject:[range autorelease]];
switch (m_protocol) {
case amnezia::Proto::OpenVpn:
if (currentProto == amnezia::Proto::WireGuard) {
if (m_controller) {
stop();
initialize();
}
launchOpenVPNTunnel(result);
currentProto = amnezia::Proto::OpenVpn;
return NoError;
}
initialize();
launchOpenVPNTunnel(result);
break;
case amnezia::Proto::WireGuard:
if (currentProto == amnezia::Proto::OpenVpn) {
if (m_controller) {
stop();
initialize();
}
launchWireguardTunnel(result);
currentProto = amnezia::Proto::WireGuard;
return NoError;
}
initialize();
launchWireguardTunnel(result);
break;
default:
break;
}
[m_controller connectWithDnsServer:dnsServersList.takeFirst().toNSString()
serverIpv6Gateway:@"FE80::1"
serverPublicKey:serverPubKey.toNSString()
presharedKey:pskKey.toNSString()
serverIpv4AddrIn:serverAddr.toNSString()
serverPort:port.toInt()
allowedIPAddressRanges:allowedIPAddressRangesNS
ipv6Enabled:NO
reason:0
failureCallback:^() {
qDebug() << "IOSVPNProtocol - connection failed";
emit connectionStateChanged(Disconnected);
}];
return NoError;
}
@@ -192,11 +117,21 @@ void IOSVpnProtocol::stop()
{
if (!m_controller) {
qDebug() << "Not correctly initialized";
emit connectionStateChanged(Disconnected);
// dispatch_async(dispatch_get_main_queue(), ^{
// emit connectionStateChanged(Disconnected);
// });
return;
}
[m_controller disconnect];
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(Disconnected);
});
[m_controller dealloc];
m_controller = nullptr;
}
void IOSVpnProtocol::resume_start()
@@ -296,3 +231,225 @@ void IOSVpnProtocol::cleanupBackendLogs()
file.remove();
}
void IOSVpnProtocol::setupWireguardProtocol(const QtJson::JsonObject &result)
{
static bool creating = false;
// No nested creation!
Q_ASSERT(creating == false);
creating = true;
QtJson::JsonObject config = result["wireguard_config_data"].toMap();
QString privateKey = config["client_priv_key"].toString();
QByteArray key = QByteArray::fromBase64(privateKey.toLocal8Bit());
qDebug() << " - " << "client_priv_key: " << config["client_priv_key"].toString();
qDebug() << " - " << "client_pub_key: " << config["client_pub_key"].toString();
qDebug() << " - " << "interface config: " << config["config"].toString();
QString addr = config["config"].toString().split("\n").takeAt(1).split(" = ").takeLast();
QString dns = config["config"].toString().split("\n").takeAt(2).split(" = ").takeLast();
QString privkey = config["config"].toString().split("\n").takeAt(3).split(" = ").takeLast();
QString pubkey = config["config"].toString().split("\n").takeAt(6).split(" = ").takeLast();
QString presharedkey = config["config"].toString().split("\n").takeAt(7).split(" = ").takeLast();
QString allowedips = config["config"].toString().split("\n").takeAt(8).split(" = ").takeLast();
QString endpoint = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast();
QString keepalive = config["config"].toString().split("\n").takeAt(10).split(" = ").takeLast();
qDebug() << " - " << "[Interface] address: " << addr;
qDebug() << " - " << "[Interface] dns: " << dns;
qDebug() << " - " << "[Interface] private key: " << privkey;
qDebug() << " - " << "[Peer] public key: " << pubkey;
qDebug() << " - " << "[Peer] preshared key: " << presharedkey;
qDebug() << " - " << "[Peer] allowed ips: " << allowedips;
qDebug() << " - " << "[Peer] endpoint: " << endpoint;
qDebug() << " - " << "[Peer] keepalive: " << keepalive;
qDebug() << " - " << "hostName: " << config["hostName"].toString();
qDebug() << " - " << "psk_key: " << config["psk_key"].toString();
qDebug() << " - " << "server_pub_key: " << config["server_pub_key"].toString();
m_controller = [[IOSVpnProtocolImpl alloc] initWithBundleID:@VPN_NE_BUNDLEID
privateKey:key.toNSData()
deviceIpv4Address:addr.toNSString()
deviceIpv6Address:@"::/0"
closure:^(ConnectionState state, NSDate* date) {
qDebug() << "Creation completed with connection state:" << state;
creating = false;
switch (state) {
case ConnectionStateError: {
[m_controller dealloc];
m_controller = nullptr;
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(VpnConnectionState::Error);
});
return;
}
case ConnectionStateConnected: {
Q_ASSERT(date);
QDateTime qtDate(QDateTime::fromNSDate(date));
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(VpnConnectionState::Connected);
});
return;
}
case ConnectionStateDisconnected:
// Just in case we are connecting, let's call disconnect.
[m_controller disconnect];
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(VpnConnectionState::Disconnected);
});
return;
}
}
callback:^(BOOL a_connected) {
if (currentProto != m_protocol) {
qDebug() << "Protocols switched: " << a_connected;
return;
}
qDebug() << "State changed: " << a_connected;
if (a_connected) {
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(Connected);
});
return;
}
// dispatch_async(dispatch_get_main_queue(), ^{
// emit connectionStateChanged(Disconnected);
// });
}];
}
void IOSVpnProtocol::setupOpenVPNProtocol(const QtJson::JsonObject &result)
{
static bool creating = false;
// No nested creation!
Q_ASSERT(creating == false);
creating = true;
QtJson::JsonObject ovpn = result["openvpn_config_data"].toMap();
QString ovpnConfig = ovpn["config"].toString();
// qDebug() << ovpn;
m_controller = [[IOSVpnProtocolImpl alloc] initWithBundleID:@VPN_NE_BUNDLEID
config:ovpnConfig.toNSString()
closure:^(ConnectionState state, NSDate* date) {
qDebug() << "OVPN Creation completed with connection state:" << state;
creating = false;
switch (state) {
case ConnectionStateError: {
[m_controller dealloc];
m_controller = nullptr;
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(VpnConnectionState::Error);
});
return;
}
case ConnectionStateConnected: {
Q_ASSERT(date);
QDateTime qtDate(QDateTime::fromNSDate(date));
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(VpnConnectionState::Connected);
});
return;
}
case ConnectionStateDisconnected:
// Just in case we are connecting, let's call disconnect.
// [m_controller disconnect];
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(VpnConnectionState::Disconnected);
});
return;
}
}
callback:^(BOOL a_connected) {
if (currentProto != m_protocol) {
qDebug() << "Protocols switched: " << a_connected;
return;
}
qDebug() << "OVPN State changed: " << a_connected;
if (a_connected) {
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(Connected);
});
return;
}
// dispatch_async(dispatch_get_main_queue(), ^{
// emit connectionStateChanged(Disconnected);
// });
}];
}
void IOSVpnProtocol::launchWireguardTunnel(const QtJson::JsonObject &result)
{
QtJson::JsonObject config = result["wireguard_config_data"].toMap();
QString clientPrivateKey = config["client_priv_key"].toString();
QByteArray key = QByteArray::fromBase64(clientPrivateKey.toLocal8Bit());
QString clientPubKey = config["client_pub_key"].toString();
QString addr = config["config"].toString().split("\n").takeAt(1).split(" = ").takeLast();
QStringList dnsServersList = config["config"].toString().split("\n").takeAt(2).split(" = ").takeLast().split(", ");
QString privkey = config["config"].toString().split("\n").takeAt(3).split(" = ").takeLast();
QString pubkey = config["config"].toString().split("\n").takeAt(6).split(" = ").takeLast();
QString presharedkey = config["config"].toString().split("\n").takeAt(7).split(" = ").takeLast();
QStringList allowedIPList = config["config"].toString().split("\n").takeAt(8).split(" = ").takeLast().split(", ");
QString endpoint = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast();
QString serverAddr = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast().split(":").takeFirst();
QString port = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast().split(":").takeLast();
QString keepalive = config["config"].toString().split("\n").takeAt(10).split(" = ").takeLast();
QString hostname = config["hostName"].toString();
QString pskKey = config["psk_key"].toString();
QString serverPubKey = config["server_pub_key"].toString();
qDebug() << "IOSVPNProtocol starts for" << hostname;
qDebug() << "DNS:" << dnsServersList.takeFirst().toNSString();
qDebug() << "serverPublicKey:" << serverPubKey.toNSString();
qDebug() << "serverIpv4AddrIn:" << serverAddr.toNSString();
qDebug() << "serverPort:" << (uint32_t)port.toInt();
qDebug() << "allowed ip list" << allowedIPList;
NSMutableArray<VPNIPAddressRange*>* allowedIPAddressRangesNS =
[NSMutableArray<VPNIPAddressRange*> arrayWithCapacity:allowedIPList.length()];
for (const IPAddressRange item : allowedIPList) {
VPNIPAddressRange* range =
[[VPNIPAddressRange alloc] initWithAddress:item.ipAddress().toNSString()
networkPrefixLength:item.range()
isIpv6:item.type() == IPAddressRange::IPv6];
[allowedIPAddressRangesNS addObject:[range autorelease]];
}
[m_controller connectWithDnsServer:dnsServersList.takeFirst().toNSString()
serverIpv6Gateway:@"FE80::1"
serverPublicKey:serverPubKey.toNSString()
presharedKey:pskKey.toNSString()
serverIpv4AddrIn:serverAddr.toNSString()
serverPort:port.toInt()
allowedIPAddressRanges:allowedIPAddressRangesNS
ipv6Enabled:NO
reason:0
failureCallback:^() {
qDebug() << "Wireguard Protocol - connection failed";
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(Disconnected);
});
}];
}
void IOSVpnProtocol::launchOpenVPNTunnel(const QtJson::JsonObject &result)
{
QtJson::JsonObject ovpn = result["openvpn_config_data"].toMap();
QString ovpnConfig = ovpn["config"].toString();
[m_controller connectWithOvpnConfig:ovpnConfig.toNSString()
failureCallback:^{
qDebug() << "IOSVPNProtocol - connection failed";
dispatch_async(dispatch_get_main_queue(), ^{
emit connectionStateChanged(Disconnected);
});
}];
}
+3 -4
View File
@@ -159,8 +159,8 @@ ErrorCode OpenVpnProtocol::start()
return lastError();
}
QString vpnLogFileNamePath = Utils::systemLogPath() + "/openvpn.log";
Utils::createEmptyFile(vpnLogFileNamePath);
// QString vpnLogFileNamePath = Utils::systemLogPath() + "/openvpn.log";
// Utils::createEmptyFile(vpnLogFileNamePath);
if (!m_managementServer.start(m_managementHost, m_managementPort)) {
setLastError(ErrorCode::OpenVpnManagementServerError);
@@ -186,8 +186,7 @@ ErrorCode OpenVpnProtocol::start()
m_openVpnProcess->setProgram(openVpnExecPath());
QStringList arguments({"--config" , configPath(),
"--management", m_managementHost, QString::number(m_managementPort),
"--management-client",
"--log", vpnLogFileNamePath
"--management-client"/*, "--log", vpnLogFileNamePath */
});
m_openVpnProcess->setArguments(arguments);
+8
View File
@@ -15,6 +15,10 @@ constexpr char password[] = "password";
constexpr char port[] = "port";
constexpr char local_port[] = "local_port";
constexpr char dns1[] = "dns1";
constexpr char dns2[] = "dns2";
constexpr char description[] = "description";
constexpr char cert[] = "cert";
constexpr char config[] = "config";
@@ -40,6 +44,7 @@ constexpr char server_priv_key[] = "server_priv_key";
constexpr char server_pub_key[] = "server_pub_key";
constexpr char psk_key[] = "psk_key";
constexpr char client_ip[] = "client_ip"; // internal ip address
constexpr char site[] = "site";
constexpr char block_outside_dns[] = "block_outside_dns";
@@ -54,6 +59,9 @@ constexpr char last_config[] = "last_config";
namespace protocols {
namespace dns {
constexpr char amneziaDnsIp[] = "172.29.172.254";
}
namespace openvpn {
constexpr char defaultSubnetAddress[] = "10.8.0.0";
+7 -2
View File
@@ -9,7 +9,10 @@
#include "shadowsocksvpnprotocol.h"
#include "openvpnovercloakprotocol.h"
#include "wireguardprotocol.h"
#include "ikev2_vpn_protocol.h"
#endif
#ifdef Q_OS_WINDOWS
#include "ikev2_vpn_protocol_windows.h"
#endif
@@ -100,12 +103,14 @@ QString VpnProtocol::vpnGateway() const
VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject& configuration)
{
switch (container) {
#if defined(Q_OS_WINDOWS)
case DockerContainer::Ipsec: return new Ikev2Protocol(configuration);
#endif
#if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
case DockerContainer::OpenVpn: return new OpenVpnProtocol(configuration);
case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration);
case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration);
case DockerContainer::WireGuard: return new WireguardProtocol(configuration);
case DockerContainer::Ipsec: return new Ikev2Protocol(configuration);
#endif
default: return nullptr;
}
+19 -3
View File
@@ -27,11 +27,9 @@
<file>fonts/Lato-Thin.ttf</file>
<file>fonts/Lato-ThinItalic.ttf</file>
<file>images/AmneziaVPN.png</file>
<file>images/server_settings.png</file>
<file>images/share.png</file>
<file>server_scripts/remove_container.sh</file>
<file>server_scripts/setup_host_firewall.sh</file>
<file>images/reload.png</file>
<file>server_scripts/openvpn_cloak/Dockerfile</file>
<file>server_scripts/openvpn_cloak/configure_container.sh</file>
<file>server_scripts/openvpn_cloak/start.sh</file>
@@ -42,7 +40,6 @@
<file>images/check.png</file>
<file>images/uncheck.png</file>
<file>images/settings_grey.png</file>
<file>images/plus.png</file>
<file>server_scripts/check_connection.sh</file>
<file>server_scripts/remove_all_containers.sh</file>
<file>server_scripts/openvpn_cloak/run_container.sh</file>
@@ -141,5 +138,24 @@
<file>images/animation.gif</file>
<file>images/connected.png</file>
<file>images/disconnected.png</file>
<file>ui/qml/Pages/PageQrDecoder.qml</file>
<file>ui/qml/Pages/PageAbout.qml</file>
<file>ui/qml/Controls/RichLabelType.qml</file>
<file>images/svg/gpp_good_black_24dp.svg</file>
<file>ui/qml/Controls/SvgImageType.qml</file>
<file>images/svg/gpp_maybe_black_24dp.svg</file>
<file>images/svg/close_black_24dp.svg</file>
<file>images/svg/delete_black_24dp.svg</file>
<file>images/svg/done_black_24dp.svg</file>
<file>images/svg/format_list_bulleted_black_24dp.svg</file>
<file>images/svg/logout_black_24dp.svg</file>
<file>images/svg/miscellaneous_services_black_24dp.svg</file>
<file>images/svg/refresh_black_24dp.svg</file>
<file>images/svg/settings_black_24dp.svg</file>
<file>images/svg/share_black_24dp.svg</file>
<file>images/svg/vpn_key_black_24dp.svg</file>
<file>images/svg/control_point_black_24dp.svg</file>
<file>images/svg/settings_suggest_black_24dp.svg</file>
<file>ui/qml/Controls/SvgButtonType.qml</file>
</qresource>
</RCC>
+20
View File
@@ -39,6 +39,26 @@ error() {
printv '' R "$1"
}
XCODEBUILD="/usr/bin/xcodebuild"
WORKINGDIR=`pwd`
compile_openvpn_adapter() {
cd 3rd/OpenVPNAdapter
$XCODEBUILD -scheme OpenVPNAdapter -configuration Debug -xcconfig Configuration/amnezia.xcconfig -sdk iphoneos -destination 'generic/platform=iOS' -project OpenVPNAdapter.xcodeproj
cd ../../
}
prepare_to_build_vpn() {
cat $WORKINGDIR/3rd/OpenVPNAdapter/Configuration/Project.xcconfig > $WORKINGDIR/3rd/OpenVPNAdapter/Configuration/amnezia.xcconfig
cat << EOF >> $WORKINGDIR/3rd/OpenVPNAdapter/Configuration/amnezia.xcconfig
PROJECT_TEMP_DIR = $WORKINGDIR/3rd/OpenVPNAdapter/build/OpenVPNAdapter.build
CONFIGURATION_BUILD_DIR = $WORKINGDIR/3rd/OpenVPNAdapter/build/Debug-iphoneos
BUILT_PRODUCTS_DIR = $WORKINGDIR/3rd/OpenVPNAdapter/build/Debug-iphoneos
EOF
}
die() {
if [[ "$1" ]]; then
error "$1"
+11 -1
View File
@@ -126,7 +126,7 @@ printn Y "Retrieve the wireguard-go version... "
print G "done."
printn Y "Cleaning the existing project... "
rm -rf mozillavpn.xcodeproj/ || die "Failed to remove things"
rm -rf AmneziaVPN.xcodeproj/ || die "Failed to remove things"
print G "done."
#print Y "Importing translation files..."
@@ -205,6 +205,16 @@ else
print G none
fi
if [ "$OS" = "ios" ]; then
print Y "Prepare to build OpenVPNAdapter..."
prepare_to_build_vpn
print Y "Building OpenVPNAdapter..."
compile_openvpn_adapter
else
print Y "No OpenVPNAdapter will be built"
fi
print Y "Creating the xcode project via qmake..."
$QMAKE \
VERSION=$SHORTVERSION \
+19 -1
View File
@@ -61,7 +61,8 @@ class XCodeprojPatcher
config.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] ||= 'macos/app/WireGuard-Bridging-Header.h'
config.build_settings['FRAMEWORK_SEARCH_PATHS'] ||= [
"$(inherited)",
"$(PROJECT_DIR)/3rd"
"$(PROJECT_DIR)/3rd",
"$(PROJECT_DIR)/3rd/OpenVPNAdapter/build/Debug-iphoneos"
]
# Versions and names
@@ -251,6 +252,11 @@ class XCodeprojPatcher
config.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] ||= 'macos/networkextension/WireGuardNetworkExtension-Bridging-Header.h'
config.build_settings['SWIFT_PRECOMPILE_BRIDGING_HEADER'] = 'NO'
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'YES'
config.build_settings['FRAMEWORK_SEARCH_PATHS'] ||= [
"$(inherited)",
"$(PROJECT_DIR)/3rd",
"$(PROJECT_DIR)/3rd/OpenVPNAdapter/build/Debug-iphoneos"
]
# Versions and names
config.build_settings['MARKETING_VERSION'] ||= shortVersion
@@ -350,6 +356,18 @@ class XCodeprojPatcher
framework_ref = frameworks_group.new_file('NetworkExtension.framework')
frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Debug-iphoneos/LZ4.framework')
frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Debug-iphoneos/mbedTLS.framework')
frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Debug-iphoneos/OpenVPNClient.framework')
frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('3rd/OpenVPNAdapter/build/Debug-iphoneos/OpenVPNAdapter.framework')
frameworks_build_phase.add_file_reference(framework_ref)
# This fails: @target_main.add_dependency @target_extension
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
+45
View File
@@ -1,3 +1,48 @@
FROM mvance/unbound:latest
LABEL maintainer="AmneziaVPN"
RUN echo " \n\
domain-insecure: \"coin.\"\n\
domain-insecure: \"emc.\"\n\
domain-insecure: \"lib.\"\n\
domain-insecure: \"bazar.\"\n\
domain-insecure: \"enum.\"\n\
\n\
stub-zone:\n\
name: coin.\n\
stub-host: seed1.emercoin.com\n\
stub-host: seed2.emercoin.com\n\
stub-first: yes\n\
\n\
stub-zone:\n\
name: emc.\n\
stub-host: seed1.emercoin.com\n\
stub-host: seed2.emercoin.com\n\
stub-first: yes\n\
\n\
stub-zone:\n\
name: lib.\n\
stub-host: seed1.emercoin.com\n\
stub-host: seed2.emercoin.com\n\
stub-first: yes\n\
\n\
stub-zone:\n\
name: bazar.\n\
stub-host: seed1.emercoin.com\n\
stub-host: seed2.emercoin.com\n\
stub-first: yes\n\
\n\
stub-zone:\n\
name: enum.\n\
stub-host: seed1.emercoin.com\n\
stub-host: seed2.emercoin.com\n\
stub-first: yes\n\
\n\
forward-zone:\n\
name: .\n\
forward-tls-upstream: yes\n\
forward-addr: 1.1.1.1@853 #cloudflare-dns.com\n\
forward-addr: 1.0.0.1@853 #cloudflare-dns.com\n\
" | tee /opt/unbound/etc/unbound/forward-records.conf
+1 -1
View File
@@ -1,2 +1,2 @@
# Run container
sudo docker run -d --restart always --cap-add=NET_ADMIN -p 53:53/udp -p 53:53/tcp --name $CONTAINER_NAME $CONTAINER_NAME
sudo docker run -d --restart always --network amnezia-dns-net --ip=172.29.172.254 -p 53:53/udp -p 53:53/tcp --name $CONTAINER_NAME $CONTAINER_NAME
@@ -5,3 +5,4 @@ sudo docker run \
-d --privileged \
--name $CONTAINER_NAME $CONTAINER_NAME
sudo docker network connect amnezia-dns-net $CONTAINER_NAME
@@ -1,5 +1,11 @@
# Run container
sudo docker run -d --restart always --cap-add=NET_ADMIN -p $OPENVPN_PORT:$OPENVPN_PORT/$OPENVPN_TRANSPORT_PROTO --name $CONTAINER_NAME $CONTAINER_NAME
sudo docker run \
-d --restart always \
--cap-add=NET_ADMIN \
-p $OPENVPN_PORT:$OPENVPN_PORT/$OPENVPN_TRANSPORT_PROTO \
--name $CONTAINER_NAME $CONTAINER_NAME
sudo docker network connect amnezia-dns-net $CONTAINER_NAME
# Create tun device if not exist
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
+3
View File
@@ -14,9 +14,12 @@ iptables -A OUTPUT -o tun0 -j ACCEPT
# Allow forwarding traffic only from the VPN.
iptables -A FORWARD -i tun0 -o eth0 -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i tun0 -o eth1 -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth1 -j MASQUERADE
# kill daemons in case of restart
killall -KILL openvpn
+12 -2
View File
@@ -2,6 +2,10 @@ FROM alpine:latest
LABEL maintainer="AmneziaVPN"
ARG SS_RELEASE="v1.13.1"
ARG CLOAK_RELEASE="v2.5.5"
ARG SERVER_ARCH
#Install required packages
RUN apk add --no-cache curl openvpn easy-rsa bash netcat-openbsd dumb-init rng-tools
RUN apk --update upgrade --no-cache
@@ -13,10 +17,16 @@ RUN mkdir -p /opt/amnezia
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
RUN chmod a+x /opt/amnezia/start.sh
RUN curl -L https://github.com/cbeuw/Cloak/releases/download/v2.5.3/ck-server-linux-amd64-v2.5.3 > /usr/bin/ck-server
RUN if [ $SERVER_ARCH="x86_64" ]; then CK_ARCH="amd64"; \
elif [ $SERVER_ARCH="i686" ]; then CK_ARCH="386"; \
elif [ $SERVER_ARCH="aarch64" ]; then CK_ARCH="arm64"; \
elif [ $SERVER_ARCH="arm" ]; then CK_ARCH="arm"; \
else exit -1; fi && \
curl -L https://github.com/cbeuw/Cloak/releases/download/${CLOAK_RELEASE}/ck-server-linux-${CK_ARCH}-${CLOAK_RELEASE} > /usr/bin/ck-server
RUN chmod a+x /usr/bin/ck-server
RUN curl -L https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.10.9/shadowsocks-v1.10.9.x86_64-unknown-linux-musl.tar.xz > /usr/bin/ss.tar.xz
RUN curl -L https://github.com/shadowsocks/shadowsocks-rust/releases/download/${SS_RELEASE}/shadowsocks-${SS_RELEASE}.${SERVER_ARCH}-unknown-linux-musl.tar.xz > /usr/bin/ss.tar.xz
RUN tar -Jxvf /usr/bin/ss.tar.xz -C /usr/bin/
RUN chmod a+x /usr/bin/ssserver
@@ -1,5 +1,11 @@
# Run container
sudo docker run -d --restart always --cap-add=NET_ADMIN -p $CLOAK_SERVER_PORT:443/tcp --name $CONTAINER_NAME $CONTAINER_NAME
sudo docker run \
-d --restart always \
--cap-add=NET_ADMIN \
-p $CLOAK_SERVER_PORT:443/tcp \
--name $CONTAINER_NAME $CONTAINER_NAME
sudo docker network connect amnezia-dns-net $CONTAINER_NAME
# Create tun device if not exist
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
@@ -14,9 +14,12 @@ iptables -A OUTPUT -o tun0 -j ACCEPT
# Allow forwarding traffic only from the VPN.
iptables -A FORWARD -i tun0 -o eth0 -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i tun0 -o eth1 -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth1 -j MASQUERADE
# kill daemons in case of restart
killall -KILL openvpn
@@ -1,7 +1,7 @@
FROM alpine:latest
LABEL maintainer="AmneziaVPN"
ARG SS_RELEASE="v1.11.2"
ARG SS_RELEASE="v1.13.1"
ARG SERVER_ARCH
#Install required packages
@@ -1,5 +1,11 @@
# Run container
sudo docker run -d --restart always --cap-add=NET_ADMIN -p $SHADOWSOCKS_SERVER_PORT:$SHADOWSOCKS_SERVER_PORT/tcp --name $CONTAINER_NAME $CONTAINER_NAME
sudo docker run \
-d --restart always \
--cap-add=NET_ADMIN \
-p $SHADOWSOCKS_SERVER_PORT:$SHADOWSOCKS_SERVER_PORT/tcp \
--name $CONTAINER_NAME $CONTAINER_NAME
sudo docker network connect amnezia-dns-net $CONTAINER_NAME
# Create tun device if not exist
sudo docker exec -i $CONTAINER_NAME bash -c 'mkdir -p /dev/net; if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200; fi'
@@ -14,9 +14,12 @@ iptables -A OUTPUT -o tun0 -j ACCEPT
# Allow forwarding traffic only from the VPN.
iptables -A FORWARD -i tun0 -o eth0 -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i tun0 -o eth1 -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth1 -j MASQUERADE
# kill daemons in case of restart
killall -KILL openvpn
+1
View File
@@ -1,3 +1,4 @@
CUR_USER=$(whoami);\
sudo mkdir -p $DOCKERFILE_FOLDER;\
sudo chown $CUR_USER $DOCKERFILE_FOLDER
if ! sudo docker network ls | grep -q amnezia-dns-net; then sudo docker network create --driver bridge --subnet=172.29.172.0/24 --opt com.docker.network.bridge.name=amn0 amnezia-dns-net; fi
@@ -10,6 +10,8 @@ sudo docker run -d \
--name $CONTAINER_NAME \
$CONTAINER_NAME
sudo docker network connect amnezia-dns-net $CONTAINER_NAME
# Prevent to route packets outside of the container in case if server behind of the NAT
#sudo docker exec -i $CONTAINER_NAME sh -c "ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up"
+5 -2
View File
@@ -17,9 +17,12 @@ iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A OUTPUT -o wg0 -j ACCEPT
# Allow forwarding traffic only from the VPN.
iptables -A FORWARD -i wg0 -o eth0 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_MASK_CIDR -j ACCEPT
iptables -A FORWARD -i wg0 -o eth0 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -i wg0 -o eth1 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR -o eth1 -j MASQUERADE
tail -f /dev/null
@@ -1,5 +1,5 @@
[Interface]
Address = 10.8.1.2/32
Address = $WIREGUARD_CLIENT_IP/32
DNS = $PRIMARY_DNS, $SECONDARY_DNS
PrivateKey = $WIREGUARD_CLIENT_PRIVATE_KEY
+15
View File
@@ -228,6 +228,21 @@ void Settings::addVpnSite(RouteMode mode, const QString &site, const QString &ip
setVpnSites(mode, sites);
}
void Settings::addVpnSites(RouteMode mode, const QMap<QString, QString> &sites)
{
QVariantMap allSites = vpnSites(mode);
for (auto i = sites.constBegin(); i != sites.constEnd(); ++i) {
const QString &site = i.key();
const QString &ip = i.value();
if (allSites.contains(site) && allSites.value(site) == ip) continue;
allSites.insert(site, ip);
}
setVpnSites(mode, allSites);
}
QStringList Settings::getVpnIps(RouteMode mode) const
{
QStringList ips;
+6
View File
@@ -67,6 +67,9 @@ public:
bool isStartMinimized() const { return m_settings.value("Conf/startMinimized", false).toBool(); }
void setStartMinimized(bool enabled) { m_settings.setValue("Conf/startMinimized", enabled); }
bool isSaveLogs() const { return m_settings.value("Conf/saveLogs", false).toBool(); }
void setSaveLogs(bool enabled) { m_settings.setValue("Conf/saveLogs", enabled); }
enum RouteMode {
VpnAllSites,
VpnOnlyForwardSites,
@@ -82,12 +85,15 @@ public:
QVariantMap vpnSites(RouteMode mode) const { return m_settings.value("Conf/" + routeModeString(mode)).toMap(); }
void setVpnSites(RouteMode mode, const QVariantMap &sites) { m_settings.setValue("Conf/"+ routeModeString(mode), sites); m_settings.sync(); }
void addVpnSite(RouteMode mode, const QString &site, const QString &ip= "");
void addVpnSites(RouteMode mode, const QMap<QString, QString> &sites); // map <site, ip>
QStringList getVpnIps(RouteMode mode) const;
void removeVpnSite(RouteMode mode, const QString &site);
void addVpnIps(RouteMode mode, const QStringList &ip);
void removeVpnSites(RouteMode mode, const QStringList &sites);
bool useAmneziaDns() const { return m_settings.value("Conf/useAmneziaDns", true).toBool(); }
void setUseAmneziaDns(bool enabled) { m_settings.setValue("Conf/useAmneziaDns", enabled); }
QString primaryDns() const;
QString secondaryDns() const;
+1 -1
View File
@@ -24,7 +24,7 @@ enum class Page {Start = 0, NewServer, NewServerProtocols, Vpn,
Wizard, WizardLow, WizardMedium, WizardHigh, WizardVpnMode, ServerConfiguringProgress,
GeneralSettings, AppSettings, NetworkSettings, ServerSettings,
ServerContainers, ServersList, ShareConnection, Sites,
ProtocolSettings, ProtocolShare};
ProtocolSettings, ProtocolShare, QrDecoder, About};
Q_ENUM_NS(Page)
static void declareQmlPageEnum() {

Some files were not shown because too many files have changed in this diff Show More