Verwandeln Sie einen einfachen Socket in einen SSL-Socket

Lesezeit: 7 Minuten

Benutzeravatar von David Mape
David Mape

Ich habe einfache C-Programme geschrieben, die Sockets (‘client’ und ‘server’) verwenden. (UNIX/Linux-Nutzung)

Die Serverseite erstellt einfach einen Socket:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

Und bindet es dann an sockaddr:

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

Und hört zu (und akzeptiert und liest):

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
read(newsockfd,buffer,255);

Der Client erstellt den Socket und schreibt dann darauf.

Nun möchte ich diese einfache Verbindung auf die einfachste, idyllischste, sauberste und schnellste Weise in eine SSL-Verbindung umwandeln.

Ich habe versucht hinzuzufügen OpenSSL zu meinem Projekt, aber ich finde keinen einfachen Weg, um das umzusetzen, was ich will.

  • Wenn Sie eher nach “einer sicheren Verbindung” als insbesondere nach SSL suchen, könnten Sie sich etwas wie anschauen Proxychains.sourceforge.net die sich außerhalb Ihrer Anwendung befindet, und richten Sie diese so ein, dass Datenverkehr über eine SSH-Verbindung gesendet wird. In Bezug auf SSL in der Anwendung ist OpenSSL ziemlich einfach, wenn Sie verstehen, wie SSL/TLS funktionieren soll. Wenn Sie eine Alternative wünschen, versuchen Sie es mit yaSSL oder gnuTLS .

    – Borealis

    8. Oktober 2011 um 17:23 Uhr

  • Definiere “einfacher Weg”. OpenSSL ist der Standard für C-Programmierer. Wenn Sie damit Schwierigkeiten haben, sollten Sie danach fragen.

    – Benutzer207421

    25. April 2013 um 1:57 Uhr

  • Überprüfen Sie diese Eine Einführung in die OpenSSL-Programmierung (Teil I). Teil II ist zu fortgeschritten und schwierig für mich. Aber Teil 2 ist einen Blick wert.

    – Rick

    21. November 2019 um 14:18 Uhr


  • Überprüfen Sie auch Sichere Programmierung mit der OpenSSL-API. Aber ich habe gerade Meinungen darüber gehört, wie schlecht Openssl ist und andere Alternativen einen Versuch wert sind.

    – Rick

    21. November 2019 um 15:08 Uhr


  • Eine weitere Option ist die Verwendung eines externen SSL-Wrapper-Tools wie z stunneldas stunnel4 Das Paket befindet sich in Debian-basierten Distributionen und ist einfach zu verwenden. Es gibt einige Einschränkungen im Vergleich zum Hinzufügen einer ordnungsgemäßen SSL-Unterstützung in Ihrem Server, aber es kann für eine schnelle Lösung gut sein. Ich mag Stunnel, weil es zum Ansatz der UNIX-Softwaretools zu passen scheint.

    – Sam Watkins

    5. Juli 2020 um 5:06 Uhr


Benutzeravatar von CaptainBli
KapitänBli

Bei der Verwendung von OpenSSL sind mehrere Schritte erforderlich. Sie müssen ein SSL-Zertifikat erstellen lassen, das das Zertifikat mit dem privaten Schlüssel enthalten kann. Achten Sie darauf, den genauen Speicherort des Zertifikats anzugeben (in diesem Beispiel befindet es sich im Stammverzeichnis). Es gibt viele gute Tutorials da draußen.

Einige beinhalten:

#include <openssl/applink.c>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

Sie müssen OpenSSL initialisieren:

void InitializeSSL()
{
    SSL_load_error_strings();
    SSL_library_init();
    OpenSSL_add_all_algorithms();
}

void DestroySSL()
{
    ERR_free_strings();
    EVP_cleanup();
}

void ShutdownSSL()
{
    SSL_shutdown(cSSL);
    SSL_free(cSSL);
}

Nun zum Großteil der Funktionalität. Möglicherweise möchten Sie Verbindungen eine While-Schleife hinzufügen.

int sockfd, newsockfd;
SSL_CTX *sslctx;
SSL *cSSL;

InitializeSSL();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd< 0)
{
    //Log and Error
    return;
}
struct sockaddr_in saiServerAddress;
bzero((char *) &saiServerAddress, sizeof(saiServerAddress));
saiServerAddress.sin_family = AF_INET;
saiServerAddress.sin_addr.s_addr = serv_addr;
saiServerAddress.sin_port = htons(aPortNumber);

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

sslctx = SSL_CTX_new( SSLv23_server_method());
SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
int use_cert = SSL_CTX_use_certificate_file(sslctx, "/serverCertificate.pem" , SSL_FILETYPE_PEM);

int use_prv = SSL_CTX_use_PrivateKey_file(sslctx, "/serverCertificate.pem", SSL_FILETYPE_PEM);

cSSL = SSL_new(sslctx);
SSL_set_fd(cSSL, newsockfd );
//Here is the SSL Accept portion.  Now all reads and writes must use SSL
ssl_err = SSL_accept(cSSL);
if(ssl_err <= 0)
{
    //Error occurred, log and close down ssl
    ShutdownSSL();
}

Sie können dann lesen oder schreiben mit:

SSL_read(cSSL, (char *)charBuffer, nBytesToRead);
SSL_write(cSSL, "Hi :3\n", 6);

Aktualisieren
Das SSL_CTX_new sollte stattdessen mit der TLS-Methode aufgerufen werden, die Ihren Anforderungen am besten entspricht, um die neueren Sicherheitsversionen zu unterstützen SSLv23_server_method(). Sehen:
OpenSSL SSL_CTX_neue Beschreibung

