shadowsocks impl
This commit is contained in:
parent
95cbb07cbb
commit
ec9ae0ef4f
20 changed files with 380 additions and 117 deletions
|
@ -12,6 +12,12 @@ enum class Protocol {
|
||||||
WireGuard
|
WireGuard
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class DockerContainer {
|
||||||
|
OpenVpn,
|
||||||
|
ShadowSocks,
|
||||||
|
WireGuard
|
||||||
|
};
|
||||||
|
|
||||||
struct ServerCredentials
|
struct ServerCredentials
|
||||||
{
|
{
|
||||||
QString hostName;
|
QString hostName;
|
||||||
|
|
|
@ -144,46 +144,77 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::createCertRequest()
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials, ErrorCode *errorCode)
|
OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(const ServerCredentials &credentials,
|
||||||
|
Protocol proto, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
OpenVpnConfigurator::ConnectionData connData = OpenVpnConfigurator::createCertRequest();
|
OpenVpnConfigurator::ConnectionData connData = OpenVpnConfigurator::createCertRequest();
|
||||||
connData.host = credentials.hostName;
|
connData.host = credentials.hostName;
|
||||||
|
|
||||||
if (connData.privKey.isEmpty() || connData.request.isEmpty()) {
|
if (connData.privKey.isEmpty() || connData.request.isEmpty()) {
|
||||||
*errorCode = ErrorCode::EasyRsaExecutableMissing;
|
if (errorCode) *errorCode = ErrorCode::EasyRsaExecutableMissing;
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString reqFileName = QString("/opt/amneziavpn_data/clients/%1.req").arg(connData.clientId);
|
QString reqFileName = QString("/opt/amneziavpn_data/clients/%1.req").arg(connData.clientId);
|
||||||
ErrorCode e = ServerController::uploadTextFileToContainer(credentials, connData.request, reqFileName);
|
|
||||||
if (e) {
|
DockerContainer container;
|
||||||
*errorCode = e;
|
if (proto == Protocol::OpenVpn) container = DockerContainer::OpenVpn;
|
||||||
|
else if (proto == Protocol::ShadowSocks) container = DockerContainer::ShadowSocks;
|
||||||
|
else {
|
||||||
|
if (errorCode) *errorCode = ErrorCode::InternalError;
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerController::signCert(credentials, connData.clientId);
|
ErrorCode e = ServerController::uploadTextFileToContainer(container, credentials, connData.request, reqFileName);
|
||||||
|
|
||||||
connData.caCert = ServerController::getTextFileFromContainer(credentials, ServerController::caCertPath(), &e);
|
|
||||||
connData.clientCert = ServerController::getTextFileFromContainer(credentials, ServerController::clientCertPath() + QString("%1.crt").arg(connData.clientId), &e);
|
|
||||||
if (e) {
|
if (e) {
|
||||||
*errorCode = e;
|
if (errorCode) *errorCode = e;
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
connData.taKey = ServerController::getTextFileFromContainer(credentials, ServerController::taKeyPath(), &e);
|
e = ServerController::signCert(container, credentials, connData.clientId);
|
||||||
|
if (e) {
|
||||||
|
if (errorCode) *errorCode = e;
|
||||||
|
return connData;
|
||||||
|
}
|
||||||
|
|
||||||
|
connData.caCert = ServerController::getTextFileFromContainer(container, credentials, ServerController::caCertPath(), &e);
|
||||||
|
connData.clientCert = ServerController::getTextFileFromContainer(container, credentials, ServerController::clientCertPath() + QString("%1.crt").arg(connData.clientId), &e);
|
||||||
|
if (e) {
|
||||||
|
if (errorCode) *errorCode = e;
|
||||||
|
return connData;
|
||||||
|
}
|
||||||
|
|
||||||
|
connData.taKey = ServerController::getTextFileFromContainer(container, credentials, ServerController::taKeyPath(), &e);
|
||||||
|
|
||||||
|
if (connData.caCert.isEmpty() || connData.clientCert.isEmpty() || connData.taKey.isEmpty()) {
|
||||||
|
if (errorCode) *errorCode = ErrorCode::RemoteProcessCrashError;
|
||||||
|
}
|
||||||
|
|
||||||
return connData;
|
return connData;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials, ErrorCode *errorCode)
|
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials,
|
||||||
|
Protocol proto, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
QFile configTemplFile(":/server_scripts/template.ovpn");
|
QFile configTemplFile;
|
||||||
|
if (proto == Protocol::OpenVpn)
|
||||||
|
configTemplFile.setFileName(":/server_scripts/template_openvpn.ovpn");
|
||||||
|
else if (proto == Protocol::ShadowSocks) {
|
||||||
|
configTemplFile.setFileName(":/server_scripts/template_shadowsocks.ovpn");
|
||||||
|
}
|
||||||
|
|
||||||
configTemplFile.open(QIODevice::ReadOnly);
|
configTemplFile.open(QIODevice::ReadOnly);
|
||||||
QString config = configTemplFile.readAll();
|
QString config = configTemplFile.readAll();
|
||||||
|
|
||||||
ConnectionData connData = prepareOpenVpnConfig(credentials, errorCode);
|
ConnectionData connData = prepareOpenVpnConfig(credentials, proto, errorCode);
|
||||||
|
|
||||||
|
if (proto == Protocol::OpenVpn)
|
||||||
|
config.replace("$PROTO", "udp");
|
||||||
|
else if (proto == Protocol::ShadowSocks) {
|
||||||
|
config.replace("$PROTO", "tcp");
|
||||||
|
config.replace("$LOCAL_PROXY_PORT", QString::number(ServerController::ssContainerPort()));
|
||||||
|
}
|
||||||
|
|
||||||
config.replace("$PROTO", "udp");
|
|
||||||
config.replace("$REMOTE_HOST", connData.host);
|
config.replace("$REMOTE_HOST", connData.host);
|
||||||
config.replace("$REMOTE_PORT", "1194");
|
config.replace("$REMOTE_PORT", "1194");
|
||||||
config.replace("$CA_CERT", connData.caCert);
|
config.replace("$CA_CERT", connData.caCert);
|
||||||
|
|
|
@ -22,7 +22,8 @@ public:
|
||||||
QString host; // host ip
|
QString host; // host ip
|
||||||
};
|
};
|
||||||
|
|
||||||
static QString genOpenVpnConfig(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr);
|
static QString genOpenVpnConfig(const ServerCredentials &credentials, Protocol proto,
|
||||||
|
ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QString getRandomString(int len);
|
static QString getRandomString(int len);
|
||||||
|
@ -34,7 +35,8 @@ private:
|
||||||
|
|
||||||
static ConnectionData createCertRequest();
|
static ConnectionData createCertRequest();
|
||||||
|
|
||||||
static ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr);
|
static ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials,
|
||||||
|
Protocol proto, ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,25 @@
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
#include "sshconnectionmanager.h"
|
#include "sshconnectionmanager.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace QSsh;
|
using namespace QSsh;
|
||||||
|
|
||||||
ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams, QString script)
|
QString ServerController::getContainerName(DockerContainer container)
|
||||||
|
{
|
||||||
|
switch (container) {
|
||||||
|
case(DockerContainer::OpenVpn): return "amnezia-openvpn";
|
||||||
|
case(DockerContainer::ShadowSocks): return "amnezia-shadowsocks";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ServerController::runScript(DockerContainer container,
|
||||||
|
const SshConnectionParameters &sshParams, QString script)
|
||||||
{
|
{
|
||||||
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
|
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
|
||||||
|
|
||||||
|
@ -26,7 +38,9 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams,
|
||||||
|
|
||||||
const QStringList &lines = script.split("\n", QString::SkipEmptyParts);
|
const QStringList &lines = script.split("\n", QString::SkipEmptyParts);
|
||||||
for (int i = 0; i < lines.count(); i++) {
|
for (int i = 0; i < lines.count(); i++) {
|
||||||
const QString &line = lines.at(i);
|
QString line = lines.at(i);
|
||||||
|
line.replace("$CONTAINER_NAME", getContainerName(container));
|
||||||
|
|
||||||
if (line.startsWith("#")) {
|
if (line.startsWith("#")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -52,23 +66,22 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams,
|
||||||
wait.quit();
|
wait.quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
|
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
|
||||||
// QString s = proc->readAllStandardOutput();
|
// QString s = proc->readAllStandardOutput();
|
||||||
// if (s != "." && !s.isEmpty()) {
|
// if (s != "." && !s.isEmpty()) {
|
||||||
// qDebug().noquote() << s;
|
// qDebug().noquote() << s;
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, [proc](){
|
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, [proc](){
|
||||||
// QString s = proc->readAllStandardError();
|
// QString s = proc->readAllStandardError();
|
||||||
// if (s != "." && !s.isEmpty()) {
|
// if (s != "." && !s.isEmpty()) {
|
||||||
// qDebug().noquote() << s;
|
// qDebug().noquote() << s;
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
proc->start();
|
proc->start();
|
||||||
|
if (i < lines.count()) {
|
||||||
if (i < lines.count() - 1) {
|
|
||||||
wait.exec();
|
wait.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,13 +94,13 @@ ErrorCode ServerController::runScript(const SshConnectionParameters &sshParams,
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode ServerController::uploadTextFileToContainer(const ServerCredentials &credentials,
|
ErrorCode ServerController::uploadTextFileToContainer(DockerContainer container,
|
||||||
QString &file, const QString &path)
|
const ServerCredentials &credentials, QString &file, const QString &path)
|
||||||
{
|
{
|
||||||
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
|
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
|
||||||
|
|
||||||
QString script = QString("docker exec -i amneziavpn sh -c \"echo \'%1\' > %2\"").
|
QString script = QString("docker exec -i %1 sh -c \"echo \'%2\' > %3\"").
|
||||||
arg(file).arg(path);
|
arg(getContainerName(container)).arg(file).arg(path);
|
||||||
|
|
||||||
qDebug().noquote() << script;
|
qDebug().noquote() << script;
|
||||||
|
|
||||||
|
@ -116,25 +129,29 @@ ErrorCode ServerController::uploadTextFileToContainer(const ServerCredentials &c
|
||||||
wait.quit();
|
wait.quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
|
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
|
||||||
// qDebug().noquote() << proc->readAllStandardOutput();
|
qDebug().noquote() << proc->readAllStandardOutput();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, [proc](){
|
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, [proc](){
|
||||||
// qDebug().noquote() << proc->readAllStandardError();
|
qDebug().noquote() << proc->readAllStandardError();
|
||||||
// });
|
});
|
||||||
|
|
||||||
proc->start();
|
proc->start();
|
||||||
wait.exec();
|
wait.exec();
|
||||||
|
|
||||||
|
// if (proc->isRunning()) {
|
||||||
|
// wait.exec();
|
||||||
|
// }
|
||||||
|
|
||||||
return fromSshProcessExitStatus(exitStatus);
|
return fromSshProcessExitStatus(exitStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ServerController::getTextFileFromContainer(const ServerCredentials &credentials, const QString &path,
|
QString ServerController::getTextFileFromContainer(DockerContainer container,
|
||||||
ErrorCode *errorCode)
|
const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode)
|
||||||
{
|
{
|
||||||
QString script = QString("docker exec -i amneziavpn sh -c \"cat \'%1\'\"").
|
QString script = QString("docker exec -i %1 sh -c \"cat \'%2\'\"").
|
||||||
arg(path);
|
arg(getContainerName(container)).arg(path);
|
||||||
|
|
||||||
qDebug().noquote() << "Copy file from container\n" << script;
|
qDebug().noquote() << "Copy file from container\n" << script;
|
||||||
|
|
||||||
|
@ -162,6 +179,10 @@ QString ServerController::getTextFileFromContainer(const ServerCredentials &cred
|
||||||
proc->start();
|
proc->start();
|
||||||
wait.exec();
|
wait.exec();
|
||||||
|
|
||||||
|
// if (proc->isRunning()) {
|
||||||
|
// wait.exec();
|
||||||
|
// }
|
||||||
|
|
||||||
if (SshRemoteProcess::ExitStatus(exitStatus) != QSsh::SshRemoteProcess::ExitStatus::NormalExit) {
|
if (SshRemoteProcess::ExitStatus(exitStatus) != QSsh::SshRemoteProcess::ExitStatus::NormalExit) {
|
||||||
if (errorCode) *errorCode = fromSshProcessExitStatus(exitStatus);
|
if (errorCode) *errorCode = fromSshProcessExitStatus(exitStatus);
|
||||||
}
|
}
|
||||||
|
@ -169,25 +190,28 @@ QString ServerController::getTextFileFromContainer(const ServerCredentials &cred
|
||||||
return proc->readAllStandardOutput();
|
return proc->readAllStandardOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode ServerController::signCert(const ServerCredentials &credentials, QString clientId)
|
ErrorCode ServerController::signCert(DockerContainer container,
|
||||||
|
const ServerCredentials &credentials, QString clientId)
|
||||||
{
|
{
|
||||||
QString script_import = QString("docker exec -i amneziavpn bash -c \"cd /opt/amneziavpn_data && "
|
QString script_import = QString("docker exec -i %1 bash -c \"cd /opt/amneziavpn_data && "
|
||||||
"easyrsa import-req /opt/amneziavpn_data/clients/%1.req %1 &>/dev/null\"")
|
"easyrsa import-req /opt/amneziavpn_data/clients/%2.req %2\"")
|
||||||
.arg(clientId);
|
.arg(getContainerName(container)).arg(clientId);
|
||||||
|
|
||||||
QString script_sign = QString("docker exec -i amneziavpn bash -c \"export EASYRSA_BATCH=1; cd /opt/amneziavpn_data && "
|
QString script_sign = QString("docker exec -i %1 bash -c \"export EASYRSA_BATCH=1; cd /opt/amneziavpn_data && "
|
||||||
"easyrsa sign-req client %1 &>/dev/null\"")
|
"easyrsa sign-req client %2\"")
|
||||||
.arg(clientId);
|
.arg(getContainerName(container)).arg(clientId);
|
||||||
|
|
||||||
QStringList script {script_import, script_sign};
|
QStringList script {script_import, script_sign};
|
||||||
|
|
||||||
return runScript(sshParams(credentials), script.join("\n"));
|
return runScript(container, sshParams(credentials), script.join("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode ServerController::checkOpenVpnServer(const ServerCredentials &credentials)
|
ErrorCode ServerController::checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials)
|
||||||
{
|
{
|
||||||
QString caCert = ServerController::getTextFileFromContainer(credentials, ServerController::caCertPath());
|
QString caCert = ServerController::getTextFileFromContainer(container,
|
||||||
QString taKey = ServerController::getTextFileFromContainer(credentials, ServerController::taKeyPath());
|
credentials, ServerController::caCertPath());
|
||||||
|
QString taKey = ServerController::getTextFileFromContainer(container,
|
||||||
|
credentials, ServerController::taKeyPath());
|
||||||
|
|
||||||
if (!caCert.isEmpty() && !taKey.isEmpty()) {
|
if (!caCert.isEmpty() && !taKey.isEmpty()) {
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
|
@ -209,15 +233,18 @@ ErrorCode ServerController::fromSshConnectionErrorCode(SshError error)
|
||||||
case(QSsh::SshAuthenticationError): return ErrorCode::SshAuthenticationError;
|
case(QSsh::SshAuthenticationError): return ErrorCode::SshAuthenticationError;
|
||||||
case(QSsh::SshClosedByServerError): return ErrorCode::SshClosedByServerError;
|
case(QSsh::SshClosedByServerError): return ErrorCode::SshClosedByServerError;
|
||||||
case(QSsh::SshInternalError): return ErrorCode::SshInternalError;
|
case(QSsh::SshInternalError): return ErrorCode::SshInternalError;
|
||||||
|
default: return ErrorCode::SshInternalError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode ServerController::fromSshProcessExitStatus(int exitStatus)
|
ErrorCode ServerController::fromSshProcessExitStatus(int exitStatus)
|
||||||
{
|
{
|
||||||
|
qDebug() << exitStatus;
|
||||||
switch (SshRemoteProcess::ExitStatus(exitStatus)) {
|
switch (SshRemoteProcess::ExitStatus(exitStatus)) {
|
||||||
case(SshRemoteProcess::ExitStatus::NormalExit): return ErrorCode::NoError;
|
case(SshRemoteProcess::ExitStatus::NormalExit): return ErrorCode::NoError;
|
||||||
case(SshRemoteProcess::ExitStatus::FailedToStart): return ErrorCode::FailedToStartRemoteProcessError;
|
case(SshRemoteProcess::ExitStatus::FailedToStart): return ErrorCode::FailedToStartRemoteProcessError;
|
||||||
case(SshRemoteProcess::ExitStatus::CrashExit): return ErrorCode::RemoteProcessCrashError;
|
case(SshRemoteProcess::ExitStatus::CrashExit): return ErrorCode::RemoteProcessCrashError;
|
||||||
|
default: return ErrorCode::SshInternalError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,10 +265,24 @@ SshConnectionParameters ServerController::sshParams(const ServerCredentials &cre
|
||||||
ErrorCode ServerController::removeServer(const ServerCredentials &credentials, Protocol proto)
|
ErrorCode ServerController::removeServer(const ServerCredentials &credentials, Protocol proto)
|
||||||
{
|
{
|
||||||
QString scriptFileName;
|
QString scriptFileName;
|
||||||
|
DockerContainer container;
|
||||||
|
|
||||||
if (proto == Protocol::OpenVpn || proto == Protocol::Any) {
|
ErrorCode errorCode;
|
||||||
scriptFileName = ":/server_scripts/remove_openvpn_server.sh";
|
if (proto == Protocol::Any) {
|
||||||
|
removeServer(credentials, Protocol::OpenVpn);
|
||||||
|
removeServer(credentials, Protocol::ShadowSocks);
|
||||||
|
return ErrorCode::NoError;
|
||||||
}
|
}
|
||||||
|
else if (proto == Protocol::OpenVpn) {
|
||||||
|
scriptFileName = ":/server_scripts/remove_container.sh";
|
||||||
|
container = DockerContainer::OpenVpn;
|
||||||
|
}
|
||||||
|
else if (proto == Protocol::ShadowSocks) {
|
||||||
|
scriptFileName = ":/server_scripts/remove_container.sh";
|
||||||
|
container = DockerContainer::ShadowSocks;
|
||||||
|
}
|
||||||
|
else return ErrorCode::NotImplementedError;
|
||||||
|
|
||||||
|
|
||||||
QString scriptData;
|
QString scriptData;
|
||||||
|
|
||||||
|
@ -251,7 +292,7 @@ ErrorCode ServerController::removeServer(const ServerCredentials &credentials, P
|
||||||
scriptData = file.readAll();
|
scriptData = file.readAll();
|
||||||
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||||
|
|
||||||
return runScript(sshParams(credentials), scriptData);
|
return runScript(container, sshParams(credentials), scriptData);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode ServerController::setupServer(const ServerCredentials &credentials, Protocol proto)
|
ErrorCode ServerController::setupServer(const ServerCredentials &credentials, Protocol proto)
|
||||||
|
@ -263,8 +304,10 @@ ErrorCode ServerController::setupServer(const ServerCredentials &credentials, Pr
|
||||||
return setupShadowSocksServer(credentials);
|
return setupShadowSocksServer(credentials);
|
||||||
}
|
}
|
||||||
else if (proto == Protocol::Any) {
|
else if (proto == Protocol::Any) {
|
||||||
|
return ErrorCode::NotImplementedError;
|
||||||
|
|
||||||
// TODO: run concurently
|
// TODO: run concurently
|
||||||
return setupOpenVpnServer(credentials);
|
// return setupOpenVpnServer(credentials);
|
||||||
//setupShadowSocksServer(credentials);
|
//setupShadowSocksServer(credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,18 +324,49 @@ ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credenti
|
||||||
scriptData = file.readAll();
|
scriptData = file.readAll();
|
||||||
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||||
|
|
||||||
ErrorCode e = runScript(sshParams(credentials), scriptData);
|
ErrorCode e = runScript(DockerContainer::OpenVpn, sshParams(credentials), scriptData);
|
||||||
if (e) return e;
|
if (e) return e;
|
||||||
|
|
||||||
//return ok;
|
return checkOpenVpnServer(DockerContainer::OpenVpn, credentials);
|
||||||
return checkOpenVpnServer(credentials);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &credentials)
|
ErrorCode ServerController::setupShadowSocksServer(const ServerCredentials &credentials)
|
||||||
{
|
{
|
||||||
Q_UNUSED(credentials)
|
// Setup openvpn part
|
||||||
|
QString scriptData;
|
||||||
|
QString scriptFileName = ":/server_scripts/setup_shadowsocks_server.sh";
|
||||||
|
QFile file(scriptFileName);
|
||||||
|
if (! file.open(QIODevice::ReadOnly)) return ErrorCode::InternalError;
|
||||||
|
|
||||||
return ErrorCode::NotImplementedError;
|
scriptData = file.readAll();
|
||||||
|
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||||
|
|
||||||
|
ErrorCode e = runScript(DockerContainer::ShadowSocks, sshParams(credentials), scriptData);
|
||||||
|
if (e) return e;
|
||||||
|
|
||||||
|
// Create ss config
|
||||||
|
QJsonObject ssConfig;
|
||||||
|
ssConfig.insert("server", "0.0.0.0");
|
||||||
|
ssConfig.insert("server_port", ssRemotePort());
|
||||||
|
ssConfig.insert("local_port", ssContainerPort());
|
||||||
|
ssConfig.insert("password", credentials.password);
|
||||||
|
ssConfig.insert("timeout", 60);
|
||||||
|
ssConfig.insert("method", ssEncryption());
|
||||||
|
QString configData = QJsonDocument(ssConfig).toJson();
|
||||||
|
QString sSConfigPath = "/opt/amneziavpn_data/ssConfig.json";
|
||||||
|
|
||||||
|
qDebug().noquote() << configData;
|
||||||
|
configData.replace("\"", "\\\"");
|
||||||
|
qDebug().noquote() << configData;
|
||||||
|
|
||||||
|
uploadTextFileToContainer(DockerContainer::ShadowSocks, credentials, configData, sSConfigPath);
|
||||||
|
|
||||||
|
// Start ss
|
||||||
|
QString script = QString("docker exec -i %1 sh -c \"ss-server -c %2 &\"").
|
||||||
|
arg(getContainerName(DockerContainer::ShadowSocks)).arg(sSConfigPath);
|
||||||
|
|
||||||
|
e = runScript(DockerContainer::ShadowSocks, sshParams(credentials), script);
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
SshConnection *ServerController::connectToHost(const SshConnectionParameters &sshParams)
|
SshConnection *ServerController::connectToHost(const SshConnectionParameters &sshParams)
|
||||||
|
|
|
@ -22,21 +22,32 @@ public:
|
||||||
static QString clientCertPath() { return "/opt/amneziavpn_data/pki/issued/"; }
|
static QString clientCertPath() { return "/opt/amneziavpn_data/pki/issued/"; }
|
||||||
static QString taKeyPath() { return "/opt/amneziavpn_data/ta.key"; }
|
static QString taKeyPath() { return "/opt/amneziavpn_data/ta.key"; }
|
||||||
|
|
||||||
|
static QString getContainerName(amnezia::DockerContainer container);
|
||||||
|
|
||||||
static QSsh::SshConnectionParameters sshParams(const ServerCredentials &credentials);
|
static QSsh::SshConnectionParameters sshParams(const ServerCredentials &credentials);
|
||||||
|
|
||||||
static ErrorCode removeServer(const ServerCredentials &credentials, Protocol proto);
|
static ErrorCode removeServer(const ServerCredentials &credentials, Protocol proto);
|
||||||
static ErrorCode setupServer(const ServerCredentials &credentials, Protocol proto);
|
static ErrorCode setupServer(const ServerCredentials &credentials, Protocol proto);
|
||||||
|
|
||||||
static ErrorCode checkOpenVpnServer(const ServerCredentials &credentials);
|
static ErrorCode checkOpenVpnServer(DockerContainer container, const ServerCredentials &credentials);
|
||||||
|
|
||||||
static ErrorCode uploadTextFileToContainer(const ServerCredentials &credentials, QString &file, const QString &path);
|
static ErrorCode uploadTextFileToContainer(DockerContainer container,
|
||||||
static QString getTextFileFromContainer(const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode = nullptr);
|
const ServerCredentials &credentials, QString &file, const QString &path);
|
||||||
|
|
||||||
static ErrorCode signCert(const ServerCredentials &credentials, QString clientId);
|
static QString getTextFileFromContainer(DockerContainer container,
|
||||||
|
const ServerCredentials &credentials, const QString &path, ErrorCode *errorCode = nullptr);
|
||||||
|
|
||||||
|
static ErrorCode signCert(DockerContainer container,
|
||||||
|
const ServerCredentials &credentials, QString clientId);
|
||||||
|
|
||||||
|
static int ssRemotePort() { return 6789; } // TODO move to ShadowSocksDefs.h
|
||||||
|
static int ssContainerPort() { return 8585; } // TODO move to ShadowSocksDefs.h
|
||||||
|
static QString ssEncryption() { return "chacha20-ietf-poly1305"; } // TODO move to ShadowSocksDefs.h
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
||||||
static ErrorCode runScript(const QSsh::SshConnectionParameters &sshParams, QString script);
|
static ErrorCode runScript(DockerContainer container,
|
||||||
|
const QSsh::SshConnectionParameters &sshParams, QString script);
|
||||||
|
|
||||||
static ErrorCode setupOpenVpnServer(const ServerCredentials &credentials);
|
static ErrorCode setupOpenVpnServer(const ServerCredentials &credentials);
|
||||||
static ErrorCode setupShadowSocksServer(const ServerCredentials &credentials);
|
static ErrorCode setupShadowSocksServer(const ServerCredentials &credentials);
|
||||||
|
|
|
@ -19,7 +19,8 @@ OpenVpnProtocol::OpenVpnProtocol(const QString& args, QObject* parent) :
|
||||||
|
|
||||||
OpenVpnProtocol::~OpenVpnProtocol()
|
OpenVpnProtocol::~OpenVpnProtocol()
|
||||||
{
|
{
|
||||||
stop();
|
qDebug() << "OpenVpnProtocol::stop()";
|
||||||
|
OpenVpnProtocol::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVpnProtocol::onMessageReceived(const Message& message)
|
void OpenVpnProtocol::onMessageReceived(const Message& message)
|
||||||
|
@ -120,7 +121,7 @@ ErrorCode OpenVpnProtocol::start()
|
||||||
|
|
||||||
m_requestFromUserToStop = false;
|
m_requestFromUserToStop = false;
|
||||||
m_openVpnStateSigTermHandlerTimer.stop();
|
m_openVpnStateSigTermHandlerTimer.stop();
|
||||||
stop();
|
OpenVpnProtocol::stop();
|
||||||
|
|
||||||
if (communicator() && !communicator()->isConnected()) {
|
if (communicator() && !communicator()->isConnected()) {
|
||||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||||
|
|
|
@ -15,7 +15,7 @@ class OpenVpnProtocol : public VpnProtocol
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit OpenVpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
explicit OpenVpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||||
~OpenVpnProtocol() override;
|
virtual ~OpenVpnProtocol() override;
|
||||||
|
|
||||||
ErrorCode start() override;
|
ErrorCode start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
|
@ -1,6 +1,68 @@
|
||||||
#include "shadowsocksvpnprotocol.h"
|
#include "shadowsocksvpnprotocol.h"
|
||||||
|
#include "core/servercontroller.h"
|
||||||
|
|
||||||
ShadowSocksVpnProtocol::ShadowSocksVpnProtocol()
|
#include "communicator.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
ShadowSocksVpnProtocol::ShadowSocksVpnProtocol(const QString &args, QObject *parent):
|
||||||
|
OpenVpnProtocol(args, parent)
|
||||||
{
|
{
|
||||||
|
m_shadowSocksConfig = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorCode ShadowSocksVpnProtocol::start()
|
||||||
|
{
|
||||||
|
qDebug() << "ShadowSocksVpnProtocol::start()";
|
||||||
|
QJsonObject config = QJsonDocument::fromJson(m_shadowSocksConfig.toUtf8()).object();
|
||||||
|
|
||||||
|
ssProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
|
ssProcess.setProgram(shadowSocksExecPath());
|
||||||
|
ssProcess.setArguments(QStringList() << "-s" << config.value("server").toString()
|
||||||
|
<< "-p" << QString::number(config.value("server_port").toInt())
|
||||||
|
<< "-l" << QString::number(config.value("local_port").toInt())
|
||||||
|
<< "-m" << config.value("method").toString()
|
||||||
|
<< "-k" << config.value("password").toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
ssProcess.start();
|
||||||
|
ssProcess.waitForStarted();
|
||||||
|
|
||||||
|
if (ssProcess.state() == QProcess::ProcessState::Running) {
|
||||||
|
setConnectionState(ConnectionState::Connecting);
|
||||||
|
|
||||||
|
return OpenVpnProtocol::start();
|
||||||
|
}
|
||||||
|
else return ErrorCode::FailedToStartRemoteProcessError;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowSocksVpnProtocol::stop()
|
||||||
|
{
|
||||||
|
qDebug() << "ShadowSocksVpnProtocol::stop()";
|
||||||
|
ssProcess.kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ShadowSocksVpnProtocol::shadowSocksExecPath() const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
return Utils::executable(QString("ss/ss-local"), true);
|
||||||
|
#else
|
||||||
|
return Utils::executable(QString("/ss-local"), true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto)
|
||||||
|
{
|
||||||
|
QJsonObject ssConfig;
|
||||||
|
ssConfig.insert("server", credentials.hostName);
|
||||||
|
ssConfig.insert("server_port", ServerController::ssRemotePort());
|
||||||
|
ssConfig.insert("local_port", ServerController::ssContainerPort());
|
||||||
|
ssConfig.insert("password", credentials.password);
|
||||||
|
ssConfig.insert("timeout", 60);
|
||||||
|
ssConfig.insert("method", ServerController::ssEncryption());
|
||||||
|
return QJsonDocument(ssConfig).toJson();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,26 @@
|
||||||
#define SHADOWSOCKSVPNPROTOCOL_H
|
#define SHADOWSOCKSVPNPROTOCOL_H
|
||||||
|
|
||||||
#include "openvpnprotocol.h"
|
#include "openvpnprotocol.h"
|
||||||
|
#include "QProcess"
|
||||||
|
|
||||||
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShadowSocksVpnProtocol();
|
ShadowSocksVpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||||
|
|
||||||
|
ErrorCode start() override;
|
||||||
|
void stop() override;
|
||||||
|
|
||||||
|
static QString genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto = Protocol::ShadowSocks);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString shadowSocksExecPath() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString m_shadowSocksConfig;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QProcess ssProcess;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHADOWSOCKSVPNPROTOCOL_H
|
#endif // SHADOWSOCKSVPNPROTOCOL_H
|
||||||
|
|
|
@ -33,10 +33,11 @@
|
||||||
<file>images/line.png</file>
|
<file>images/line.png</file>
|
||||||
<file>images/server_settings.png</file>
|
<file>images/server_settings.png</file>
|
||||||
<file>images/share.png</file>
|
<file>images/share.png</file>
|
||||||
<file>server_scripts/remove_openvpn_server.sh</file>
|
<file>server_scripts/remove_container.sh</file>
|
||||||
<file>server_scripts/setup_openvpn_server.sh</file>
|
<file>server_scripts/setup_openvpn_server.sh</file>
|
||||||
<file>server_scripts/template.ovpn</file>
|
<file>server_scripts/template_openvpn.ovpn</file>
|
||||||
<file>images/background_connected.png</file>
|
<file>images/background_connected.png</file>
|
||||||
<file>server_scripts/setup_shadowsocks_server.sh</file>
|
<file>server_scripts/setup_shadowsocks_server.sh</file>
|
||||||
|
<file>server_scripts/template_shadowsocks.ovpn</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
2
client/server_scripts/remove_container.sh
Normal file
2
client/server_scripts/remove_container.sh
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
docker stop $CONTAINER_NAME
|
||||||
|
docker rm -f $CONTAINER_NAME
|
|
@ -1,2 +0,0 @@
|
||||||
sudo docker stop amneziavpn
|
|
||||||
sudo docker rm -f amneziavpn
|
|
|
@ -1,24 +1,21 @@
|
||||||
#DOCKER_IMAGE="amneziavpn/openvpn:latest"
|
#CONTAINER_NAME=... this var will be set in ServerController
|
||||||
#CONTAINER_NAME="amneziavpn"
|
|
||||||
|
|
||||||
#sudo apt update
|
#apt update
|
||||||
sudo apt install -y docker.io curl
|
apt install -y docker.io curl
|
||||||
sudo systemctl start docker
|
systemctl start docker
|
||||||
|
|
||||||
sudo docker stop amneziavpn
|
docker stop $CONTAINER_NAME
|
||||||
sudo docker rm -f amneziavpn
|
docker rm -f $CONTAINER_NAME
|
||||||
sudo docker pull amneziavpn/openvpn:latest
|
docker pull amneziavpn/openvpn:latest
|
||||||
sudo docker run -d --restart always --cap-add=NET_ADMIN -p 1194:1194/udp --name amneziavpn amneziavpn/openvpn:latest
|
docker run -d --restart always --cap-add=NET_ADMIN -p 1194:1194/udp --name $CONTAINER_NAME amneziavpn/openvpn:latest
|
||||||
|
|
||||||
|
|
||||||
docker exec -i amneziavpn sh -c "mkdir -p /opt/amneziavpn_data/clients"
|
docker exec -i $CONTAINER_NAME sh -c "mkdir -p /opt/amneziavpn_data/clients"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa init-pki"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa gen-dh"
|
||||||
|
|
||||||
#docker exec -i amneziavpn sh -c "cat /proc/sys/kernel/random/entropy_avail"
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && cp pki/dh.pem /etc/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req MyReq nopass << EOF2 yes EOF2"
|
||||||
docker exec -i amneziavpn sh -c "cd /opt/amneziavpn_data && easyrsa init-pki"
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa sign-req server MyReq << EOF3 yes EOF3"
|
||||||
docker exec -i amneziavpn sh -c "cd /opt/amneziavpn_data && easyrsa gen-dh"
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && openvpn --genkey --secret ta.key << EOF4"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && cp pki/ca.crt pki/issued/MyReq.crt pki/private/MyReq.key ta.key /etc/openvpn"
|
||||||
docker exec -i amneziavpn sh -c "cd /opt/amneziavpn_data && cp pki/dh.pem /etc/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req MyReq nopass << EOF2 yes EOF2"
|
docker exec -i $CONTAINER_NAME sh -c "openvpn --config /etc/openvpn/server.conf &"
|
||||||
docker exec -i amneziavpn sh -c "cd /opt/amneziavpn_data && easyrsa sign-req server MyReq << EOF3 yes EOF3"
|
|
||||||
docker exec -i amneziavpn sh -c "cd /opt/amneziavpn_data && openvpn --genkey --secret ta.key << EOF4"
|
|
||||||
docker exec -i amneziavpn sh -c "cd /opt/amneziavpn_data && cp pki/ca.crt pki/issued/MyReq.crt pki/private/MyReq.key ta.key /etc/openvpn"
|
|
||||||
docker exec -i amneziavpn sh -c "openvpn --config /etc/openvpn/server.conf &"
|
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
#DOCKER_IMAGE="amneziavpn/shadow-vpn:latest"
|
#CONTAINER_NAME=... this var will be set in ServerController
|
||||||
#CONTAINER_NAME="shadow-vpn"
|
|
||||||
|
|
||||||
#sudo apt update
|
#apt update
|
||||||
sudo apt install -y docker.io curl
|
apt install -y docker.io curl
|
||||||
sudo systemctl start docker
|
systemctl start docker
|
||||||
|
|
||||||
sudo docker stop shadow-vpn
|
docker stop $CONTAINER_NAME
|
||||||
sudo docker rm -f shadow-vpn
|
docker rm -f $CONTAINER_NAME
|
||||||
sudo docker pull amneziavpn/shadow-vpn:latest
|
docker pull amneziavpn/shadowsocks:latest
|
||||||
sudo docker run -d --restart always --cap-add=NET_ADMIN -p 1194:1194/tcp -p 6789:6789/tcp --name shadow-vpn amneziavpn/shadow-vpn:latest
|
docker run -d --restart always --cap-add=NET_ADMIN -p 1194:1194/tcp -p 6789:6789/tcp --name $CONTAINER_NAME amneziavpn/shadowsocks:latest
|
||||||
|
|
||||||
|
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "mkdir -p /opt/amneziavpn_data/clients"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa init-pki"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa gen-dh"
|
||||||
|
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && cp pki/dh.pem /etc/openvpn && easyrsa build-ca nopass << EOF yes EOF && easyrsa gen-req MyReq nopass << EOF2 yes EOF2"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && easyrsa sign-req server MyReq << EOF3 yes EOF3"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && openvpn --genkey --secret ta.key << EOF4"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "cd /opt/amneziavpn_data && cp pki/ca.crt pki/issued/MyReq.crt pki/private/MyReq.key ta.key /etc/openvpn"
|
||||||
|
docker exec -i $CONTAINER_NAME sh -c "openvpn --config /etc/openvpn/server.conf &"
|
||||||
|
|
|
@ -14,6 +14,7 @@ key-direction 1
|
||||||
remote-cert-tls server
|
remote-cert-tls server
|
||||||
|
|
||||||
remote $REMOTE_HOST $REMOTE_PORT
|
remote $REMOTE_HOST $REMOTE_PORT
|
||||||
|
|
||||||
<ca>
|
<ca>
|
||||||
$CA_CERT
|
$CA_CERT
|
||||||
</ca>
|
</ca>
|
31
client/server_scripts/template_shadowsocks.ovpn
Normal file
31
client/server_scripts/template_shadowsocks.ovpn
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
client
|
||||||
|
dev tun
|
||||||
|
proto $PROTO
|
||||||
|
resolv-retry infinite
|
||||||
|
nobind
|
||||||
|
persist-key
|
||||||
|
persist-tun
|
||||||
|
cipher AES-256-GCM
|
||||||
|
auth SHA512
|
||||||
|
verb 3
|
||||||
|
tls-client
|
||||||
|
tls-version-min 1.2
|
||||||
|
key-direction 1
|
||||||
|
remote-cert-tls server
|
||||||
|
|
||||||
|
socks-proxy 127.0.0.1 $LOCAL_PROXY_PORT
|
||||||
|
route $REMOTE_HOST 255.255.255.255 net_gateway
|
||||||
|
remote $REMOTE_HOST $REMOTE_PORT
|
||||||
|
|
||||||
|
<ca>
|
||||||
|
$CA_CERT
|
||||||
|
</ca>
|
||||||
|
<cert>
|
||||||
|
$CLIENT_CERT
|
||||||
|
</cert>
|
||||||
|
<key>
|
||||||
|
$PRIV_KEY
|
||||||
|
</key>
|
||||||
|
<tls-auth>
|
||||||
|
$TA_KEY
|
||||||
|
</tls-auth>
|
|
@ -336,6 +336,8 @@ void MainWindow::onBytesChanged(quint64 receivedData, quint64 sentData)
|
||||||
|
|
||||||
void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
||||||
{
|
{
|
||||||
|
qDebug() << "MainWindow::onConnectionStateChanged" << VpnProtocol::textConnectionState(state);
|
||||||
|
|
||||||
bool pushButtonConnectEnabled = false;
|
bool pushButtonConnectEnabled = false;
|
||||||
ui->label_state->setText(VpnProtocol::textConnectionState(state));
|
ui->label_state->setText(VpnProtocol::textConnectionState(state));
|
||||||
|
|
||||||
|
@ -541,6 +543,7 @@ void MainWindow::onConnect()
|
||||||
QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode));
|
QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->pushButton_connect->setEnabled(false);
|
ui->pushButton_connect->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,7 @@ QStackedWidget QWidget {
|
||||||
</string>
|
</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="page_start">
|
<widget class="QWidget" name="page_start">
|
||||||
<widget class="QLabel" name="label_23">
|
<widget class="QLabel" name="label_23">
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <core/servercontroller.h>
|
#include <core/servercontroller.h>
|
||||||
|
|
||||||
#include "protocols/openvpnprotocol.h"
|
#include "protocols/openvpnprotocol.h"
|
||||||
|
#include "protocols/shadowsocksvpnprotocol.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "vpnconnection.h"
|
#include "vpnconnection.h"
|
||||||
|
|
||||||
|
@ -36,8 +37,8 @@ ErrorCode VpnConnection::lastError() const
|
||||||
ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials, Protocol protocol)
|
ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials, Protocol protocol)
|
||||||
{
|
{
|
||||||
ErrorCode errorCode = ErrorCode::NoError;
|
ErrorCode errorCode = ErrorCode::NoError;
|
||||||
if (protocol == Protocol::OpenVpn) {
|
if (protocol == Protocol::OpenVpn || protocol == Protocol::ShadowSocks) {
|
||||||
QString configData = OpenVpnConfigurator::genOpenVpnConfig(credentials, &errorCode);
|
QString configData = OpenVpnConfigurator::genOpenVpnConfig(credentials, protocol, &errorCode);
|
||||||
if (errorCode) {
|
if (errorCode) {
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
@ -51,8 +52,7 @@ ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials,
|
||||||
|
|
||||||
return ErrorCode::FailedToSaveConfigData;
|
return ErrorCode::FailedToSaveConfigData;
|
||||||
}
|
}
|
||||||
else if (protocol == Protocol::ShadowSocks) {
|
else {
|
||||||
// Request OpenVPN config and ShadowSocks
|
|
||||||
return ErrorCode::NotImplementedError;
|
return ErrorCode::NotImplementedError;
|
||||||
}
|
}
|
||||||
return ErrorCode::NotImplementedError;
|
return ErrorCode::NotImplementedError;
|
||||||
|
@ -61,6 +61,8 @@ ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials,
|
||||||
|
|
||||||
ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Protocol protocol)
|
ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Protocol protocol)
|
||||||
{
|
{
|
||||||
|
// protocol = Protocol::ShadowSocks;
|
||||||
|
|
||||||
// TODO: Try protocols one by one in case of Protocol::Any
|
// TODO: Try protocols one by one in case of Protocol::Any
|
||||||
// TODO: Implement some behavior in case if connection not stable
|
// TODO: Implement some behavior in case if connection not stable
|
||||||
qDebug() << "Connect to VPN";
|
qDebug() << "Connect to VPN";
|
||||||
|
@ -81,8 +83,18 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Prot
|
||||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||||
}
|
}
|
||||||
else if (protocol == Protocol::ShadowSocks) {
|
else if (protocol == Protocol::ShadowSocks) {
|
||||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
ErrorCode e = requestVpnConfig(credentials, Protocol::ShadowSocks);
|
||||||
return ErrorCode::NotImplementedError;
|
if (e) {
|
||||||
|
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
if (m_vpnProtocol) {
|
||||||
|
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vpnProtocol.reset(new ShadowSocksVpnProtocol(ShadowSocksVpnProtocol::genShadowSocksConfig(credentials)));
|
||||||
|
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState)));
|
connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState)));
|
||||||
|
@ -107,6 +119,12 @@ void VpnConnection::disconnectFromVpn()
|
||||||
m_vpnProtocol.data()->stop();
|
m_vpnProtocol.data()->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VpnProtocol::ConnectionState VpnConnection::connectionState()
|
||||||
|
{
|
||||||
|
if (!m_vpnProtocol) return VpnProtocol::ConnectionState::Disconnected;
|
||||||
|
return m_vpnProtocol->connectionState();
|
||||||
|
}
|
||||||
|
|
||||||
bool VpnConnection::onConnected() const
|
bool VpnConnection::onConnected() const
|
||||||
{
|
{
|
||||||
if (!m_vpnProtocol.data()) {
|
if (!m_vpnProtocol.data()) {
|
||||||
|
|
|
@ -27,6 +27,8 @@ public:
|
||||||
bool onDisconnected() const;
|
bool onDisconnected() const;
|
||||||
void disconnectFromVpn();
|
void disconnectFromVpn();
|
||||||
|
|
||||||
|
VpnProtocol::ConnectionState connectionState();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||||
void connectionStateChanged(VpnProtocol::ConnectionState state);
|
void connectionStateChanged(VpnProtocol::ConnectionState state);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue