Custom routing done
ShadowSocks enabled by default
This commit is contained in:
parent
f91854594c
commit
a1cb4ac544
36 changed files with 482 additions and 780 deletions
|
@ -19,7 +19,6 @@ HEADERS += \
|
|||
debug.h \
|
||||
defines.h \
|
||||
managementserver.h \
|
||||
message.h \
|
||||
protocols/shadowsocksvpnprotocol.h \
|
||||
runguard.h \
|
||||
settings.h \
|
||||
|
@ -37,7 +36,6 @@ SOURCES += \
|
|||
debug.cpp \
|
||||
main.cpp \
|
||||
managementserver.cpp \
|
||||
message.cpp \
|
||||
protocols/shadowsocksvpnprotocol.cpp \
|
||||
runguard.cpp \
|
||||
settings.cpp \
|
||||
|
|
|
@ -34,8 +34,9 @@ enum ErrorCode
|
|||
InternalError,
|
||||
NotImplementedError,
|
||||
|
||||
// Server errorz
|
||||
// Server errors
|
||||
ServerCheckFailed,
|
||||
ServerPortAlreadyAllocatedError,
|
||||
|
||||
// Ssh connection errors
|
||||
SshSocketError, SshTimeoutError, SshProtocolError,
|
||||
|
@ -62,6 +63,15 @@ enum ErrorCode
|
|||
OpenVpnUnknownError
|
||||
};
|
||||
|
||||
namespace config {
|
||||
// config keys
|
||||
static QString key_openvpn_config_data() { return "openvpn_config_data"; }
|
||||
static QString key_openvpn_config_path() { return "openvpn_config_path"; }
|
||||
static QString key_shadowsocks_config_data() { return "shadowsocks_config_data"; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace amnezia
|
||||
|
||||
#endif // DEFS_H
|
||||
|
|
|
@ -11,7 +11,10 @@ static QString errorString(ErrorCode code){
|
|||
case(NoError): return QObject::tr("No error");
|
||||
case(UnknownError): return QObject::tr("Unknown Error");
|
||||
case(NotImplementedError): return QObject::tr("Function not implemented");
|
||||
|
||||
// Server errors
|
||||
case(ServerCheckFailed): return QObject::tr("Server check failed");
|
||||
case(ServerPortAlreadyAllocatedError): return QObject::tr("Server port already used. Check for another software");
|
||||
|
||||
// Ssh connection errors
|
||||
case(SshSocketError): return QObject::tr("Ssh connection error");
|
||||
|
|
|
@ -7,7 +7,18 @@ IpcClient &IpcClient::Instance()
|
|||
return s;
|
||||
}
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> IpcClient::createPrivilegedProcess()
|
||||
bool IpcClient::init()
|
||||
{
|
||||
Instance().m_localSocket->waitForConnected();
|
||||
|
||||
if (!Instance().m_ipcClient) {
|
||||
qDebug() << "IpcClient::init failed";
|
||||
return false;
|
||||
}
|
||||
return Instance().m_ipcClient->isReplicaValid();
|
||||
}
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> IpcClient::CreatePrivilegedProcess()
|
||||
{
|
||||
if (! Instance().m_ipcClient || ! Instance().m_ipcClient->isReplicaValid()) {
|
||||
qWarning() << "IpcClient::createPrivilegedProcess : IpcClient IpcClient replica is not valid";
|
||||
|
@ -18,47 +29,40 @@ QSharedPointer<IpcProcessInterfaceReplica> IpcClient::createPrivilegedProcess()
|
|||
futureResult.waitForFinished(1000);
|
||||
|
||||
int pid = futureResult.returnValue();
|
||||
QSharedPointer<QRemoteObjectNode> replicaNode(new QRemoteObjectNode);
|
||||
//Instance().m_processNodes.insert(pid, replica);
|
||||
|
||||
auto pd = QSharedPointer<ProcessDescriptor>(new ProcessDescriptor());
|
||||
Instance().m_processNodes.insert(pid, pd);
|
||||
|
||||
QSharedPointer<QLocalSocket> socket(new QLocalSocket(replicaNode.data()));
|
||||
QSharedPointer<IpcProcessInterfaceReplica> ptr;
|
||||
pd->localSocket.reset(new QLocalSocket(pd->replicaNode.data()));
|
||||
|
||||
connect(socket.data(), &QLocalSocket::connected, replicaNode.data(), [socket, replicaNode, &ptr]() {
|
||||
replicaNode->addClientSideConnection(socket.data());
|
||||
connect(pd->localSocket.data(), &QLocalSocket::connected, pd->replicaNode.data(), [pd]() {
|
||||
pd->replicaNode->addClientSideConnection(pd->localSocket.data());
|
||||
|
||||
ptr.reset(replicaNode->acquire<IpcProcessInterfaceReplica>());
|
||||
pd->ipcProcess.reset(pd->replicaNode->acquire<IpcProcessInterfaceReplica>());
|
||||
if (!pd->ipcProcess) {
|
||||
qWarning() << "Acquire IpcProcessInterfaceReplica failed";
|
||||
}
|
||||
else {
|
||||
pd->ipcProcess->waitForSource(1000);
|
||||
if (!pd->ipcProcess->isReplicaValid()) {
|
||||
qWarning() << "IpcProcessInterfaceReplica replica is not connected!";
|
||||
}
|
||||
|
||||
ptr->waitForSource(1000);
|
||||
|
||||
if (!ptr->isReplicaValid()) {
|
||||
qWarning() << "IpcProcessInterfaceReplica replica is not connected!";
|
||||
connect(pd->ipcProcess.data(), &IpcProcessInterfaceReplica::destroyed, pd->ipcProcess.data(), [pd](){
|
||||
pd->replicaNode->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
socket->connectToServer(amnezia::getIpcProcessUrl(pid));
|
||||
socket->waitForConnected();
|
||||
|
||||
auto proccessReplica = QSharedPointer<IpcProcessInterfaceReplica>(ptr);
|
||||
|
||||
|
||||
|
||||
// replica->connectToNode(QUrl(amnezia::getIpcProcessUrl(pid)));
|
||||
// auto ptr = QSharedPointer<IpcProcessInterfaceReplica>(replica->acquire<IpcProcessInterfaceReplica>());
|
||||
connect(proccessReplica.data(), &IpcProcessInterfaceReplica::destroyed, proccessReplica.data(), [replicaNode](){
|
||||
replicaNode->deleteLater();
|
||||
});
|
||||
pd->localSocket->connectToServer(amnezia::getIpcProcessUrl(pid));
|
||||
pd->localSocket->waitForConnected();
|
||||
|
||||
auto proccessReplica = QSharedPointer<IpcProcessInterfaceReplica>(pd->ipcProcess);
|
||||
return proccessReplica;
|
||||
}
|
||||
|
||||
IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
// m_ClientNode.connectToNode(QUrl(amnezia::getIpcServiceUrl()));
|
||||
// qDebug() << QUrl(amnezia::getIpcServiceUrl());
|
||||
|
||||
|
||||
m_localSocket.reset(new QLocalSocket(this));
|
||||
connect(m_localSocket.data(), &QLocalSocket::connected, &m_ClientNode, [this]() {
|
||||
m_ClientNode.addClientSideConnection(m_localSocket.data());
|
||||
|
@ -72,20 +76,4 @@ IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
|||
|
||||
});
|
||||
m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
|
||||
|
||||
|
||||
|
||||
// connect(m_ipcClient.data(), &IpcInterfaceReplica::stateChanged, [&](QRemoteObjectReplica::State state, QRemoteObjectReplica::State oldState){
|
||||
|
||||
//// qDebug() << "state" << state;
|
||||
//// for (int i = 0; i < 10; ++i) {
|
||||
//// QRemoteObjectPendingReply<qint64> future = m_ipcClient->createPrivilegedProcess("", QStringList());
|
||||
|
||||
//// future.waitForFinished();
|
||||
//// qDebug() << "QRemoteObjectPendingReply" << QDateTime::currentMSecsSinceEpoch() - future.returnValue();
|
||||
|
||||
//// }
|
||||
// });
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,21 +12,31 @@ class IpcClient : public QObject
|
|||
Q_OBJECT
|
||||
public:
|
||||
static IpcClient &Instance();
|
||||
static bool init() { return Instance().m_ipcClient->isReplicaValid(); }
|
||||
static QSharedPointer<IpcInterfaceReplica> ipcClient() { return Instance().m_ipcClient; }
|
||||
|
||||
static QSharedPointer<IpcProcessInterfaceReplica> createPrivilegedProcess();
|
||||
static bool init();
|
||||
static QSharedPointer<IpcInterfaceReplica> Interface() { return Instance().m_ipcClient; }
|
||||
static QSharedPointer<IpcProcessInterfaceReplica> CreatePrivilegedProcess();
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
explicit IpcClient(QObject *parent = nullptr);
|
||||
|
||||
QRemoteObjectNode m_ClientNode; // create remote object node
|
||||
QRemoteObjectNode m_ClientNode;
|
||||
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
|
||||
QSharedPointer<QLocalSocket> m_localSocket;
|
||||
|
||||
//QMap<int, QSharedPointer<QRemoteObjectNode>> m_processNodes;
|
||||
struct ProcessDescriptor {
|
||||
ProcessDescriptor () {
|
||||
replicaNode = QSharedPointer<QRemoteObjectNode>(new QRemoteObjectNode());
|
||||
ipcProcess = QSharedPointer<IpcProcessInterfaceReplica>();
|
||||
localSocket = QSharedPointer<QLocalSocket>();
|
||||
}
|
||||
QSharedPointer<IpcProcessInterfaceReplica> ipcProcess;
|
||||
QSharedPointer<QRemoteObjectNode> replicaNode;
|
||||
QSharedPointer<QLocalSocket> localSocket;
|
||||
};
|
||||
|
||||
QMap<int, QSharedPointer<ProcessDescriptor>> m_processNodes;
|
||||
};
|
||||
|
||||
#endif // IPCCLIENT_H
|
||||
|
|
|
@ -195,6 +195,12 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
|||
return connData;
|
||||
}
|
||||
|
||||
Settings &OpenVpnConfigurator::m_settings()
|
||||
{
|
||||
static Settings s;
|
||||
return s;
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials,
|
||||
Protocol proto, ErrorCode *errorCode)
|
||||
{
|
||||
|
@ -217,6 +223,13 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
|||
config.replace("$LOCAL_PROXY_PORT", QString::number(ServerController::ssContainerPort()));
|
||||
}
|
||||
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
if (m_settings().customRouting()) {
|
||||
config.replace("redirect-gateway def1 bypass-dhcp", "");
|
||||
}
|
||||
|
||||
config.replace("$REMOTE_HOST", connData.host);
|
||||
config.replace("$REMOTE_PORT", "1194");
|
||||
config.replace("$CA_CERT", connData.caCert);
|
||||
|
@ -224,5 +237,6 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
|||
config.replace("$PRIV_KEY", connData.privKey);
|
||||
config.replace("$TA_KEY", connData.taKey);
|
||||
|
||||
//qDebug().noquote() << config;
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QProcessEnvironment>
|
||||
|
||||
#include "defs.h"
|
||||
#include "settings.h"
|
||||
#include "servercontroller.h"
|
||||
|
||||
|
||||
|
@ -37,6 +38,8 @@ private:
|
|||
|
||||
static ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials,
|
||||
Protocol proto, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static Settings &m_settings();
|
||||
};
|
||||
|
||||
#endif // OPENVPNCONFIGURATOR_H
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QTimer>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QApplication>
|
||||
|
||||
#include "sshconnectionmanager.h"
|
||||
|
||||
|
@ -23,7 +24,9 @@ QString ServerController::getContainerName(DockerContainer container)
|
|||
}
|
||||
|
||||
ErrorCode ServerController::runScript(DockerContainer container,
|
||||
const SshConnectionParameters &sshParams, QString script)
|
||||
const SshConnectionParameters &sshParams, QString script,
|
||||
const std::function<void(const QString &)> &cbReadStdOut,
|
||||
const std::function<void(const QString &)> &cbReadStdErr)
|
||||
{
|
||||
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
|
||||
|
||||
|
@ -66,18 +69,20 @@ ErrorCode ServerController::runScript(DockerContainer container,
|
|||
wait.quit();
|
||||
});
|
||||
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, &wait, [proc, cbReadStdOut](){
|
||||
QString s = proc->readAllStandardOutput();
|
||||
if (s != "." && !s.isEmpty()) {
|
||||
qDebug().noquote() << s;
|
||||
qDebug().noquote() << "stdout" << s;
|
||||
}
|
||||
if (cbReadStdOut) cbReadStdOut(s);
|
||||
});
|
||||
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, [proc](){
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, &wait, [proc, cbReadStdErr](){
|
||||
QString s = proc->readAllStandardError();
|
||||
if (s != "." && !s.isEmpty()) {
|
||||
qDebug().noquote() << s;
|
||||
qDebug().noquote() << "stderr" << s;
|
||||
}
|
||||
if (cbReadStdErr) cbReadStdErr(s);
|
||||
});
|
||||
|
||||
proc->start();
|
||||
|
@ -272,11 +277,12 @@ ErrorCode ServerController::removeServer(const ServerCredentials &credentials, P
|
|||
QString scriptFileName;
|
||||
DockerContainer container;
|
||||
|
||||
ErrorCode errorCode;
|
||||
if (proto == Protocol::Any) {
|
||||
removeServer(credentials, Protocol::OpenVpn);
|
||||
removeServer(credentials, Protocol::ShadowSocks);
|
||||
return ErrorCode::NoError;
|
||||
ErrorCode e = removeServer(credentials, Protocol::OpenVpn);
|
||||
if (e) {
|
||||
return e;
|
||||
}
|
||||
return removeServer(credentials, Protocol::ShadowSocks);
|
||||
}
|
||||
else if (proto == Protocol::OpenVpn) {
|
||||
scriptFileName = ":/server_scripts/remove_container.sh";
|
||||
|
@ -309,14 +315,14 @@ ErrorCode ServerController::setupServer(const ServerCredentials &credentials, Pr
|
|||
return setupShadowSocksServer(credentials);
|
||||
}
|
||||
else if (proto == Protocol::Any) {
|
||||
return ErrorCode::NotImplementedError;
|
||||
//return ErrorCode::NotImplementedError;
|
||||
|
||||
// TODO: run concurently
|
||||
// return setupOpenVpnServer(credentials);
|
||||
//setupShadowSocksServer(credentials);
|
||||
setupOpenVpnServer(credentials);
|
||||
setupShadowSocksServer(credentials);
|
||||
}
|
||||
|
||||
return ErrorCode::NotImplementedError;
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credentials)
|
||||
|
@ -329,8 +335,20 @@ ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credenti
|
|||
scriptData = file.readAll();
|
||||
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
|
||||
ErrorCode e = runScript(DockerContainer::OpenVpn, sshParams(credentials), scriptData);
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
auto cbReadStdErr = [&](const QString &data) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
ErrorCode e = runScript(DockerContainer::OpenVpn, sshParams(credentials), scriptData, cbReadStdOut, cbReadStdErr);
|
||||
if (e) return e;
|
||||
QApplication::processEvents();
|
||||
|
||||
if (stdOut.contains("port is already allocated")) return ErrorCode::ServerPortAlreadyAllocatedError;
|
||||
if (stdOut.contains("Error response from daemon")) return ErrorCode::ServerCheckFailed;
|
||||
|
||||
return checkOpenVpnServer(DockerContainer::OpenVpn, credentials);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,9 @@ public:
|
|||
private:
|
||||
static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
||||
static ErrorCode runScript(DockerContainer container,
|
||||
const QSsh::SshConnectionParameters &sshParams, QString script);
|
||||
const QSsh::SshConnectionParameters &sshParams, QString script,
|
||||
const std::function<void(const QString &)> &cbReadStdOut = nullptr,
|
||||
const std::function<void(const QString &)> &cbReadStdErr = nullptr);
|
||||
|
||||
static ErrorCode setupOpenVpnServer(const ServerCredentials &credentials);
|
||||
static ErrorCode setupShadowSocksServer(const ServerCredentials &credentials);
|
||||
|
|
|
@ -54,8 +54,7 @@ void ManagementServer::onNewConnection()
|
|||
|
||||
void ManagementServer::onSocketError(QAbstractSocket::SocketError socketError)
|
||||
{
|
||||
Q_UNUSED(socketError);
|
||||
|
||||
Q_UNUSED(socketError)
|
||||
qDebug().noquote() << QString("Mananement server error: %1").arg(m_socket->errorString());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
#include "message.h"
|
||||
|
||||
Message::Message(State state, const QStringList& args) :
|
||||
m_valid(true),
|
||||
m_state(state),
|
||||
m_args(args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Message::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
QString Message::textState() const
|
||||
{
|
||||
switch (m_state) {
|
||||
case State::Unknown: return "Unknown";
|
||||
case State::Initialize: return "Initialize";
|
||||
case State::StartRequest: return "StartRequest";
|
||||
case State::Started: return "Started";
|
||||
case State::FinishRequest: return "FinishRequest";
|
||||
case State::Finished: return "Finished";
|
||||
case State::RoutesAddRequest: return "RoutesAddRequest";
|
||||
case State::RouteDeleteRequest: return "RouteDeleteRequest";
|
||||
case State::ClearSavedRoutesRequest: return "ClearSavedRoutesRequest";
|
||||
case State::FlushDnsRequest: return "FlushDnsRequest";
|
||||
case State::InstallDriverRequest: return "InstallDriverRequest";
|
||||
default:
|
||||
;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString Message::rawData() const
|
||||
{
|
||||
return m_rawData;
|
||||
}
|
||||
|
||||
Message::State Message::state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
QString Message::toString() const
|
||||
{
|
||||
if (!isValid()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString("%1%2%3")
|
||||
.arg(textState())
|
||||
.arg(m_dataSeparator)
|
||||
.arg(argsToString());
|
||||
}
|
||||
|
||||
QString Message::argAtIndex(int index) const
|
||||
{
|
||||
if ((index + 1) > args().size()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return args().at(index);
|
||||
}
|
||||
|
||||
QStringList Message::args() const
|
||||
{
|
||||
return m_args;
|
||||
}
|
||||
|
||||
QString Message::argsToString() const
|
||||
{
|
||||
return m_args.join(m_argSeparator);
|
||||
}
|
||||
|
||||
Message::Message(const QString& data)
|
||||
{
|
||||
m_rawData = data;
|
||||
m_valid = false;
|
||||
if (data.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList dataList = data.split(m_dataSeparator);
|
||||
if ((dataList.size() != 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool stateFound = false;
|
||||
for (int i = static_cast<int>(State::Unknown); i <= static_cast<int>(State::InstallDriverRequest); i++ ) {
|
||||
m_state = static_cast<State>(i);
|
||||
if (textState() == dataList.at(0)) {
|
||||
stateFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateFound) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_args = dataList.at(1).split(m_argSeparator);
|
||||
m_valid = true;
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#ifndef MESSAGE_H
|
||||
#define MESSAGE_H
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
class Message {
|
||||
|
||||
public:
|
||||
enum class State {Unknown, Initialize, StartRequest, Started, FinishRequest, Finished,
|
||||
RoutesAddRequest, RouteDeleteRequest, ClearSavedRoutesRequest, FlushDnsRequest, InstallDriverRequest};
|
||||
Message(State state, const QStringList& args);
|
||||
Message(const QString& data);
|
||||
|
||||
QString argAtIndex(int index) const;
|
||||
QString argsToString() const;
|
||||
QString toString() const;
|
||||
QStringList args() const;
|
||||
State state() const;
|
||||
bool isValid() const;
|
||||
QString rawData() const;
|
||||
|
||||
protected:
|
||||
QString textState() const;
|
||||
|
||||
const QString m_argSeparator = ",";
|
||||
const QString m_dataSeparator = "|";
|
||||
|
||||
bool m_valid;
|
||||
State m_state;
|
||||
QStringList m_args;
|
||||
QString m_rawData;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_H
|
|
@ -9,13 +9,10 @@
|
|||
#include "openvpnprotocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
OpenVpnProtocol::OpenVpnProtocol(const QString& args, QObject* parent) :
|
||||
VpnProtocol(args, parent)
|
||||
//m_requestFromUserToStop(false)
|
||||
OpenVpnProtocol::OpenVpnProtocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
setConfigFile(args);
|
||||
//connect(m_communicator, &Communicator::messageReceived, this, &OpenVpnProtocol::onMessageReceived);
|
||||
readOpenVpnConfiguration(configuration);
|
||||
connect(&m_managementServer, &ManagementServer::readyRead, this, &OpenVpnProtocol::onReadyReadDataFromManagementServer);
|
||||
}
|
||||
|
||||
|
@ -25,35 +22,14 @@ OpenVpnProtocol::~OpenVpnProtocol()
|
|||
OpenVpnProtocol::stop();
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::onMessageReceived(const Message& message)
|
||||
{
|
||||
if (!message.isValid()) {
|
||||
qWarning().noquote() << QString("Message received: '%1', but it is not valid").arg(message.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.state()) {
|
||||
case Message::State::Started:
|
||||
qDebug() << "OpenVPN process started";
|
||||
break;
|
||||
case Message::State::Finished:
|
||||
qDebug().noquote() << QString("OpenVPN process finished with status %1").arg(message.argAtIndex(1));
|
||||
onOpenVpnProcessFinished(message.argAtIndex(1).toInt());
|
||||
break;
|
||||
default:
|
||||
qDebug().noquote() << QString("Message received: '%1'").arg(message.toString());
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::stop()
|
||||
{
|
||||
// TODO: need refactoring
|
||||
// sendTermSignal() will evet return true while server connected
|
||||
// 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::TunnelReconnecting)) {
|
||||
(m_connectionState == VpnProtocol::ConnectionState::Reconnecting)) {
|
||||
if (!sendTermSignal()) {
|
||||
killOpenVpnProcess();
|
||||
}
|
||||
|
@ -61,27 +37,51 @@ void OpenVpnProtocol::stop()
|
|||
}
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::killOpenVpnProcess()
|
||||
ErrorCode OpenVpnProtocol::checkAndSetupTapDriver()
|
||||
{
|
||||
// send command to kill openvpn process (if any).
|
||||
if (!IpcClient::Interface()) {
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
QRemoteObjectPendingReply<QStringList> resultCheck = IpcClient::Interface()->getTapList();
|
||||
resultCheck.waitForFinished();
|
||||
|
||||
if (resultCheck.returnValue().isEmpty()){
|
||||
QRemoteObjectPendingReply<bool> resultInstall = IpcClient::Interface()->checkAndInstallDriver();
|
||||
resultInstall.waitForFinished();
|
||||
|
||||
if (!resultInstall.returnValue()) return ErrorCode::OpenVpnUnknownError;
|
||||
}
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
bool OpenVpnProtocol::setConfigFile(const QString& configFileNamePath)
|
||||
void OpenVpnProtocol::killOpenVpnProcess()
|
||||
{
|
||||
m_configFileName = configFileNamePath;
|
||||
QFileInfo file(m_configFileName);
|
||||
|
||||
if (file.fileName().isEmpty()) {
|
||||
m_configFileName = Utils::defaultVpnConfigFileName();
|
||||
if (m_openVpnProcess){
|
||||
m_openVpnProcess->close();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_configFileName.isEmpty()) {
|
||||
return false;
|
||||
void OpenVpnProtocol::readOpenVpnConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
if (configuration.contains(config::key_openvpn_config_data())) {
|
||||
m_configFile.open();
|
||||
m_configFile.write(configuration.value(config::key_openvpn_config_data()).toString().toUtf8());
|
||||
m_configFile.close();
|
||||
m_configFileName = m_configFile.fileName();
|
||||
|
||||
qDebug().noquote() << QString("Set config data") << m_configFileName;
|
||||
}
|
||||
else if (configuration.contains(config::key_openvpn_config_path())) {
|
||||
m_configFileName = configuration.value(config::key_openvpn_config_path()).toString();
|
||||
QFileInfo file(m_configFileName);
|
||||
|
||||
qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
if (file.fileName().isEmpty()) {
|
||||
m_configFileName = Utils::defaultVpnConfigFileName();
|
||||
}
|
||||
|
||||
return false;
|
||||
qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenVpnProtocol::openVpnProcessIsRunning() const
|
||||
|
@ -99,7 +99,7 @@ QString OpenVpnProtocol::configPath() const
|
|||
return m_configFileName;
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::writeCommand(const QString& command)
|
||||
void OpenVpnProtocol::sendManagementCommand(const QString& command)
|
||||
{
|
||||
QIODevice *device = dynamic_cast<QIODevice*>(m_managementServer.socket().data());
|
||||
if (device) {
|
||||
|
@ -128,17 +128,9 @@ QString OpenVpnProtocol::openVpnExecPath() const
|
|||
|
||||
ErrorCode OpenVpnProtocol::start()
|
||||
{
|
||||
qDebug() << "Start OpenVPN connection";
|
||||
|
||||
//m_requestFromUserToStop = false;
|
||||
m_openVpnStateSigTermHandlerTimer.stop();
|
||||
//qDebug() << "Start OpenVPN connection";
|
||||
OpenVpnProtocol::stop();
|
||||
|
||||
// if (communicator() && !communicator()->isConnected()) {
|
||||
// setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
// return lastError();
|
||||
// }
|
||||
|
||||
if (!QFileInfo::exists(openVpnExecPath())) {
|
||||
setLastError(ErrorCode::OpenVpnExecutableMissing);
|
||||
return lastError();
|
||||
|
@ -152,13 +144,6 @@ ErrorCode OpenVpnProtocol::start()
|
|||
QString vpnLogFileNamePath = Utils::systemLogPath() + "/openvpn.log";
|
||||
Utils::createEmptyFile(vpnLogFileNamePath);
|
||||
|
||||
QStringList args({openVpnExecPath(),
|
||||
"--config" , configPath(),
|
||||
"--management", m_managementHost, QString::number(m_managementPort),
|
||||
"--management-client",
|
||||
"--log-append", vpnLogFileNamePath
|
||||
});
|
||||
|
||||
if (!m_managementServer.start(m_managementHost, m_managementPort)) {
|
||||
setLastError(ErrorCode::OpenVpnManagementServerError);
|
||||
return lastError();
|
||||
|
@ -166,16 +151,18 @@ ErrorCode OpenVpnProtocol::start()
|
|||
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
|
||||
m_openVpnProcess = IpcClient::createPrivilegedProcess();
|
||||
m_openVpnProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
if (!m_openVpnProcess) {
|
||||
qWarning() << "IpcProcess replica is not created!";
|
||||
//qWarning() << "IpcProcess replica is not created!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
m_openVpnProcess->waitForSource(1000);
|
||||
if (!m_openVpnProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
m_openVpnProcess->setProgram(openVpnExecPath());
|
||||
|
@ -195,6 +182,10 @@ ErrorCode OpenVpnProtocol::start()
|
|||
qDebug() << "IpcProcessInterfaceReplica stateChanged" << newState;
|
||||
});
|
||||
|
||||
connect(m_openVpnProcess.data(), &IpcProcessInterfaceReplica::finished, this, [&]() {
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
});
|
||||
|
||||
m_openVpnProcess->start();
|
||||
|
||||
//m_communicator->sendMessage(Message(Message::State::StartRequest, args));
|
||||
|
@ -203,20 +194,6 @@ ErrorCode OpenVpnProtocol::start()
|
|||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::openVpnStateSigTermHandlerTimerEvent()
|
||||
{
|
||||
bool processStatus = openVpnProcessIsRunning();
|
||||
if (processStatus) {
|
||||
killOpenVpnProcess();
|
||||
}
|
||||
onOpenVpnProcessFinished(0);
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::openVpnStateSigTermHandler()
|
||||
{
|
||||
m_openVpnStateSigTermHandlerTimer.start(5000);
|
||||
}
|
||||
|
||||
bool OpenVpnProtocol::sendTermSignal()
|
||||
{
|
||||
return m_managementServer.writeCommand("signal SIGTERM");
|
||||
|
@ -256,10 +233,11 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
|
|||
setConnectionState(VpnProtocol::ConnectionState::Connected);
|
||||
continue;
|
||||
} else if (line.contains("EXITING,SIGTER")) {
|
||||
openVpnStateSigTermHandler();
|
||||
//openVpnStateSigTermHandler();
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnecting);
|
||||
continue;
|
||||
} else if (line.contains("RECONNECTING")) {
|
||||
setConnectionState(VpnProtocol::ConnectionState::TunnelReconnecting);
|
||||
setConnectionState(VpnProtocol::ConnectionState::Reconnecting);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -294,19 +272,6 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
|
|||
}
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::onOpenVpnProcessFinished(int exitCode)
|
||||
{
|
||||
m_openVpnStateSigTermHandlerTimer.stop();
|
||||
if (m_connectionState == VpnProtocol::ConnectionState::Disconnected) {
|
||||
qDebug() << "Already in disconnected state";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug().noquote() << QString("Process finished with code: %1").arg(exitCode);
|
||||
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnected);
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::updateVpnGateway()
|
||||
{
|
||||
QProcess ipconfig;
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <QTimer>
|
||||
|
||||
#include "managementserver.h"
|
||||
#include "message.h"
|
||||
#include "vpnprotocol.h"
|
||||
|
||||
#include "core/ipcclient.h"
|
||||
|
@ -16,39 +15,35 @@ class OpenVpnProtocol : public VpnProtocol
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OpenVpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||
explicit OpenVpnProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~OpenVpnProtocol() override;
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
ErrorCode checkAndSetupTapDriver();
|
||||
|
||||
protected slots:
|
||||
void onMessageReceived(const Message& message);
|
||||
void onOpenVpnProcessFinished(int exitCode);
|
||||
void onReadyReadDataFromManagementServer();
|
||||
|
||||
protected:
|
||||
private:
|
||||
QString configPath() const;
|
||||
QString openVpnExecPath() const;
|
||||
bool openVpnProcessIsRunning() const;
|
||||
bool sendTermSignal();
|
||||
bool setConfigFile(const QString& configFileNamePath);
|
||||
void readOpenVpnConfiguration(const QJsonObject &configuration);
|
||||
void disconnectFromManagementServer();
|
||||
void killOpenVpnProcess();
|
||||
void openVpnStateSigTermHandler();
|
||||
void openVpnStateSigTermHandlerTimerEvent();
|
||||
void sendByteCount();
|
||||
void sendInitialData();
|
||||
void writeCommand(const QString& command);
|
||||
void sendManagementCommand(const QString& command);
|
||||
|
||||
const QString m_managementHost = "127.0.0.1";
|
||||
const unsigned int m_managementPort = 57775;
|
||||
|
||||
ManagementServer m_managementServer;
|
||||
QString m_configFileName;
|
||||
QTimer m_openVpnStateSigTermHandlerTimer;
|
||||
//bool m_requestFromUserToStop;
|
||||
|
||||
QTemporaryFile m_configFile;
|
||||
|
||||
private:
|
||||
void updateRouteGateway(QString line);
|
||||
|
|
|
@ -8,31 +8,34 @@
|
|||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
ShadowSocksVpnProtocol::ShadowSocksVpnProtocol(const QString &args, QObject *parent):
|
||||
OpenVpnProtocol(args, parent)
|
||||
ShadowSocksVpnProtocol::ShadowSocksVpnProtocol(const QJsonObject &configuration, QObject *parent):
|
||||
OpenVpnProtocol(configuration, parent)
|
||||
{
|
||||
m_shadowSocksConfig = args;
|
||||
readShadowSocksConfiguration(configuration);
|
||||
}
|
||||
|
||||
ErrorCode ShadowSocksVpnProtocol::start()
|
||||
{
|
||||
qDebug() << "ShadowSocksVpnProtocol::start()";
|
||||
QJsonObject config = QJsonDocument::fromJson(m_shadowSocksConfig.toUtf8()).object();
|
||||
|
||||
ssProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
m_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()
|
||||
m_ssProcess.setProgram(shadowSocksExecPath());
|
||||
m_ssProcess.setArguments(QStringList() << "-s" << m_shadowSocksConfig.value("server").toString()
|
||||
<< "-p" << QString::number(m_shadowSocksConfig.value("server_port").toInt())
|
||||
<< "-l" << QString::number(m_shadowSocksConfig.value("local_port").toInt())
|
||||
<< "-m" << m_shadowSocksConfig.value("method").toString()
|
||||
<< "-k" << m_shadowSocksConfig.value("password").toString()
|
||||
);
|
||||
|
||||
ssProcess.start();
|
||||
ssProcess.waitForStarted();
|
||||
connect(&m_ssProcess, &QProcess::readyRead, this, [this](){
|
||||
qDebug().noquote() << m_ssProcess.readAll();
|
||||
});
|
||||
|
||||
if (ssProcess.state() == QProcess::ProcessState::Running) {
|
||||
m_ssProcess.start();
|
||||
m_ssProcess.waitForStarted();
|
||||
|
||||
if (m_ssProcess.state() == QProcess::ProcessState::Running) {
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
|
||||
return OpenVpnProtocol::start();
|
||||
|
@ -42,8 +45,10 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
|||
|
||||
void ShadowSocksVpnProtocol::stop()
|
||||
{
|
||||
OpenVpnProtocol::stop();
|
||||
|
||||
qDebug() << "ShadowSocksVpnProtocol::stop()";
|
||||
ssProcess.kill();
|
||||
m_ssProcess.close();
|
||||
}
|
||||
|
||||
QString ShadowSocksVpnProtocol::shadowSocksExecPath() const
|
||||
|
@ -55,7 +60,7 @@ QString ShadowSocksVpnProtocol::shadowSocksExecPath() const
|
|||
#endif
|
||||
}
|
||||
|
||||
QString ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto)
|
||||
QJsonObject ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto)
|
||||
{
|
||||
QJsonObject ssConfig;
|
||||
ssConfig.insert("server", credentials.hostName);
|
||||
|
@ -64,5 +69,10 @@ QString ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &cr
|
|||
ssConfig.insert("password", credentials.password);
|
||||
ssConfig.insert("timeout", 60);
|
||||
ssConfig.insert("method", ServerController::ssEncryption());
|
||||
return QJsonDocument(ssConfig).toJson();
|
||||
return ssConfig;
|
||||
}
|
||||
|
||||
void ShadowSocksVpnProtocol::readShadowSocksConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
m_shadowSocksConfig = configuration.value(config::key_shadowsocks_config_data()).toObject();
|
||||
}
|
||||
|
|
|
@ -7,21 +7,22 @@
|
|||
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
||||
{
|
||||
public:
|
||||
ShadowSocksVpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||
ShadowSocksVpnProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
static QString genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto = Protocol::ShadowSocks);
|
||||
static QJsonObject genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto = Protocol::ShadowSocks);
|
||||
|
||||
protected:
|
||||
void readShadowSocksConfiguration(const QJsonObject &configuration);
|
||||
QString shadowSocksExecPath() const;
|
||||
|
||||
protected:
|
||||
QString m_shadowSocksConfig;
|
||||
QJsonObject m_shadowSocksConfig;
|
||||
|
||||
private:
|
||||
QProcess ssProcess;
|
||||
QProcess m_ssProcess;
|
||||
};
|
||||
|
||||
#endif // SHADOWSOCKSVPNPROTOCOL_H
|
||||
|
|
|
@ -1,42 +1,26 @@
|
|||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
//#include "communicator.h"
|
||||
#include "vpnprotocol.h"
|
||||
#include "core/errorstrings.h"
|
||||
|
||||
//Communicator* VpnProtocol::m_communicator = nullptr;
|
||||
|
||||
VpnProtocol::VpnProtocol(const QString& args, QObject* parent)
|
||||
VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject* parent)
|
||||
: QObject(parent),
|
||||
m_connectionState(ConnectionState::Unknown),
|
||||
m_rawConfig(configuration),
|
||||
m_timeoutTimer(new QTimer(this)),
|
||||
m_receivedBytes(0),
|
||||
m_sentBytes(0)
|
||||
{
|
||||
m_timeoutTimer->setSingleShot(true);
|
||||
connect(m_timeoutTimer, &QTimer::timeout, this, &VpnProtocol::onTimeout);
|
||||
|
||||
Q_UNUSED(args)
|
||||
}
|
||||
|
||||
//void VpnProtocol::initializeCommunicator(QObject* parent)
|
||||
//{
|
||||
// if (!m_communicator) {
|
||||
// m_communicator = new Communicator(parent);
|
||||
// }
|
||||
//}
|
||||
|
||||
//Communicator* VpnProtocol::communicator()
|
||||
//{
|
||||
// return m_communicator;
|
||||
//}
|
||||
|
||||
void VpnProtocol::setLastError(ErrorCode lastError)
|
||||
{
|
||||
m_lastError = lastError;
|
||||
if (lastError){
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
setConnectionState(ConnectionState::Error);
|
||||
}
|
||||
qCritical().noquote() << "VpnProtocol error, code" << m_lastError << errorString(m_lastError);
|
||||
}
|
||||
|
@ -79,9 +63,14 @@ void VpnProtocol::setBytesChanged(quint64 receivedBytes, quint64 sentBytes)
|
|||
|
||||
void VpnProtocol::setConnectionState(VpnProtocol::ConnectionState state)
|
||||
{
|
||||
qDebug() << "VpnProtocol::setConnectionState" << textConnectionState(state);
|
||||
|
||||
if (m_connectionState == state) {
|
||||
return;
|
||||
}
|
||||
if (m_connectionState == ConnectionState::Disconnected && state == ConnectionState::Disconnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_connectionState = state;
|
||||
if (m_connectionState == ConnectionState::Disconnected) {
|
||||
|
@ -113,7 +102,7 @@ QString VpnProtocol::textConnectionState(ConnectionState connectionState)
|
|||
case ConnectionState::Connecting: return tr("Connecting...");
|
||||
case ConnectionState::Connected: return tr("Connected");
|
||||
case ConnectionState::Disconnecting: return tr("Disconnecting...");
|
||||
case ConnectionState::TunnelReconnecting: return tr("Reconnecting...");
|
||||
case ConnectionState::Reconnecting: return tr("Reconnecting...");
|
||||
case ConnectionState::Error: return tr("Error");
|
||||
default:
|
||||
;
|
||||
|
@ -127,12 +116,12 @@ QString VpnProtocol::textConnectionState() const
|
|||
return textConnectionState(m_connectionState);
|
||||
}
|
||||
|
||||
bool VpnProtocol::onConnected() const
|
||||
bool VpnProtocol::isConnected() const
|
||||
{
|
||||
return m_connectionState == ConnectionState::Connected;
|
||||
}
|
||||
|
||||
bool VpnProtocol::onDisconnected() const
|
||||
bool VpnProtocol::isDisconnected() const
|
||||
{
|
||||
return m_connectionState == ConnectionState::Disconnected;
|
||||
}
|
||||
|
|
|
@ -3,30 +3,29 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/defs.h"
|
||||
using namespace amnezia;
|
||||
|
||||
class QTimer;
|
||||
class Communicator;
|
||||
|
||||
class VpnProtocol : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||
explicit VpnProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~VpnProtocol() override = default;
|
||||
|
||||
enum class ConnectionState {Unknown, Disconnected, Preparing, Connecting, Connected, Disconnecting, TunnelReconnecting, Error};
|
||||
enum ConnectionState {Unknown, Disconnected, Preparing, Connecting, Connected, Disconnecting, Reconnecting, Error};
|
||||
Q_ENUM(ConnectionState)
|
||||
|
||||
static Communicator* communicator();
|
||||
static QString textConnectionState(ConnectionState connectionState);
|
||||
//static void initializeCommunicator(QObject* parent = nullptr);
|
||||
|
||||
|
||||
virtual bool onConnected() const;
|
||||
virtual bool onDisconnected() const;
|
||||
virtual bool isConnected() const;
|
||||
virtual bool isDisconnected() const;
|
||||
virtual ErrorCode start() = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
|
@ -54,18 +53,17 @@ protected:
|
|||
virtual void setBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
virtual void setConnectionState(VpnProtocol::ConnectionState state);
|
||||
|
||||
//static Communicator* m_communicator;
|
||||
|
||||
ConnectionState m_connectionState;
|
||||
QString m_routeGateway;
|
||||
QString m_vpnGateway;
|
||||
|
||||
QJsonObject m_rawConfig;
|
||||
|
||||
private:
|
||||
QTimer* m_timeoutTimer;
|
||||
ErrorCode m_lastError;
|
||||
quint64 m_receivedBytes;
|
||||
quint64 m_sentBytes;
|
||||
|
||||
};
|
||||
|
||||
#endif // VPNPROTOCOL_H
|
||||
|
|
|
@ -12,6 +12,11 @@ tls-client
|
|||
tls-version-min 1.2
|
||||
key-direction 1
|
||||
remote-cert-tls server
|
||||
redirect-gateway def1 bypass-dhcp
|
||||
|
||||
dhcp-option DNS $PRIMARY_DNS
|
||||
dhcp-option DNS $SECONDARY_DNS
|
||||
block-outside-dns
|
||||
|
||||
remote $REMOTE_HOST $REMOTE_PORT
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ tls-client
|
|||
tls-version-min 1.2
|
||||
key-direction 1
|
||||
remote-cert-tls server
|
||||
redirect-gateway def1 bypass-dhcp
|
||||
|
||||
dhcp-option DNS $PRIMARY_DNS
|
||||
dhcp-option DNS $SECONDARY_DNS
|
||||
block-outside-dns
|
||||
|
||||
socks-proxy 127.0.0.1 $LOCAL_PROXY_PORT
|
||||
route $REMOTE_HOST 255.255.255.255 net_gateway
|
||||
|
|
|
@ -6,27 +6,6 @@ Settings::Settings(QObject* parent) :
|
|||
QObject(parent),
|
||||
m_settings (ORGANIZATION_NAME, APPLICATION_NAME, this)
|
||||
{
|
||||
read();
|
||||
}
|
||||
|
||||
void Settings::read()
|
||||
{
|
||||
m_settings.beginGroup("Server");
|
||||
m_userName = m_settings.value("userName", QString()).toString();
|
||||
m_password = m_settings.value("password", QString()).toString();
|
||||
m_serverName = m_settings.value("serverName", QString()).toString();
|
||||
m_serverPort = m_settings.value("serverPort", 22).toInt();
|
||||
m_settings.endGroup();
|
||||
}
|
||||
|
||||
void Settings::save()
|
||||
{
|
||||
m_settings.beginGroup("Server");
|
||||
m_settings.setValue("userName", m_userName);
|
||||
m_settings.setValue("password", m_password);
|
||||
m_settings.setValue("serverName", m_serverName);
|
||||
m_settings.setValue("serverPort", m_serverPort);
|
||||
m_settings.endGroup();
|
||||
}
|
||||
|
||||
bool Settings::haveAuthData() const
|
||||
|
@ -34,26 +13,6 @@ bool Settings::haveAuthData() const
|
|||
return (!serverName().isEmpty() && !userName().isEmpty() && !password().isEmpty());
|
||||
}
|
||||
|
||||
void Settings::setUserName(const QString& login)
|
||||
{
|
||||
m_userName = login;
|
||||
}
|
||||
|
||||
void Settings::setPassword(const QString& password)
|
||||
{
|
||||
m_password = password;
|
||||
}
|
||||
|
||||
void Settings::setServerName(const QString& serverName)
|
||||
{
|
||||
m_serverName = serverName;
|
||||
}
|
||||
|
||||
void Settings::setServerPort(int serverPort)
|
||||
{
|
||||
m_serverPort = serverPort;
|
||||
}
|
||||
|
||||
void Settings::setServerCredentials(const ServerCredentials &credentials)
|
||||
{
|
||||
setServerName(credentials.hostName);
|
||||
|
|
|
@ -18,40 +18,50 @@ class Settings : public QObject
|
|||
public:
|
||||
explicit Settings(QObject* parent = nullptr);
|
||||
|
||||
void read();
|
||||
void save();
|
||||
QString userName() const { return m_settings.value("Server/userName", QString()).toString(); }
|
||||
void setUserName(const QString& login) { m_settings.setValue("Server/userName", login); }
|
||||
|
||||
void setUserName(const QString& login);
|
||||
void setPassword(const QString& password);
|
||||
void setServerName(const QString& serverName);
|
||||
void setServerPort(int serverPort = 22);
|
||||
void setServerCredentials(const ServerCredentials &credentials);
|
||||
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); }
|
||||
|
||||
QString userName() const { return m_userName; }
|
||||
QString password() const { return m_password; }
|
||||
QString serverName() const { return m_serverName; }
|
||||
int serverPort() const { return m_serverPort; }
|
||||
ServerCredentials serverCredentials();
|
||||
|
||||
|
||||
void setServerCredentials(const ServerCredentials &credentials);
|
||||
bool haveAuthData() const;
|
||||
|
||||
bool customRouting() const { return m_settings.value("Conf/customRouting", false).toBool(); }
|
||||
void setCustomRouting(bool customRouting) { m_settings.setValue("Conf/customRouting", customRouting); }
|
||||
|
||||
// list of sites to pass blocking added by user
|
||||
QStringList customSites() { return m_settings.value("customSites").toStringList(); }
|
||||
void setCustomSites(const QStringList &customSites) { m_settings.setValue("customSites", customSites); }
|
||||
QStringList customSites() { return m_settings.value("Conf/customSites").toStringList(); }
|
||||
void setCustomSites(const QStringList &customSites) { m_settings.setValue("Conf/customSites", customSites); }
|
||||
|
||||
// list of ips to pass blocking generated from customSites
|
||||
QStringList customIps() { return m_settings.value("customIps").toStringList(); }
|
||||
void setCustomIps(const QStringList &customIps) { m_settings.setValue("customIps", customIps); }
|
||||
QStringList customIps() { return m_settings.value("Conf/customIps").toStringList(); }
|
||||
void setCustomIps(const QStringList &customIps) { m_settings.setValue("Conf/customIps", customIps); }
|
||||
|
||||
QString primaryDns() const { return m_settings.value("Conf/primaryDns", cloudFlareNs1()).toString(); }
|
||||
QString secondaryDns() const { return m_settings.value("Conf/secondaryDns", cloudFlareNs2()).toString(); }
|
||||
|
||||
protected:
|
||||
//QString primaryDns() const { return m_primaryDns; }
|
||||
void setPrimaryDns(const QString &primaryDns) { m_settings.setValue("Conf/primaryDns", primaryDns); }
|
||||
|
||||
//QString secondaryDns() const { return m_secondaryDns; }
|
||||
void setSecondaryDns(const QString &secondaryDns) { m_settings.setValue("Conf/secondaryDns", secondaryDns); }
|
||||
|
||||
QString cloudFlareNs1() const { return "1.1.1.1"; }
|
||||
QString cloudFlareNs2() const { return "1.0.0.1"; }
|
||||
|
||||
QString openNicNs5() const { return "94.103.153.176"; }
|
||||
QString openNicNs13() const { return "144.76.103.143"; }
|
||||
|
||||
private:
|
||||
QSettings m_settings;
|
||||
QString m_userName;
|
||||
QString m_password;
|
||||
QString m_serverName;
|
||||
int m_serverPort;
|
||||
};
|
||||
|
||||
#endif // SETTINGS_H
|
||||
|
|
|
@ -71,9 +71,9 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
ui->pushButton_sites_add_custom->click();
|
||||
});
|
||||
|
||||
initCustomSites();
|
||||
updateSettings();
|
||||
|
||||
ui->pushButton_general_settings_exit->hide();
|
||||
//ui->pushButton_general_settings_exit->hide();
|
||||
//ui->pushButton_share_connection->hide();
|
||||
|
||||
setFixedSize(width(),height());
|
||||
|
@ -101,7 +101,7 @@ MainWindow::~MainWindow()
|
|||
for (int i = 0; i < 50; i++) {
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
QThread::msleep(100);
|
||||
if (m_vpnConnection->onDisconnected()) {
|
||||
if (m_vpnConnection->isDisconnected()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +249,6 @@ void MainWindow::onPushButtonNewServerConnectWithNewData(bool)
|
|||
|
||||
if (ok) {
|
||||
m_settings.setServerCredentials(serverCredentials);
|
||||
m_settings.save();
|
||||
|
||||
goToPage(Page::Vpn);
|
||||
qApp->processEvents();
|
||||
|
@ -272,7 +271,6 @@ void MainWindow::onPushButtonNewServerConnectWithExistingCode(bool)
|
|||
credentials.password = o.value("w").toString();
|
||||
|
||||
m_settings.setServerCredentials(credentials);
|
||||
m_settings.save();
|
||||
|
||||
goToPage(Page::Vpn);
|
||||
qDebug() << QString("Added server %3@%1:%2").
|
||||
|
@ -299,7 +297,7 @@ bool MainWindow::installServer(ServerCredentials credentials,
|
|||
timer.start(1000);
|
||||
|
||||
|
||||
ErrorCode e = ServerController::setupServer(credentials, Protocol::OpenVpn);
|
||||
ErrorCode e = ServerController::setupServer(credentials, Protocol::Any);
|
||||
if (e) {
|
||||
page->setEnabled(true);
|
||||
button->setVisible(true);
|
||||
|
@ -377,14 +375,11 @@ void MainWindow::onPushButtonForgetServer(bool)
|
|||
m_settings.setServerName("");
|
||||
m_settings.setServerPort();
|
||||
|
||||
m_settings.save();
|
||||
|
||||
goToPage(Page::Start);
|
||||
}
|
||||
|
||||
void MainWindow::onBytesChanged(quint64 receivedData, quint64 sentData)
|
||||
{
|
||||
qDebug() << "MainWindow::onBytesChanged" << receivedData << sentData;
|
||||
ui->label_speed_received->setText(VpnConnection::bytesPerSecToText(receivedData));
|
||||
ui->label_speed_sent->setText(VpnConnection::bytesPerSecToText(sentData));
|
||||
}
|
||||
|
@ -394,6 +389,7 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
|||
qDebug() << "MainWindow::onConnectionStateChanged" << VpnProtocol::textConnectionState(state);
|
||||
|
||||
bool pushButtonConnectEnabled = false;
|
||||
bool radioButtonsModeEnabled = false;
|
||||
ui->label_state->setText(VpnProtocol::textConnectionState(state));
|
||||
|
||||
setTrayState(state);
|
||||
|
@ -403,32 +399,41 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
|||
onBytesChanged(0,0);
|
||||
ui->pushButton_connect->setChecked(false);
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = true;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Preparing:
|
||||
pushButtonConnectEnabled = false;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Connecting:
|
||||
pushButtonConnectEnabled = false;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Connected:
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Disconnecting:
|
||||
pushButtonConnectEnabled = false;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::TunnelReconnecting:
|
||||
case VpnProtocol::ConnectionState::Reconnecting:
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Error:
|
||||
ui->pushButton_connect->setChecked(false);
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = true;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Unknown:
|
||||
default:
|
||||
pushButtonConnectEnabled = true;
|
||||
;
|
||||
radioButtonsModeEnabled = true;
|
||||
}
|
||||
|
||||
ui->pushButton_connect->setEnabled(pushButtonConnectEnabled);
|
||||
ui->radioButton_mode_all_sites->setEnabled(radioButtonsModeEnabled);
|
||||
ui->radioButton_mode_selected_sites->setEnabled(radioButtonsModeEnabled);
|
||||
}
|
||||
|
||||
void MainWindow::onVpnProtocolError(ErrorCode errorCode)
|
||||
|
@ -519,7 +524,7 @@ void MainWindow::setupUiConnections()
|
|||
connect(ui->pushButton_server_settings_clear, SIGNAL(clicked(bool)), this, SLOT(onPushButtonClearServer(bool)));
|
||||
connect(ui->pushButton_server_settings_forget, SIGNAL(clicked(bool)), this, SLOT(onPushButtonForgetServer(bool)));
|
||||
|
||||
connect(ui->pushButton_blocked_list, &QPushButton::clicked, this, [this](){ goToPage(Page::Sites); });
|
||||
connect(ui->pushButton_vpn_add_site, &QPushButton::clicked, this, [this](){ goToPage(Page::Sites); });
|
||||
connect(ui->pushButton_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); });
|
||||
connect(ui->pushButton_server_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); });
|
||||
connect(ui->pushButton_share_connection, &QPushButton::clicked, this, [this](){
|
||||
|
@ -545,6 +550,12 @@ void MainWindow::setupUiConnections()
|
|||
|
||||
connect(ui->pushButton_sites_add_custom, &QPushButton::clicked, this, [this](){ onPushButtonAddCustomSitesClicked(); });
|
||||
connect(ui->pushButton_sites_delete_custom, &QPushButton::clicked, this, [this](){ onPushButtonDeleteCustomSiteClicked(); });
|
||||
|
||||
connect(ui->radioButton_mode_selected_sites, &QRadioButton::toggled, ui->pushButton_vpn_add_site, &QPushButton::setEnabled);
|
||||
|
||||
connect(ui->radioButton_mode_selected_sites, &QRadioButton::toggled, this, [this](bool toggled) {
|
||||
m_settings.setCustomRouting(toggled);
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::setTrayState(VpnProtocol::ConnectionState state)
|
||||
|
@ -570,7 +581,7 @@ void MainWindow::setTrayState(VpnProtocol::ConnectionState state)
|
|||
case VpnProtocol::ConnectionState::Disconnecting:
|
||||
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::TunnelReconnecting:
|
||||
case VpnProtocol::ConnectionState::Reconnecting:
|
||||
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Error:
|
||||
|
@ -663,13 +674,13 @@ void MainWindow::onPushButtonAddCustomSitesClicked()
|
|||
customIps.append(newIp);
|
||||
m_settings.setCustomIps(customIps);
|
||||
|
||||
// add to routes immediatelly
|
||||
// if (vpnStatus() == VPNStatusConnected) {
|
||||
// //Router::Instance().routeAdd(newIp, vpnGate());
|
||||
// }
|
||||
if (m_vpnConnection->connectionState() == VpnProtocol::ConnectionState::Connected) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnConnection->vpnProtocol()->vpnGateway(),
|
||||
QStringList() << newIp);
|
||||
}
|
||||
}
|
||||
|
||||
initCustomSites();
|
||||
updateSettings();
|
||||
|
||||
ui->lineEdit_sites_add_custom->clear();
|
||||
}
|
||||
|
@ -700,15 +711,19 @@ void MainWindow::onPushButtonDeleteCustomSiteClicked()
|
|||
m_settings.setCustomIps(customIps);
|
||||
|
||||
|
||||
initCustomSites();
|
||||
updateSettings();
|
||||
|
||||
//Router::Instance().routeDelete(Utils::getIPAddress(ipToDelete));
|
||||
//Router::Instance().flushDns();
|
||||
if (m_vpnConnection->connectionState() == VpnProtocol::ConnectionState::Connected) {
|
||||
IpcClient::Interface()->routeDelete(ipToDelete);
|
||||
IpcClient::Interface()->flushDns();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::initCustomSites()
|
||||
void MainWindow::updateSettings()
|
||||
{
|
||||
customSitesModel->setStringList(m_settings.customSites());
|
||||
ui->radioButton_mode_selected_sites->setChecked(m_settings.customRouting());
|
||||
ui->pushButton_vpn_add_site->setEnabled(m_settings.customRouting());
|
||||
}
|
||||
|
||||
void MainWindow::updateShareCode()
|
||||
|
@ -721,4 +736,6 @@ void MainWindow::updateShareCode()
|
|||
|
||||
QByteArray ba = QJsonDocument(o).toJson().toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
ui->textEdit_sharing_code->setText(QString("vpn://%1").arg(QString(ba)));
|
||||
|
||||
//qDebug() << "Share code" << QJsonDocument(o).toJson();
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ private:
|
|||
void setTrayIcon(const QString &iconPath);
|
||||
|
||||
void setupUiConnections();
|
||||
void initCustomSites();
|
||||
void updateSettings();
|
||||
|
||||
void updateShareCode();
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ QPushButton:hover {
|
|||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_start">
|
||||
<widget class="QLabel" name="label_23">
|
||||
|
@ -315,32 +315,6 @@ color: #333333;</string>
|
|||
<string>Connection code</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="progressBar_new_server_connection_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>40</x>
|
||||
<y>220</y>
|
||||
<width>301</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background: #181922;
|
||||
border-radius: 4px;</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>Connecting...</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
|
@ -944,7 +918,10 @@ font: 16px "Lato"; </string>
|
|||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton_blocked_list">
|
||||
<widget class="QPushButton" name="pushButton_vpn_add_site">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
|
@ -972,7 +949,10 @@ font-size: 16px;
|
|||
line-height: 21px;
|
||||
|
||||
}
|
||||
</string>
|
||||
|
||||
QPushButton:!enabled {
|
||||
background: #484952;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+ Add site</string>
|
||||
|
@ -1099,7 +1079,7 @@ color: #181922;
|
|||
</widget>
|
||||
<widget class="QRadioButton" name="radioButton_mode_all_sites">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
|
@ -1116,9 +1096,9 @@ color: #181922;
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="radioButton_mode_include_selected_sites">
|
||||
<widget class="QRadioButton" name="radioButton_mode_selected_sites">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
|
@ -1157,23 +1137,6 @@ color: #181922;
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>460</y>
|
||||
<width>361</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">image: url(:/images/AmneziaVPN.png);
|
||||
background-color: rgb(255, 255, 255);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_sites">
|
||||
<property name="styleSheet">
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <core/openvpnconfigurator.h>
|
||||
#include <core/servercontroller.h>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "core/ipcclient.h"
|
||||
#include "protocols/openvpnprotocol.h"
|
||||
#include "protocols/shadowsocksvpnprotocol.h"
|
||||
#include "utils.h"
|
||||
#include "vpnconnection.h"
|
||||
//#include "communicator.h"
|
||||
|
||||
VpnConnection::VpnConnection(QObject* parent) : QObject(parent)
|
||||
{
|
||||
QTimer::singleShot(0, [](){
|
||||
QTimer::singleShot(0, this, [this](){
|
||||
if (!IpcClient::init()) {
|
||||
qWarning() << "Error occured when init IPC client";
|
||||
emit serviceIsNotReady();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//VpnProtocol::initializeCommunicator(parent);
|
||||
VpnConnection::~VpnConnection()
|
||||
{
|
||||
m_vpnProtocol.clear();
|
||||
}
|
||||
|
||||
void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
|
||||
|
@ -30,28 +35,37 @@ void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
|
|||
|
||||
void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
||||
{
|
||||
// if (state == VpnProtocol::ConnectionState::Connected){
|
||||
// m_vpnProtocol->communicator()->sendMessage(Message(Message::State::FlushDnsRequest, QStringList()));
|
||||
if (IpcClient::Interface()) {
|
||||
if (state == VpnProtocol::ConnectionState::Connected && IpcClient::Interface()){
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
// // add routes
|
||||
// const QStringList &black_custom = m_settings.customIps();
|
||||
// qDebug() << "onConnect :: adding custom black routes, count:" << black_custom.size();
|
||||
if (m_settings.customRouting()) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(),
|
||||
QStringList() << m_settings.primaryDns() << m_settings.secondaryDns());
|
||||
|
||||
const QStringList &black_custom = m_settings.customIps();
|
||||
qDebug() << "onConnect :: adding custom black routes, count:" << black_custom.size();
|
||||
|
||||
// QStringList args;
|
||||
// args << m_vpnProtocol->vpnGateway();
|
||||
// args << black_custom;
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), black_custom);
|
||||
}
|
||||
}
|
||||
else if (state == VpnProtocol::ConnectionState::Error || state == VpnProtocol::ConnectionState::Disconnected) {
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
if (m_settings.customRouting()) {
|
||||
IpcClient::Interface()->clearSavedRoutes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Message m(Message::State::RoutesAddRequest, args);
|
||||
// m_vpnProtocol->communicator()->sendMessage(m);
|
||||
// }
|
||||
// else if (state == VpnProtocol::ConnectionState::Error) {
|
||||
// m_vpnProtocol->communicator()->sendMessage(Message(Message::State::ClearSavedRoutesRequest, QStringList()));
|
||||
// m_vpnProtocol->communicator()->sendMessage(Message(Message::State::FlushDnsRequest, QStringList()));
|
||||
// }
|
||||
emit connectionStateChanged(state);
|
||||
}
|
||||
|
||||
QSharedPointer<VpnProtocol> VpnConnection::vpnProtocol() const
|
||||
{
|
||||
return m_vpnProtocol;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::lastError() const
|
||||
{
|
||||
if (!m_vpnProtocol.data()) {
|
||||
|
@ -61,11 +75,12 @@ ErrorCode VpnConnection::lastError() const
|
|||
return m_vpnProtocol.data()->lastError();
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials, Protocol protocol)
|
||||
ErrorCode VpnConnection::createVpnConfiguration(const ServerCredentials &credentials, Protocol protocol)
|
||||
{
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
if (protocol == Protocol::OpenVpn || protocol == Protocol::ShadowSocks) {
|
||||
QString configData = OpenVpnConfigurator::genOpenVpnConfig(credentials, protocol, &errorCode);
|
||||
QString openVpnConfigData = OpenVpnConfigurator::genOpenVpnConfig(credentials, protocol, &errorCode);
|
||||
m_vpnConfiguration.insert(config::key_openvpn_config_data(), openVpnConfigData);
|
||||
if (errorCode) {
|
||||
return errorCode;
|
||||
}
|
||||
|
@ -73,57 +88,64 @@ ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials,
|
|||
QFile file(Utils::defaultVpnConfigFileName());
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
||||
QTextStream stream(&file);
|
||||
stream << configData << endl;
|
||||
return ErrorCode::NoError;
|
||||
stream << openVpnConfigData << endl;
|
||||
}
|
||||
else {
|
||||
return ErrorCode::FailedToSaveConfigData;
|
||||
}
|
||||
|
||||
return ErrorCode::FailedToSaveConfigData;
|
||||
}
|
||||
else {
|
||||
return ErrorCode::NotImplementedError;
|
||||
}
|
||||
return ErrorCode::NotImplementedError;
|
||||
|
||||
if (protocol == Protocol::ShadowSocks) {
|
||||
QJsonObject ssConfigData = ShadowSocksVpnProtocol::genShadowSocksConfig(credentials);
|
||||
m_vpnConfiguration.insert(config::key_shadowsocks_config_data(), ssConfigData);
|
||||
}
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Protocol protocol)
|
||||
{
|
||||
// protocol = Protocol::ShadowSocks;
|
||||
qDebug() << "connectToVpn, CustomRouting is" << m_settings.customRouting();
|
||||
//protocol = Protocol::ShadowSocks;
|
||||
|
||||
// TODO: Try protocols one by one in case of Protocol::Any
|
||||
// TODO: Implement some behavior in case if connection not stable
|
||||
qDebug() << "Connect to VPN";
|
||||
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Connecting);
|
||||
|
||||
if (m_vpnProtocol) {
|
||||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
m_vpnProtocol->stop();
|
||||
m_vpnProtocol->deleteLater();
|
||||
}
|
||||
|
||||
qApp->processEvents();
|
||||
|
||||
if (protocol == Protocol::Any || protocol == Protocol::OpenVpn) {
|
||||
ErrorCode e = requestVpnConfig(credentials, Protocol::OpenVpn);
|
||||
ErrorCode e = createVpnConfiguration(credentials, Protocol::OpenVpn);
|
||||
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 OpenVpnProtocol(m_vpnConfiguration));
|
||||
e = static_cast<OpenVpnProtocol *>(m_vpnProtocol.data())->checkAndSetupTapDriver();
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
return e;
|
||||
}
|
||||
m_vpnProtocol.reset(new OpenVpnProtocol());
|
||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
}
|
||||
else if (protocol == Protocol::ShadowSocks) {
|
||||
ErrorCode e = requestVpnConfig(credentials, Protocol::ShadowSocks);
|
||||
ErrorCode e = createVpnConfiguration(credentials, Protocol::ShadowSocks);
|
||||
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);
|
||||
|
||||
m_vpnProtocol.reset(new ShadowSocksVpnProtocol(m_vpnConfiguration));
|
||||
}
|
||||
|
||||
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(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64)));
|
||||
|
||||
|
@ -155,20 +177,20 @@ VpnProtocol::ConnectionState VpnConnection::connectionState()
|
|||
return m_vpnProtocol->connectionState();
|
||||
}
|
||||
|
||||
bool VpnConnection::onConnected() const
|
||||
bool VpnConnection::isConnected() const
|
||||
{
|
||||
if (!m_vpnProtocol.data()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_vpnProtocol.data()->onConnected();
|
||||
return m_vpnProtocol.data()->isConnected();
|
||||
}
|
||||
|
||||
bool VpnConnection::onDisconnected() const
|
||||
bool VpnConnection::isDisconnected() const
|
||||
{
|
||||
if (!m_vpnProtocol.data()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_vpnProtocol.data()->onDisconnected();
|
||||
return m_vpnProtocol.data()->isDisconnected();
|
||||
}
|
||||
|
|
|
@ -19,34 +19,40 @@ class VpnConnection : public QObject
|
|||
|
||||
public:
|
||||
explicit VpnConnection(QObject* parent = nullptr);
|
||||
~VpnConnection() override = default;
|
||||
~VpnConnection() override;
|
||||
|
||||
static QString bytesPerSecToText(quint64 bytes);
|
||||
|
||||
ErrorCode lastError() const;
|
||||
ErrorCode requestVpnConfig(const ServerCredentials &credentials, Protocol protocol);
|
||||
ErrorCode createVpnConfiguration(const ServerCredentials &credentials, Protocol protocol);
|
||||
|
||||
ErrorCode connectToVpn(const ServerCredentials &credentials, Protocol protocol = Protocol::Any);
|
||||
bool onConnected() const;
|
||||
bool onDisconnected() const;
|
||||
void disconnectFromVpn();
|
||||
|
||||
bool isConnected() const;
|
||||
bool isDisconnected() const;
|
||||
|
||||
VpnProtocol::ConnectionState connectionState();
|
||||
|
||||
QSharedPointer<VpnProtocol> vpnProtocol() const;
|
||||
|
||||
signals:
|
||||
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void connectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
void vpnProtocolError(amnezia::ErrorCode error);
|
||||
|
||||
void serviceIsNotReady();
|
||||
|
||||
protected slots:
|
||||
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void onConnectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
|
||||
protected:
|
||||
|
||||
QScopedPointer<VpnProtocol> m_vpnProtocol;
|
||||
QSharedPointer<VpnProtocol> m_vpnProtocol;
|
||||
|
||||
private:
|
||||
Settings m_settings;
|
||||
QJsonObject m_vpnConfiguration;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue