Add insecure websocket support and start with tcp server support

This commit is contained in:
Simon Stürz 2019-06-06 15:39:00 +02:00 committed by Simon Stürz
parent df5a240189
commit 9fd2a3440f
16 changed files with 204 additions and 22 deletions

View File

@ -72,10 +72,10 @@ void Engine::start(ProxyConfiguration *configuration)
Q_ASSERT_X(m_authenticator != nullptr, "Engine", "There is no authenticator registerd.");
m_proxyServer = new ProxyServer(this);
m_webSocketServer = new WebSocketServer(m_configuration->sslConfiguration(), this);
m_webSocketServer = new WebSocketServer(m_configuration->sslEnabled(), m_configuration->sslConfiguration(), this);
QUrl websocketServerUrl;
websocketServerUrl.setScheme("wss");
websocketServerUrl.setScheme(m_configuration->sslEnabled() ? "wss" : "ws");
websocketServerUrl.setHost(m_configuration->webSocketServerHost().toString());
websocketServerUrl.setPort(m_configuration->webSocketServerPort());

View File

@ -71,6 +71,7 @@ bool ProxyConfiguration::loadConfiguration(const QString &fileName)
settings.endGroup();
settings.beginGroup("SSL");
setSslEnabled(settings.value("enabled", true).toBool());
setSslCertificateFileName(settings.value("certificate", "/etc/ssl/certs/ssl-cert-snakeoil.pem").toString());
setSslCertificateKeyFileName(settings.value("certificateKey", "/etc/ssl/private/ssl-cert-snakeoil.key").toString());
setSslCertificateChainFileName(settings.value("certificateChain", "").toString());
@ -256,6 +257,16 @@ void ProxyConfiguration::setAwsCredentialsUrl(const QUrl &url)
m_awsCredentialsUrl = url;
}
bool ProxyConfiguration::sslEnabled() const
{
return m_sslEnabled;
}
void ProxyConfiguration::setSslEnabled(bool enabled)
{
m_sslEnabled = enabled;
}
QString ProxyConfiguration::sslCertificateFileName() const
{
return m_sslCertificateFileName;
@ -349,6 +360,7 @@ QDebug operator<<(QDebug debug, ProxyConfiguration *configuration)
debug.nospace() << " - Authorizer lambda function:" << configuration->awsAuthorizerLambdaFunctionName() << endl;
debug.nospace() << " - Credentials URL:" << configuration->awsCredentialsUrl().toString() << endl;
debug.nospace() << "SSL configuration" << endl;
debug.nospace() << " - Enabled:" << configuration->sslEnabled() << endl;
debug.nospace() << " - Certificate:" << configuration->sslCertificateFileName() << endl;
debug.nospace() << " - Certificate key:" << configuration->sslCertificateKeyFileName() << endl;
debug.nospace() << " - Certificate chain:" << configuration->sslCertificateChainFileName() << endl;

View File

@ -85,6 +85,9 @@ public:
void setAwsCredentialsUrl(const QUrl &url);
// Ssl
bool sslEnabled() const;
void setSslEnabled(bool enabled);
QString sslCertificateFileName() const;
void setSslCertificateFileName(const QString &fileName);
@ -130,6 +133,7 @@ private:
QUrl m_awsCredentialsUrl;
// Ssl
bool m_sslEnabled = true;
QString m_sslCertificateFileName = "/etc/ssl/certs/ssl-cert-snakeoil.pem";
QString m_sslCertificateKeyFileName = "/etc/ssl/private/ssl-cert-snakeoil.key";
QString m_sslCertificateChainFileName;

View File

@ -32,8 +32,9 @@
namespace remoteproxy {
WebSocketServer::WebSocketServer(const QSslConfiguration &sslConfiguration, QObject *parent) :
WebSocketServer::WebSocketServer(bool sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent) :
TransportInterface(parent),
m_sslEnabled(sslEnabled),
m_sslConfiguration(sslConfiguration)
{
m_serverName = "Websocket server";
@ -181,8 +182,12 @@ void WebSocketServer::onServerError(QWebSocketProtocol::CloseCode closeCode)
bool WebSocketServer::startServer()
{
m_server = new QWebSocketServer(QCoreApplication::applicationName(), QWebSocketServer::SecureMode, this);
m_server->setSslConfiguration(sslConfiguration());
if (m_sslEnabled) {
m_server = new QWebSocketServer(QCoreApplication::applicationName(), QWebSocketServer::SecureMode, this);
m_server->setSslConfiguration(sslConfiguration());
} else {
m_server = new QWebSocketServer(QCoreApplication::applicationName(), QWebSocketServer::NonSecureMode, this);
}
connect (m_server, &QWebSocketServer::newConnection, this, &WebSocketServer::onClientConnected);
connect (m_server, &QWebSocketServer::acceptError, this, &WebSocketServer::onAcceptError);

View File

@ -43,7 +43,7 @@ class WebSocketServer : public TransportInterface
{
Q_OBJECT
public:
explicit WebSocketServer(const QSslConfiguration &sslConfiguration, QObject *parent = nullptr);
explicit WebSocketServer(bool sslEnabled, const QSslConfiguration &sslConfiguration, QObject *parent = nullptr);
~WebSocketServer() override;
QUrl serverUrl() const;
@ -59,6 +59,7 @@ public:
private:
QUrl m_serverUrl;
QWebSocketServer *m_server = nullptr;
bool m_sslEnabled;
QSslConfiguration m_sslConfiguration;
bool m_enabled = false;

View File

@ -1,6 +1,7 @@
INCLUDEPATH += $${PWD}
HEADERS += \
$$PWD/tcpsocketconnection.h \
$${PWD}/proxyjsonrpcclient.h \
$${PWD}/jsonreply.h \
$${PWD}/remoteproxyconnection.h \
@ -8,6 +9,7 @@ HEADERS += \
$${PWD}/websocketconnection.h
SOURCES += \
$$PWD/tcpsocketconnection.cpp \
$${PWD}/proxyjsonrpcclient.cpp \
$${PWD}/jsonreply.cpp \
$${PWD}/remoteproxyconnection.cpp \

View File

@ -34,6 +34,11 @@ ProxyConnection::ProxyConnection(QObject *parent) : QObject(parent)
}
QUrl ProxyConnection::serverUrl() const
{
return m_serverUrl;
}
bool ProxyConnection::connected()
{
return m_connected;
@ -48,6 +53,11 @@ void ProxyConnection::setConnected(bool connected)
emit connectedChanged(m_connected);
}
void ProxyConnection::setServerUrl(const QUrl &serverUrl)
{
m_serverUrl = serverUrl;
}
ProxyConnection::~ProxyConnection()
{

View File

@ -28,6 +28,7 @@
#ifndef SOCKETCONNECTOR_H
#define SOCKETCONNECTOR_H
#include <QUrl>
#include <QObject>
#include <QSslError>
#include <QHostAddress>
@ -43,7 +44,7 @@ public:
virtual void sendData(const QByteArray &data) = 0;
virtual QUrl serverUrl() const = 0;
QUrl serverUrl() const;
virtual void ignoreSslErrors() = 0;
virtual void ignoreSslErrors(const QList<QSslError> &errors) = 0;
@ -52,9 +53,11 @@ public:
private:
bool m_connected = false;
QUrl m_serverUrl;
protected:
void setConnected(bool connected);
void setServerUrl(const QUrl &serverUrl);
signals:
void connectedChanged(bool connected);

View File

@ -43,6 +43,15 @@ RemoteProxyConnection::RemoteProxyConnection(const QUuid &clientUuid, const QStr
}
RemoteProxyConnection::RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, RemoteProxyConnection::ConnectionType connectionType, QObject *parent) :
QObject(parent),
m_clientUuid(clientUuid),
m_clientName(clientName),
m_connectionType(connectionType)
{
}
RemoteProxyConnection::~RemoteProxyConnection()
{

View File

@ -69,6 +69,7 @@ public:
Q_ENUM(State)
explicit RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, QObject *parent = nullptr);
RemoteProxyConnection(const QUuid &clientUuid, const QString &clientName, ConnectionType connectionType, QObject *parent = nullptr);
~RemoteProxyConnection();
RemoteProxyConnection::State state() const;
@ -94,9 +95,9 @@ public:
QString tunnelPartnerUuid() const;
private:
ConnectionType m_connectionType = ConnectionTypeWebSocket;
QUuid m_clientUuid;
QString m_clientName;
ConnectionType m_connectionType = ConnectionTypeWebSocket;
QUrl m_serverUrl;

View File

@ -0,0 +1,95 @@
#include "tcpsocketconnection.h"
Q_LOGGING_CATEGORY(dcRemoteProxyClientTcpSocket, "RemoteProxyClientTcpSocket")
namespace remoteproxyclient {
TcpSocketConnection::TcpSocketConnection(QObject *parent) :
ProxyConnection(parent)
{
m_tcpSocket = new QSslSocket(this);
connect(m_tcpSocket, &QSslSocket::disconnected, this, &TcpSocketConnection::onDisconnected);
connect(m_tcpSocket, &QSslSocket::encrypted, this, &TcpSocketConnection::onEncrypted);
connect(m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
connect(m_tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onStateChanged(QAbstractSocket::SocketState)));
connect(m_tcpSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SIGNAL(sslErrors(QList<QSslError>)));
}
TcpSocketConnection::~TcpSocketConnection()
{
m_tcpSocket->close();
}
void TcpSocketConnection::sendData(const QByteArray &data)
{
m_tcpSocket->write(data);
}
void TcpSocketConnection::ignoreSslErrors()
{
m_tcpSocket->ignoreSslErrors();
}
void TcpSocketConnection::ignoreSslErrors(const QList<QSslError> &errors)
{
m_tcpSocket->ignoreSslErrors(errors);
}
void TcpSocketConnection::onDisconnected()
{
qCDebug(dcRemoteProxyClientTcpSocket()) << "Disconnected from" << serverUrl().toString();
setConnected(false);
}
void TcpSocketConnection::onEncrypted()
{
qCDebug(dcRemoteProxyClientTcpSocket()) << "Connection encrypted";
}
void TcpSocketConnection::onError(QAbstractSocket::SocketError error)
{
qCDebug(dcRemoteProxyClientTcpSocket()) << "Socket error occured" << error << m_tcpSocket->errorString();
emit errorOccured(error);
}
void TcpSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
{
qCDebug(dcRemoteProxyClientTcpSocket()) << "Socket state changed" << state;
switch (state) {
case QAbstractSocket::ConnectedState:
qCDebug(dcRemoteProxyClientTcpSocket()) << "Connected with" << serverUrl().toString();
setConnected(true);
break;
default:
setConnected(false);
break;
}
emit stateChanged(state);
}
void TcpSocketConnection::onReadyRead()
{
emit dataReceived(m_tcpSocket->readAll());
}
void TcpSocketConnection::connectServer(const QUrl &serverUrl)
{
qCDebug(dcRemoteProxyClientTcpSocket()) << "Connecting to" << this->serverUrl().toString();
setServerUrl(serverUrl);
if (serverUrl.scheme() == "tcp") {
m_tcpSocket->connectToHost(QHostAddress(this->serverUrl().host()), static_cast<quint16>(this->serverUrl().port()));
} else {
m_tcpSocket->connectToHostEncrypted(this->serverUrl().host(), static_cast<quint16>(this->serverUrl().port()));
}
}
void TcpSocketConnection::disconnectServer()
{
qCDebug(dcRemoteProxyClientTcpSocket()) << "Disconnecting from" << serverUrl().toString();
m_tcpSocket->close();
}
}

View File

@ -0,0 +1,46 @@
#ifndef TCPSOCKETCONNECTION_H
#define TCPSOCKETCONNECTION_H
#include <QObject>
#include <QTcpSocket>
#include <QSslSocket>
#include <QLoggingCategory>
#include "proxyconnection.h"
Q_DECLARE_LOGGING_CATEGORY(dcRemoteProxyClienTcpSocket)
namespace remoteproxyclient {
class TcpSocketConnection : public ProxyConnection
{
Q_OBJECT
public:
explicit TcpSocketConnection(QObject *parent = nullptr);
~TcpSocketConnection() override;
void sendData(const QByteArray &data) override;
void ignoreSslErrors() override;
void ignoreSslErrors(const QList<QSslError> &errors) override;
private:
QSslSocket *m_tcpSocket = nullptr;
private slots:
void onDisconnected();
void onEncrypted();
void onError(QAbstractSocket::SocketError error);
void onStateChanged(QAbstractSocket::SocketState state);
void onReadyRead();
public slots:
void connectServer(const QUrl &serverUrl) override;
void disconnectServer() override;
};
}
#endif // TCPSOCKETCONNECTION_H

View File

@ -49,11 +49,6 @@ WebSocketConnection::~WebSocketConnection()
m_webSocket->close();
}
QUrl WebSocketConnection::serverUrl() const
{
return m_serverUrl;
}
void WebSocketConnection::sendData(const QByteArray &data)
{
m_webSocket->sendTextMessage(QString::fromUtf8(data + '\n'));
@ -108,10 +103,10 @@ void WebSocketConnection::connectServer(const QUrl &serverUrl)
if (connected()) {
m_webSocket->close();
}
setServerUrl(serverUrl);
m_serverUrl = serverUrl;
qCDebug(dcRemoteProxyClientWebSocket()) << "Connecting to" << m_serverUrl.toString();
m_webSocket->open(m_serverUrl);
qCDebug(dcRemoteProxyClientWebSocket()) << "Connecting to" << this->serverUrl().toString();
m_webSocket->open(this->serverUrl());
}
void WebSocketConnection::disconnectServer()

View File

@ -46,15 +46,12 @@ public:
explicit WebSocketConnection(QObject *parent = nullptr);
~WebSocketConnection() override;
QUrl serverUrl() const override;
void sendData(const QByteArray &data) override;
void ignoreSslErrors() override;
void ignoreSslErrors(const QList<QSslError> &errors) override;
private:
QUrl m_serverUrl;
QWebSocket *m_webSocket = nullptr;
private slots:

View File

@ -15,6 +15,7 @@ authorizerLambdaFunction=system-services-authorizer-dev-checkToken
awsCredentialsUrl=http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2-Remote-Connection-Proxy-Role
[SSL]
enabled=true
certificate=/etc/ssl/certs/ssl-cert-snakeoil.pem
certificateKey=/etc/ssl/private/ssl-cert-snakeoil.key
certificateChain=

View File

@ -186,9 +186,11 @@ int main(int argc, char *argv[])
}
// Verify SSL configuration
if (configuration->sslConfiguration().isNull()) {
qCCritical(dcApplication()) << "No SSL configuration specified. The server does not suppoert insecure connections.";
if (configuration->sslEnabled() && configuration->sslConfiguration().isNull()) {
qCCritical(dcApplication()) << "SSL is enabled but no SSL configuration specified.";
exit(-1);
} else {
qCDebug(dcApplication()) << "Using SSL version:" << QSslSocket::sslLibraryVersionString();
}
qCDebug(dcApplication()) << "==========================================================";
@ -203,7 +205,6 @@ int main(int argc, char *argv[])
if (s_loggingEnabled)
qCDebug(dcApplication()) << "Logging enabled. Writing logs to" << s_logFile.fileName();
qCDebug(dcApplication()) << "Using SSL version:" << QSslSocket::sslLibraryVersionString();
Authenticator *authenticator = nullptr;
if (parser.isSet(mockAuthenticatorOption)) {