Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Encrypted TCP connection between client and server with dynamic server domain



  • Hello!
    I want to create some applications with asymetric encrypted connection over TCP.
    I think, the most easy way is using QSslSocket and QSslServer, but server and clients locate inside local network without internet.
    Additionally, server has dynamic IP (and report himself IP to clients using broadcast UDP). In this case client must to ignore QSslError::HostNameMismatch so in this case certificate of the server has no effect.

    What is better way to set encrypted connection between clients and server if we can to share public keys before start?
    Thanks)))


  • Lifetime Qt Champion

    Hi,

    How do you generate the certificates ?



  • @SGaist using openssl))


  • Lifetime Qt Champion

    You might want to provide more information about the procedure you use as well as the parameters you use.



  • @SGaist I'm sorry for delay)))
    I build the certificate using:

    openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.cert
    openssl req -newkey rsa:2048 -nodes -keyout client.key -x509 -days 365 -out client.cert
    

    Then i use server.key as my private key and server.cert as certificate.
    For QWebSocketServer (on server side):

    QWebSocketServer server(QWebSocketServer::SecureMode);
    QSslConfiguration m_sslConfiguration;
    m_sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyPeer);
    m_sslConfiguration.setLocalCertificate(QSslCertificate(<server.cert>));
    m_sslConfiguration.setPrivateKey(QSslKey(<server.key>, QSsl::Rsa, QSsl::Pem));
    // add client's certificate
    QList<QSslCertificate>	newCertificates{QSslCertificate(<client.cert>, QSsl::Pem)};
    m_sslConfiguration.setCaCertificates(newCertificates);
    server->setSslConfiguration(m_sslConfiguration);
    

    On client side:

    auto m_socket = new QWebSocket;
    // ignore HostNameMismatch(!!!) and SelfSignedCertificate
    connect(m_socket, &QWebSocket::sslErrors, [this](const QList<QSslError> &errors) {
    		// search not ignnorable errors
    		auto it = std::find_if(errors.constBegin(), errors.constEnd(), [](const QSslError &e){
    			static const QList<QSslError>	ignorableErrors{QSslError::HostNameMismatch, QSslError::SelfSignedCertificate};
    			return !ignorableErrors.contains(e);
    		});
    		if (it != errors.constEnd()) return m_socket->ignoreSslErrors();
    	});
    // set our certificate and key
    QSslConfiguration	conf;
    conf.setPeerVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone);
    conf.setLocalCertificate(<client.cert>);
    conf.setPrivateKey(<client.key>);
    m_socket->setSslConfiguration(conf);
    
    

    So, that works but we are ignore HostNameMismatch because server's host name is dynamic but i still need to set certificate on server side because that doesn't work without.

    I have 2 questions:

    1. Can i do not set certificate of server of server side in secure mode?
    2. If not, how to verify certificate on client side if host is dynamic? I tried to enable VerifyPeer and add certificate of server on client side but it's ignoring if HostNameMismatch

    PS: I need to check the certificate of client on server. Checking certificate of server on client is not very impotrant


  • Lifetime Qt Champion

    The host name is dynamic ? How is it generated ?

    No you can't establish a secure connection with only the client having a certificate.



  • @SGaist Client and server locate in local network with DHCP server. Server sends UDP broadcast datagram to report clients about its IP. The IP can be changed, so host name (i.e. IP address) is dynamic


  • Lifetime Qt Champion

    A host name and an IP address are two different things even if related. A host name provides a common name that you can use with a DNS to look up for its IP address.

    Therefore does your target have a fixed name ?



  • @SGaist My target - is IP adress+port in local network. For example, wss://192.168.1.20:3000. There isn't DNS. This IP (192.168.1.20) can be changed in any time.
    PS: I use self-signed certificates to the server and the client



  • @BrMisha said in Encrypted TCP connection between client and server with dynamic server domain:
    At this point, this is a networking problem, not a Qt related issue.

    Given that said,

    This IP (192.168.1.20) can be changed in any time.

    Well, that's not a good use case to use digital certificates issued for IP values. Please keep in mind that the certificate will have a domain name (i.e. google.com) or an IP (192.168.1.1) "embedded" in it, and the machine using such certificate must have either such domain name or such IP. If not, the whole security concept is useless.

    So if you still wants to go assigning a dynamic IP to your server, it looks like you should go with DNS resolution and creating the certificate using domain names.
    You may even want to resort to use the .local domain for your internal LAN.

    PS: I use self-signed certificates to the server and the client

    You may want to take that into account while working with Qt code, see this interesting post.


Log in to reply