Add local sockets

unix-socket
Simon Stürz 2022-05-18 17:08:40 +02:00
parent 4683f4888e
commit b255e52396
12 changed files with 261 additions and 16 deletions

View File

@ -77,6 +77,7 @@ void Engine::start(ProxyConfiguration *configuration)
m_proxyServer = new ProxyServer(this);
m_webSocketServerProxy = new WebSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
m_tcpSocketServerProxy = new TcpSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
m_unixSocketServerProxy = new UnixSocketServer(m_configuration->localSocketFileName(), this);
// Configure websocket server
QUrl websocketServerUrl;
@ -95,6 +96,7 @@ void Engine::start(ProxyConfiguration *configuration)
// Register the transport interfaces in the proxy server
m_proxyServer->registerTransportInterface(m_webSocketServerProxy);
m_proxyServer->registerTransportInterface(m_tcpSocketServerProxy);
m_proxyServer->registerTransportInterface(m_unixSocketServerProxy);
// Start the server
qCDebug(dcEngine()) << "Starting the proxy servers...";
@ -211,6 +213,11 @@ WebSocketServer *Engine::webSocketServerProxy() const
return m_webSocketServerProxy;
}
UnixSocketServer *Engine::unixSocketServerProxy() const
{
return m_unixSocketServerProxy;
}
TcpSocketServer *Engine::tcpSocketServerTunnelProxy() const
{
return m_tcpSocketServerTunnelProxy;

View File

@ -42,6 +42,7 @@
#include "server/jsonrpcserver.h"
#include "server/tcpsocketserver.h"
#include "server/websocketserver.h"
#include "server/unixsocketserver.h"
#include "authentication/authenticator.h"
#include "tunnelproxy/tunnelproxyserver.h"
@ -75,6 +76,7 @@ public:
TcpSocketServer *tcpSocketServerProxy() const;
WebSocketServer *webSocketServerProxy() const;
UnixSocketServer *unixSocketServerProxy() const;
TcpSocketServer *tcpSocketServerTunnelProxy() const;
WebSocketServer *webSocketServerTunnelProxy() const;
@ -103,6 +105,7 @@ private:
TcpSocketServer *m_tcpSocketServerProxy = nullptr;
WebSocketServer *m_webSocketServerProxy = nullptr;
UnixSocketServer *m_unixSocketServerProxy = nullptr;
TcpSocketServer *m_tcpSocketServerTunnelProxy = nullptr;
WebSocketServer *m_webSocketServerTunnelProxy = nullptr;

View File

@ -27,6 +27,7 @@ HEADERS += \
proxy/tunnelconnection.h \
server/tcpsocketserver.h \
server/transportinterface.h \
server/unixsocketserver.h \
server/websocketserver.h \
server/jsonrpcserver.h \
server/transportclient.h \
@ -60,6 +61,7 @@ SOURCES += \
server/tcpsocketserver.cpp \
server/transportinterface.cpp \
server/transportclient.cpp \
server/unixsocketserver.cpp \
server/websocketserver.cpp \
server/jsonrpcserver.cpp \
server/monitorserver.cpp \

View File

@ -43,5 +43,7 @@ Q_LOGGING_CATEGORY(dcProxyServerTraffic, "ProxyServerTraffic")
Q_LOGGING_CATEGORY(dcTunnelProxyServer, "TunnelProxyServer")
Q_LOGGING_CATEGORY(dcTunnelProxyServerTraffic, "TunnelProxyServerTraffic")
Q_LOGGING_CATEGORY(dcMonitorServer, "MonitorServer")
Q_LOGGING_CATEGORY(dcUnixSocketServer, "UnixSocketServer")
Q_LOGGING_CATEGORY(dcUnixSocketServerTraffic, "UnixSocketServerTraffic")
Q_LOGGING_CATEGORY(dcAwsCredentialsProvider, "AwsCredentialsProvider")
Q_LOGGING_CATEGORY(dcAwsCredentialsProviderTraffic, "AwsCredentialsProviderTraffic")

View File

@ -47,6 +47,8 @@ Q_DECLARE_LOGGING_CATEGORY(dcProxyServerTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcTunnelProxyServer)
Q_DECLARE_LOGGING_CATEGORY(dcTunnelProxyServerTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcMonitorServer)
Q_DECLARE_LOGGING_CATEGORY(dcUnixSocketServer)
Q_DECLARE_LOGGING_CATEGORY(dcUnixSocketServerTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcAwsCredentialsProvider)
Q_DECLARE_LOGGING_CATEGORY(dcAwsCredentialsProviderTraffic)

View File

@ -87,6 +87,10 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName)
setTcpServerPort(static_cast<quint16>(settings.value("port", 1213).toInt()));
settings.endGroup();
settings.beginGroup("LocalSocketServer");
setTcpServerHost(QHostAddress(settings.value("localSocketFileName", "/run/nymea-remoteproxy.socket").toString()));
settings.endGroup();
settings.beginGroup("WebSocketServerTunnelProxy");
setWebSocketServerTunnelProxyHost(QHostAddress(settings.value("host", "127.0.0.1").toString()));
setWebSocketServerTunnelProxyPort(static_cast<quint16>(settings.value("port", 2212).toInt()));
@ -352,6 +356,11 @@ void ProxyConfiguration::setTcpServerPort(quint16 port)
m_tcpServerPort = port;
}
QString ProxyConfiguration::localSocketFileName() const
{
return m_localSocketFileName;
}
QHostAddress ProxyConfiguration::webSocketServerTunnelProxyHost() const
{
return m_webSocketServerTunnelProxyHost;
@ -436,6 +445,8 @@ QDebug operator<<(QDebug debug, ProxyConfiguration *configuration)
debug.nospace() << "TcpServer Proxy" << endl;
debug.nospace() << " - Host:" << configuration->tcpServerHost().toString() << endl;
debug.nospace() << " - Port:" << configuration->tcpServerPort() << endl;
debug.nospace() << "LocalSocket Proxy" << endl;
debug.nospace() << " - Socket file:" << configuration->localSocketFileName() << endl;
debug.nospace() << "WebSocketServer TunnelProxy" << endl;
debug.nospace() << " - Host:" << configuration->webSocketServerTunnelProxyHost().toString() << endl;
debug.nospace() << " - Port:" << configuration->webSocketServerTunnelProxyPort() << endl;

View File

@ -113,6 +113,9 @@ public:
quint16 tcpServerPort() const;
void setTcpServerPort(quint16 port);
// LocalServer
QString localSocketFileName() const;
// WebSocketServer (tunnel)
QHostAddress webSocketServerTunnelProxyHost() const;
void setWebSocketServerTunnelProxyHost(const QHostAddress &address);
@ -127,7 +130,6 @@ public:
quint16 tcpServerTunnelProxyPort() const;
void setTcpServerTunnelProxyPort(quint16 port);
private:
// ProxyServer
QString m_fileName;
@ -162,11 +164,14 @@ private:
QHostAddress m_tcpServerHost = QHostAddress::LocalHost;
quint16 m_tcpServerPort = 1213;
// WebSocketServer (proxy)
// LocalSocketServer (proxy)
QString m_localSocketFileName = "/run/nymea-remoteproxy.socket";
// WebSocketServer (tunnel)
QHostAddress m_webSocketServerTunnelProxyHost = QHostAddress::LocalHost;
quint16 m_webSocketServerTunnelProxyPort = 2212;
// TcpServer (proxy)
// TcpServer (tunnel)
QHostAddress m_tcpServerTunnelProxyHost = QHostAddress::LocalHost;
quint16 m_tcpServerTunnelProxyPort = 2213;

View File

@ -0,0 +1,148 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under
* the terms of the GNU General Public License as published by the Free Software Foundation,
* GNU version 3. this project is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "unixsocketserver.h"
#include <QFile>
#include "loggingcategories.h"
namespace remoteproxy {
UnixSocketServer::UnixSocketServer(QString socketFileName, QObject *parent) :
TransportInterface(parent),
m_socketFileName(socketFileName)
{
m_serverName = "LOCAL";
}
UnixSocketServer::~UnixSocketServer()
{
stopServer();
}
void UnixSocketServer::sendData(const QUuid &clientId, const QByteArray &data)
{
QLocalSocket *client = nullptr;
client = m_clientList.value(clientId);
if (!client) {
qCWarning(dcUnixSocketServer()) << "Client" << clientId << "unknown to this transport";
return;
}
qCDebug(dcUnixSocketServerTraffic()) << "Send data to" << clientId.toString() << data;
if (client->write(data) < 0) {
qCWarning(dcUnixSocketServer()) << "Could not write data to client socket" << clientId.toString();
}
client->flush();
}
void UnixSocketServer::killClientConnection(const QUuid &clientId, const QString &killReason)
{
QLocalSocket *client = m_clientList.value(clientId);
if (!client)
return;
if (client->state() == QLocalSocket::ConnectedState) {
qCWarning(dcUnixSocketServer()) << "Killing client connection" << clientId.toString() << "Reason:" << killReason;
client->close();
}
}
bool UnixSocketServer::running() const
{
if (!m_server)
return false;
return m_server->isListening();
}
bool UnixSocketServer::startServer()
{
qCDebug(dcUnixSocketServer()) << "Starting server on" << m_socketFileName;
// Make sure the monitor can be created
if (QFile::exists(m_socketFileName)) {
qCDebug(dcUnixSocketServer()) << "Clean up old unix socket";
QFile::remove(m_socketFileName);
}
m_server = new QLocalServer(this);
m_server->setSocketOptions(QLocalServer::UserAccessOption | QLocalServer::GroupAccessOption | QLocalServer::OtherAccessOption);
if (!m_server->listen(m_socketFileName)) {
qCWarning(dcUnixSocketServer()) << "Could not start local server for monitor on" << m_serverName << m_server->errorString();
delete m_server;
m_server = nullptr;
return false;
}
connect(m_server, &QLocalServer::newConnection, this, &UnixSocketServer::onClientConnected);
qCDebug(dcUnixSocketServer()) << "Started successfully on" << m_serverName;
return true;
}
bool UnixSocketServer::stopServer()
{
if (!m_server)
return true;
qCDebug(dcUnixSocketServer()) << "Stopping server" << m_serverName;
foreach (QLocalSocket *clientConnection, m_clientList) {
clientConnection->close();
}
m_server->close();
delete m_server;
m_server = nullptr;
return true;
}
void UnixSocketServer::onClientConnected()
{
QLocalSocket *client = m_server->nextPendingConnection();
QUuid clientId = QUuid::createUuid();
qCDebug(dcUnixSocketServer()) << "New client connected" << clientId.toString();
m_clientList.insert(clientId, client);
connect(client, &QLocalSocket::disconnected, this, [=](){
QUuid clientId = m_clientList.key(client);
qCDebug(dcUnixSocketServer()) << "Client disconnected:" << clientId.toString();
if (m_clientList.take(clientId)) {
emit clientDisconnected(clientId);
}
});
connect(client, &QLocalSocket::readyRead, this, [=](){
QByteArray data = client->readAll();
qCDebug(dcUnixSocketServerTraffic()) << "Incomming data from" << clientId.toString() << data;
emit dataAvailable(clientId, data);
});
emit clientConnected(clientId, QHostAddress::LocalHost);
}
}

View File

@ -0,0 +1,68 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2022, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by copyright law, and
* remains the property of nymea GmbH. All rights, including reproduction, publication,
* editing and translation, are reserved. The use of this project is subject to the terms of a
* license agreement to be concluded with nymea GmbH in accordance with the terms
* of use of nymea GmbH, available under https://nymea.io/license
*
* GNU General Public License Usage
* Alternatively, this project may be redistributed and/or modified under
* the terms of the GNU General Public License as published by the Free Software Foundation,
* GNU version 3. this project is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this project.
* If not, see <https://www.gnu.org/licenses/>.
*
* For any further details and any questions please contact us under contact@nymea.io
* or see our FAQ/Licensing Information on https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef UNIXSOCKETSERVER_H
#define UNIXSOCKETSERVER_H
#include <QObject>
#include <QUuid>
#include <QLocalServer>
#include <QLocalSocket>
#include "transportinterface.h"
namespace remoteproxy {
class UnixSocketServer : public TransportInterface
{
Q_OBJECT
public:
explicit UnixSocketServer(QString socketFileName, QObject *parent = nullptr);
~UnixSocketServer() override;
void sendData(const QUuid &clientId, const QByteArray &data) override;
void killClientConnection(const QUuid &clientId, const QString &killReason) override;
bool running() const override;
public slots:
bool startServer() override;
bool stopServer() override;
private:
QString m_socketFileName;
QLocalServer *m_server = nullptr;
QHash<QUuid, QLocalSocket *> m_clientList;
private slots:
void onClientConnected();
};
}
#endif // UNIXSOCKETSERVER_H

View File

@ -7,10 +7,16 @@ JsonRpc.debug=true
JsonRpcTraffic.debug=false
WebSocketServer.debug=true
WebSocketServerTraffic.debug=false
TcpSocketServer.debug=true
TcpSocketServerTraffic.debug=false
UnixSocketServer.debug=true
UnixSocketServerTraffic.debug=false
Authentication.debug=true
AuthenticationProcess.debug=false
ProxyServer.debug=true
ProxyServerTraffic.debug=false
TunnelProxyServer.debug=true
TunnelProxyServerTraffic.debug=false
MonitorServer.debug=true
AwsCredentialsProvider.debug=false
AwsCredentialsProviderTraffic.debug=false

View File

@ -28,6 +28,9 @@ port=443
host=127.0.0.1
port=80
[LocalSocketServer]
localSocketFileName=/run/nymea-remoteproxy.socket
[WebSocketServerTunnelProxy]
host=127.0.0.1
port=2212

View File

@ -118,7 +118,7 @@ int main(int argc, char *argv[])
"registered nymea deamons to establish a tunnel connection.\n\n"
"Version: %1\n"
"API version: %2\n\n"
"Copyright %3 2021 nymea GmbH <developer@nymea.io>\n")
"Copyright %3 2022 nymea GmbH <developer@nymea.io>\n")
.arg(SERVER_VERSION_STRING)
.arg(API_VERSION_STRING)
.arg(QChar(0xA9)));
@ -175,18 +175,6 @@ int main(int argc, char *argv[])
}
}
// Verify webserver configuration
if (configuration->webSocketServerProxyHost().isNull()) {
qCCritical(dcApplication()) << "Invalid web socket host address passed.";
exit(-1);
}
// Verify tcp server configuration
if (configuration->tcpServerHost().isNull()) {
qCCritical(dcApplication()) << "Invalid TCP server host address passed.";
exit(-1);
}
// Verify SSL configuration
if (configuration->sslEnabled() && configuration->sslConfiguration().isNull()) {
qCCritical(dcApplication()) << "SSL is enabled but no SSL configuration specified.";