Merge pull request #752 from amnezia-vpn/feature/ssh-one-session

ssh client now reuses an existing session instead of opening a new one
This commit is contained in:
pokamest 2024-04-18 05:05:00 -07:00 committed by GitHub
commit f0085f52eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 395 additions and 451 deletions

View file

@ -64,13 +64,12 @@ void ClientManagementModel::migration(const QByteArray &clientsTableString)
}
}
ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCredentials credentials)
ErrorCode ClientManagementModel::updateModel(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController)
{
beginResetModel();
m_clientsTable = QJsonArray();
ServerController serverController(m_settings);
ErrorCode error = ErrorCode::NoError;
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
@ -80,7 +79,7 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
const QByteArray clientsTableString = serverController.getTextFileFromContainer(container, credentials, clientsTableFile, error);
const QByteArray clientsTableString = serverController->getTextFileFromContainer(container, credentials, clientsTableFile, error);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the clientsTable file from the server";
endResetModel();
@ -95,9 +94,9 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
int count = 0;
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
error = getOpenVpnClients(serverController, container, credentials, count);
error = getOpenVpnClients(container, credentials, serverController, count);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
error = getWireGuardClients(serverController, container, credentials, count);
error = getWireGuardClients(container, credentials, serverController, count);
}
if (error != ErrorCode::NoError) {
endResetModel();
@ -106,7 +105,7 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
const QByteArray newClientsTableString = QJsonDocument(m_clientsTable).toJson();
if (clientsTableString != newClientsTableString) {
error = serverController.uploadTextFileToContainer(container, credentials, newClientsTableString, clientsTableFile);
error = serverController->uploadTextFileToContainer(container, credentials, newClientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
}
@ -117,8 +116,8 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
return error;
}
ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverController, DockerContainer container,
ServerCredentials credentials, int &count)
ErrorCode ClientManagementModel::getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, int &count)
{
ErrorCode error = ErrorCode::NoError;
QString stdOut;
@ -128,8 +127,8 @@ ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverContr
};
const QString getOpenVpnClientsList = "sudo docker exec -i $CONTAINER_NAME bash -c 'ls /opt/amnezia/openvpn/pki/issued'";
QString script = serverController.replaceVars(getOpenVpnClientsList, serverController.genVarsForScript(credentials, container));
error = serverController.runScript(credentials, script, cbReadStdOut);
QString script = serverController->replaceVars(getOpenVpnClientsList, serverController->genVarsForScript(credentials, container));
error = serverController->runScript(credentials, script, cbReadStdOut);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to retrieve the list of issued certificates on the server";
return error;
@ -158,13 +157,13 @@ ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverContr
return error;
}
ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverController, DockerContainer container,
ServerCredentials credentials, int &count)
ErrorCode ClientManagementModel::getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, int &count)
{
ErrorCode error = ErrorCode::NoError;
const QString wireGuardConfigFile = QString("opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
const QString wireguardConfigString = serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server";
return error;
@ -198,7 +197,7 @@ ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverCon
bool ClientManagementModel::isClientExists(const QString &clientId)
{
for (const QJsonValue &value : qAsConst(m_clientsTable)) {
for (const QJsonValue &value : std::as_const(m_clientsTable)) {
if (value.isObject()) {
QJsonObject obj = value.toObject();
if (obj.contains(configKey::clientId) && obj[configKey::clientId].toString() == clientId) {
@ -210,7 +209,8 @@ bool ClientManagementModel::isClientExists(const QString &clientId)
}
ErrorCode ClientManagementModel::appendClient(const DockerContainer container, const ServerCredentials &credentials,
const QJsonObject &containerConfig, const QString &clientName)
const QJsonObject &containerConfig, const QString &clientName,
const QSharedPointer<ServerController> &serverController)
{
Proto protocol;
if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
@ -223,22 +223,22 @@ ErrorCode ClientManagementModel::appendClient(const DockerContainer container, c
auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig);
return appendClient(protocolConfig.value(config_key::clientId).toString(), clientName, container, credentials);
return appendClient(protocolConfig.value(config_key::clientId).toString(), clientName, container, credentials, serverController);
}
ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
ServerCredentials credentials)
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController)
{
ErrorCode error = ErrorCode::NoError;
error = updateModel(container, credentials);
error = updateModel(container, credentials, serverController);
if (error != ErrorCode::NoError) {
return error;
}
for (int i = 0; i < m_clientsTable.size(); i++) {
if (m_clientsTable.at(i).toObject().value(configKey::clientId) == clientId) {
return renameClient(i, clientName, container, credentials, true);
return renameClient(i, clientName, container, credentials, serverController, true);
}
}
@ -255,7 +255,6 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
ServerController serverController(m_settings);
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
@ -263,7 +262,7 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
}
@ -272,7 +271,8 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
}
ErrorCode ClientManagementModel::renameClient(const int row, const QString &clientName, const DockerContainer container,
ServerCredentials credentials, bool addTimeStamp)
const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, bool addTimeStamp)
{
auto client = m_clientsTable.at(row).toObject();
auto userData = client[configKey::userData].toObject();
@ -287,7 +287,6 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
ServerController serverController(m_settings);
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
@ -295,7 +294,7 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
ErrorCode error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
ErrorCode error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
}
@ -303,17 +302,17 @@ ErrorCode ClientManagementModel::renameClient(const int row, const QString &clie
return error;
}
ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContainer container, ServerCredentials credentials,
const int serverIndex)
ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContainer container, const ServerCredentials &credentials,
const int serverIndex, const QSharedPointer<ServerController> &serverController)
{
ErrorCode errorCode = ErrorCode::NoError;
auto client = m_clientsTable.at(row).toObject();
QString clientId = client.value(configKey::clientId).toString();
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
errorCode = revokeOpenVpn(row, container, credentials, serverIndex);
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
errorCode = revokeWireGuard(row, container, credentials);
errorCode = revokeWireGuard(row, container, credentials, serverController);
}
if (errorCode == ErrorCode::NoError) {
@ -340,11 +339,12 @@ ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContain
return errorCode;
}
ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig, const DockerContainer container, ServerCredentials credentials,
const int serverIndex)
ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig, const DockerContainer container,
const ServerCredentials &credentials, const int serverIndex,
const QSharedPointer<ServerController> &serverController)
{
ErrorCode errorCode = ErrorCode::NoError;
errorCode = updateModel(container, credentials);
errorCode = updateModel(container, credentials, serverController);
if (errorCode != ErrorCode::NoError) {
return errorCode;
}
@ -375,15 +375,15 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
}
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
errorCode = revokeOpenVpn(row, container, credentials, serverIndex);
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
errorCode = revokeWireGuard(row, container, credentials);
errorCode = revokeWireGuard(row, container, credentials, serverController);
}
return errorCode;
}
ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials,
const int serverIndex)
ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials,
const int serverIndex, const QSharedPointer<ServerController> &serverController)
{
auto client = m_clientsTable.at(row).toObject();
QString clientId = client.value(configKey::clientId).toString();
@ -396,9 +396,8 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
"cp pki/crl.pem .'")
.arg(clientId);
ServerController serverController(m_settings);
const QString script = serverController.replaceVars(getOpenVpnCertData, serverController.genVarsForScript(credentials, container));
ErrorCode error = serverController.runScript(credentials, script);
const QString script = serverController->replaceVars(getOpenVpnCertData, serverController->genVarsForScript(credentials, container));
ErrorCode error = serverController->runScript(credentials, script);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to revoke the certificate";
return error;
@ -412,7 +411,7 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable");
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(DockerContainer::OpenVpn));
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
return error;
@ -421,14 +420,14 @@ ErrorCode ClientManagementModel::revokeOpenVpn(const int row, const DockerContai
return ErrorCode::NoError;
}
ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials)
ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController)
{
ErrorCode error = ErrorCode::NoError;
ServerController serverController(m_settings);
const QString wireGuardConfigFile =
QString("/opt/amnezia/%1/wg0.conf").arg(container == DockerContainer::WireGuard ? "wireguard" : "awg");
const QString wireguardConfigString = serverController.getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
const QString wireguardConfigString = serverController->getTextFileFromContainer(container, credentials, wireGuardConfigFile, error);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the wg conf file from the server";
return error;
@ -446,7 +445,7 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
}
QString newWireGuardConfig = configSections.join("[");
newWireGuardConfig.insert(0, "[");
error = serverController.uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile);
error = serverController->uploadTextFileToContainer(container, credentials, newWireGuardConfig, wireGuardConfigFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the wg conf file to the server";
return error;
@ -464,16 +463,16 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
} else {
clientsTableFile = clientsTableFile.arg(ContainerProps::containerTypeToString(container));
}
error = serverController.uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
if (error != ErrorCode::NoError) {
logger.error() << "Failed to upload the clientsTable file to the server";
return error;
}
const QString script = "sudo docker exec -i $CONTAINER_NAME bash -c 'wg syncconf wg0 <(wg-quick strip %1)'";
error = serverController.runScript(
error = serverController->runScript(
credentials,
serverController.replaceVars(script.arg(wireGuardConfigFile), serverController.genVarsForScript(credentials, container)));
serverController->replaceVars(script.arg(wireGuardConfigFile), serverController->genVarsForScript(credentials, container)));
if (error != ErrorCode::NoError) {
logger.error() << "Failed to execute the command 'wg syncconf' on the server";
return error;

View file

@ -23,15 +23,18 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
ErrorCode updateModel(DockerContainer container, ServerCredentials credentials);
ErrorCode updateModel(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController);
ErrorCode appendClient(const DockerContainer container, const ServerCredentials &credentials, const QJsonObject &containerConfig,
const QString &clientName);
const QString &clientName, const QSharedPointer<ServerController> &serverController);
ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
ServerCredentials credentials);
ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, ServerCredentials credentials,
bool addTimeStamp = false);
ErrorCode revokeClient(const int index, const DockerContainer container, ServerCredentials credentials, const int serverIndex);
ErrorCode revokeClient(const QJsonObject &containerConfig, const DockerContainer container, ServerCredentials credentials, const int serverIndex);
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController);
ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, bool addTimeStamp = false);
ErrorCode revokeClient(const int index, const DockerContainer container, const ServerCredentials &credentials, const int serverIndex,
const QSharedPointer<ServerController> &serverController);
ErrorCode revokeClient(const QJsonObject &containerConfig, const DockerContainer container, const ServerCredentials &credentials,
const int serverIndex, const QSharedPointer<ServerController> &serverController);
protected:
QHash<int, QByteArray> roleNames() const override;
@ -44,11 +47,15 @@ private:
void migration(const QByteArray &clientsTableString);
ErrorCode revokeOpenVpn(const int row, const DockerContainer container, ServerCredentials credentials, const int serverIndex);
ErrorCode revokeWireGuard(const int row, const DockerContainer container, ServerCredentials credentials);
ErrorCode revokeOpenVpn(const int row, const DockerContainer container, const ServerCredentials &credentials, const int serverIndex,
const QSharedPointer<ServerController> &serverController);
ErrorCode revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController);
ErrorCode getOpenVpnClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count);
ErrorCode getWireGuardClients(ServerController &serverController, DockerContainer container, ServerCredentials credentials, int &count);
ErrorCode getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, int &count);
ErrorCode getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
const QSharedPointer<ServerController> &serverController, int &count);
QJsonArray m_clientsTable;

