Fix tunnel proxy configuration and make it independent from the cloud configuration

This commit is contained in:
Simon Stürz 2022-03-01 13:51:27 +01:00
parent 1e132a49ac
commit 3eb3b8ad8a
5 changed files with 93 additions and 51 deletions

View File

@ -212,33 +212,14 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) :
}
// Tunnel Proxy Server
createDefaults = !settings.childGroups().contains("TunnelProxyServer");
if (settings.childGroups().contains("TunnelProxyServer")) {
settings.beginGroup("TunnelProxyServer");
if (settings.value("disabled").toBool()) {
qCDebug(dcConfiguration) << "Tunnel proxy server disabled by configuration.";
} else if (!settings.childGroups().isEmpty()) {
foreach (const QString &key, settings.childGroups()) {
TunnelProxyServerConfiguration config = readTunnelProxyServerConfig(key);
m_tunnelProxyServerConfigs[config.id] = config;
}
} else {
createDefaults = true;
foreach (const QString &key, settings.childGroups()) {
TunnelProxyServerConfiguration config = readTunnelProxyServerConfig(key);
m_tunnelProxyServerConfigs[config.id] = config;
}
settings.endGroup();
}
if (createDefaults) {
qCWarning(dcConfiguration) << "No Tunnel Proxy server configuration found. Generating default of remoteproxy.nymea.io:2213";
TunnelProxyServerConfiguration config;
config.id = "default";
config.address = "remoteproxy.nymea.io";
config.port = 2213;
config.sslEnabled = true;
config.authenticationEnabled = true;
config.ignoreSslErrors = false;
m_tunnelProxyServerConfigs[config.id] = config;
storeTunnelProxyServerConfig(config);
}
// Write defaults for log settings
settings.beginGroup("Logs");
@ -403,7 +384,7 @@ QHash<QString, TunnelProxyServerConfiguration> NymeaConfiguration::tunnelProxySe
void NymeaConfiguration::setTunnelProxyServerConfiguration(const TunnelProxyServerConfiguration &config)
{
m_tunnelProxyServerConfigs[config.id] = config;
storeServerConfig("TunnelProxyServer", config);
storeTunnelProxyServerConfig(config);
emit tunnelProxyServerConfigurationChanged(config.id);
}
@ -791,7 +772,30 @@ QDebug operator <<(QDebug debug, const ServerConfiguration &configuration)
debug.nospace() << ", " << configuration.id;
debug.nospace() << ", " << QString("%1:%2").arg(configuration.address).arg(configuration.port);
debug.nospace() << ") ";
return debug;
return debug.maybeSpace();
}
QDebug operator <<(QDebug debug, const TunnelProxyServerConfiguration &configuration)
{
debug.nospace() << "TunnelProxyServerConfiguration(" << configuration.id;
debug.nospace() << ", " << QString("%1:%2").arg(configuration.address).arg(configuration.port);
if (configuration.sslEnabled) {
debug.nospace() << ", SSL enabled";
} else {
debug.nospace() << ", SSL disabled";
}
if (configuration.authenticationEnabled) {
debug.nospace() << ", Authentication enabled";
} else {
debug.nospace() << ", Authentication disabled";
}
if (configuration.ignoreSslErrors) {
debug.nospace() << ", Ignoring SSL errors";
}
debug.nospace() << ") ";
return debug.maybeSpace();
}
}

View File

