mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-20 02:00:55 +07:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 52450ef2f5 | |||
| 69170940c9 | |||
| e89caaee52 | |||
| 0b3535ff13 | |||
| e7a22ad159 | |||
| 74a517d985 | |||
| d57e56de70 | |||
| e2f8f77adf | |||
| db543b62ba | |||
| 999087337e | |||
| 6788f0b7eb | |||
| 2f6fb0d557 | |||
| 8bdfe1741a | |||
| 739781ece3 | |||
| 7e74b95976 | |||
| 531695bd0b | |||
| dd959e7b26 | |||
| c4235a60c8 | |||
| f75456060f | |||
| 623aae3718 | |||
| 974832f7d9 | |||
| d13df65bfb | |||
| 80ada3f241 | |||
| aad3677d45 | |||
| 8892d3c5d9 | |||
| da08bef2f9 | |||
| d79483e967 | |||
| 906391f786 | |||
| 48a4aa399b | |||
| a8dd319a9d | |||
| 815686cba6 | |||
| 7232a14926 | |||
| dd526959eb | |||
| fe6f89c551 | |||
| 16c754e004 | |||
| 8792a8673a | |||
| 9376df8703 | |||
| 435ee58d40 | |||
| 9dbe15a0e3 | |||
| 34b97bdc24 | |||
| 6c74f30d79 | |||
| 97e918ae72 | |||
| d0c66a693b | |||
| 0ea085cc02 | |||
| 7fd13faa59 | |||
| d4c0e519d9 | |||
| 4ba964db47 | |||
| 45e5ec76dd | |||
| df27003998 | |||
| 9002568474 | |||
| 5c5411261a | |||
| acf878c8dd | |||
| 491a09b175 | |||
| 51f7e6811e | |||
| eee6b8b10f | |||
| dc4a1c6eca | |||
| 02810ff844 |
+3
-1
@@ -5,7 +5,9 @@ AmneziaVPN.dmg
|
||||
AmneziaVPN.exe
|
||||
AmneziaVPN_*.exe
|
||||
deploy/build/*
|
||||
winbuild.bat
|
||||
deploy/build_32/*
|
||||
deploy/build_64/*
|
||||
winbuild*.bat
|
||||
|
||||
# Qt-es
|
||||
/.qmake.cache
|
||||
|
||||
+75
-19
@@ -10,18 +10,23 @@ jobs:
|
||||
include:
|
||||
- name: MacOS
|
||||
os: osx
|
||||
osx_image: xcode12.2
|
||||
osx_image: xcode12.5
|
||||
|
||||
env:
|
||||
- QT_VERSION=5.15.1
|
||||
- QT_VERSION=5.15.2
|
||||
- QIF_VERSION=4.1
|
||||
- QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
|
||||
- QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
|
||||
|
||||
script:
|
||||
- |
|
||||
if [ ! -f $HOME/Qt/$QT_VERSION/clang_64/bin/qmake ]; then \
|
||||
brew install p7zip && \
|
||||
pip3 install aqtinstall requests py7zr && \
|
||||
python3 -m pip install --upgrade pip && \
|
||||
pip install -U aqtinstall requests py7zr && \
|
||||
pip show aqtinstall && \
|
||||
python3 -m aqt install --outputdir $HOME/Qt $QT_VERSION mac desktop clang_64 -m qtbase && \
|
||||
python3 -m aqt tool --outputdir $HOME/Qt mac tools_ifw 4.0.1 qt.tools.ifw.40;
|
||||
python3 -m aqt tool --outputdir $HOME/Qt mac tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./};
|
||||
fi
|
||||
- bash deploy/build_macos.sh
|
||||
|
||||
@@ -35,40 +40,91 @@ jobs:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
|
||||
- name: Windows
|
||||
- name: Windows_x64
|
||||
os: windows
|
||||
|
||||
env:
|
||||
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
|
||||
- QT_VERSION=5.14.2
|
||||
- QIF_VERSION=4.1
|
||||
- QT_BIN_DIR="c:\\Qt\\$QT_VERSION\\msvc2017_64\\bin"
|
||||
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
|
||||
- BUILD_ARCH=64
|
||||
|
||||
before_install:
|
||||
- if [ ! -f /C/Qt/5.14.2/msvc2017/bin/qmake ]; then choco install python --version 3.9.1; fi
|
||||
- if [ ! -f /C/Qt/$QT_VERSION/msvc2017_64/bin/qmake ]; then choco install python --version 3.9.1; fi
|
||||
|
||||
script:
|
||||
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build"
|
||||
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
|
||||
- |
|
||||
if [ ! -f /C/Qt/5.14.2/msvc2017/bin/qmake ]; then \
|
||||
pip3 install aqtinstall requests py7zr && \
|
||||
python -m aqt install --outputdir /C/Qt 5.14.2 windows desktop win32_msvc2017 -m qtbase && \
|
||||
python -m aqt tool --outputdir /C/Qt windows tools_ifw 4.0.1 qt.tools.ifw.40; \
|
||||
if [ ! -f /C/Qt/$QT_VERSION/msvc2017_64/bin/qmake ]; then \
|
||||
python -m pip install --upgrade pip && \
|
||||
pip3 install -U aqtinstall requests py7zr && \
|
||||
pip3 show aqtinstall && \
|
||||
python -m aqt install --outputdir /C/Qt $QT_VERSION windows desktop win64_msvc2017_64 -m qtbase && \
|
||||
python -m aqt tool --outputdir /C/Qt windows tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./}; \
|
||||
fi
|
||||
- echo 'call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools\VsDevCmd.bat"' > winbuild.bat
|
||||
- echo -e "\r\n" >> winbuild.bat
|
||||
- echo 'call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsamd64_x86.bat"' >> winbuild.bat
|
||||
- echo -e "\r\n" >> winbuild.bat
|
||||
- echo -e "set WIN_CERT_PW=$WIN_CERT_PW" >> winbuild.bat
|
||||
- echo -e "\r\n" >> winbuild.bat
|
||||
- echo -e "call deploy\\\build_windows.bat" >> winbuild.bat
|
||||
- echo set BUILD_ARCH=$BUILD_ARCH > winbuild.bat
|
||||
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
|
||||
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
|
||||
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
|
||||
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64" >> winbuild.bat
|
||||
- echo set WIN_CERT_PW=$WIN_CERT_PW >> winbuild.bat
|
||||
- echo call deploy\\build_windows.bat >> winbuild.bat
|
||||
- cmd //c winbuild.bat
|
||||
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
token: $GH_TOKEN
|
||||
skip_cleanup: true
|
||||
file:
|
||||
- "AmneziaVPN.exe"
|
||||
- "AmneziaVPN_x64.exe"
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
- name: Windows_x32
|
||||
os: windows
|
||||
|
||||
env:
|
||||
- PATH=/c/Python39:/c/Python39/Scripts:$PATH
|
||||
- QT_VERSION=5.14.2
|
||||
- QIF_VERSION=4.1
|
||||
- QT_BIN_DIR="c:\\Qt\\${QT_VERSION}\\msvc2017\\bin"
|
||||
- QIF_BIN_DIR="c:\\Qt\\Tools\\QtInstallerFramework\\${QIF_VERSION}\\bin"
|
||||
- BUILD_ARCH=32
|
||||
|
||||
before_install:
|
||||
- if [ ! -f /C/Qt/$QT_VERSION/msvc2017/bin/qmake ]; then choco install python --version 3.9.1; fi
|
||||
|
||||
script:
|
||||
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build"
|
||||
- dir "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
|
||||
- |
|
||||
if [ ! -f /C/Qt/$QT_VERSION/msvc2017/bin/qmake ]; then \
|
||||
python -m pip install --upgrade pip && \
|
||||
pip3 install -U aqtinstall requests py7zr && \
|
||||
pip3 show aqtinstall && \
|
||||
python -m aqt install --outputdir /C/Qt $QT_VERSION windows desktop win32_msvc2017 -m qtbase && \
|
||||
python -m aqt tool --outputdir /C/Qt windows tools_ifw $QIF_VERSION qt.tools.ifw.${QIF_VERSION/./}; \
|
||||
fi
|
||||
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\"" > winbuild.bat
|
||||
- echo set BUILD_ARCH=$BUILD_ARCH >> winbuild.bat
|
||||
- echo set QT_BIN_DIR="$QT_BIN_DIR" >> winbuild.bat
|
||||
- echo set QIF_BIN_DIR="$QIF_BIN_DIR" >> winbuild.bat
|
||||
- echo call \""C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvars${BUILD_ARCH}.bat\"" >> winbuild.bat
|
||||
- echo set WIN_CERT_PW=$WIN_CERT_PW >> winbuild.bat
|
||||
- echo call deploy\\build_windows.bat >> winbuild.bat
|
||||
- cmd //c winbuild.bat
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
token: $GH_TOKEN
|
||||
skip_cleanup: true
|
||||
file:
|
||||
- "AmneziaVPN_x32.exe"
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
@@ -39,5 +39,11 @@ Look to the `build_macos.sh` and `build_windows.bat` scripts in `deploy` folder
|
||||
GPL v.3
|
||||
|
||||
## Contacts
|
||||
[https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - main support channel
|
||||
[https://amnezia.org](https://amnezia.org) - our website
|
||||
[https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
|
||||
[https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Telegram support channel (Russian)
|
||||
[https://signal.group/...](https://signal.group/#CjQKIB2gUf8QH_IXnOJMGQWMDjYz9cNfmRQipGWLFiIgc4MwEhAKBONrSiWHvoUFbbD0xwdh) - Signal channel
|
||||
[https://amnezia.org](https://amnezia.org) - project website
|
||||
|
||||
## Donate
|
||||
Bitcoin: bc1qn9rhsffuxwnhcuuu4qzrwp4upkrq94xnh8r26u
|
||||
Buy coffee for AmneziaVPN : [https://ko-fi.com/amnezia_vpn](https://ko-fi.com/amnezia_vpn)
|
||||
|
||||
@@ -15,7 +15,9 @@ HEADERS += \
|
||||
../ipc/ipc.h \
|
||||
configurators/cloak_configurator.h \
|
||||
configurators/shadowsocks_configurator.h \
|
||||
configurators/ssh_configurator.h \
|
||||
configurators/vpn_configurator.h \
|
||||
configurators/wireguard_configurator.h \
|
||||
core/defs.h \
|
||||
core/errorstrings.h \
|
||||
core/ipcclient.h \
|
||||
@@ -29,11 +31,13 @@ HEADERS += \
|
||||
protocols/openvpnovercloakprotocol.h \
|
||||
protocols/protocols_defs.h \
|
||||
protocols/shadowsocksvpnprotocol.h \
|
||||
protocols/wireguardprotocol.h \
|
||||
settings.h \
|
||||
ui/Controls/SlidingStackedWidget.h \
|
||||
ui/mainwindow.h \
|
||||
ui/qautostart.h \
|
||||
ui/server_widget.h \
|
||||
ui/sites_model.h \
|
||||
utils.h \
|
||||
vpnconnection.h \
|
||||
protocols/vpnprotocol.h \
|
||||
@@ -42,7 +46,9 @@ HEADERS += \
|
||||
SOURCES += \
|
||||
configurators/cloak_configurator.cpp \
|
||||
configurators/shadowsocks_configurator.cpp \
|
||||
configurators/ssh_configurator.cpp \
|
||||
configurators/vpn_configurator.cpp \
|
||||
configurators/wireguard_configurator.cpp \
|
||||
core/errorstrings.cpp \
|
||||
core/ipcclient.cpp \
|
||||
configurators/openvpn_configurator.cpp \
|
||||
@@ -55,11 +61,13 @@ SOURCES += \
|
||||
protocols/openvpnovercloakprotocol.cpp \
|
||||
protocols/protocols_defs.cpp \
|
||||
protocols/shadowsocksvpnprotocol.cpp \
|
||||
protocols/wireguardprotocol.cpp \
|
||||
settings.cpp \
|
||||
ui/Controls/SlidingStackedWidget.cpp \
|
||||
ui/mainwindow.cpp \
|
||||
ui/qautostart.cpp \
|
||||
ui/server_widget.cpp \
|
||||
ui/sites_model.cpp \
|
||||
utils.cpp \
|
||||
vpnconnection.cpp \
|
||||
protocols/vpnprotocol.cpp \
|
||||
|
||||
@@ -38,6 +38,7 @@ QString CloakConfigurator::genCloakConfig(const ServerCredentials &credentials,
|
||||
// transfer params to protocol runner
|
||||
config.insert(config_key::transport_proto, "$OPENVPN_TRANSPORT_PROTO");
|
||||
config.insert(config_key::remote, credentials.hostName);
|
||||
config.insert(config_key::port, "$CLOAK_SERVER_PORT");
|
||||
|
||||
QString textCfg = ServerController::replaceVars(QJsonDocument(config).toJson(),
|
||||
ServerController::genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
@@ -5,19 +5,17 @@
|
||||
#include <QTemporaryDir>
|
||||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
#include <utils.h>
|
||||
|
||||
#include "core/server_defs.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
#include "core/scripts_registry.h"
|
||||
#include "utils.h"
|
||||
|
||||
QString OpenVpnConfigurator::getEasyRsaShPath()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
// easyrsa sh path should looks like
|
||||
// "/Program Files (x86)/AmneziaVPN/easyrsa/easyrsa"
|
||||
QString easyRsaShPath = QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\easyrsa\\easyrsa";
|
||||
easyRsaShPath = "\"" + easyRsaShPath + "\"";
|
||||
qDebug().noquote() << "EasyRsa sh path" << easyRsaShPath;
|
||||
|
||||
return easyRsaShPath;
|
||||
@@ -34,7 +32,7 @@ QProcessEnvironment OpenVpnConfigurator::prepareEnv()
|
||||
#ifdef Q_OS_WIN
|
||||
pathEnvVar.clear();
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\cygwin;");
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\openvpn\\i386;");
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\openvpn;");
|
||||
#else
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
|
||||
#endif
|
||||
@@ -52,7 +50,7 @@ ErrorCode OpenVpnConfigurator::initPKI(const QString &path)
|
||||
#ifdef Q_OS_WIN
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProgram("cmd.exe");
|
||||
p.setNativeArguments(QString("/C \"ash.exe %1\"").arg(getEasyRsaShPath() + " init-pki"));
|
||||
p.setNativeArguments(QString("/C \"ash.exe \"%1\" %2\"").arg(getEasyRsaShPath()).arg("init-pki"));
|
||||
qDebug().noquote() << "EasyRsa tmp path" << path;
|
||||
qDebug().noquote() << "EasyRsa args" << p.nativeArguments();
|
||||
#else
|
||||
@@ -81,7 +79,10 @@ ErrorCode OpenVpnConfigurator::genReq(const QString &path, const QString &client
|
||||
#ifdef Q_OS_WIN
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProgram("cmd.exe");
|
||||
p.setNativeArguments(QString("/C \"ash.exe %1\"").arg(getEasyRsaShPath() + " gen-req " + clientId + " nopass"));
|
||||
p.setNativeArguments(QString("/C \"ash.exe \"%1\" %2 %3 %4\"")
|
||||
.arg(getEasyRsaShPath())
|
||||
.arg("gen-req").arg(clientId).arg("nopass"));
|
||||
|
||||
qDebug().noquote() << "EasyRsa args" << p.nativeArguments();
|
||||
#else
|
||||
p.setArguments(QStringList() << "gen-req" << clientId << "nopass");
|
||||
@@ -203,14 +204,21 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
||||
config.replace("$OPENVPN_CA_CERT", connData.caCert);
|
||||
config.replace("$OPENVPN_CLIENT_CERT", connData.clientCert);
|
||||
config.replace("$OPENVPN_PRIV_KEY", connData.privKey);
|
||||
config.replace("$OPENVPN_TA_KEY", connData.taKey);
|
||||
|
||||
if (config.contains("$OPENVPN_TA_KEY")) {
|
||||
config.replace("$OPENVPN_TA_KEY", connData.taKey);
|
||||
}
|
||||
else {
|
||||
config.replace("<tls-auth>", "");
|
||||
config.replace("</tls-auth>", "");
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
config.replace("block-outside-dns", "");
|
||||
#endif
|
||||
|
||||
//qDebug().noquote() << config;
|
||||
return processConfigWithLocalSettings(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::processConfigWithLocalSettings(QString config)
|
||||
@@ -219,45 +227,43 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(QString config)
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
if (m_settings().customRouting()) {
|
||||
if (m_settings().routeMode() != Settings::VpnAllSites) {
|
||||
config.replace("redirect-gateway def1 bypass-dhcp", "");
|
||||
}
|
||||
else {
|
||||
if(!config.contains("redirect-gateway def1 bypass-dhcp")) {
|
||||
config.append("redirect-gateway def1 bypass-dhcp\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
config.replace("block-outside-dns", "");
|
||||
QString dnsConf = QString(
|
||||
"\nscript-security 2\n"
|
||||
"up %1/update-resolv-conf.sh\n"
|
||||
"down %1/update-resolv-conf.sh\n").
|
||||
arg(qApp->applicationDirPath());
|
||||
|
||||
config.append(dnsConf);
|
||||
#endif
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::convertOpenSShKey(const QString &key)
|
||||
QString OpenVpnConfigurator::processConfigWithExportSettings(QString config)
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
QTemporaryFile tmp;
|
||||
#ifdef QT_DEBUG
|
||||
tmp.setAutoRemove(false);
|
||||
#endif
|
||||
tmp.open();
|
||||
tmp.write(key.toUtf8());
|
||||
tmp.close();
|
||||
if(!config.contains("redirect-gateway def1 bypass-dhcp")) {
|
||||
config.append("redirect-gateway def1 bypass-dhcp\n");
|
||||
}
|
||||
|
||||
// ssh-keygen -p -P "" -N "" -m pem -f id_ssh
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProgram("cmd.exe");
|
||||
p.setNativeArguments(QString("/C \"ssh-keygen.exe -p -P \"\" -N \"\" -m pem -f \"%1\"\"").arg(tmp.fileName()));
|
||||
#else
|
||||
p.setProgram("ssh-keygen");
|
||||
p.setArguments(QStringList() << "-p" << "-P" << "" << "-N" << "" << "-m" << "pem" << "-f" << tmp.fileName());
|
||||
#ifdef Q_OS_MAC
|
||||
config.replace("block-outside-dns", "");
|
||||
#endif
|
||||
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
|
||||
qDebug().noquote() << "OpenVpnConfigurator::convertOpenSShKey" << p.exitCode() << p.exitStatus() << p.readAll();
|
||||
|
||||
tmp.open();
|
||||
|
||||
return tmp.readAll();
|
||||
return config;
|
||||
}
|
||||
|
||||
ErrorCode OpenVpnConfigurator::signCert(DockerContainer container,
|
||||
|
||||
@@ -26,8 +26,7 @@ public:
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static QString processConfigWithLocalSettings(QString config);
|
||||
|
||||
static QString convertOpenSShKey(const QString &key);
|
||||
static QString processConfigWithExportSettings(QString config);
|
||||
|
||||
static ErrorCode signCert(DockerContainer container,
|
||||
const ServerCredentials &credentials, QString clientId);
|
||||
|
||||
@@ -32,6 +32,6 @@ QString ShadowSocksConfigurator::genShadowSocksConfig(const ServerCredentials &c
|
||||
QString textCfg = ServerController::replaceVars(QJsonDocument(config).toJson(),
|
||||
ServerController::genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
qDebug().noquote() << textCfg;
|
||||
//qDebug().noquote() << textCfg;
|
||||
return textCfg;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "ssh_configurator.h"
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryDir>
|
||||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QTextEdit>
|
||||
#include <QPlainTextEdit>
|
||||
#include <qtimer.h>
|
||||
|
||||
#include "core/server_defs.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace QSsh;
|
||||
|
||||
|
||||
QString SshConfigurator::convertOpenSShKey(const QString &key)
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
QTemporaryFile tmp;
|
||||
#ifdef QT_DEBUG
|
||||
tmp.setAutoRemove(false);
|
||||
#endif
|
||||
tmp.open();
|
||||
tmp.write(key.toUtf8());
|
||||
tmp.close();
|
||||
|
||||
// ssh-keygen -p -P "" -N "" -m pem -f id_ssh
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProgram("cmd.exe");
|
||||
p.setNativeArguments(QString("/C \"ssh-keygen.exe -p -P \"\" -N \"\" -m pem -f \"%1\"\"").arg(tmp.fileName()));
|
||||
#else
|
||||
p.setProgram("ssh-keygen");
|
||||
p.setArguments(QStringList() << "-p" << "-P" << "" << "-N" << "" << "-m" << "pem" << "-f" << tmp.fileName());
|
||||
#endif
|
||||
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
|
||||
qDebug().noquote() << "OpenVpnConfigurator::convertOpenSShKey" << p.exitCode() << p.exitStatus() << p.readAll();
|
||||
|
||||
tmp.open();
|
||||
|
||||
return tmp.readAll();
|
||||
}
|
||||
|
||||
void SshConfigurator::openSshTerminal(const ServerCredentials &credentials)
|
||||
{
|
||||
QProcess *p = new QProcess();
|
||||
p->setReadChannelMode(QProcess::SeparateChannels);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
p->setProcessEnvironment(prepareEnv());
|
||||
p->setProgram(qApp->applicationDirPath() + "\\cygwin\\putty.exe");
|
||||
|
||||
if (credentials.password.contains("PRIVATE KEY")) {
|
||||
// todo: connect by key
|
||||
// p->setNativeArguments(QString("%1@%2")
|
||||
// .arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
||||
}
|
||||
else {
|
||||
p->setNativeArguments(QString("%1@%2 -pw %3")
|
||||
.arg(credentials.userName).arg(credentials.hostName).arg(credentials.password));
|
||||
}
|
||||
#else
|
||||
p->setProgram("/bin/bash");
|
||||
#endif
|
||||
|
||||
p->startDetached();
|
||||
}
|
||||
|
||||
QProcessEnvironment SshConfigurator::prepareEnv()
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString pathEnvVar = env.value("PATH");
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
pathEnvVar.clear();
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\cygwin;");
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\openvpn;");
|
||||
#else
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
|
||||
#endif
|
||||
|
||||
env.insert("PATH", pathEnvVar);
|
||||
//qDebug().noquote() << "ENV PATH" << pathEnvVar;
|
||||
return env;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef SSH_CONFIGURATOR_H
|
||||
#define SSH_CONFIGURATOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "settings.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
class SshConfigurator
|
||||
{
|
||||
public:
|
||||
static QProcessEnvironment prepareEnv();
|
||||
static QString convertOpenSShKey(const QString &key);
|
||||
static void openSshTerminal(const ServerCredentials &credentials);
|
||||
|
||||
};
|
||||
|
||||
#endif // SSH_CONFIGURATOR_H
|
||||
@@ -0,0 +1,178 @@
|
||||
#include "wireguard_configurator.h"
|
||||
#include <QApplication>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryDir>
|
||||
#include <QDebug>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include "sftpdefs.h"
|
||||
|
||||
#include "core/server_defs.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
#include "core/scripts_registry.h"
|
||||
#include "utils.h"
|
||||
|
||||
QProcessEnvironment WireguardConfigurator::prepareEnv()
|
||||
{
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QString pathEnvVar = env.value("PATH");
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
pathEnvVar.clear();
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\wireguard;");
|
||||
#else
|
||||
pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
|
||||
#endif
|
||||
|
||||
env.insert("PATH", pathEnvVar);
|
||||
qDebug().noquote() << "ENV PATH" << pathEnvVar;
|
||||
return env;
|
||||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::genClientKeys()
|
||||
{
|
||||
ConnectionData connData;
|
||||
|
||||
QString program;
|
||||
#ifdef Q_OS_WIN
|
||||
program = QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\wireguard\\wg.exe";
|
||||
#else
|
||||
program = QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS/wg";
|
||||
#endif
|
||||
|
||||
// Priv
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
p.setProgram(program);
|
||||
|
||||
p.setArguments(QStringList() << "genkey");
|
||||
|
||||
p.start();
|
||||
p.waitForFinished();
|
||||
|
||||
connData.clientPrivKey = QString(p.readAll());
|
||||
connData.clientPrivKey.replace("\r", "");
|
||||
connData.clientPrivKey.replace("\n", "");
|
||||
}
|
||||
|
||||
// Pub
|
||||
{
|
||||
QProcess p;
|
||||
p.setProcessEnvironment(prepareEnv());
|
||||
p.setProcessChannelMode(QProcess::MergedChannels);
|
||||
p.setProgram(program);
|
||||
|
||||
p.setArguments(QStringList() << "pubkey");
|
||||
|
||||
p.start();
|
||||
p.write(connData.clientPrivKey.toUtf8());
|
||||
p.closeWriteChannel();
|
||||
p.waitForFinished();
|
||||
|
||||
connData.clientPubKey = QString(p.readAll());
|
||||
connData.clientPubKey.replace("\r", "");
|
||||
connData.clientPubKey.replace("\n", "");
|
||||
}
|
||||
|
||||
return connData;
|
||||
}
|
||||
|
||||
WireguardConfigurator::ConnectionData WireguardConfigurator::prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode)
|
||||
{
|
||||
WireguardConfigurator::ConnectionData connData = WireguardConfigurator::genClientKeys();
|
||||
connData.host = credentials.hostName;
|
||||
|
||||
if (connData.clientPrivKey.isEmpty() || connData.clientPubKey.isEmpty()) {
|
||||
if (errorCode) *errorCode = ErrorCode::EasyRsaExecutableMissing;
|
||||
return connData;
|
||||
}
|
||||
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
connData.serverPubKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPublicKeyPath, &e);
|
||||
connData.serverPubKey.replace("\n", "");
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
connData.pskKey = ServerController::getTextFileFromContainer(container, credentials, amnezia::protocols::wireguard::serverPskKeyPath, &e);
|
||||
connData.pskKey.replace("\n", "");
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
|
||||
QString configPart = QString(
|
||||
"[Peer]\n"
|
||||
"PublicKey = %1\n"
|
||||
"PresharedKey = %2\n"
|
||||
"AllowedIPs = $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR\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;
|
||||
|
||||
e = ServerController::uploadTextFileToContainer(container, credentials, configPart,
|
||||
protocols::wireguard::serverConfigPath, QSsh::SftpOverwriteMode::SftpAppendToExisting);
|
||||
|
||||
if (e) {
|
||||
if (errorCode) *errorCode = e;
|
||||
return connData;
|
||||
}
|
||||
|
||||
e = ServerController::runScript(ServerController::sshParams(credentials),
|
||||
ServerController::replaceVars("sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip /opt/amnezia/wireguard/wg0.conf)'",
|
||||
ServerController::genVarsForScript(credentials, container)));
|
||||
|
||||
return connData;
|
||||
}
|
||||
|
||||
Settings &WireguardConfigurator::m_settings()
|
||||
{
|
||||
static Settings s;
|
||||
return s;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, const QJsonObject &containerConfig, ErrorCode *errorCode)
|
||||
{
|
||||
QString config = ServerController::replaceVars(amnezia::scriptData(ProtocolScriptType::wireguard_template, container),
|
||||
ServerController::genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
ConnectionData connData = prepareWireguardConfig(credentials, container, errorCode);
|
||||
if (errorCode && *errorCode) {
|
||||
return "";
|
||||
}
|
||||
|
||||
config.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", connData.clientPrivKey);
|
||||
config.replace("$WIREGUARD_SERVER_PUBLIC_KEY", connData.serverPubKey);
|
||||
config.replace("$WIREGUARD_PSK", connData.pskKey);
|
||||
|
||||
qDebug().noquote() << config;
|
||||
return config;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::processConfigWithLocalSettings(QString config)
|
||||
{
|
||||
// TODO replace DNS if it already set
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
QString WireguardConfigurator::processConfigWithExportSettings(QString config)
|
||||
{
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
return config;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef WIREGUARD_CONFIGURATOR_H
|
||||
#define WIREGUARD_CONFIGURATOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
#include "core/defs.h"
|
||||
#include "settings.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
class WireguardConfigurator
|
||||
{
|
||||
public:
|
||||
|
||||
struct ConnectionData {
|
||||
QString clientPrivKey; // client private key
|
||||
QString clientPubKey; // client public key
|
||||
QString serverPubKey; // tls-auth key
|
||||
QString pskKey; // preshared key
|
||||
QString host; // host ip
|
||||
};
|
||||
|
||||
static QString genWireguardConfig(const ServerCredentials &credentials, DockerContainer container,
|
||||
const QJsonObject &containerConfig, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static QString processConfigWithLocalSettings(QString config);
|
||||
static QString processConfigWithExportSettings(QString config);
|
||||
|
||||
|
||||
private:
|
||||
static QProcessEnvironment prepareEnv();
|
||||
|
||||
static ConnectionData prepareWireguardConfig(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static ConnectionData genClientKeys();
|
||||
|
||||
static Settings &m_settings();
|
||||
};
|
||||
|
||||
#endif // WIREGUARD_CONFIGURATOR_H
|
||||
+5
-1
@@ -13,7 +13,7 @@ struct ServerCredentials
|
||||
QString password;
|
||||
int port = 22;
|
||||
|
||||
bool isValid() { return !hostName.isEmpty() && !userName.isEmpty() && !password.isEmpty() && port > 0; }
|
||||
bool isValid() const { return !hostName.isEmpty() && !userName.isEmpty() && !password.isEmpty() && port > 0; }
|
||||
};
|
||||
|
||||
enum ErrorCode
|
||||
@@ -44,6 +44,7 @@ enum ErrorCode
|
||||
OpenVpnConfigMissing,
|
||||
OpenVpnManagementServerError,
|
||||
EasyRsaError,
|
||||
ConfigMissing,
|
||||
|
||||
// Distro errors
|
||||
OpenVpnExecutableMissing,
|
||||
@@ -51,10 +52,12 @@ enum ErrorCode
|
||||
ShadowSocksExecutableMissing,
|
||||
CloakExecutableMissing,
|
||||
AmneziaServiceConnectionFailed,
|
||||
ExecutableMissing,
|
||||
|
||||
// VPN errors
|
||||
OpenVpnAdaptersInUseError,
|
||||
OpenVpnUnknownError,
|
||||
OpenVpnTapAdapterError,
|
||||
|
||||
// 3rd party utils errors
|
||||
OpenVpnExecutableCrashed,
|
||||
@@ -68,6 +71,7 @@ const char key_openvpn_config_data[] = "openvpn_config_data";
|
||||
const char key_openvpn_config_path[] = "openvpn_config_path";
|
||||
const char key_shadowsocks_config_data[] = "shadowsocks_config_data";
|
||||
const char key_cloak_config_data[] = "cloak_config_data";
|
||||
const char key_wireguard_config_data[] = "wireguard_config_data";
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,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(InternalError):
|
||||
default:
|
||||
|
||||
@@ -48,7 +48,7 @@ QSharedPointer<IpcProcessInterfaceReplica> IpcClient::CreatePrivilegedProcess()
|
||||
qWarning() << "IpcProcessInterfaceReplica replica is not connected!";
|
||||
}
|
||||
|
||||
connect(pd->ipcProcess.data(), &IpcProcessInterfaceReplica::destroyed, pd->ipcProcess.data(), [pd](){
|
||||
QObject::connect(pd->ipcProcess.data(), &IpcProcessInterfaceReplica::destroyed, pd->ipcProcess.data(), [pd](){
|
||||
pd->replicaNode->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ QString amnezia::scriptName(ProtocolScriptType type)
|
||||
case ProtocolScriptType::configure_container: return QLatin1String("configure_container.sh");
|
||||
case ProtocolScriptType::container_startup: return QLatin1String("start.sh");
|
||||
case ProtocolScriptType::openvpn_template: return QLatin1String("template.ovpn");
|
||||
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ enum ProtocolScriptType {
|
||||
run_container,
|
||||
configure_container,
|
||||
container_startup,
|
||||
openvpn_template
|
||||
openvpn_template,
|
||||
wireguard_template
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -120,7 +120,8 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams,
|
||||
}
|
||||
|
||||
ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path)
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path,
|
||||
QSsh::SftpOverwriteMode overwriteMode)
|
||||
{
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
QString tmpFileName = QString("/tmp/%1.tmp").arg(Utils::getRandomString(16));
|
||||
@@ -132,11 +133,29 @@ ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
if (overwriteMode == QSsh::SftpOverwriteMode::SftpOverwriteExisting) {
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(path),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
|
||||
if (e) return e;
|
||||
}
|
||||
else if (overwriteMode == QSsh::SftpOverwriteMode::SftpAppendToExisting) {
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker cp %1 $CONTAINER_NAME:/%2").arg(tmpFileName).arg(tmpFileName),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
|
||||
if (e) return e;
|
||||
|
||||
e = runScript(sshParams(credentials),
|
||||
replaceVars(QString("sudo docker exec -i $CONTAINER_NAME sh -c \"cat %1 >> %2\"").arg(tmpFileName).arg(path),
|
||||
genVarsForScript(credentials, container)), cbReadStd, cbReadStd);
|
||||
|
||||
if (e) return e;
|
||||
}
|
||||
else return ErrorCode::NotImplementedError;
|
||||
|
||||
|
||||
if (e) return e;
|
||||
if (stdOut.contains("Error: No such container:")) {
|
||||
return ErrorCode::ServerContainerMissingError;
|
||||
}
|
||||
@@ -199,15 +218,16 @@ QString ServerController::getTextFileFromContainer(DockerContainer container,
|
||||
if (errorCode) *errorCode = fromSshProcessExitStatus(exitStatus);
|
||||
}
|
||||
|
||||
if (errorCode) *errorCode = ErrorCode::NoError;
|
||||
return proc->readAllStandardOutput();
|
||||
}
|
||||
|
||||
ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials)
|
||||
{
|
||||
QString caCert = ServerController::getTextFileFromContainer(container,
|
||||
credentials, amnezia::protocols::openvpn::caCertPath);
|
||||
credentials, protocols::openvpn::caCertPath);
|
||||
QString taKey = ServerController::getTextFileFromContainer(container,
|
||||
credentials, amnezia::protocols::openvpn::taKeyPath);
|
||||
credentials, protocols::openvpn::taKeyPath);
|
||||
|
||||
if (!caCert.isEmpty() && !taKey.isEmpty()) {
|
||||
return ErrorCode::NoError;
|
||||
@@ -217,7 +237,8 @@ ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const
|
||||
}
|
||||
}
|
||||
|
||||
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath)
|
||||
ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath,
|
||||
QSsh::SftpOverwriteMode overwriteMode)
|
||||
{
|
||||
SshConnection *client = connectToHost(sshParams(credentials));
|
||||
if (client->state() != SshConnection::State::Connected) {
|
||||
@@ -343,46 +364,33 @@ ErrorCode ServerController::removeContainer(const ServerCredentials &credentials
|
||||
ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
qDebug().noquote() << "ServerController::setupContainer" << containerToString(container);
|
||||
qDebug().noquote() << QJsonDocument(config).toJson();
|
||||
//qDebug().noquote() << QJsonDocument(config).toJson();
|
||||
ErrorCode e = ErrorCode::NoError;
|
||||
|
||||
// e = runScript(sshParams(credentials),
|
||||
// replaceVars(amnezia::scriptData(SharedScriptType::install_docker),
|
||||
// genVarsForScript(credentials)));
|
||||
|
||||
// if (e) return e;
|
||||
|
||||
e = installDockerWorker(credentials, container);
|
||||
if (e) return e;
|
||||
qDebug().noquote() << "ServerController::setupContainer installDockerWorker finished";
|
||||
|
||||
e = prepareHostWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
qDebug().noquote() << "ServerController::setupContainer prepareHostWorker finished";
|
||||
|
||||
removeContainer(credentials, container);
|
||||
qDebug().noquote() << "ServerController::setupContainer removeContainer finished";
|
||||
|
||||
e = buildContainerWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
qDebug().noquote() << "ServerController::setupContainer buildContainerWorker finished";
|
||||
|
||||
e = runContainerWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
qDebug().noquote() << "ServerController::setupContainer runContainerWorker finished";
|
||||
|
||||
e = configureContainerWorker(credentials, container, config);
|
||||
if (e) return e;
|
||||
qDebug().noquote() << "ServerController::setupContainer configureContainerWorker finished";
|
||||
|
||||
return startupContainerWorker(credentials, container, config);
|
||||
|
||||
|
||||
|
||||
|
||||
// if (container == DockerContainer::OpenVpn) {
|
||||
// return setupOpenVpnServer(credentials, config);
|
||||
// }
|
||||
// else if (container == DockerContainer::OpenVpnOverShadowSocks) {
|
||||
// return setupShadowSocksServer(credentials, config);
|
||||
// }
|
||||
// else if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
// return setupOpenVpnOverCloakServer(credentials, config);
|
||||
// }
|
||||
|
||||
// return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::updateContainer(const ServerCredentials &credentials, DockerContainer container,
|
||||
@@ -438,33 +446,6 @@ bool ServerController::isReinstallContainerRequred(DockerContainer container, co
|
||||
return false;
|
||||
}
|
||||
|
||||
//ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
//{
|
||||
// return ErrorCode::NotImplementedError;
|
||||
//}
|
||||
|
||||
//ErrorCode ServerController::setupOpenVpnOverCloakServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
//{
|
||||
// ErrorCode e = ErrorCode::NoError;
|
||||
// DockerContainer container = DockerContainer::OpenVpnOverCloak;
|
||||
|
||||
// e = prepareHostWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
|
||||
// removeContainer(credentials, container);
|
||||
|
||||
// e = buildContainerWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
|
||||
// e = runContainerWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
|
||||
// e = configureContainerWorker(credentials, container, config);
|
||||
// if (e) return e;
|
||||
|
||||
// return startupContainerWorker(credentials, container, config);
|
||||
//}
|
||||
|
||||
ErrorCode ServerController::installDockerWorker(const ServerCredentials &credentials, DockerContainer container)
|
||||
{
|
||||
QString stdOut;
|
||||
@@ -515,9 +496,23 @@ ErrorCode ServerController::buildContainerWorker(const ServerCredentials &creden
|
||||
|
||||
ErrorCode ServerController::runContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
return runScript(sshParams(credentials),
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
ErrorCode e = runScript(sshParams(credentials),
|
||||
replaceVars(amnezia::scriptData(ProtocolScriptType::run_container, container),
|
||||
genVarsForScript(credentials, container, config)));
|
||||
genVarsForScript(credentials, container, config)),
|
||||
cbReadStdOut, cbReadStdErr);
|
||||
|
||||
if (stdOut.contains("address already in use")) return ErrorCode::ServerPortAlreadyAllocatedError;
|
||||
if (stdOut.contains("is already in use by container")) return ErrorCode::ServerPortAlreadyAllocatedError;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
@@ -540,62 +535,12 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred
|
||||
genVarsForScript(credentials, container, config)));
|
||||
}
|
||||
|
||||
//ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &credentials, const QJsonObject &config)
|
||||
//{
|
||||
// return ErrorCode::NotImplementedError;
|
||||
//// // Setup openvpn part
|
||||
//// QString scriptData;
|
||||
//// QString scriptFileName = ":/server_scripts/setup_shadowsocks_server.sh";
|
||||
//// QFile file(scriptFileName);
|
||||
//// if (! file.open(QIODevice::ReadOnly)) return ErrorCode::InternalError;
|
||||
|
||||
//// scriptData = file.readAll();
|
||||
//// if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
|
||||
//// QString stdOut;
|
||||
//// auto cbReadStdOut = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
//// stdOut += data + "\n";
|
||||
|
||||
//// if (data.contains("Automatically restart Docker daemon?")) {
|
||||
//// proc->write("yes\n");
|
||||
//// }
|
||||
//// };
|
||||
//// auto cbReadStdErr = [&](const QString &data, QSharedPointer<QSsh::SshRemoteProcess> proc) {
|
||||
//// stdOut += data + "\n";
|
||||
//// };
|
||||
|
||||
//// ErrorCode e = runScript(genVarsForScript(credentials, DockerContainer::ShadowSocks), sshParams(credentials), scriptData, cbReadStdOut, cbReadStdErr);
|
||||
//// if (e) return e;
|
||||
|
||||
//// // Create ss config
|
||||
//// QJsonObject ssConfig;
|
||||
//// ssConfig.insert("server", "0.0.0.0");
|
||||
//// ssConfig.insert("server_port", amnezia::protocols::shadowsocks::ssRemotePort());
|
||||
//// ssConfig.insert("local_port", amnezia::protocols::shadowsocks::ssContainerPort());
|
||||
//// ssConfig.insert("password", QString(QCryptographicHash::hash(credentials.password.toUtf8(), QCryptographicHash::Sha256).toHex()));
|
||||
//// ssConfig.insert("timeout", 60);
|
||||
//// ssConfig.insert("method", amnezia::protocols::shadowsocks::ssEncryption());
|
||||
//// QString configData = QJsonDocument(ssConfig).toJson();
|
||||
//// QString sSConfigPath = "/opt/amneziavpn_data/ssConfig.json";
|
||||
|
||||
//// configData.replace("\"", "\\\"");
|
||||
//// //qDebug().noquote() << configData;
|
||||
|
||||
//// uploadTextFileToContainer(DockerContainer::ShadowSocks, credentials, configData, sSConfigPath);
|
||||
|
||||
//// // Start ss
|
||||
//// QString script = QString("sudo docker exec -d %1 sh -c \"ss-server -c %2\"").
|
||||
//// arg(amnezia::containerToString(DockerContainer::ShadowSocks)).arg(sSConfigPath);
|
||||
|
||||
//// e = runScript(genVarsForScript(credentials, DockerContainer::ShadowSocks), sshParams(credentials), script);
|
||||
// // return e;
|
||||
//}
|
||||
|
||||
ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
|
||||
{
|
||||
const QJsonObject &openvpnConfig = config.value(config_key::openvpn).toObject();
|
||||
const QJsonObject &cloakConfig = config.value(config_key::cloak).toObject();
|
||||
const QJsonObject &ssConfig = config.value(config_key::shadowsocks).toObject();
|
||||
const QJsonObject &wireguarConfig = config.value(config_key::wireguard).toObject();
|
||||
//
|
||||
|
||||
Vars vars;
|
||||
@@ -603,30 +548,46 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
|
||||
vars.append({{"$REMOTE_HOST", credentials.hostName}});
|
||||
|
||||
// OpenVPN vars
|
||||
vars.append({{"$VPN_SUBNET_IP", openvpnConfig.value(config_key::subnet_address).toString(amnezia::protocols::vpnDefaultSubnetAddress) }});
|
||||
vars.append({{"$VPN_SUBNET_MASK_VAL", openvpnConfig.value(config_key::subnet_mask_val).toString(amnezia::protocols::vpnDefaultSubnetMaskVal) }});
|
||||
vars.append({{"$VPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(amnezia::protocols::vpnDefaultSubnetMask) }});
|
||||
vars.append({{"$OPENVPN_SUBNET_IP", openvpnConfig.value(config_key::subnet_address).toString(protocols::openvpn::defaultSubnetAddress) }});
|
||||
vars.append({{"$OPENVPN_SUBNET_CIDR", openvpnConfig.value(config_key::subnet_cidr).toString(protocols::openvpn::defaultSubnetCidr) }});
|
||||
vars.append({{"$OPENVPN_SUBNET_MASK", openvpnConfig.value(config_key::subnet_mask).toString(protocols::openvpn::defaultSubnetMask) }});
|
||||
|
||||
vars.append({{"$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(amnezia::protocols::openvpn::defaultPort) }});
|
||||
vars.append({{"$OPENVPN_TRANSPORT_PROTO", openvpnConfig.value(config_key::transport_proto).toString(amnezia::protocols::openvpn::defaultTransportProto) }});
|
||||
vars.append({{"$OPENVPN_PORT", openvpnConfig.value(config_key::port).toString(protocols::openvpn::defaultPort) }});
|
||||
vars.append({{"$OPENVPN_TRANSPORT_PROTO", openvpnConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto) }});
|
||||
|
||||
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(amnezia::protocols::openvpn::defaultNcpDisable);
|
||||
bool isNcpDisabled = openvpnConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable);
|
||||
vars.append({{"$OPENVPN_NCP_DISABLE", isNcpDisabled ? protocols::openvpn::ncpDisableString : "" }});
|
||||
vars.append({{"$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(amnezia::protocols::openvpn::defaultCipher) }});
|
||||
vars.append({{"$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(amnezia::protocols::openvpn::defaultHash) }});
|
||||
|
||||
vars.append({{"$OPENVPN_CIPHER", openvpnConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher) }});
|
||||
vars.append({{"$OPENVPN_HASH", openvpnConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash) }});
|
||||
|
||||
bool isTlsAuth = openvpnConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth);
|
||||
vars.append({{"$OPENVPN_TLS_AUTH", isTlsAuth ? protocols::openvpn::tlsAuthString : "" }});
|
||||
if (!isTlsAuth) {
|
||||
// erase $OPENVPN_TA_KEY, so it will not set in OpenVpnConfigurator::genOpenVpnConfig
|
||||
vars.append({{"$OPENVPN_TA_KEY", "" }});
|
||||
}
|
||||
|
||||
// ShadowSocks vars
|
||||
vars.append({{"$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(amnezia::protocols::shadowsocks::defaultPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_LOCAL_PORT", ssConfig.value(config_key::local_port).toString(amnezia::protocols::shadowsocks::defaultLocalProxyPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(amnezia::protocols::shadowsocks::defaultCipher) }});
|
||||
vars.append({{"$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_LOCAL_PORT", ssConfig.value(config_key::local_port).toString(protocols::shadowsocks::defaultLocalProxyPort) }});
|
||||
vars.append({{"$SHADOWSOCKS_CIPHER", ssConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher) }});
|
||||
|
||||
vars.append({{"$CONTAINER_NAME", amnezia::containerToString(container)}});
|
||||
vars.append({{"$DOCKERFILE_FOLDER", "/opt/amnezia/" + amnezia::containerToString(container)}});
|
||||
|
||||
// Cloak vars
|
||||
vars.append({{"$CLOAK_SERVER_PORT", config.value(config_key::port).toString(protocols::cloak::defaultPort) }});
|
||||
vars.append({{"$CLOAK_SERVER_PORT", cloakConfig.value(config_key::port).toString(protocols::cloak::defaultPort) }});
|
||||
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_SERVER_PORT", wireguarConfig.value(config_key::port).toString(protocols::wireguard::defaultPort) }});
|
||||
|
||||
|
||||
QString serverIp = Utils::getIPAddress(credentials.hostName);
|
||||
if (!serverIp.isEmpty()) {
|
||||
vars.append({{"$SERVER_IP_ADDRESS", serverIp}});
|
||||
@@ -730,5 +691,6 @@ QString ServerController::replaceVars(const QString &script, const Vars &vars)
|
||||
//qDebug() << "Replacing" << var.first << var.second;
|
||||
s.replace(var.first, var.second);
|
||||
}
|
||||
//qDebug().noquote() << script;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "defs.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
#include "sftpdefs.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
||||
@@ -35,10 +36,12 @@ public:
|
||||
|
||||
static ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials);
|
||||
|
||||
static ErrorCode uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data, const QString &remotePath);
|
||||
static ErrorCode uploadFileToHost(const ServerCredentials &credentials, const QByteArray &data,
|
||||
const QString &remotePath, QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting);
|
||||
|
||||
static ErrorCode uploadTextFileToContainer(DockerContainer container,
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path);
|
||||
const ServerCredentials &credentials, const QString &file, const QString &path,
|
||||
QSsh::SftpOverwriteMode overwriteMode = QSsh::SftpOverwriteMode::SftpOverwriteExisting);
|
||||
|
||||
static QString getTextFileFromContainer(DockerContainer container,
|
||||
const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode = nullptr);
|
||||
@@ -54,15 +57,11 @@ public:
|
||||
static Vars genVarsForScript(const ServerCredentials &credentials, DockerContainer container = DockerContainer::None, const QJsonObject &config = QJsonObject());
|
||||
|
||||
static QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr);
|
||||
private:
|
||||
static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
||||
|
||||
private:
|
||||
|
||||
static ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container);
|
||||
|
||||
//static ErrorCode setupOpenVpnServer(const ServerCredentials &credentials, const QJsonObject &config = QJsonObject());
|
||||
//static ErrorCode setupOpenVpnOverCloakServer(const ServerCredentials &credentials, const QJsonObject &config = QJsonObject());
|
||||
// static ErrorCode setupShadowSocksServer(const ServerCredentials &credentials, const QJsonObject &config = QJsonObject());
|
||||
|
||||
static ErrorCode prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
static ErrorCode buildContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
static ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject());
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@
|
||||
#define APPLICATION_NAME "AmneziaVPN"
|
||||
#define SERVICE_NAME "AmneziaVPN-service"
|
||||
#define ORGANIZATION_NAME "AmneziaVPN.ORG"
|
||||
#define APP_VERSION "1.6.0.0"
|
||||
#define APP_MAJOR_VERSION "1.8.0"
|
||||
#define APP_VERSION "1.8.0.0"
|
||||
|
||||
#endif // DEFINES_H
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 150 B |
Binary file not shown.
|
Before Width: | Height: | Size: 215 B After Width: | Height: | Size: 324 B |
+12
-5
@@ -68,18 +68,25 @@ int main(int argc, char *argv[])
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
|
||||
QCommandLineOption c_autostart {{"a", "autostart"}, "System autostart"};
|
||||
parser.addOption(c_autostart);
|
||||
|
||||
parser.process(app);
|
||||
|
||||
if (!Debug::init()) {
|
||||
qWarning() << "Initialization of debug subsystem failed";
|
||||
}
|
||||
|
||||
QFont f("Lato Regular", 10);
|
||||
f.setStyleStrategy(QFont::PreferAntialias);
|
||||
app.setFont(f);
|
||||
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
MainWindow mainWindow;
|
||||
mainWindow.show();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (parser.isSet("a")) mainWindow.showOnStartup();
|
||||
else mainWindow.show();
|
||||
#else
|
||||
mainWindow.showOnStartup();
|
||||
#endif
|
||||
|
||||
if (app.isPrimary()) {
|
||||
QObject::connect(&app, &SingleApplication::instanceStarted, &mainWindow, [&](){
|
||||
|
||||
@@ -3,11 +3,11 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
IDI_ICON1 ICON "../images/app.ico"
|
||||
|
||||
#define VER_FILEVERSION 1,6,0,0
|
||||
#define VER_FILEVERSION_STR "1.6.0.0\0"
|
||||
#define VER_FILEVERSION 1,7,0,0
|
||||
#define VER_FILEVERSION_STR "1.7.0.0\0"
|
||||
|
||||
#define VER_PRODUCTVERSION 1,6,0,0
|
||||
#define VER_PRODUCTVERSION_STR "1.6.0.0\0"
|
||||
#define VER_PRODUCTVERSION 1,7,0,0
|
||||
#define VER_PRODUCTVERSION_STR "1.7.0.0\0"
|
||||
|
||||
#define VER_COMPANYNAME_STR "AmneziaVPN"
|
||||
#define VER_FILEDESCRIPTION_STR "AmneziaVPN"
|
||||
|
||||
@@ -38,7 +38,7 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
||||
|
||||
QStringList args = QStringList() << "-c" << m_cloakCfgFile.fileName()
|
||||
<< "-s" << m_cloakConfig.value(config_key::remote).toString()
|
||||
<< "-p" << amnezia::protocols::cloak::defaultPort
|
||||
<< "-p" << m_cloakConfig.value(config_key::port).toString(amnezia::protocols::cloak::defaultPort)
|
||||
<< "-l" << amnezia::protocols::openvpn::defaultPort;
|
||||
|
||||
if (m_cloakConfig.value(config_key::transport_proto).toString() == protocols::UDP) {
|
||||
@@ -57,9 +57,9 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
||||
qDebug().noquote() << "ck-client:" << m_ckProcess.readAllStandardOutput();
|
||||
});
|
||||
|
||||
connect(&m_ckProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus){
|
||||
m_errorHandlerConnection = connect(&m_ckProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus){
|
||||
qDebug().noquote() << "OpenVpnOverCloakProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnected);
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
if (exitStatus != QProcess::NormalExit){
|
||||
emit protocolError(amnezia::ErrorCode::CloakExecutableCrashed);
|
||||
stop();
|
||||
@@ -83,6 +83,7 @@ ErrorCode OpenVpnOverCloakProtocol::start()
|
||||
|
||||
void OpenVpnOverCloakProtocol::stop()
|
||||
{
|
||||
disconnect(m_errorHandlerConnection);
|
||||
OpenVpnProtocol::stop();
|
||||
|
||||
qDebug() << "OpenVpnOverCloakProtocol::stop()";
|
||||
|
||||
@@ -25,6 +25,7 @@ private:
|
||||
private:
|
||||
QProcess m_ckProcess;
|
||||
QTemporaryFile m_cloakCfgFile;
|
||||
QMetaObject::Connection m_errorHandlerConnection;
|
||||
};
|
||||
|
||||
#endif // OPENVPNOVERCLOAKPROTOCOL_H
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include "debug.h"
|
||||
#include "openvpnprotocol.h"
|
||||
#include "defines.h"
|
||||
#include "utils.h"
|
||||
#include "openvpnprotocol.h"
|
||||
|
||||
|
||||
OpenVpnProtocol::OpenVpnProtocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
Utils::initializePath(defaultConfigPath());
|
||||
|
||||
readOpenVpnConfiguration(configuration);
|
||||
connect(&m_managementServer, &ManagementServer::readyRead, this, &OpenVpnProtocol::onReadyReadDataFromManagementServer);
|
||||
}
|
||||
@@ -22,22 +26,33 @@ OpenVpnProtocol::~OpenVpnProtocol()
|
||||
QThread::msleep(200);
|
||||
}
|
||||
|
||||
QString OpenVpnProtocol::defaultConfigFileName()
|
||||
{
|
||||
qDebug() << "OpenVpnProtocol::defaultConfigFileName" << defaultConfigPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
|
||||
return defaultConfigPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
|
||||
}
|
||||
|
||||
QString OpenVpnProtocol::defaultConfigPath()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/config";
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::stop()
|
||||
{
|
||||
qDebug() << "OpenVpnProtocol::stop()";
|
||||
|
||||
// TODO: need refactoring
|
||||
// sendTermSignal() will even return true while server connected ???
|
||||
if ((m_connectionState == VpnProtocol::ConnectionState::Preparing) ||
|
||||
(m_connectionState == VpnProtocol::ConnectionState::Connecting) ||
|
||||
(m_connectionState == VpnProtocol::ConnectionState::Connected) ||
|
||||
(m_connectionState == VpnProtocol::ConnectionState::Reconnecting)) {
|
||||
if ((m_connectionState == VpnProtocol::Preparing) ||
|
||||
(m_connectionState == VpnProtocol::Connecting) ||
|
||||
(m_connectionState == VpnProtocol::Connected) ||
|
||||
(m_connectionState == VpnProtocol::Reconnecting)) {
|
||||
if (!sendTermSignal()) {
|
||||
killOpenVpnProcess();
|
||||
}
|
||||
m_managementServer.stop();
|
||||
qApp->processEvents();
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnecting);
|
||||
setConnectionState(VpnProtocol::Disconnecting);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +69,7 @@ ErrorCode OpenVpnProtocol::checkAndSetupTapDriver()
|
||||
QRemoteObjectPendingReply<bool> resultInstall = IpcClient::Interface()->checkAndInstallDriver();
|
||||
resultInstall.waitForFinished();
|
||||
|
||||
if (!resultInstall.returnValue()) return ErrorCode::OpenVpnUnknownError;
|
||||
if (!resultInstall.returnValue()) return ErrorCode::OpenVpnTapAdapterError;
|
||||
}
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
@@ -81,7 +96,7 @@ void OpenVpnProtocol::readOpenVpnConfiguration(const QJsonObject &configuration)
|
||||
QFileInfo file(m_configFileName);
|
||||
|
||||
if (file.fileName().isEmpty()) {
|
||||
m_configFileName = Utils::defaultVpnConfigFileName();
|
||||
m_configFileName = defaultConfigFileName();
|
||||
}
|
||||
|
||||
qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
@@ -125,9 +140,9 @@ void OpenVpnProtocol::updateRouteGateway(QString line)
|
||||
QString OpenVpnProtocol::openVpnExecPath() const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return Utils::executable(QString("openvpn/%1/openvpn").arg(QSysInfo::buildCpuArchitecture()), true);
|
||||
return Utils::executable("openvpn/openvpn", true);
|
||||
#else
|
||||
return Utils::executable(QString("/openvpn"), true);
|
||||
return Utils::executable("/openvpn", true);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -174,7 +189,7 @@ ErrorCode OpenVpnProtocol::start()
|
||||
QStringList arguments({"--config" , configPath(),
|
||||
"--management", m_managementHost, QString::number(m_managementPort),
|
||||
"--management-client",
|
||||
"--log-append", vpnLogFileNamePath
|
||||
"--log", vpnLogFileNamePath
|
||||
});
|
||||
m_openVpnProcess->setArguments(arguments);
|
||||
|
||||
@@ -233,14 +248,14 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
|
||||
if (line.contains("CONNECTED,SUCCESS")) {
|
||||
sendByteCount();
|
||||
stopTimeoutTimer();
|
||||
setConnectionState(VpnProtocol::ConnectionState::Connected);
|
||||
setConnectionState(VpnProtocol::Connected);
|
||||
continue;
|
||||
} else if (line.contains("EXITING,SIGTER")) {
|
||||
//openVpnStateSigTermHandler();
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnecting);
|
||||
setConnectionState(VpnProtocol::Disconnecting);
|
||||
continue;
|
||||
} else if (line.contains("RECONNECTING")) {
|
||||
setConnectionState(VpnProtocol::ConnectionState::Reconnecting);
|
||||
setConnectionState(VpnProtocol::Reconnecting);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -288,52 +303,11 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
|
||||
for (const QString &l : params) {
|
||||
if (l.contains("ifconfig")) {
|
||||
if (l.split(" ").size() == 3) {
|
||||
m_vpnAddress = l.split(" ").at(1);
|
||||
m_vpnLocalAddress = l.split(" ").at(1);
|
||||
m_vpnGateway = l.split(" ").at(2);
|
||||
|
||||
qDebug() << QString("Set vpn address %1, gw %2").arg(m_vpnAddress).arg(vpnGateway());
|
||||
qDebug() << QString("Set vpn local address %1, gw %2").arg(m_vpnLocalAddress).arg(vpnGateway());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// QProcess ipconfig;
|
||||
// ipconfig.start("ipconfig", QStringList() << "/all");
|
||||
// ipconfig.waitForStarted();
|
||||
// ipconfig.waitForFinished();
|
||||
|
||||
// QString d = ipconfig.readAll();
|
||||
// d.replace("\r", "");
|
||||
// //qDebug().noquote() << d;
|
||||
|
||||
// QStringList adapters = d.split(":\n");
|
||||
|
||||
// bool isTapV9Present = false;
|
||||
// QString tapV9;
|
||||
// for (int i = 0; i < adapters.size(); ++i) {
|
||||
// if (adapters.at(i).contains("TAP-Windows Adapter V9")) {
|
||||
// isTapV9Present = true;
|
||||
// tapV9 = adapters.at(i);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (!isTapV9Present) {
|
||||
// m_vpnGateway = "";
|
||||
// }
|
||||
|
||||
// QStringList lines = tapV9.split("\n");
|
||||
// for (int i = 0; i < lines.size(); ++i) {
|
||||
// if (!lines.at(i).contains("DHCP")) continue;
|
||||
|
||||
// QRegularExpression re("(: )([\\d\\.]+)($)");
|
||||
// QRegularExpressionMatch match = re.match(lines.at(i));
|
||||
|
||||
// if (match.hasMatch()) {
|
||||
// qDebug().noquote() << "Current VPN Gateway IP Address: " << match.captured(0);
|
||||
// m_vpnGateway = match.captured(2);
|
||||
// return;
|
||||
// }
|
||||
// else continue;
|
||||
// }
|
||||
|
||||
// m_vpnGateway = "";
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ public:
|
||||
void stop() override;
|
||||
|
||||
ErrorCode checkAndSetupTapDriver();
|
||||
static QString defaultConfigFileName();
|
||||
static QString defaultConfigPath();
|
||||
|
||||
protected slots:
|
||||
void onReadyReadDataFromManagementServer();
|
||||
|
||||
@@ -29,13 +29,14 @@ constexpr char transport_proto[] = "transport_proto";
|
||||
constexpr char cipher[] = "cipher";
|
||||
constexpr char hash[] = "hash";
|
||||
constexpr char ncp_disable[] = "ncp_disable";
|
||||
constexpr char tls_auth[] = "tls_auth";
|
||||
|
||||
constexpr char site[] = "site";
|
||||
constexpr char block_outside_dns[] = "block_outside_dns";
|
||||
|
||||
constexpr char subnet_address[] = "subnet_address";
|
||||
constexpr char subnet_mask[] = "subnet_mask";
|
||||
constexpr char subnet_mask_val[] = "subnet_mask_val";
|
||||
constexpr char subnet_cidr[] = "subnet_cidr";
|
||||
|
||||
// proto config keys
|
||||
constexpr char last_config[] = "last_config";
|
||||
@@ -54,14 +55,16 @@ constexpr char amnezia_wireguard[] = "amnezia-wireguard";
|
||||
|
||||
namespace protocols {
|
||||
|
||||
constexpr char vpnDefaultSubnetAddress[] = "10.8.0.0";
|
||||
constexpr char vpnDefaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char vpnDefaultSubnetMaskVal[] = "24";
|
||||
|
||||
|
||||
constexpr char UDP[] = "udp"; // case sens
|
||||
constexpr char TCP[] = "tcp";
|
||||
|
||||
namespace openvpn {
|
||||
constexpr char defaultSubnetAddress[] = "10.8.0.0";
|
||||
constexpr char defaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char defaultSubnetCidr[] = "24";
|
||||
|
||||
constexpr char caCertPath[] = "/opt/amnezia/openvpn/pki/ca.crt";
|
||||
constexpr char clientCertPath[] = "/opt/amnezia/openvpn/pki/issued";
|
||||
constexpr char taKeyPath[] = "/opt/amnezia/openvpn/ta.key";
|
||||
@@ -72,7 +75,9 @@ constexpr char defaultCipher[] = "AES-256-GCM";
|
||||
constexpr char defaultHash[] = "SHA512";
|
||||
constexpr bool defaultBlockOutsideDns = true;
|
||||
constexpr bool defaultNcpDisable = false;
|
||||
constexpr bool defaultTlsAuth = true;
|
||||
constexpr char ncpDisableString[] = "ncp-disable";
|
||||
constexpr char tlsAuthString[] = "tls-auth /opt/amnezia/openvpn/ta.key 0";
|
||||
|
||||
}
|
||||
|
||||
@@ -93,6 +98,17 @@ constexpr char defaultCipher[] = "chacha20-ietf-poly1305";
|
||||
|
||||
}
|
||||
|
||||
namespace wireguard {
|
||||
constexpr char defaultSubnetAddress[] = "10.8.1.0";
|
||||
constexpr char defaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char defaultSubnetCidr[] = "24";
|
||||
|
||||
constexpr char defaultPort[] = "51820";
|
||||
constexpr char serverConfigPath[] = "/opt/amnezia/wireguard/wg0.conf";
|
||||
constexpr char serverPublicKeyPath[] = "/opt/amnezia/wireguard/wireguard_server_public_key.key";
|
||||
constexpr char serverPskKeyPath[] = "/opt/amnezia/wireguard/wireguard_psk.key";
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace protocols
|
||||
|
||||
@@ -53,7 +53,7 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
||||
|
||||
connect(&m_ssProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus){
|
||||
qDebug().noquote() << "ShadowSocksVpnProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnected);
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
if (exitStatus != QProcess::NormalExit){
|
||||
emit protocolError(amnezia::ErrorCode::ShadowSocksExecutableCrashed);
|
||||
stop();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "vpnprotocol.h"
|
||||
#include "core/errorstrings.h"
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject* parent)
|
||||
: QObject(parent),
|
||||
|
||||
@@ -55,7 +55,7 @@ protected:
|
||||
|
||||
ConnectionState m_connectionState;
|
||||
QString m_routeGateway;
|
||||
QString m_vpnAddress;
|
||||
QString m_vpnLocalAddress;
|
||||
QString m_vpnGateway;
|
||||
|
||||
QJsonObject m_rawConfig;
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QTcpSocket>
|
||||
#include <QThread>
|
||||
|
||||
#include "debug.h"
|
||||
#include "wireguardprotocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
//m_configFile.setFileTemplate(QDir::tempPath() + QDir::separator() + serviceName() + ".conf");
|
||||
m_configFile.setFileName(QDir::tempPath() + QDir::separator() + serviceName() + ".conf");
|
||||
readWireguardConfiguration(configuration);
|
||||
}
|
||||
|
||||
WireguardProtocol::~WireguardProtocol()
|
||||
{
|
||||
qDebug() << "WireguardProtocol::~WireguardProtocol()";
|
||||
WireguardProtocol::stop();
|
||||
QThread::msleep(200);
|
||||
}
|
||||
|
||||
void WireguardProtocol::stop()
|
||||
{
|
||||
if (!QFileInfo::exists(wireguardExecPath())) {
|
||||
qCritical() << "Wireguard executable missing!";
|
||||
setLastError(ErrorCode::ExecutableMissing);
|
||||
return;
|
||||
}
|
||||
|
||||
m_wireguardStopProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
if (!m_wireguardStopProcess) {
|
||||
qCritical() << "IpcProcess replica is not created!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return;
|
||||
}
|
||||
|
||||
m_wireguardStopProcess->waitForSource(1000);
|
||||
if (!m_wireguardStopProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return;
|
||||
}
|
||||
|
||||
m_wireguardStopProcess->setProgram(wireguardExecPath());
|
||||
|
||||
|
||||
QStringList arguments({"/uninstalltunnelservice", serviceName(), });
|
||||
m_wireguardStopProcess->setArguments(arguments);
|
||||
|
||||
qDebug() << arguments.join(" ");
|
||||
|
||||
connect(m_wireguardStopProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, this, [this](QProcess::ProcessError error) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error;
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
});
|
||||
|
||||
connect(m_wireguardStopProcess.data(), &IpcProcessInterfaceReplica::stateChanged, this, [this](QProcess::ProcessState newState) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol Stop stateChanged" << newState;
|
||||
});
|
||||
|
||||
m_wireguardStopProcess->start();
|
||||
|
||||
setConnectionState(VpnProtocol::Disconnected);
|
||||
}
|
||||
|
||||
void WireguardProtocol::readWireguardConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
if (configuration.contains(config::key_wireguard_config_data)) {
|
||||
if (!m_configFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
qCritical() << "Failed to save wireguard config to" << m_configFile.fileName();
|
||||
return;
|
||||
}
|
||||
|
||||
m_isConfigLoaded = true;
|
||||
|
||||
m_configFile.write(configuration.value(config::key_wireguard_config_data).toString().toUtf8());
|
||||
m_configFile.close();
|
||||
m_configFileName = m_configFile.fileName();
|
||||
|
||||
qDebug().noquote() << QString("Set config data") << m_configFileName;
|
||||
qDebug().noquote() << QString("Set config data") << configuration.value(config::key_wireguard_config_data).toString().toUtf8();
|
||||
}
|
||||
// else if (configuration.contains(config::key_wireguard_config_path)) {
|
||||
// m_configFileName = configuration.value(config::key_wireguard_config_path).toString();
|
||||
// QFileInfo file(m_configFileName);
|
||||
|
||||
// if (file.fileName().isEmpty()) {
|
||||
// m_configFileName = defaultConfigFileName();
|
||||
// }
|
||||
|
||||
// qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
// }
|
||||
}
|
||||
|
||||
//bool WireguardProtocol::openVpnProcessIsRunning() const
|
||||
//{
|
||||
// return Utils::processIsRunning("openvpn");
|
||||
//}
|
||||
|
||||
QString WireguardProtocol::configPath() const
|
||||
{
|
||||
return m_configFileName;
|
||||
}
|
||||
|
||||
void WireguardProtocol::updateRouteGateway(QString line)
|
||||
{
|
||||
// TODO: fix for macos
|
||||
line = line.split("ROUTE_GATEWAY", QString::SkipEmptyParts).at(1);
|
||||
if (!line.contains("/")) return;
|
||||
m_routeGateway = line.split("/", QString::SkipEmptyParts).first();
|
||||
m_routeGateway.replace(" ", "");
|
||||
qDebug() << "Set VPN route gateway" << m_routeGateway;
|
||||
}
|
||||
|
||||
QString WireguardProtocol::wireguardExecPath() const
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return Utils::executable("wireguard/wireguard", true);
|
||||
#else
|
||||
return Utils::executable("/wireguard", true);
|
||||
#endif
|
||||
}
|
||||
|
||||
ErrorCode WireguardProtocol::start()
|
||||
{
|
||||
if (!m_isConfigLoaded) {
|
||||
setLastError(ErrorCode::ConfigMissing);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
//qDebug() << "Start OpenVPN connection";
|
||||
WireguardProtocol::stop();
|
||||
|
||||
if (!QFileInfo::exists(wireguardExecPath())) {
|
||||
setLastError(ErrorCode::ExecutableMissing);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
if (!QFileInfo::exists(configPath())) {
|
||||
setLastError(ErrorCode::ConfigMissing);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
|
||||
m_wireguardStartProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
if (!m_wireguardStartProcess) {
|
||||
//qWarning() << "IpcProcess replica is not created!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
m_wireguardStartProcess->waitForSource(1000);
|
||||
if (!m_wireguardStartProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
m_wireguardStartProcess->setProgram(wireguardExecPath());
|
||||
|
||||
|
||||
QStringList arguments({"/installtunnelservice", configPath(), });
|
||||
m_wireguardStartProcess->setArguments(arguments);
|
||||
|
||||
qDebug() << arguments.join(" ");
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, this, [this](QProcess::ProcessError error) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error;
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::stateChanged, this, [this](QProcess::ProcessState newState) {
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol stateChanged" << newState;
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::finished, this, [this]() {
|
||||
setConnectionState(ConnectionState::Connected);
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyRead, this, [this]() {
|
||||
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAll();
|
||||
reply.waitForFinished(1000);
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol readyRead" << reply.returnValue();
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyReadStandardOutput, this, [this]() {
|
||||
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAllStandardOutput();
|
||||
reply.waitForFinished(1000);
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardOutput" << reply.returnValue();
|
||||
});
|
||||
|
||||
connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyReadStandardError, this, [this]() {
|
||||
QRemoteObjectPendingReply<QByteArray> reply = m_wireguardStartProcess->readAllStandardError();
|
||||
reply.waitForFinished(1000);
|
||||
qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardError" << reply.returnValue();
|
||||
});
|
||||
|
||||
m_wireguardStartProcess->start();
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
void WireguardProtocol::updateVpnGateway(const QString &line)
|
||||
{
|
||||
// // line looks like
|
||||
// // PUSH: Received control message: 'PUSH_REPLY,route 10.8.0.1,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM'
|
||||
|
||||
// QStringList params = line.split(",");
|
||||
// for (const QString &l : params) {
|
||||
// if (l.contains("ifconfig")) {
|
||||
// if (l.split(" ").size() == 3) {
|
||||
// m_vpnLocalAddress = l.split(" ").at(1);
|
||||
// m_vpnGateway = l.split(" ").at(2);
|
||||
|
||||
// qDebug() << QString("Set vpn local address %1, gw %2").arg(m_vpnLocalAddress).arg(vpnGateway());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
QString WireguardProtocol::serviceName() const
|
||||
{
|
||||
return "AmneziaVPN.WireGuard0";
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef WIREGUARDPROTOCOL_H
|
||||
#define WIREGUARDPROTOCOL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include "vpnprotocol.h"
|
||||
#include "core/ipcclient.h"
|
||||
|
||||
class WireguardProtocol : public VpnProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WireguardProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~WireguardProtocol() override;
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
private:
|
||||
QString configPath() const;
|
||||
QString wireguardExecPath() const;
|
||||
//bool openVpnProcessIsRunning() const;
|
||||
void readWireguardConfiguration(const QJsonObject &configuration);
|
||||
|
||||
void updateRouteGateway(QString line);
|
||||
void updateVpnGateway(const QString &line);
|
||||
QString serviceName() const;
|
||||
|
||||
|
||||
private:
|
||||
QString m_configFileName;
|
||||
QFile m_configFile;
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> m_wireguardStartProcess;
|
||||
QSharedPointer<IpcProcessInterfaceReplica> m_wireguardStopProcess;
|
||||
|
||||
bool m_isConfigLoaded = false;
|
||||
|
||||
};
|
||||
|
||||
#endif // WIREGUARDPROTOCOL_H
|
||||
@@ -61,5 +61,11 @@
|
||||
<file>server_scripts/openvpn_shadowsocks/run_container.sh</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/start.sh</file>
|
||||
<file>server_scripts/openvpn_shadowsocks/template.ovpn</file>
|
||||
<file>images/folder.png</file>
|
||||
<file>server_scripts/wireguard/configure_container.sh</file>
|
||||
<file>server_scripts/wireguard/Dockerfile</file>
|
||||
<file>server_scripts/wireguard/run_container.sh</file>
|
||||
<file>server_scripts/wireguard/start.sh</file>
|
||||
<file>server_scripts/wireguard/template.conf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; sudo $pm update -y -q
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else pm=$pm_yum; fi; sudo $pm install -y -q curl
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum"; if [[ -f "$pm_apt" ]]; then sudo export DEBIAN_FRONTEND=noninteractive; sudo $pm_apt install -y -q docker.io; else sudo $pm_yum install -y -q docker; fi
|
||||
pm_apt="/usr/bin/apt-get"; pm_yum="/usr/bin/yum";\
|
||||
if [[ -f "$pm_apt" ]]; then pm=$pm_apt; docker_pkg="docker.io"; else pm=$pm_yum; docker_pkg="docker"; fi;\
|
||||
if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi;\
|
||||
docker_service=$(systemctl list-units --full -all | grep docker.service);\
|
||||
if [[ -f "$pm_apt" ]]; then export DEBIAN_FRONTEND=noninteractive; fi;\
|
||||
if [[ -z "$docker_service" ]]; then sudo $pm update -y -q; sudo $pm install -y -q curl $docker_pkg; fi;\
|
||||
sudo systemctl start docker
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ ca /opt/amnezia/openvpn/ca.crt \\n\
|
||||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
server $OPENVPN_SUBNET_IP $OPENVPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
@@ -23,5 +23,5 @@ status openvpn-status.log \\n\
|
||||
verb 1 \\n\
|
||||
tls-server \\n\
|
||||
tls-version-min 1.2 \\n\
|
||||
tls-auth /opt/amnezia/openvpn/ta.key 0" >>/opt/amnezia/openvpn/server.conf'
|
||||
$OPENVPN_TLS_AUTH" >/opt/amnezia/openvpn/server.conf'
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||
|
||||
if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net; mknod /dev/net/tun c 10 200; fi
|
||||
|
||||
@@ -12,10 +13,10 @@ iptables -A FORWARD -i tun0 -j ACCEPT
|
||||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -o eth0 -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 $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
|
||||
@@ -16,6 +16,10 @@ 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 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 tar -Jxvf /usr/bin/ss.tar.xz -C /usr/bin/
|
||||
RUN chmod a+x /usr/bin/ssserver
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
fs.file-max = 51200 \n\
|
||||
|
||||
@@ -7,7 +7,7 @@ ca /opt/amnezia/openvpn/ca.crt \\n\
|
||||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
server $OPENVPN_SUBNET_IP $OPENVPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
@@ -23,7 +23,7 @@ status openvpn-status.log \\n\
|
||||
verb 1 \\n\
|
||||
tls-server \\n\
|
||||
tls-version-min 1.2 \\n\
|
||||
tls-auth /opt/amnezia/openvpn/ta.key 0" >>/opt/amnezia/openvpn/server.conf'
|
||||
$OPENVPN_TLS_AUTH" >/opt/amnezia/openvpn/server.conf'
|
||||
|
||||
# Cloak config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
@@ -37,9 +37,13 @@ echo $CLOAK_PRIVATE_KEY > /opt/amnezia/cloak/cloak_private.key; \
|
||||
echo -e "{\\n\
|
||||
\"ProxyBook\": {\\n\
|
||||
\"openvpn\": [\\n\
|
||||
\"$OPENVPN_TRANSPORT_PROTO\",\\n\
|
||||
\"localhost:$OPENVPN_PORT\"\\n\
|
||||
]\\n\
|
||||
\"$OPENVPN_TRANSPORT_PROTO\",\\n\
|
||||
\"localhost:$OPENVPN_PORT\"\\n\
|
||||
],\\n\
|
||||
\"shadowsocks\": [\\n\
|
||||
\"tcp\",\\n\
|
||||
\"localhost:$SHADOWSOCKS_SERVER_PORT\"\\n\
|
||||
]\\n\
|
||||
},\\n\
|
||||
\"BypassUID\": [\\n\
|
||||
\"$CLOAK_BYPASS_UID\"\\n\
|
||||
@@ -51,3 +55,17 @@ echo -e "{\\n\
|
||||
\"DatabasePath\": \"userinfo.db\",\\n\
|
||||
\"StreamTimeout\": 300\\n\
|
||||
}" >/opt/amnezia/cloak/ck-config.json'
|
||||
|
||||
# ShadowSocks config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
mkdir -p /opt/amnezia/shadowsocks; \
|
||||
cd /opt/amnezia/shadowsocks || exit 1; \
|
||||
SHADOWSOCKS_PASSWORD=$(openssl rand -base64 32 | tr "=" "A" | tr "+" "A" | tr "/" "A") && echo $SHADOWSOCKS_PASSWORD > /opt/amnezia/shadowsocks/shadowsocks.key; \
|
||||
echo -e "{\\n\
|
||||
\"local_port\": 8585,\\n\
|
||||
\"method\": \"$SHADOWSOCKS_CIPHER\",\\n\
|
||||
\"password\": \"$SHADOWSOCKS_PASSWORD\",\\n\
|
||||
\"server\": \"0.0.0.0\",\\n\
|
||||
\"server_port\": $SHADOWSOCKS_SERVER_PORT,\\n\
|
||||
\"timeout\": 60\\n\
|
||||
}" >/opt/amnezia/shadowsocks/ss-config.json'
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||
|
||||
if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net; mknod /dev/net/tun c 10 200; fi
|
||||
|
||||
@@ -12,17 +13,19 @@ iptables -A FORWARD -i tun0 -j ACCEPT
|
||||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -o eth0 -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 $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
killall -KILL ck-server
|
||||
killall -KILL ssserver
|
||||
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/openvpn/ca.crt ]; then (openvpn --config /opt/amnezia/openvpn/server.conf --daemon); fi
|
||||
if [ -f /opt/amnezia/shadowsocks/ss-config.json ]; then (ssserver -c /opt/amnezia/shadowsocks/ss-config.json &); fi
|
||||
if [ -f /opt/amnezia/cloak/ck-config.json ]; then (ck-server -c /opt/amnezia/cloak/ck-config.json &); fi
|
||||
|
||||
tail -f /dev/null
|
||||
|
||||
@@ -7,7 +7,7 @@ ca /opt/amnezia/openvpn/ca.crt \\n\
|
||||
cert /opt/amnezia/openvpn/AmneziaReq.crt \\n\
|
||||
key /opt/amnezia/openvpn/AmneziaReq.key \\n\
|
||||
dh /opt/amnezia/openvpn/dh.pem \\n\
|
||||
server $VPN_SUBNET_IP $VPN_SUBNET_MASK \\n\
|
||||
server $OPENVPN_SUBNET_IP $OPENVPN_SUBNET_MASK \\n\
|
||||
ifconfig-pool-persist ipp.txt \\n\
|
||||
duplicate-cn \\n\
|
||||
keepalive 10 120 \\n\
|
||||
@@ -23,9 +23,9 @@ status openvpn-status.log \\n\
|
||||
verb 1 \\n\
|
||||
tls-server \\n\
|
||||
tls-version-min 1.2 \\n\
|
||||
tls-auth /opt/amnezia/openvpn/ta.key 0" >>/opt/amnezia/openvpn/server.conf'
|
||||
$OPENVPN_TLS_AUTH" >/opt/amnezia/openvpn/server.conf'
|
||||
|
||||
# Cloak config
|
||||
# ShadowSocks config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
mkdir -p /opt/amnezia/shadowsocks; \
|
||||
cd /opt/amnezia/shadowsocks || exit 1; \
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||
|
||||
if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net; mknod /dev/net/tun c 10 200; fi
|
||||
|
||||
@@ -12,10 +13,10 @@ iptables -A FORWARD -i tun0 -j ACCEPT
|
||||
iptables -A OUTPUT -o tun0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i tun0 -o eth0 -s $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -j ACCEPT
|
||||
iptables -A FORWARD -i tun0 -o eth0 -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 $VPN_SUBNET_IP/$VPN_SUBNET_MASK_VAL -o eth0 -j MASQUERADE
|
||||
iptables -t nat -A POSTROUTING -s $OPENVPN_SUBNET_IP/$OPENVPN_SUBNET_CIDR -o eth0 -j MASQUERADE
|
||||
|
||||
# kill daemons in case of restart
|
||||
killall -KILL openvpn
|
||||
@@ -24,4 +25,5 @@ killall -KILL ssserver
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/openvpn/ca.crt ]; then (openvpn --config /opt/amnezia/openvpn/server.conf --daemon); fi
|
||||
if [ -f /opt/amnezia/shadowsocks/ss-config.json ]; then (ssserver -c /opt/amnezia/shadowsocks/ss-config.json &); fi
|
||||
|
||||
tail -f /dev/null
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
FROM alpine:latest
|
||||
|
||||
LABEL maintainer="AmneziaVPN"
|
||||
|
||||
#Install required packages
|
||||
RUN apk add --no-cache curl wireguard-tools dumb-init
|
||||
RUN apk --update upgrade --no-cache
|
||||
|
||||
RUN mkdir -p /opt/amnezia
|
||||
RUN echo -e "#!/bin/bash\ntail -f /dev/null" > /opt/amnezia/start.sh
|
||||
RUN chmod a+x /opt/amnezia/start.sh
|
||||
|
||||
# Tune network
|
||||
RUN echo -e " \n\
|
||||
fs.file-max = 51200 \n\
|
||||
\n\
|
||||
net.core.rmem_max = 67108864 \n\
|
||||
net.core.wmem_max = 67108864 \n\
|
||||
net.core.netdev_max_backlog = 250000 \n\
|
||||
net.core.somaxconn = 4096 \n\
|
||||
\n\
|
||||
net.ipv4.tcp_syncookies = 1 \n\
|
||||
net.ipv4.tcp_tw_reuse = 1 \n\
|
||||
net.ipv4.tcp_tw_recycle = 0 \n\
|
||||
net.ipv4.tcp_fin_timeout = 30 \n\
|
||||
net.ipv4.tcp_keepalive_time = 1200 \n\
|
||||
net.ipv4.ip_local_port_range = 10000 65000 \n\
|
||||
net.ipv4.tcp_max_syn_backlog = 8192 \n\
|
||||
net.ipv4.tcp_max_tw_buckets = 5000 \n\
|
||||
net.ipv4.tcp_fastopen = 3 \n\
|
||||
net.ipv4.tcp_mem = 25600 51200 102400 \n\
|
||||
net.ipv4.tcp_rmem = 4096 87380 67108864 \n\
|
||||
net.ipv4.tcp_wmem = 4096 65536 67108864 \n\
|
||||
net.ipv4.tcp_mtu_probing = 1 \n\
|
||||
net.ipv4.tcp_congestion_control = hybla \n\
|
||||
# for low-latency network, use cubic instead \n\
|
||||
# net.ipv4.tcp_congestion_control = cubic \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/sysctl.conf && \
|
||||
mkdir -p /etc/security && \
|
||||
echo -e " \n\
|
||||
* soft nofile 51200 \n\
|
||||
* hard nofile 51200 \n\
|
||||
" | sed -e 's/^\s\+//g' | tee -a /etc/security/limits.conf
|
||||
|
||||
ENTRYPOINT [ "dumb-init", "/opt/amnezia/start.sh" ]
|
||||
CMD [ "" ]
|
||||
@@ -0,0 +1,13 @@
|
||||
# Wireguard config
|
||||
sudo docker exec -i $CONTAINER_NAME bash -c '\
|
||||
mkdir -p /opt/amnezia/wireguard; \
|
||||
cd /opt/amnezia/wireguard || exit 1; \
|
||||
WIREGUARD_SERVER_PRIVATE_KEY=$(wg genkey) && echo $WIREGUARD_SERVER_PRIVATE_KEY > /opt/amnezia/wireguard/wireguard_server_private_key.key; \
|
||||
WIREGUARD_SERVER_PUBLIC_KEY=$(echo $WIREGUARD_SERVER_PRIVATE_KEY | wg pubkey) && echo $WIREGUARD_SERVER_PUBLIC_KEY > /opt/amnezia/wireguard/wireguard_server_public_key.key; \
|
||||
WIREGUARD_PSK=$(wg genpsk) && echo $WIREGUARD_PSK > /opt/amnezia/wireguard/wireguard_psk.key; \
|
||||
echo -e "\
|
||||
[Interface]\\n\
|
||||
PrivateKey = $WIREGUARD_SERVER_PRIVATE_KEY \\n\
|
||||
Address = $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_CIDR \\n\
|
||||
ListenPort = $WIREGUARD_SERVER_PORT \\n\
|
||||
" >/opt/amnezia/wireguard/wg0.conf'
|
||||
@@ -0,0 +1,15 @@
|
||||
# Run container
|
||||
sudo docker run -d \
|
||||
--restart always \
|
||||
--privileged \
|
||||
--cap-add=NET_ADMIN \
|
||||
--cap-add=SYS_MODULE \
|
||||
-p $WIREGUARD_SERVER_PORT:$WIREGUARD_SERVER_PORT/udp \
|
||||
-v /lib/modules:/lib/modules \
|
||||
--sysctl="net.ipv4.conf.all.src_valid_mark=1" \
|
||||
--name $CONTAINER_NAME \
|
||||
$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"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This scripts copied from Amnezia client to Docker container to /opt/amnezia and launched every time container starts
|
||||
|
||||
echo "Container startup"
|
||||
#ifconfig eth0:0 $SERVER_IP_ADDRESS netmask 255.255.255.255 up
|
||||
|
||||
# kill daemons in case of restart
|
||||
wg-quick down /opt/amnezia/wireguard/wg0.conf
|
||||
|
||||
# start daemons if configured
|
||||
if [ -f /opt/amnezia/wireguard/wg0.conf ]; then (wg-quick up /opt/amnezia/wireguard/wg0.conf); fi
|
||||
|
||||
# Allow traffic on the TUN interface.
|
||||
iptables -A INPUT -i wg0 -j ACCEPT
|
||||
iptables -A FORWARD -i wg0 -j ACCEPT
|
||||
iptables -A OUTPUT -o wg0 -j ACCEPT
|
||||
|
||||
# Allow forwarding traffic only from the VPN.
|
||||
iptables -A FORWARD -i wg0 -o eth0 -s $WIREGUARD_SUBNET_IP/$WIREGUARD_SUBNET_MASK_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
|
||||
|
||||
tail -f /dev/null
|
||||
@@ -0,0 +1,11 @@
|
||||
[Interface]
|
||||
Address = 10.8.1.2/32
|
||||
DNS = 1.1.1.1, 1.0.0.1
|
||||
PrivateKey = $WIREGUARD_CLIENT_PRIVATE_KEY
|
||||
|
||||
[Peer]
|
||||
PublicKey = $WIREGUARD_SERVER_PUBLIC_KEY
|
||||
PresharedKey = $WIREGUARD_PSK
|
||||
AllowedIPs = 0.0.0.0/0, ::/0
|
||||
Endpoint = $SERVER_IP_ADDRESS:$WIREGUARD_SERVER_PORT
|
||||
PersistentKeepalive = 25
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "defines.h"
|
||||
#include "settings.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include "protocols/protocols_defs.h"
|
||||
@@ -205,6 +206,118 @@ QString Settings::nextAvailableServerName() const
|
||||
return tr("Server") + " " + QString::number(i);
|
||||
}
|
||||
|
||||
QString Settings::routeModeString(RouteMode mode) const
|
||||
{
|
||||
switch (mode) {
|
||||
case VpnAllSites:
|
||||
return "AllSites";
|
||||
case VpnOnlyForwardSites:
|
||||
return "ForwardSites";
|
||||
case VpnAllExceptSites:
|
||||
return "ExceptSites";
|
||||
}
|
||||
}
|
||||
|
||||
void Settings::addVpnSite(RouteMode mode, const QString &site, const QString &ip)
|
||||
{
|
||||
QVariantMap sites = vpnSites(mode);
|
||||
if (sites.contains(site) && ip.isEmpty()) return;
|
||||
|
||||
sites.insert(site, ip);
|
||||
setVpnSites(mode, sites);
|
||||
}
|
||||
|
||||
QStringList Settings::getVpnIps(RouteMode mode) const
|
||||
{
|
||||
QStringList ips;
|
||||
const QVariantMap &m = vpnSites(mode);
|
||||
for (auto i = m.constBegin(); i != m.constEnd(); ++i) {
|
||||
if (Utils::checkIpSubnetFormat(i.key())) {
|
||||
ips.append(i.key());
|
||||
}
|
||||
else if (Utils::checkIpSubnetFormat(i.value().toString())) {
|
||||
ips.append(i.value().toString());
|
||||
}
|
||||
}
|
||||
ips.removeDuplicates();
|
||||
return ips;
|
||||
}
|
||||
|
||||
void Settings::removeVpnSite(RouteMode mode, const QString &site)
|
||||
{
|
||||
QVariantMap sites = vpnSites(mode);
|
||||
if (!sites.contains(site)) return;
|
||||
|
||||
sites.remove(site);
|
||||
setVpnSites(mode, sites);
|
||||
}
|
||||
|
||||
void Settings::addVpnIps(RouteMode mode, const QStringList &ips)
|
||||
{
|
||||
QVariantMap sites = vpnSites(mode);
|
||||
for (const QString &ip : ips) {
|
||||
if (ip.isEmpty()) continue;
|
||||
|
||||
sites.insert(ip, "");
|
||||
}
|
||||
|
||||
setVpnSites(mode, sites);
|
||||
}
|
||||
|
||||
void Settings::removeVpnSites(RouteMode mode, const QStringList &sites)
|
||||
{
|
||||
QVariantMap sitesMap = vpnSites(mode);
|
||||
for (const QString &site : sites) {
|
||||
if (site.isEmpty()) continue;
|
||||
|
||||
sitesMap.remove(site);
|
||||
}
|
||||
|
||||
setVpnSites(mode, sitesMap);
|
||||
}
|
||||
|
||||
//void Settings::addVpnForwardSite(const QString &site, const QString &ip)
|
||||
//{
|
||||
// auto sites = vpnForwardSites();
|
||||
// QStringList l = sites.value(site).toStringList();
|
||||
// if (!l.contains(ip)) {
|
||||
// l.append(ip);
|
||||
// setVpnForwardSites(sites);
|
||||
// }
|
||||
//}
|
||||
|
||||
//QStringList Settings::getVpnForwardIps() const
|
||||
//{
|
||||
// QStringList ips;
|
||||
// const QVariantMap &m = vpnForwardSites();
|
||||
// for (const QVariant &v : m) {
|
||||
// ips.append(v.toStringList());
|
||||
// }
|
||||
// ips.removeDuplicates();
|
||||
// return ips;
|
||||
//}
|
||||
|
||||
//void Settings::addVpnExceptSite(const QString &site, const QString &ip)
|
||||
//{
|
||||
// auto sites = vpnExceptSites();
|
||||
// QStringList l = sites.value(site).toStringList();
|
||||
// if (!l.contains(ip)) {
|
||||
// l.append(ip);
|
||||
// setVpnExceptSites(sites);
|
||||
// }
|
||||
//}
|
||||
|
||||
//QStringList Settings::getVpnExceptIps() const
|
||||
//{
|
||||
// QStringList ips;
|
||||
// const QVariantMap &m = vpnExceptSites();
|
||||
// for (const QVariant &v : m) {
|
||||
// ips.append(v.toStringList());
|
||||
// }
|
||||
// ips.removeDuplicates();
|
||||
// return ips;
|
||||
//}
|
||||
|
||||
QString Settings::primaryDns() const { return m_settings.value("Conf/primaryDns", cloudFlareNs1).toString(); }
|
||||
|
||||
QString Settings::secondaryDns() const { return m_settings.value("Conf/secondaryDns", cloudFlareNs2).toString(); }
|
||||
|
||||
+25
-24
@@ -23,19 +23,6 @@ class Settings : public QObject
|
||||
public:
|
||||
explicit Settings(QObject* parent = nullptr);
|
||||
|
||||
|
||||
// QString userName() const { return m_settings.value("Server/userName", QString()).toString(); }
|
||||
// void setUserName(const QString& login) { m_settings.setValue("Server/userName", login); }
|
||||
|
||||
// QString password() const { return m_settings.value("Server/password", QString()).toString(); }
|
||||
// void setPassword(const QString& password) { m_settings.setValue("Server/password", password); }
|
||||
|
||||
// QString serverName() const { return m_settings.value("Server/serverName", QString()).toString(); }
|
||||
// void setServerName(const QString& serverName) { m_settings.setValue("Server/serverName", serverName); }
|
||||
|
||||
// int serverPort() const { return m_settings.value("Server/serverPort", 22).toInt(); }
|
||||
// void setServerPort(int serverPort = 22) { m_settings.setValue("Server/serverPort", serverPort); }
|
||||
|
||||
ServerCredentials defaultServerCredentials() const;
|
||||
ServerCredentials serverCredentials(int index) const;
|
||||
//void setServerCredentials(const ServerCredentials &credentials);
|
||||
@@ -74,19 +61,33 @@ public:
|
||||
QString nextAvailableServerName() const;
|
||||
|
||||
// App settings section
|
||||
bool isAutoConnect() const { return m_settings.value("Conf/autoConnect", QString()).toBool(); }
|
||||
bool isAutoConnect() const { return m_settings.value("Conf/autoConnect", false).toBool(); }
|
||||
void setAutoConnect(bool enabled) { m_settings.setValue("Conf/autoConnect", enabled); }
|
||||
|
||||
bool customRouting() const { return m_settings.value("Conf/customRouting", false).toBool(); }
|
||||
void setCustomRouting(bool customRouting) { m_settings.setValue("Conf/customRouting", customRouting); }
|
||||
bool isStartMinimized() const { return m_settings.value("Conf/startMinimized", false).toBool(); }
|
||||
void setStartMinimized(bool enabled) { m_settings.setValue("Conf/startMinimized", enabled); }
|
||||
|
||||
// list of sites to pass blocking added by user
|
||||
QStringList customSites() { return m_settings.value("Conf/customSites").toStringList(); }
|
||||
void setCustomSites(const QStringList &customSites) { m_settings.setValue("Conf/customSites", customSites); }
|
||||
enum RouteMode {
|
||||
VpnAllSites,
|
||||
VpnOnlyForwardSites,
|
||||
VpnAllExceptSites
|
||||
};
|
||||
Q_ENUM (RouteMode)
|
||||
|
||||
QString routeModeString(RouteMode mode) const;
|
||||
|
||||
RouteMode routeMode() const { return static_cast<RouteMode>(m_settings.value("Conf/routeMode", 0).toInt()); }
|
||||
void setRouteMode(RouteMode mode) { m_settings.setValue("Conf/routeMode", mode); }
|
||||
|
||||
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= "");
|
||||
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);
|
||||
|
||||
// list of ips to pass blocking generated from customSites
|
||||
QStringList customIps() { return m_settings.value("Conf/customIps").toStringList(); }
|
||||
void setCustomIps(const QStringList &customIps) { m_settings.setValue("Conf/customIps", customIps); }
|
||||
|
||||
QString primaryDns() const;
|
||||
QString secondaryDns() const;
|
||||
@@ -100,8 +101,8 @@ public:
|
||||
static const char cloudFlareNs1[];
|
||||
static const char cloudFlareNs2[];
|
||||
|
||||
static constexpr char openNicNs5[] = "94.103.153.176";
|
||||
static constexpr char openNicNs13[] = "144.76.103.143";
|
||||
// static constexpr char openNicNs5[] = "94.103.153.176";
|
||||
// static constexpr char openNicNs13[] = "144.76.103.143";
|
||||
|
||||
|
||||
public:
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -121,6 +121,8 @@ void SlidingStackedWidget::slideInWgtImpl(QWidget * newwidget, enum t_direction
|
||||
}
|
||||
else m_active = true;
|
||||
|
||||
m_nextWidget = newwidget;
|
||||
|
||||
enum t_direction directionhint;
|
||||
int now = currentIndex(); // currentIndex() is a function inherited from QStackedWidget
|
||||
int next = indexOf(newwidget);
|
||||
@@ -209,6 +211,18 @@ void SlidingStackedWidget::slideInWgtImpl(QWidget * newwidget, enum t_direction
|
||||
// that we implement here below in animationDoneSlot.
|
||||
}
|
||||
|
||||
void SlidingStackedWidget::setCurrentWidget(QWidget *w)
|
||||
{
|
||||
m_nextWidget = w;
|
||||
QStackedWidget::setCurrentWidget(w);
|
||||
}
|
||||
|
||||
QWidget *SlidingStackedWidget::nextWidget() const
|
||||
{
|
||||
if (m_nextWidget == nullptr) return currentWidget();
|
||||
return m_nextWidget;
|
||||
}
|
||||
|
||||
void SlidingStackedWidget::animationDoneSlot(void) {
|
||||
// when ready, call the QStackedWidget slot setCurrentIndex(int)
|
||||
setCurrentIndex(m_next); // this function is inherited from QStackedWidget
|
||||
|
||||
@@ -34,6 +34,9 @@ public:
|
||||
SlidingStackedWidget(QWidget *parent);
|
||||
~SlidingStackedWidget(void);
|
||||
|
||||
QWidget *nextWidget() const;
|
||||
void setCurrentWidget(QWidget *w);
|
||||
|
||||
public slots:
|
||||
// Some basic settings API
|
||||
void setSpeed(int speed); // animation duration in milliseconds
|
||||
@@ -77,6 +80,8 @@ protected:
|
||||
QPropertyAnimation *animnow;
|
||||
QPropertyAnimation *animnext;
|
||||
QParallelAnimationGroup *animgroup;
|
||||
|
||||
QWidget *m_nextWidget = nullptr;
|
||||
};
|
||||
|
||||
#endif // SLIDINGSTACKEDWIDGET_H
|
||||
|
||||
+697
-304
File diff suppressed because it is too large
Load Diff
+25
-8
@@ -17,6 +17,7 @@
|
||||
#include "protocols/vpnprotocol.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "sites_model.h"
|
||||
|
||||
class VpnConnection;
|
||||
|
||||
@@ -40,11 +41,15 @@ public:
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
enum Page {Start, NewServer, NewServer_2, Vpn, GeneralSettings, AppSettings, NetworkSettings,
|
||||
ServerSettings, ServerVpnProtocols, ServersList, ShareConnection, Sites,
|
||||
enum Page {Start, NewServer, NewServerProtocols, Vpn,
|
||||
Wizard, WizardLow, WizardMedium, WizardHigh, WizardVpnMode, ServerConfiguring,
|
||||
GeneralSettings, AppSettings, NetworkSettings, ServerSettings,
|
||||
ServerVpnProtocols, ServersList, ShareConnection, Sites,
|
||||
OpenVpnSettings, ShadowSocksSettings, CloakSettings};
|
||||
Q_ENUM(Page)
|
||||
|
||||
void showOnStartup();
|
||||
|
||||
private slots:
|
||||
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void onConnectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
@@ -52,14 +57,13 @@ private slots:
|
||||
|
||||
void onPushButtonConnectClicked(bool checked);
|
||||
void onPushButtonNewServerConnect(bool);
|
||||
void onPushButtonNewServerConnectConfigure(bool);
|
||||
void installServer(const QMap<DockerContainer, QJsonObject> &containers);
|
||||
void onPushButtonNewServerImport(bool);
|
||||
|
||||
void onPushButtonClearServer(bool);
|
||||
void onPushButtonForgetServer(bool);
|
||||
|
||||
void onPushButtonAddCustomSitesClicked();
|
||||
void onPushButtonDeleteCustomSiteClicked(const QString &siteToDelete);
|
||||
|
||||
void onTrayActionConnect(); // connect from context menu
|
||||
void setTrayState(VpnProtocol::ConnectionState state);
|
||||
@@ -79,7 +83,7 @@ private:
|
||||
QWidget *getPageWidget(Page page);
|
||||
Page currentPage();
|
||||
|
||||
bool installServer(ServerCredentials credentials, QList<DockerContainer> containers, QJsonArray configs,
|
||||
bool installContainers(ServerCredentials credentials, const QMap<DockerContainer, QJsonObject> &containers,
|
||||
QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info);
|
||||
|
||||
ErrorCode doInstallAction(const std::function<ErrorCode()> &action, QWidget *page, QProgressBar *progress, QPushButton *button, QLabel *info);
|
||||
@@ -88,6 +92,13 @@ private:
|
||||
void setTrayIcon(const QString &iconPath);
|
||||
|
||||
void setupUiConnections();
|
||||
void setupNewServerConnections();
|
||||
void setupWizardConnections();
|
||||
void setupVpnPageConnections();
|
||||
void setupSitesPageConnections();
|
||||
void setupAppSettingsConnections();
|
||||
void setupGeneralSettingsConnections();
|
||||
void setupNetworkSettingsConnections();
|
||||
void setupProtocolsPageConnections();
|
||||
void setupNewServerPageConnections();
|
||||
void setupServerSettingsPageConnections();
|
||||
@@ -97,10 +108,10 @@ private:
|
||||
void updateSitesPage();
|
||||
void updateVpnPage();
|
||||
void updateAppSettingsPage();
|
||||
void updateGeneralSettingPage();
|
||||
void updateServerPage();
|
||||
void updateServersListPage();
|
||||
void updateProtocolsPage();
|
||||
void updateShareCodePage();
|
||||
void updateOpenVpnPage(const QJsonObject &openvpnConfig, DockerContainer container, bool haveAuthData);
|
||||
void updateShadowSocksPage(const QJsonObject &ssConfig, DockerContainer container, bool haveAuthData);
|
||||
void updateCloakPage(const QJsonObject &ckConfig, DockerContainer container, bool haveAuthData);
|
||||
@@ -108,7 +119,6 @@ private:
|
||||
void updateSharingPage(int serverIndex, const ServerCredentials &credentials,
|
||||
DockerContainer container);
|
||||
|
||||
void makeSitesListItem(QListWidget* listWidget, const QString &address);
|
||||
void makeServersListItem(QListWidget* listWidget, const QJsonObject &server, bool isDefault, int index);
|
||||
|
||||
void updateQRCodeImage(const QString &text, QLabel *label);
|
||||
@@ -117,11 +127,16 @@ private:
|
||||
QJsonObject getShadowSocksConfigFromPage(QJsonObject oldConfig);
|
||||
QJsonObject getCloakConfigFromPage(QJsonObject oldConfig);
|
||||
|
||||
QMap<DockerContainer, QJsonObject> getInstallConfigsFromProtocolsPage() const;
|
||||
QMap<DockerContainer, QJsonObject> getInstallConfigsFromWizardPage() const;
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
VpnConnection* m_vpnConnection;
|
||||
Settings m_settings;
|
||||
|
||||
QMap<Settings::RouteMode, SitesModel *> sitesModels;
|
||||
|
||||
QAction* m_trayActionConnect;
|
||||
QAction* m_trayActionDisconnect;
|
||||
|
||||
@@ -137,6 +152,8 @@ private:
|
||||
|
||||
bool canMove = false;
|
||||
QPoint offset;
|
||||
bool needToHideCustomTitlebar = false;
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
@@ -151,7 +168,7 @@ private:
|
||||
QStack<Page> pagesStack;
|
||||
int selectedServerIndex = -1; // server index to use when proto settings page opened
|
||||
DockerContainer selectedDockerContainer; // same
|
||||
ServerCredentials installCredentials; // used to save cred between pages new_server and new_server_2
|
||||
ServerCredentials installCredentials; // used to save cred between pages new_server and new_server_protocols and wizard
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
+2136
-320
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
#include "sites_model.h"
|
||||
|
||||
SitesModel::SitesModel(Settings::RouteMode mode, QObject *parent)
|
||||
: m_mode(mode),
|
||||
QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void SitesModel::resetCache()
|
||||
{
|
||||
beginResetModel();
|
||||
m_ipsCache.clear();
|
||||
m_cacheReady = false;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant SitesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
// FIXME: Implement me!
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int SitesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (!m_cacheReady) genCache();
|
||||
return m_ipsCache.size();
|
||||
}
|
||||
|
||||
int SitesModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
QVariant SitesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (!m_cacheReady) genCache();
|
||||
|
||||
if (role == Qt::DisplayRole){
|
||||
if (m_ipsCache.isEmpty()) return QVariant();
|
||||
|
||||
if (index.column() == 0) {
|
||||
return m_ipsCache.at(index.row()).first;
|
||||
}
|
||||
if (index.column() == 1) {
|
||||
return m_ipsCache.at(index.row()).second;
|
||||
}
|
||||
}
|
||||
|
||||
// if (role == Qt::TextAlignmentRole && index.column() == 1) {
|
||||
// return Qt::AlignRight;
|
||||
// }
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void SitesModel::genCache() const
|
||||
{
|
||||
qDebug() << "SitesModel::genCache";
|
||||
m_ipsCache.clear();
|
||||
|
||||
const QVariantMap &sites = m_settings.vpnSites(m_mode);
|
||||
auto i = sites.constBegin();
|
||||
while (i != sites.constEnd()) {
|
||||
m_ipsCache.append(qMakePair(i.key(), i.value().toString()));
|
||||
++i;
|
||||
}
|
||||
|
||||
m_cacheReady= true;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef SITESMODEL_H
|
||||
#define SITESMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
class SitesModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SitesModel(Settings::RouteMode mode, QObject *parent = nullptr);
|
||||
void resetCache();
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
private:
|
||||
void genCache() const;
|
||||
|
||||
private:
|
||||
Settings::RouteMode m_mode;
|
||||
Settings m_settings;
|
||||
|
||||
mutable QVector<QPair<QString, QString>> m_ipsCache;
|
||||
mutable bool m_cacheReady = false;
|
||||
};
|
||||
|
||||
#endif // SITESMODEL_H
|
||||
+58
-20
@@ -23,11 +23,6 @@ QString Utils::getRandomString(int len)
|
||||
return randomString;
|
||||
}
|
||||
|
||||
QString Utils::defaultVpnConfigFileName()
|
||||
{
|
||||
return configPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
|
||||
}
|
||||
|
||||
QString Utils::systemLogPath()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -54,11 +49,6 @@ bool Utils::initializePath(const QString& path)
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Utils::configPath()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/config";
|
||||
}
|
||||
|
||||
bool Utils::createEmptyFile(const QString& path)
|
||||
{
|
||||
QFile f(path);
|
||||
@@ -139,19 +129,27 @@ QString Utils::getStringBetween(const QString& s, const QString& a, const QStrin
|
||||
return s.mid(ap, bp - ap).trimmed();
|
||||
}
|
||||
|
||||
bool Utils::checkIPFormat(const QString& ip)
|
||||
bool Utils::checkIPv4Format(const QString& ip)
|
||||
{
|
||||
if (ip.isEmpty()) return false;
|
||||
int count = ip.count(".");
|
||||
if(count != 3)
|
||||
return false;
|
||||
if(count != 3) return false;
|
||||
|
||||
QStringList list = ip.trimmed().split(".");
|
||||
foreach(QString it, list) {
|
||||
if(it.toInt() <= 255 && it.toInt() >= 0)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
QHostAddress addr(ip);
|
||||
return (addr.protocol() == QAbstractSocket::NetworkLayerProtocol::IPv4Protocol);
|
||||
}
|
||||
|
||||
bool Utils::checkIpSubnetFormat(const QString &ip)
|
||||
{
|
||||
if (!ip.contains("/")) return checkIPv4Format(ip);
|
||||
|
||||
QStringList parts = ip.split("/");
|
||||
if (parts.size() != 2) return false;
|
||||
|
||||
bool ok;
|
||||
int subnet = parts.at(1).toInt(&ok);
|
||||
if (subnet >= 0 && subnet <= 32 && ok) return checkIPv4Format(parts.at(0));
|
||||
else return false;
|
||||
}
|
||||
|
||||
void Utils::killProcessByName(const QString &name)
|
||||
@@ -164,6 +162,46 @@ void Utils::killProcessByName(const QString &name)
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Utils::netMaskFromIpWithSubnet(const QString ip)
|
||||
{
|
||||
if (!ip.contains("/")) return "255.255.255.255";
|
||||
|
||||
bool ok;
|
||||
int prefix = ip.split("/").at(1).toInt(&ok);
|
||||
if (!ok) return "255.255.255.255";
|
||||
|
||||
unsigned long mask = (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF;
|
||||
|
||||
return QString("%1.%2.%3.%4")
|
||||
.arg(mask >> 24)
|
||||
.arg((mask >> 16) & 0xFF)
|
||||
.arg((mask >> 8) & 0xFF)
|
||||
.arg( mask & 0xFF);
|
||||
}
|
||||
|
||||
QString Utils::ipAddressFromIpWithSubnet(const QString ip)
|
||||
{
|
||||
if (ip.count(".") != 3) return "";
|
||||
return ip.split("/").first();
|
||||
}
|
||||
|
||||
QStringList Utils::summarizeRoutes(const QStringList &ips, const QString cidr)
|
||||
{
|
||||
// QMap<int, int>
|
||||
// QHostAddress
|
||||
|
||||
// QMap<QString, QStringList> subnets; // <"a.b", <list subnets>>
|
||||
|
||||
// for (const QString &ip : ips) {
|
||||
// if (ip.count(".") != 3) continue;
|
||||
|
||||
// const QStringList &parts = ip.split(".");
|
||||
// subnets[parts.at(0) + "." + parts.at(1)].append(ip);
|
||||
// }
|
||||
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// Inspired from http://stackoverflow.com/a/15281070/1529139
|
||||
// and http://stackoverflow.com/q/40059902/1529139
|
||||
|
||||
+10
-3
@@ -13,8 +13,6 @@ class Utils {
|
||||
public:
|
||||
static QString getRandomString(int len);
|
||||
|
||||
static QString configPath();
|
||||
static QString defaultVpnConfigFileName();
|
||||
static QString executable(const QString& baseName, bool absPath);
|
||||
static QString systemLogPath();
|
||||
static bool createEmptyFile(const QString& path);
|
||||
@@ -22,11 +20,15 @@ public:
|
||||
|
||||
static QString getIPAddress(const QString& host);
|
||||
static QString getStringBetween(const QString& s, const QString& a, const QString& b);
|
||||
static bool checkIPFormat(const QString& ip);
|
||||
static bool checkIPv4Format(const QString& ip);
|
||||
static bool checkIpSubnetFormat(const QString& ip);
|
||||
static QRegExp ipAddressRegExp() { return QRegExp("^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\\.(?!$)|$)){4}$"); }
|
||||
static QRegExp ipAddressPortRegExp() { return QRegExp("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}"
|
||||
"(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\\:[0-9]{1,5}){0,1}$"); }
|
||||
|
||||
static QRegExp ipAddressWithSubnetRegExp() { return QRegExp("(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}"
|
||||
"(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\\/[0-9]{1,2}){0,1}"); }
|
||||
|
||||
static QRegExp ipNetwork24RegExp() { return QRegExp("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}"
|
||||
"0$"); }
|
||||
|
||||
@@ -35,6 +37,11 @@ public:
|
||||
static bool processIsRunning(const QString& fileName);
|
||||
static void killProcessByName(const QString &name);
|
||||
|
||||
static QString netMaskFromIpWithSubnet(const QString ip);
|
||||
static QString ipAddressFromIpWithSubnet(const QString ip);
|
||||
|
||||
static QStringList summarizeRoutes(const QStringList &ips, const QString cidr);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
static bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent);
|
||||
#endif
|
||||
|
||||
+102
-28
@@ -6,7 +6,9 @@
|
||||
#include <configurators/openvpn_configurator.h>
|
||||
#include <configurators/cloak_configurator.h>
|
||||
#include <configurators/shadowsocks_configurator.h>
|
||||
#include <configurators/wireguard_configurator.h>
|
||||
#include <core/servercontroller.h>
|
||||
#include <protocols/wireguardprotocol.h>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "core/ipcclient.h"
|
||||
@@ -40,25 +42,33 @@ void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
|
||||
void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
||||
{
|
||||
if (IpcClient::Interface()) {
|
||||
if (state == VpnProtocol::ConnectionState::Connected && IpcClient::Interface()){
|
||||
if (state == VpnProtocol::Connected){
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
if (m_settings.customRouting()) {
|
||||
IpcClient::Interface()->routeDelete("0.0.0.0", m_vpnProtocol->vpnGateway());
|
||||
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(),
|
||||
QStringList() << m_settings.primaryDns() << m_settings.secondaryDns());
|
||||
|
||||
const QStringList &black_custom = m_settings.customIps();
|
||||
qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << black_custom.size();
|
||||
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), black_custom);
|
||||
if (m_settings.routeMode() != Settings::VpnAllSites) {
|
||||
IpcClient::Interface()->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0");
|
||||
//qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size();
|
||||
}
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(),
|
||||
QStringList() << m_settings.primaryDns() << m_settings.secondaryDns());
|
||||
|
||||
|
||||
if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), m_settings.getVpnIps(Settings::VpnOnlyForwardSites));
|
||||
}
|
||||
else if (m_settings.routeMode() == Settings::VpnAllExceptSites) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0/1");
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "128.0.0.0/1");
|
||||
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), QStringList() << remoteAddress());
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), m_settings.getVpnIps(Settings::VpnAllExceptSites));
|
||||
}
|
||||
|
||||
}
|
||||
else if (state == VpnProtocol::ConnectionState::Error) {
|
||||
else if (state == VpnProtocol::Error) {
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
if (m_settings.customRouting()) {
|
||||
if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
IpcClient::Interface()->clearSavedRoutes();
|
||||
}
|
||||
}
|
||||
@@ -67,11 +77,45 @@ void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
||||
emit connectionStateChanged(state);
|
||||
}
|
||||
|
||||
const QString &VpnConnection::remoteAddress() const
|
||||
{
|
||||
return m_remoteAddress;
|
||||
}
|
||||
|
||||
QSharedPointer<VpnProtocol> VpnConnection::vpnProtocol() const
|
||||
{
|
||||
return m_vpnProtocol;
|
||||
}
|
||||
|
||||
void VpnConnection::addRoutes(const QStringList &ips)
|
||||
{
|
||||
if (connectionState() == VpnProtocol::Connected && IpcClient::Interface()) {
|
||||
if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), ips);
|
||||
}
|
||||
else if (m_settings.routeMode() == Settings::VpnAllExceptSites) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->routeGateway(), ips);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VpnConnection::deleteRoutes(const QStringList &ips)
|
||||
{
|
||||
if (connectionState() == VpnProtocol::Connected && IpcClient::Interface()) {
|
||||
if (m_settings.routeMode() == Settings::VpnOnlyForwardSites) {
|
||||
IpcClient::Interface()->routeDeleteList(vpnProtocol()->vpnGateway(), ips);
|
||||
}
|
||||
else if (m_settings.routeMode() == Settings::VpnAllExceptSites) {
|
||||
IpcClient::Interface()->routeDeleteList(m_vpnProtocol->routeGateway(), ips);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VpnConnection::flushDns()
|
||||
{
|
||||
if (IpcClient::Interface()) IpcClient::Interface()->flushDns();
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::lastError() const
|
||||
{
|
||||
if (!m_vpnProtocol.data()) {
|
||||
@@ -105,7 +149,10 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex,
|
||||
|
||||
QString configData;
|
||||
if (lastVpnConfig.contains(proto)) {
|
||||
configData = OpenVpnConfigurator::processConfigWithLocalSettings(lastVpnConfig.value(proto));
|
||||
configData = lastVpnConfig.value(proto);
|
||||
if (proto == Protocol::OpenVpn) {
|
||||
configData = OpenVpnConfigurator::processConfigWithLocalSettings(configData);
|
||||
}
|
||||
qDebug() << "VpnConnection::createVpnConfiguration: using saved config for" << protoToString(proto);
|
||||
}
|
||||
else {
|
||||
@@ -113,6 +160,7 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex,
|
||||
if (proto == Protocol::OpenVpn) {
|
||||
configData = OpenVpnConfigurator::genOpenVpnConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
configData = OpenVpnConfigurator::processConfigWithLocalSettings(configData);
|
||||
}
|
||||
else if (proto == Protocol::Cloak) {
|
||||
configData = CloakConfigurator::genCloakConfig(credentials,
|
||||
@@ -122,6 +170,10 @@ QString VpnConnection::createVpnConfigurationForProto(int serverIndex,
|
||||
configData = ShadowSocksConfigurator::genShadowSocksConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
}
|
||||
else if (proto == Protocol::WireGuard) {
|
||||
configData = WireguardConfigurator::genWireguardConfig(credentials,
|
||||
container, containerConfig, &e);
|
||||
}
|
||||
|
||||
if (errorCode && e) {
|
||||
*errorCode = e;
|
||||
@@ -160,7 +212,7 @@ ErrorCode VpnConnection::createVpnConfiguration(int serverIndex,
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
QFile file(Utils::defaultVpnConfigFileName());
|
||||
QFile file(OpenVpnProtocol::defaultConfigFileName());
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
||||
QTextStream stream(&file);
|
||||
stream << openVpnConfigData << endl;
|
||||
@@ -189,17 +241,29 @@ ErrorCode VpnConnection::createVpnConfiguration(int serverIndex,
|
||||
m_vpnConfiguration.insert(config::key_cloak_config_data, cloakConfigData);
|
||||
}
|
||||
|
||||
if (container == DockerContainer::WireGuard) {
|
||||
QString wgConfigData = createVpnConfigurationForProto(
|
||||
serverIndex, credentials, container, containerConfig, Protocol::WireGuard, &errorCode);
|
||||
|
||||
m_vpnConfiguration.insert(config::key_wireguard_config_data, wgConfigData);
|
||||
}
|
||||
|
||||
//qDebug().noquote() << "VPN config" << QJsonDocument(m_vpnConfiguration).toJson();
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig)
|
||||
ErrorCode VpnConnection::connectToVpn(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig)
|
||||
{
|
||||
qDebug() << "СonnectToVpn, CustomRouting is" << m_settings.customRouting();
|
||||
qDebug() << QString("СonnectToVpn, Server index is %1, container is %2, route mode is")
|
||||
.arg(serverIndex).arg(containerToString(container)) << m_settings.routeMode();
|
||||
m_remoteAddress = credentials.hostName;
|
||||
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Connecting);
|
||||
emit connectionStateChanged(VpnProtocol::Connecting);
|
||||
|
||||
ServerController::setupServerFirewall(credentials);
|
||||
if (credentials.isValid()) {
|
||||
ServerController::setupServerFirewall(credentials);
|
||||
}
|
||||
|
||||
if (m_vpnProtocol) {
|
||||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
@@ -210,45 +274,54 @@ ErrorCode VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &
|
||||
if (container == DockerContainer::None || container == DockerContainer::OpenVpn) {
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpn, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
|
||||
m_vpnProtocol.reset(new OpenVpnProtocol(m_vpnConfiguration));
|
||||
e = static_cast<OpenVpnProtocol *>(m_vpnProtocol.data())->checkAndSetupTapDriver();
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
else if (container == DockerContainer::OpenVpnOverShadowSocks) {
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpnOverShadowSocks, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
|
||||
m_vpnProtocol.reset(new ShadowSocksVpnProtocol(m_vpnConfiguration));
|
||||
e = static_cast<OpenVpnProtocol *>(m_vpnProtocol.data())->checkAndSetupTapDriver();
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
else if (container == DockerContainer::OpenVpnOverCloak) {
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::OpenVpnOverCloak, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
|
||||
m_vpnProtocol.reset(new OpenVpnOverCloakProtocol(m_vpnConfiguration));
|
||||
e = static_cast<OpenVpnProtocol *>(m_vpnProtocol.data())->checkAndSetupTapDriver();
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
else if (container == DockerContainer::WireGuard) {
|
||||
ErrorCode e = createVpnConfiguration(serverIndex, credentials, DockerContainer::WireGuard, containerConfig);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::Error);
|
||||
return e;
|
||||
}
|
||||
|
||||
m_vpnProtocol.reset(new WireguardProtocol(m_vpnConfiguration));
|
||||
}
|
||||
|
||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState)));
|
||||
@@ -269,9 +342,10 @@ void VpnConnection::disconnectFromVpn()
|
||||
{
|
||||
qDebug() << "Disconnect from VPN";
|
||||
|
||||
IpcClient::Interface()->flushDns();
|
||||
if (IpcClient::Interface()) {
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
if (m_settings.customRouting()) {
|
||||
// delete cached routes
|
||||
IpcClient::Interface()->clearSavedRoutes();
|
||||
}
|
||||
|
||||
@@ -283,7 +357,7 @@ void VpnConnection::disconnectFromVpn()
|
||||
|
||||
VpnProtocol::ConnectionState VpnConnection::connectionState()
|
||||
{
|
||||
if (!m_vpnProtocol) return VpnProtocol::ConnectionState::Disconnected;
|
||||
if (!m_vpnProtocol) return VpnProtocol::Disconnected;
|
||||
return m_vpnProtocol->connectionState();
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -33,16 +33,23 @@ public:
|
||||
ErrorCode createVpnConfiguration(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
|
||||
ErrorCode connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
ErrorCode connectToVpn(int serverIndex,
|
||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
|
||||
void disconnectFromVpn();
|
||||
|
||||
bool isConnected() const;
|
||||
bool isDisconnected() const;
|
||||
|
||||
VpnProtocol::ConnectionState connectionState();
|
||||
|
||||
QSharedPointer<VpnProtocol> vpnProtocol() const;
|
||||
|
||||
void addRoutes(const QStringList &ips);
|
||||
void deleteRoutes(const QStringList &ips);
|
||||
void flushDns();
|
||||
|
||||
const QString &remoteAddress() const;
|
||||
|
||||
signals:
|
||||
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void connectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
@@ -60,6 +67,8 @@ protected:
|
||||
private:
|
||||
Settings m_settings;
|
||||
QJsonObject m_vpnConfiguration;
|
||||
QJsonObject m_routeMode;
|
||||
QString m_remoteAddress;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -28,10 +28,12 @@ QMAKE_STASH_FILE=$PROJECT_DIR/.qmake_stash
|
||||
DMG_FILENAME=$PROJECT_DIR/${APP_NAME}_unsigned.dmg
|
||||
|
||||
# Seacrh Qt
|
||||
if [ -z "${QT_VERSION+x}" ]; then export QT_VERSION=5.15.2; fi
|
||||
|
||||
if [ -z "${QT_VERSION+x}" ]; then
|
||||
QT_VERSION=5.15.2;
|
||||
QIF_VERSION=4.1
|
||||
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
|
||||
QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/4.0/bin
|
||||
QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
|
||||
fi
|
||||
|
||||
echo "Using Qt in $QT_BIN_DIR"
|
||||
echo "Using QIF in $QIF_BIN_DIR"
|
||||
@@ -115,7 +117,7 @@ if [ "${MAC_CERT_PW+x}" ]; then
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $DMG_FILENAME
|
||||
/usr/bin/codesign --verify -vvvv $DMG_FILENAME || true
|
||||
spctl -a -vvvv $DMG_FILENAME || true
|
||||
#xcrun altool --notarize-app -f $DMG_FILENAME -t osx --primary-bundle-id $APP_DOMAIN -u $APPLE_DEV_EMAIL
|
||||
#xcrun altool --notarize-app -f $DMG_FILENAME -t osx --primary-bundle-id $APP_DOMAIN -u $APPLE_DEV_EMAIL -p $APPLE_DEV_PASSWORD
|
||||
#xcrun stapler staple $DMG_FILENAME
|
||||
#xcrun stapler validate $DMG_FILENAME
|
||||
fi
|
||||
|
||||
Executable
+160
@@ -0,0 +1,160 @@
|
||||
#!/bin/bash
|
||||
echo "Build script started ..."
|
||||
|
||||
set -o errexit -o nounset
|
||||
|
||||
# Hold on to current directory
|
||||
PROJECT_DIR=$(pwd)
|
||||
DEPLOY_DIR=$PROJECT_DIR/deploy
|
||||
|
||||
mkdir -p $DEPLOY_DIR/build
|
||||
BUILD_DIR=$DEPLOY_DIR/build
|
||||
|
||||
echo "Project dir: ${PROJECT_DIR}"
|
||||
echo "Build dir: ${BUILD_DIR}"
|
||||
|
||||
APP_NAME=AmneziaVPN
|
||||
APP_FILENAME=$APP_NAME.app
|
||||
APP_DOMAIN=org.amneziavpn.package
|
||||
PLIST_NAME=$APP_NAME.plist
|
||||
|
||||
OUT_APP_DIR=$BUILD_DIR/client
|
||||
BUNDLE_DIR=$OUT_APP_DIR/$APP_FILENAME
|
||||
|
||||
DEPLOY_DATA_DIR=$PROJECT_DIR/deploy/data/macos
|
||||
INSTALLER_DATA_DIR=$BUILD_DIR/installer/packages/$APP_DOMAIN/data
|
||||
INSTALLER_BUNDLE_DIR=$BUILD_DIR/installer/$APP_FILENAME
|
||||
|
||||
PRO_FILE_PATH=$PROJECT_DIR/$APP_NAME.pro
|
||||
QMAKE_STASH_FILE=$PROJECT_DIR/.qmake_stash
|
||||
DMG_FILENAME=$PROJECT_DIR/${APP_NAME}_unsigned.dmg
|
||||
|
||||
# Seacrh Qt
|
||||
if [ -z "${QT_VERSION+x}" ]; then
|
||||
QT_VERSION=5.15.2;
|
||||
QIF_VERSION=4.1
|
||||
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
|
||||
QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
|
||||
fi
|
||||
|
||||
echo "Using Qt in $QT_BIN_DIR"
|
||||
echo "Using QIF in $QIF_BIN_DIR"
|
||||
|
||||
|
||||
# Checking env
|
||||
$QT_BIN_DIR/qmake -v
|
||||
make -v
|
||||
clang -v
|
||||
|
||||
# Build App
|
||||
echo "Building App..."
|
||||
cd $BUILD_DIR
|
||||
|
||||
$QT_BIN_DIR/qmake $PROJECT_DIR/AmneziaVPN.pro 'CONFIG+=release CONFIG+=x86_64'
|
||||
make -j `sysctl -n hw.ncpu`
|
||||
|
||||
# Build and run tests here
|
||||
|
||||
echo "____________________________________"
|
||||
echo "............Deploy.................."
|
||||
echo "____________________________________"
|
||||
|
||||
# Package
|
||||
echo "Packaging ..."
|
||||
|
||||
#cd $DEPLOY_DIR
|
||||
|
||||
$QT_BIN_DIR/macdeployqt $OUT_APP_DIR/$APP_FILENAME -always-overwrite
|
||||
cp -av $BUILD_DIR/service/server/$APP_NAME-service.app/Contents/macOS/$APP_NAME-service $BUNDLE_DIR/Contents/macOS
|
||||
cp -Rv $PROJECT_DIR/deploy/data/macos/* $BUNDLE_DIR/Contents/macOS
|
||||
rm -f $BUNDLE_DIR/Contents/macOS/post_install.sh $BUNDLE_DIR/Contents/macOS/post_uninstall.sh
|
||||
|
||||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
|
||||
CERTIFICATE_P12=$DEPLOY_DIR/PrivacyTechAppleCertDeveloperId.p12
|
||||
WWDRCA=$DEPLOY_DIR/WWDRCA.cer
|
||||
KEYCHAIN=amnezia.build.keychain
|
||||
TEMP_PASS=tmp_pass
|
||||
|
||||
security create-keychain -p $TEMP_PASS $KEYCHAIN || true
|
||||
security default-keychain -s $KEYCHAIN
|
||||
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||
|
||||
security default-keychain
|
||||
security list-keychains
|
||||
|
||||
security import $WWDRCA -k $KEYCHAIN -T /usr/bin/codesign || true
|
||||
security import $CERTIFICATE_P12 -k $KEYCHAIN -P $MAC_CERT_PW -T /usr/bin/codesign || true
|
||||
|
||||
security set-key-partition-list -S apple-tool:,apple: -k $TEMP_PASS $KEYCHAIN
|
||||
security find-identity -p codesigning
|
||||
|
||||
echo "Signing App bundle..."
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $BUNDLE_DIR
|
||||
/usr/bin/codesign --verify -vvvv $BUNDLE_DIR || true
|
||||
spctl -a -vvvv $BUNDLE_DIR || true
|
||||
|
||||
echo "Notatizing App bundle..."
|
||||
/usr/bin/ditto -c -k --keepParent $BUNDLE_DIR $PROJECT_DIR/Bundle_to_notarize.zip
|
||||
xcrun altool --notarize-app -f $PROJECT_DIR/Bundle_to_notarize.zip -t osx --primary-bundle-id "$APP_DOMAIN" -u "$APPLE_DEV_EMAIL" -p $APPLE_DEV_PASSWORD
|
||||
rm $PROJECT_DIR/Bundle_to_notarize.zip
|
||||
sleep 600
|
||||
xcrun stapler staple $BUNDLE_DIR
|
||||
xcrun stapler validate $BUNDLE_DIR
|
||||
spctl -a -vvvv $BUNDLE_DIR || true
|
||||
|
||||
fi
|
||||
|
||||
echo "Packaging installer..."
|
||||
mkdir -p $INSTALLER_DATA_DIR
|
||||
cp -av $PROJECT_DIR/deploy/installer $BUILD_DIR
|
||||
cp -av $DEPLOY_DATA_DIR/post_install.sh $INSTALLER_DATA_DIR/post_install.sh
|
||||
cp -av $DEPLOY_DATA_DIR/post_uninstall.sh $INSTALLER_DATA_DIR/post_uninstall.sh
|
||||
cp -av $DEPLOY_DATA_DIR/$PLIST_NAME $INSTALLER_DATA_DIR/$PLIST_NAME
|
||||
|
||||
chmod a+x $INSTALLER_DATA_DIR/post_install.sh $INSTALLER_DATA_DIR/post_uninstall.sh
|
||||
|
||||
cd $BUNDLE_DIR
|
||||
tar czf $INSTALLER_DATA_DIR/$APP_NAME.tar.gz ./
|
||||
|
||||
echo "Building installer..."
|
||||
$QIF_BIN_DIR/binarycreator --offline-only -v -c $BUILD_DIR/installer/config/macos.xml -p $BUILD_DIR/installer/packages -f $INSTALLER_BUNDLE_DIR
|
||||
|
||||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
echo "Signing installer bundle..."
|
||||
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $INSTALLER_BUNDLE_DIR
|
||||
/usr/bin/codesign --verify -vvvv $INSTALLER_BUNDLE_DIR || true
|
||||
|
||||
echo "Notatizing installer bundle..."
|
||||
/usr/bin/ditto -c -k --keepParent $INSTALLER_BUNDLE_DIR $PROJECT_DIR/Installer_bundle_to_notarize.zip
|
||||
xcrun altool --notarize-app -f $PROJECT_DIR/Installer_bundle_to_notarize.zip -t osx --primary-bundle-id "$APP_DOMAIN" -u "$APPLE_DEV_EMAIL" -p $APPLE_DEV_PASSWORD
|
||||
rm $PROJECT_DIR/Installer_bundle_to_notarize.zip
|
||||
sleep 600
|
||||
xcrun stapler staple $INSTALLER_BUNDLE_DIR
|
||||
xcrun stapler validate $INSTALLER_BUNDLE_DIR
|
||||
spctl -a -vvvv $INSTALLER_BUNDLE_DIR || true
|
||||
|
||||
fi
|
||||
|
||||
echo "Building DMG installer..."
|
||||
hdiutil create -volname $APP_NAME -srcfolder $BUILD_DIR/installer/$APP_NAME.app -ov -format UDZO $DMG_FILENAME
|
||||
|
||||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
echo "Signing DMG installer..."
|
||||
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $DMG_FILENAME
|
||||
/usr/bin/codesign --verify -vvvv $DMG_FILENAME || true
|
||||
|
||||
echo "Notatizing DMG installer..."
|
||||
xcrun altool --notarize-app -f $DMG_FILENAME -t osx --primary-bundle-id $APP_DOMAIN -u $APPLE_DEV_EMAIL -p $APPLE_DEV_PASSWORD
|
||||
sleep 600
|
||||
xcrun stapler staple $DMG_FILENAME
|
||||
xcrun stapler validate $DMG_FILENAME
|
||||
|
||||
fi
|
||||
|
||||
echo "Finished, artifact is $DMG_FILENAME"
|
||||
|
||||
# restore keychain
|
||||
security default-keychain -s login.keychain
|
||||
+15
-16
@@ -4,9 +4,6 @@ CHCP 1252
|
||||
|
||||
REM %VAR:"=% mean dequoted %VAR%
|
||||
|
||||
set QT_BIN_DIR="c:\Qt\5.14.2\msvc2017\bin"
|
||||
set QIF_BIN_DIR="c:\Qt\Tools\QtInstallerFramework\4.0\bin"
|
||||
|
||||
set PATH=%QT_BIN_DIR:"=%;%PATH%
|
||||
|
||||
echo "Using Qt in %QT_BIN_DIR%"
|
||||
@@ -16,9 +13,9 @@ REM Hold on to current directory
|
||||
set PROJECT_DIR=%cd%
|
||||
set SCRIPT_DIR=%PROJECT_DIR:"=%\deploy
|
||||
|
||||
set WORK_DIR=%SCRIPT_DIR:"=%\build_%BUILD_ARCH:"=%
|
||||
rmdir /Q /S %WORK_DIR%
|
||||
mkdir %SCRIPT_DIR:"=%\build
|
||||
set WORK_DIR=%SCRIPT_DIR:"=%\build
|
||||
mkdir %WORK_DIR%
|
||||
|
||||
|
||||
set APP_NAME=AmneziaVPN
|
||||
@@ -26,23 +23,23 @@ set APP_FILENAME=%APP_NAME:"=%.exe
|
||||
set APP_DOMAIN=org.amneziavpn.package
|
||||
set RELEASE_DIR=%WORK_DIR:"=%
|
||||
set OUT_APP_DIR=%RELEASE_DIR:"=%\client\release
|
||||
set DEPLOY_DATA_DIR=%SCRIPT_DIR:"=%\data\windows
|
||||
set DEPLOY_DATA_DIR=%SCRIPT_DIR:"=%\data\windows\x%BUILD_ARCH:"=%
|
||||
set INSTALLER_DATA_DIR=%RELEASE_DIR:"=%\installer\packages\%APP_DOMAIN:"=%\data
|
||||
set PRO_FILE_PATH=%PROJECT_DIR:"=%\%APP_NAME:"=%.pro
|
||||
set QMAKE_STASH_FILE=%PROJECT_DIR:"=%\.qmake_stash
|
||||
set TARGET_FILENAME=%PROJECT_DIR:"=%\%APP_NAME:"=%.exe
|
||||
set TARGET_FILENAME=%PROJECT_DIR:"=%\%APP_NAME:"=%_x%BUILD_ARCH:"=%.exe
|
||||
|
||||
echo "Environment:"
|
||||
echo "APP_FILENAME: %APP_FILENAME%"
|
||||
echo "PROJECT_DIR: %PROJECT_DIR%"
|
||||
echo "SCRIPT_DIR: %SCRIPT_DIR%"
|
||||
echo "SCRIPT_DIR: %SCRIPT_DIR%"
|
||||
echo "RELEASE_DIR: %RELEASE_DIR%"
|
||||
echo "OUT_APP_DIR: %OUT_APP_DIR%"
|
||||
echo "DEPLOY_DATA_DIR: %DEPLOY_DATA_DIR%"
|
||||
echo "DEPLOY_DATA_DIR: %DEPLOY_DATA_DIR%"
|
||||
echo "INSTALLER_DATA_DIR: %INSTALLER_DATA_DIR%"
|
||||
echo "PRO_FILE_PATH: %PRO_FILE_PATH%"
|
||||
echo "PRO_FILE_PATH: %PRO_FILE_PATH%"
|
||||
echo "QMAKE_STASH_FILE: %QMAKE_STASH_FILE%"
|
||||
echo "TARGET_FILENAME: %TARGET_FILENAME%"
|
||||
echo "TARGET_FILENAME: %TARGET_FILENAME%"
|
||||
|
||||
rem Signing staff
|
||||
powershell Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine
|
||||
@@ -60,7 +57,7 @@ Del %TARGET_FILENAME%
|
||||
nmake /?
|
||||
|
||||
cd %PROJECT_DIR%
|
||||
"%QT_BIN_DIR:"=%\qmake" -spec win32-msvc -o deploy\build\Makefile
|
||||
"%QT_BIN_DIR:"=%\qmake" -spec win32-msvc -o "%WORK_DIR:"=%\Makefile"
|
||||
|
||||
cd %WORK_DIR%
|
||||
set CL=/MP
|
||||
@@ -84,11 +81,11 @@ signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://ti
|
||||
signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 *.dll
|
||||
|
||||
echo "Copying deploy data..."
|
||||
xcopy %DEPLOY_DATA_DIR% %OUT_APP_DIR% /s /e /y /i /f
|
||||
xcopy %DEPLOY_DATA_DIR% %OUT_APP_DIR% /s /e /y /i /f
|
||||
|
||||
|
||||
cd %SCRIPT_DIR%
|
||||
xcopy %SCRIPT_DIR:"=%\installer %RELEASE_DIR:"=%\installer /s /e /y /i /f
|
||||
xcopy %SCRIPT_DIR:"=%\installer %RELEASE_DIR:"=%\installer /s /e /y /i /f
|
||||
mkdir %INSTALLER_DATA_DIR%
|
||||
|
||||
echo "Deploy finished, content:"
|
||||
@@ -102,8 +99,10 @@ cd "%RELEASE_DIR:"=%\installer"
|
||||
echo "Creating installer..."
|
||||
"%QIF_BIN_DIR:"=%\binarycreator" --offline-only -v -c config\windows.xml -p packages -f %TARGET_FILENAME%
|
||||
|
||||
timeout 5
|
||||
|
||||
cd %PROJECT_DIR%
|
||||
signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 %TARGET_FILENAME%
|
||||
signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 "%TARGET_FILENAME%"
|
||||
|
||||
echo "Finished, see %TARGET_FILENAME%"
|
||||
exit 0
|
||||
exit 0
|
||||
|
||||
@@ -29,4 +29,4 @@ launchctl load $LAUNCH_DAEMONS_PLIST_NAME
|
||||
echo "`date` Service status: $?" >> $LOG_FILE
|
||||
echo "`date` Script finished" >> $LOG_FILE
|
||||
|
||||
rm -- "$0"
|
||||
#rm -- "$0"
|
||||
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Mac name-resolution updater based on @cl's script here:
|
||||
# https://blog.netnerds.net/2011/10/openvpn-update-client-dns-on-mac-os-x-using-from-the-command-line/
|
||||
# Openvpn envar parsing taken from the script in debian's openvpn package.
|
||||
# Smushed together and improved by @andrewgdotcom.
|
||||
|
||||
# Parses DHCP options from openvpn to update resolv.conf
|
||||
# To use set as 'up' and 'down' script in your openvpn *.conf:
|
||||
# up /etc/openvpn/update-resolv-conf
|
||||
# down /etc/openvpn/update-resolv-conf
|
||||
|
||||
[ "$script_type" ] || exit 0
|
||||
[ "$dev" ] || exit 0
|
||||
|
||||
PATH=$PATH:/usr/sbin/
|
||||
NMSRVRS=()
|
||||
SRCHS=()
|
||||
|
||||
# Get adapter list
|
||||
IFS=$'\n' read -d '' -ra adapters < <(networksetup -listallnetworkservices |grep -v denotes) || true
|
||||
|
||||
split_into_parts()
|
||||
{
|
||||
part1="$1"
|
||||
part2="$2"
|
||||
part3="$3"
|
||||
}
|
||||
|
||||
update_all_dns()
|
||||
{
|
||||
for adapter in "${adapters[@]}"
|
||||
do
|
||||
echo updating dns for $adapter
|
||||
# set dns server to the vpn dns server
|
||||
if [[ "${SRCHS[@]}" ]]; then
|
||||
networksetup -setsearchdomains "$adapter" "${SRCHS[@]}"
|
||||
fi
|
||||
if [[ "${NMSRVRS[@]}" ]]; then
|
||||
networksetup -setdnsservers "$adapter" "${NMSRVRS[@]}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
clear_all_dns()
|
||||
{
|
||||
for adapter in "${adapters[@]}"
|
||||
do
|
||||
echo updating dns for $adapter
|
||||
networksetup -setdnsservers "$adapter" empty
|
||||
networksetup -setsearchdomains "$adapter" empty
|
||||
done
|
||||
}
|
||||
|
||||
case "$script_type" in
|
||||
up)
|
||||
for optionvarname in ${!foreign_option_*} ; do
|
||||
option="${!optionvarname}"
|
||||
echo "$option"
|
||||
split_into_parts $option
|
||||
if [ "$part1" = "dhcp-option" ] ; then
|
||||
if [ "$part2" = "DNS" ] ; then
|
||||
NMSRVRS=(${NMSRVRS[@]} $part3)
|
||||
elif [ "$part2" = "DOMAIN" ] ; then
|
||||
SRCHS=(${SRCHS[@]} $part3)
|
||||
fi
|
||||
fi
|
||||
done
|
||||
update_all_dns
|
||||
;;
|
||||
down)
|
||||
clear_all_dns
|
||||
;;
|
||||
esac
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user