View file

@ -421,10 +421,10 @@ const QString ServersModel::getDefaultServerDefaultContainerName()
return ContainerProps::containerHumanNames().value(defaultContainer);
}
ErrorCode ServersModel::removeAllContainers()
ErrorCode ServersModel::removeAllContainers(const QSharedPointer<ServerController> &serverController)
{
ServerController serverController(m_settings);
ErrorCode errorCode = serverController.removeAllContainers(m_settings->serverCredentials(m_processedServerIndex));
ErrorCode errorCode = serverController->removeAllContainers(m_settings->serverCredentials(m_processedServerIndex));
if (errorCode == ErrorCode::NoError) {
QJsonObject s = m_servers.at(m_processedServerIndex).toObject();
@ -436,22 +436,22 @@ ErrorCode ServersModel::removeAllContainers()
return errorCode;
}
ErrorCode ServersModel::rebootServer()
ErrorCode ServersModel::rebootServer(const QSharedPointer<ServerController> &serverController)
{
ServerController serverController(m_settings);
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
ErrorCode errorCode = serverController.rebootServer(credentials);
ErrorCode errorCode = serverController->rebootServer(credentials);
return errorCode;
}
ErrorCode ServersModel::removeContainer(const int containerIndex)
ErrorCode ServersModel::removeContainer(const QSharedPointer<ServerController> &serverController, const int containerIndex)
{
ServerController serverController(m_settings);
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
auto dockerContainer = static_cast<DockerContainer>(containerIndex);
ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer);
ErrorCode errorCode = serverController->removeContainer(credentials, dockerContainer);
if (errorCode == ErrorCode::NoError) {
QJsonObject server = m_servers.at(m_processedServerIndex).toObject();

View file

@ -4,6 +4,7 @@
#include <QAbstractListModel>
#include "settings.h"
#include "core/controllers/serverController.h"
class ServersModel : public QAbstractListModel
{
@ -88,9 +89,9 @@ public slots:
void clearCachedProfile(const DockerContainer container);
ErrorCode removeContainer(const int containerIndex);
ErrorCode removeAllContainers();
ErrorCode rebootServer();
ErrorCode removeContainer(const QSharedPointer<ServerController> &serverController, const int containerIndex);
ErrorCode removeAllContainers(const QSharedPointer<ServerController> &serverController);
ErrorCode rebootServer(const QSharedPointer<ServerController> &serverController);
void setDefaultContainer(const int serverIndex, const int containerIndex);