TLS_method(), TLS_server_method(), TLS_client_method().
Dies sind die allgemeinen Zwecke version-flexibel SSL/TLS-Methoden. Die tatsächlich verwendete Protokollversion wird auf die höchste Version ausgehandelt, die von Client und Server gegenseitig unterstützt wird. Die unterstützten Protokolle sind SSLv3, TLSv1, TLSv1.1, TLSv1.2 und TLSv1.3.

  • nicht so “einfach” wie ich dachte, aber endlich (Gott sei Dank!) sehe ich etwas Code. Ist das plattformübergreifend oder nur für Unix/Unix-ähnliche Systeme?

    – Juliomalegrie

    1. Mai 2013 um 23:55 Uhr


  • Ich habe ähnlichen Code auf mehreren Plattformen verwendet: Arm, Linux und Windows.

    – CaptainBli

    15. September 2013 um 16:11 Uhr

  • Letzte if ist doch falsch. Es sollte sein if (ssl_err <= 0) { nur dann ist es ein Fehler. SSL_accept() kehrt zurück 1 auf Erfolg, 0 auf “kontrolliertes Versagen” und -1 auf “fataler Ausfall”. Siehe Manpage.

    – Jite

    25. August 2014 um 12:02 Uhr

  • Außerdem funktionieren DH-Chiffren nicht, wenn SSL_CTX_set_tmp_dh[_callback]() wird nicht gerufen. Habe gerade auf die harte Tour herausgefunden, dass aNULL-Chiffren ohne sie nicht funktionieren und Alarm Nummer 40 erzeugen.

    – Roman Dmitrienko

    19. Juli 2015 um 15:37 Uhr

  • @DevNull Das SSLv23_server_method() gibt an, dass der Server SSLv2 und v3 versteht und nun veraltet ist. Um TLS 1.1 und 1.2 zu unterstützen, ersetzen Sie diese Methode durch TLS_server_method(). Quelle

    – ezPaint

    23. Juni 2016 um 15:21 Uhr


OpenSSL ist ziemlich schwierig. Es ist leicht, versehentlich Ihre gesamte Sicherheit wegzuwerfen, indem Sie die Verhandlungen nicht genau richtig führen. (Verdammt, ich wurde persönlich von einem Fehler gebissen, bei dem Curl die OpenSSL-Warnungen nicht genau richtig las und mit einigen Websites nicht kommunizieren konnte.)

Wenn Sie wirklich schnell und einfach wollen, setzen Sie Zucht vor Ihrem Programm und nennen Sie es einen Tag. SSL in einem anderen Prozess zu haben, wird Sie nicht verlangsamen: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html

  • Dies ist eine praktische Antwort, aber sie beantwortet die Frage nicht wirklich.

    – Schweizerisch

    1. Mai 2013 um 23:50 Uhr

  • STUD wurde 2016 aufgegeben. Die Readme empfiehlt: github.com/varnish/hitch

    – Karl

    26. Dezember 2016 um 20:54 Uhr

Benutzeravatar von 18446744073709551615
18446744073709551615

Für andere wie mich:

Da war mal ein Beispiel in der SSL-Quelle im Verzeichnis demos/ssl/ mit Beispielcode in C++. Jetzt ist es nur über den Verlauf verfügbar:
https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

Sie müssen wahrscheinlich eine funktionierende Version finden, ich habe diese Antwort ursprünglich am 6. November 2015 gepostet. Und ich musste die Quelle bearbeiten – nicht viel.

Zertifikate: .pem ein demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps

Wie Sie gesehen haben, ist es ziemlich haarig. Aber der “einfache” Teil ist, nachdem Sie Ihre SSL/TLS-Sitzung mit OpenSSL eingerichtet haben, ist das Muster, dem Sie zum Lesen/Schreiben auf einem Socket für HTTPS folgen, dasselbe wie das, dem Sie für HTTP folgen.

Der Unterschied ist, dass Sie die verwenden SSL_read/SSL_write Funktionen statt der read/write Funktionen. Das SSL_read/SSL_write Funktionen nehmen ein SSL Zeiger als erstes Argument anstelle eines Dateideskriptors.

Wie auch immer, hier ist ein voll funktionsfähiges OpenSSL-Beispiel für eine Unix-Umgebung mit Kompilierungs-/Ausführungsanweisungen, APT-Abhängigkeiten und Referenzen. Es ist nur ein weiterer funktionierender Code, an dem Sie sich die Zähne ausbeißen können.

Bei erfolgreicher Kompilierung wird eine Warnung zu einer veralteten OpenSSL-Funktion angezeigt.

Bei erfolgreicher Ausführung wird der Betreff des TLS-Zertifikats von example.com in der Standardausgabe ausgegeben, gefolgt vom HTML-Inhalt von example.com.

https://github.com/angstyloop/c-web/blob/main/openssl-fetch-example.c

Getestet auf Ubuntu 22.04.

Hier meine Beispiel-SSL-Socket-Server-Threads (Mehrfachverbindung) https://github.com/breakermind/CppLinux/blob/master/QtSslServerThreads/breakermindsslserver.cpp

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <iostream>

#include <breakermindsslserver.h>

using namespace std;

int main(int argc, char *argv[])
{
    BreakermindSslServer boom;
    boom.Start(123,"/home/user/c++/qt/BreakermindServer/certificate.crt", "/home/user/c++/qt/BreakermindServer/private.key");
    return 0;
}

  • Bitte fügen Sie die Lösung direkt in Ihren SO-Beitrag ein.

    – Maciej Jureczko

    8. November 2017 um 11:26 Uhr

  • Bitte fügen Sie die Lösung direkt in Ihren SO-Beitrag ein.

    – Maciej Jureczko

    8. November 2017 um 11:26 Uhr

1423470cookie-checkVerwandeln Sie einen einfachen Socket in einen SSL-Socket

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy