Custom routing done

ShadowSocks enabled by default
This commit is contained in:
pokamest 2021-02-18 15:00:41 +03:00
parent f91854594c
commit a1cb4ac544
36 changed files with 482 additions and 780 deletions

View file

@ -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

View file

@ -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");

View file

@ -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();
//// }
// });
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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);