@ -46,6 +46,7 @@ class ServerConfiguration {
Q_PROPERTY(uint port MEMBER port)
Q_PROPERTY(bool sslEnabled MEMBER sslEnabled)
Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled)
public:
QString id;
QString address;
@ -69,19 +70,34 @@ class WebServerConfiguration: public ServerConfiguration
{
Q_GADGET
Q_PROPERTY(QString publicFolder MEMBER publicFolder)
public:
QString publicFolder;
bool restServerEnabled = false;
bool operator==(const WebServerConfiguration &other) const {
return ServerConfiguration::operator==(other)
&& publicFolder == other.publicFolder
&& restServerEnabled == other.restServerEnabled;
}
};
class TunnelProxyServerConfiguration: public ServerConfiguration
{
Q_GADGET
Q_PROPERTY(bool ignoreSslErrors MEMBER ignoreSslErrors)
public:
bool ignoreSslErrors = false;
bool operator==(const TunnelProxyServerConfiguration &other) const {
return ServerConfiguration::operator==(other)
&& ignoreSslErrors == other.ignoreSslErrors;
}
};
QDebug operator <<(QDebug debug, const TunnelProxyServerConfiguration &configuration);
class MqttPolicy
{
Q_GADGET

View File

@ -169,7 +169,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
foreach (const TunnelProxyServerConfiguration &config, configuration->tunnelProxyServerConfigurations()) {
TunnelProxyServer *tunnelProxyServer = new TunnelProxyServer(configuration->serverName(), configuration->serverUuid(), config, this);
qCDebug(dcServerManager()) << "Creating tunnel proxy server" << config;
qCDebug(dcServerManager()) << "Creating tunnel proxy server using" << config;
m_tunnelProxyServers.insert(config.id, tunnelProxyServer);
connect(tunnelProxyServer, &TunnelProxyServer::runningChanged, this, [this, tunnelProxyServer](bool running){
if (running) {
@ -183,10 +183,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
// FIXME: make use of SSL over tunnel proxy connections
// FIXME: make sure the authentication is enabled for the tunnel proxy
// Note: only start the tunnel proxy server if cloud is connected
if (configuration->cloudEnabled()) {
tunnelProxyServer->startServer();
}
tunnelProxyServer->startServer();
}
foreach (const WebServerConfiguration &config, configuration->webServerConfigurations()) {
@ -248,12 +245,12 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
ServerConfiguration config = NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id);
TcpServer *server = m_tcpServers.value(id);
if (server) {
qDebug(dcServerManager()) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
qCDebug(dcServerManager()) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
unregisterZeroConfService(config.id, "tcp");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcServerManager()) << "Received a TCP Server config change event but don't have a TCP Server instance for it. Creating new Server instance.";
qCDebug(dcServerManager()) << "Received a TCP Server config change event but don't have a TCP Server instance for it. Creating new Server instance.";
server = new TcpServer(config, m_sslConfiguration, this);
m_tcpServers.insert(config.id, server);
}
@ -266,7 +263,7 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
void ServerManager::tcpServerConfigurationRemoved(const QString &id)
{
if (!m_tcpServers.contains(id)) {
qWarning(dcServerManager()) << "Received a TCP Server config removed event but don't have a TCP Server instance for it.";
qCWarning(dcServerManager()) << "Received a TCP Server config removed event but don't have a TCP Server instance for it.";
return;
}
TcpServer *server = m_tcpServers.take(id);
@ -281,12 +278,12 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
WebSocketServer *server = m_webSocketServers.value(id);
ServerConfiguration config = NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id);
if (server) {
qDebug(dcServerManager()) << "Restarting WebSocket server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
qCDebug(dcServerManager()) << "Restarting WebSocket server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
unregisterZeroConfService(id, "ws");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcServerManager()) << "Received a WebSocket Server config change event but don't have a WebSocket Server instance for it. Creating new instance.";
qCDebug(dcServerManager()) << "Received a WebSocket Server config change event but don't have a WebSocket Server instance for it. Creating new instance.";
server = new WebSocketServer(config, m_sslConfiguration, this);
m_webSocketServers.insert(server->configuration().id, server);
}
@ -299,7 +296,7 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
void ServerManager::webSocketServerConfigurationRemoved(const QString &id)
{
if (!m_webSocketServers.contains(id)) {
qWarning(dcServerManager()) << "Received a WebSocket Server config removed event but don't have a WebSocket Server instance for it.";
qCWarning(dcServerManager()) << "Received a WebSocket Server config removed event but don't have a WebSocket Server instance for it.";
return;
}
WebSocketServer *server = m_webSocketServers.take(id);
@ -314,12 +311,12 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
WebServerConfiguration config = NymeaCore::instance()->configuration()->webServerConfigurations().value(id);
WebServer *server = m_webServers.value(id);
if (server) {
qDebug(dcServerManager()) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
qCDebug(dcServerManager()) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
unregisterZeroConfService(id, "http");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcServerManager()) << "Received a Web Server config change event but don't have a Web Server instance for it. Creating new WebServer instance on" << config.address << config.port << "(SSL:" << config.sslEnabled << ")";
qCDebug(dcServerManager()) << "Received a Web Server config change event but don't have a Web Server instance for it. Creating new WebServer instance on" << config.address << config.port << "(SSL:" << config.sslEnabled << ")";
server = new WebServer(config, m_sslConfiguration, this);
m_webServers.insert(config.id, server);
}
@ -331,7 +328,7 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
void ServerManager::webServerConfigurationRemoved(const QString &id)
{
if (!m_webServers.contains(id)) {
qWarning(dcServerManager()) << "Received a Web Server config removed event but don't have a Web Server instance for it.";
qCWarning(dcServerManager()) << "Received a Web Server config removed event but don't have a Web Server instance for it.";
return;
}
WebServer *server = m_webServers.take(id);
@ -373,23 +370,31 @@ void ServerManager::tunnelProxyServerConfigurationChanged(const QString &id)
TunnelProxyServer *server = m_tunnelProxyServers.value(id);
TunnelProxyServerConfiguration config = NymeaCore::instance()->configuration()->tunnelProxyServerConfigurations().value(id);
if (server) {
qDebug(dcServerManager()) << "Restarting tunnel proxy connection for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
unregisterZeroConfService(id, "ws");
qCDebug(dcServerManager()) << "Restarting tunnel proxy connection using" << config;
server->stopServer();
server->setConfiguration(config);
server->setTunnelProxyConfig(config);
} else {
qDebug(dcServerManager()) << "Received a tunnel proxy config change event but don't have a WebSocket Server instance for it. Creating new instance.";
qCDebug(dcServerManager()) << "Received a tunnel proxy config change event but don't have a tunnel proxy server instance for it.";
qCDebug(dcServerManager()) << "Creating tunnel proxy server using" << config;
server = new TunnelProxyServer(m_nymeaConfiguration->serverName(), m_nymeaConfiguration->serverUuid(), config, this);
m_tunnelProxyServers.insert(server->configuration().id, server);
connect(server, &TunnelProxyServer::runningChanged, this, [this, server](bool running){
if (running) {
// Note: enable authentication in any case, we don't want to expose unprotected access trough the internet
m_jsonServer->registerTransportInterface(server, true);
} else {
m_jsonServer->unregisterTransportInterface(server);
}
});
}
m_jsonServer->registerTransportInterface(server, config.authenticationEnabled);
server->startServer();
}
void ServerManager::tunnelProxyServerConfigurationRemoved(const QString &id)
{
if (!m_tunnelProxyServers.contains(id)) {
qWarning(dcServerManager()) << "Received a tunnel proxy config removed event but don't have a tunnel proxy connection for it.";
qCWarning(dcServerManager()) << "Received a tunnel proxy config removed event but don't have a tunnel proxy connection for it.";
return;
}
TunnelProxyServer *server = m_tunnelProxyServers.take(id);

View File

@ -37,7 +37,7 @@ namespace nymeaserver {
TunnelProxyServer::TunnelProxyServer(const QString &serverName, const QUuid &serverUuid, const TunnelProxyServerConfiguration &configuration, QObject *parent) :
TransportInterface(configuration, parent),
m_config(configuration),
m_tunnelProxyConfig(configuration),
m_serverName(serverName),
m_serverUuid(serverUuid)
{
@ -47,9 +47,7 @@ TunnelProxyServer::TunnelProxyServer(const QString &serverName, const QUuid &ser
qCWarning(dcTunnelProxyServer()) << "=====================================================================================================================";
}
m_serverUrl.setScheme(configuration.sslEnabled ? "ssl" : "tcp");
m_serverUrl.setHost(configuration.address);
m_serverUrl.setPort(configuration.port);
initConfiguration();
m_tunnelProxySocketServer = new TunnelProxySocketServer(m_serverUuid, m_serverName, this);
connect(m_tunnelProxySocketServer, &TunnelProxySocketServer::stateChanged, this, &TunnelProxyServer::onStateChanged);
@ -99,8 +97,15 @@ void TunnelProxyServer::setServerName(const QString &serverName)
m_serverName = serverName;
}
void TunnelProxyServer::setTunnelProxyConfig(const TunnelProxyServerConfiguration &tunnelProxyConfig)
{
m_tunnelProxyConfig = tunnelProxyConfig;
}
bool TunnelProxyServer::startServer()
{
initConfiguration();
qCDebug(dcTunnelProxyServer()) << "Connecting to tunnel proxy server at:" << m_serverUrl;
m_tunnelProxySocketServer->startServer(m_serverUrl);
return true;
@ -142,8 +147,7 @@ void TunnelProxyServer::onServerErrorOccurred(TunnelProxySocketServer::Error err
void TunnelProxyServer::onSslErrors(const QList<QSslError> &errors)
{
qCDebug(dcTunnelProxyServer()) << "Remote proxy connection SSL errors occurred" << errors;
// FIXME: make this configurable
if (m_config.ignoreSslErrors) {
if (m_tunnelProxyConfig.ignoreSslErrors) {
qCWarning(dcTunnelProxyServer()) << "Ingoring SSL errors on tunnel proxy connection:" << errors;
m_tunnelProxySocketServer->ignoreSslErrors();
} else {
@ -172,4 +176,13 @@ void TunnelProxyServer::onClientDisconnected(TunnelProxySocket *tunnelProxySocke
emit clientDisconnected(clientId);
}
void TunnelProxyServer::initConfiguration()
{
qCDebug(dcTunnelProxyServer()) << "Init configuration" << m_tunnelProxyConfig;
m_serverUrl.setScheme(m_tunnelProxyConfig.sslEnabled ? "ssl" : "tcp");
m_serverUrl.setHost(m_tunnelProxyConfig.address);
m_serverUrl.setPort(m_tunnelProxyConfig.port);
qCDebug(dcTunnelProxyServer()) << "Using server URL" << m_serverUrl.toString();
}
}

View File

@ -57,6 +57,8 @@ public:
public slots:
void setServerName(const QString &serverName) override;
void setTunnelProxyConfig(const TunnelProxyServerConfiguration &tunnelProxyConfig);
bool startServer() override;
bool stopServer() override;
@ -74,7 +76,7 @@ private slots:
void onClientDisconnected(TunnelProxySocket *tunnelProxySocket);
private:
TunnelProxyServerConfiguration m_config;
TunnelProxyServerConfiguration m_tunnelProxyConfig;
TunnelProxySocketServer *m_tunnelProxySocketServer = nullptr;
QString m_serverName;
QUuid m_serverUuid;
@ -82,6 +84,8 @@ private:
QHash<QUuid, TunnelProxySocket *> m_clients;
void initConfiguration();
};
}