Breakermind Temat założony przez niniejszego użytkownika |
C++ ssl socket serwer wiele połączeń z openssl » 2017-08-26 17:18:13 Witam Wszystkich! Napisałem serwer ssl z bibliotekami openssl wiele połączeń (przerobiona wersja tego z tutoriala na stronie openssl): #include <iostream> #include <algorithm> #include <stdio.h> #include <cstdio> #include <unistd.h> #include <string> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <openssl/ssl.h> #include <openssl/err.h>
#include <pthread.h> #include <errno.h> #include <signal.h>
const int readSize = 8192;
char buffer[ 8192 ];
char end[] = "...";
int received, count = 0; int TotalReceived = 0;
int opt = 1;
pid_t pid; int currpid = 0;
#define PORT 3333 int create_socket( int port ) { int s; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons( port ); addr.sin_addr.s_addr = htonl( INADDR_ANY ); s = socket( AF_INET, SOCK_STREAM, 0 ); if( s < 0 ) { perror( "Unable to create socket" ); exit( EXIT_FAILURE ); } if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR,( char * ) & opt, sizeof( opt ) ) < 0 ) { perror( "setsockopt" ); exit( EXIT_FAILURE ); } if( bind( s,( struct sockaddr * ) & addr, sizeof( addr ) ) < 0 ) { perror( "Unable to bind" ); exit( EXIT_FAILURE ); } if( listen( s, 2 ) < 0 ) { perror( "Unable to listen" ); exit( EXIT_FAILURE ); } return s; }
void ShowCerts( SSL * ssl ) { X509 * cert; char * line; cert = SSL_get_peer_certificate( ssl ); if( cert != NULL ) { printf( "Server certificates:\n" ); line = X509_NAME_oneline( X509_get_subject_name( cert ), 0, 0 ); printf( "Subject: %s\n", line ); free( line ); line = X509_NAME_oneline( X509_get_issuer_name( cert ), 0, 0 ); printf( "Issuer: %s\n", line ); free( line ); X509_free( cert ); } else printf( "No certificates.\n" ); }
void init_openssl() { SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); }
void cleanup_openssl() { EVP_cleanup(); }
SSL_CTX * create_context() { const SSL_METHOD * method; SSL_CTX * ctx; method = SSLv23_server_method(); ctx = SSL_CTX_new( method ); if( !ctx ) { perror( "Unable to create SSL context" ); ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } return ctx; }
void configure_context( SSL_CTX * ctx ) { SSL_CTX_set_ecdh_auto( ctx, 1 ); if( SSL_CTX_use_certificate_file( ctx, "certificate.crt", SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } if( SSL_CTX_use_PrivateKey_file( ctx, "private.key", SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } }
int main( int argc, char ** argv ) { SSL_library_init(); int sock; SSL_CTX * ctx; init_openssl(); ctx = create_context(); configure_context( ctx ); sock = create_socket( PORT ); while( 1 ) { int users = 0; struct sockaddr_in addr; uint len = sizeof( addr ); SSL * ssl; const char reply[] = "220 Hello from server\n"; const char reply1[] = "250 Next Command MAIL FROM:\n"; int client = accept( sock,( struct sockaddr * ) & addr, & len ); printf( "Connection: %s:%d\n", inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) ); pid = fork(); if( pid > 0 ) { currpid = pid; fprintf( stderr, "Mam mowego klienta, pid=%d\n", currpid ); continue; } if( client < 0 ) { perror( "Unable to accept" ); exit( EXIT_FAILURE ); } ssl = SSL_new( ctx ); SSL_set_fd( ssl, client ); ShowCerts( ssl ); if( SSL_accept( ssl ) <= 0 ) { ERR_print_errors_fp( stderr ); } else { SSL_write( ssl, reply, strlen( reply ) ); } received = SSL_read( ssl, buffer, readSize ); if( received > 0 ) { TotalReceived += received; printf( "PID %i Buffsize - %i - %.*s \n", getpid(), received, received, buffer ); } int z = 1; while( z == 1 ) { SSL_write( ssl, reply1, strlen( reply1 ) ); received = SSL_read( ssl, buffer, readSize ); if( received > 0 ) { TotalReceived += received; printf( "PID %i Buffsize - %i - %.*s \n", getpid(), received, received, buffer ); } printf( "Client send: %s\n", buffer ); std::string buf = std::string( buffer ); std::string end = std::string( end ); buf = buf.substr( 0, 3 ); ggg = end.substr( 0, 3 ); std::cout << "Compare " << buf.size() << " z " << ggg.size() << " end "; std::cout << "Compare " << std::string( buffer ) << " z " << std::string( end ) << " end "; if( std::string( end ) == std::string( buf ) ) { printf( "%s\n", "End connection " ); z = 0; SSL_shutdown( ssl ); } else { printf( "%s\n", "Working connection" ); } } SSL_free( ssl ); close( client ); } close( sock ); SSL_CTX_free( ctx ); cleanup_openssl(); }
lub link https://github.com/breakermind/CppLinux/blob/master/SslServer/serverSsl.cpp
Kompiluję tak: g++ -o server server.cpp -lssl -lcrypto
Po instalacji: apt-get install openssl libssl-dev
Teraz pytanie (!!!): 1. Czy faktycznie jest to serwer ssl czy gdzieś zrobiłem jakiś błąd? 2. I w jaki sposób można go usprawnić? 3. I jak przerobić na tredy, mam zamiar napisać serwer smtp na bazie danych? 4. Gdzie znajdę bibliotekę do pobierania rekordów MX i SPF z serwera DNS lub jakiś przykład? 5. Gdzie znajdę bibliotekę do parsowania wiadomości e-mail do mimemessage i do zapisywania do plików .eml? 6. Gdzie znajdę bibliotekę do wysyłania wiadomości SMTP z załącznikami koniecznie z SSL? 7. Gdzie znajdę bibliotekę do parsowania klas do JSON i z powrotem do klas? Ps. Serwer działa, obsługuje wiele połączeń, testuje przez połączenie z terminala:
openssl s_client -connect 127.0.0.1:3333 // lub telnet-ssl -z ssl 127.0.0.1 3333
Połączenie z terminala, konsoli za pomocą openssl: openssl s_client -connect hostname:25 -starttls smtp
|
|
mateczek |
» 2017-08-27 06:37:47 I w jaki sposób można go usprawnić |
Jakoś zawsze można 1 masz pomiksowane wywołania printf() i cout z dwóch różnych bibliotek a robią to samo. 2 skoro to jednak c++ można by obiektowo 3 można dodać obsługę wątków aby serwer faktycznie obsługiwał więcej połączeń a nie tylko połącz wyślij odpowiedź i rozłącz. Bo wydaje mi się że w tej chwili to jakoś tak działa(nie kompilowałem) |
|
Breakermind Temat założony przez niniejszego użytkownika |
» 2017-08-27 10:09:49 Ok, lecz chodzi mi bardziej o samo funkcjonowanie SSL z openssl (czy faktycznie śmiga to po ssl !) a nie podstawowe rzeczy (te poprawie później to wersja na szybko). Co do połączeń to serwer tworzy nowy proces dla każdego połączenia i czeka na dane w pętli dla każdego nowego użytkownika (z tego co wyczytałem :) w opisach funkcji fork() ). pid = fork(); if( pid > 0 ) { currpid = pid; fprintf( stderr, "Mam mowego klienta, pid=%d\n", currpid ); continue; }
Czytałem o jakimś BIO i to te kwestie mnie bardziej w tym przykładzie interesują (jak je zaimplementować i czy są potrzebne)? Tu mam przykład z BIO lecz coś mi nie działa (i nie wiem w jakim celu jest dhparam certyfikat - przykład z hakin9 kleiłem z pdf zapewne czegoś nie dodaje podczas kompilowania): #include <errno.h> #include <unistd.h> #include <malloc.h> #include <string.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> #include <netinet/in.h> #include <resolv.h> #include "openssl/ssl.h" #include "openssl/err.h" #include <openssl/bio.h> #include <openssl/ssl.h>
#define DEFAULTPORT "555" #define CERTIFICATE_FILE "/home/user/c++/server/certificate.pem" #define PRIVATE_KEY "/home/user/c++/server/certificate.pem"
#define DH_FILE "/home/user/c++/server/dhserver.pem" #define RESPONSE "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n"
SSL_CTX * server_ssl_initialize_ctx2() { SSL_CTX * ctx; BIO * dhbio; SSL_library_init(); SSL_load_error_strings(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); ctx = SSL_CTX_new( SSLv23_server_method() ); if( !ctx ) { perror( "Unable to create SSL context" ); ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } if( SSL_CTX_use_certificate_file( ctx, CERTIFICATE_FILE, SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } if( SSL_CTX_use_PrivateKey_file( ctx, PRIVATE_KEY, SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } return ctx; }
SSL_CTX * server_ssl_initialize_ctx() { SSL_CTX * ctx; BIO * dhbio; SSL_library_init(); SSL_load_error_strings(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); ctx = SSL_CTX_new( SSLv23_server_method() ); if( !ctx ) { perror( "Unable to create SSL context" ); ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } if( SSL_CTX_use_certificate_file( ctx, CERTIFICATE_FILE, SSL_FILETYPE_PEM ) != 1 ) { fprintf( stderr, "Błąd wczytywania certyfikatu.\n" ); ERR_print_errors_fp( stderr ); return NULL; } if( SSL_CTX_use_PrivateKey_file( ctx, PRIVATE_KEY, SSL_FILETYPE_PEM ) != 1 ) { fprintf( stderr, "Błąd wczytywania klucza prywatnego.\n" ); ERR_print_errors_fp( stderr ); return NULL; } if( SSL_CTX_check_private_key( ctx ) != 1 ) { fprintf( stderr, "Klucz prywatny zdaje się nienależeć do certyfikatu.\n" ); ERR_print_errors_fp( stderr ); return NULL; } if(( dhbio = BIO_new_file( DH_FILE, "r" ) ) == NULL ) { fprintf( stderr, "Błąd we wczytywaniu parametrów DH. Pomijamy ten krok.\n" ); ERR_print_errors_fp( stderr ); } else { DH * dh = PEM_read_bio_DHparams( dhbio, NULL, NULL, NULL ); BIO_free( dhbio ); if( SSL_CTX_set_tmp_dh( ctx, dh ) < 0 ) { fprintf( stderr, "Błąd w ustawianiu paremetrów DH. Pomijamy.\n" ); ERR_print_errors_fp( stderr ); } } return ctx; }
void sigchild_handler( int sig ) { int status; pid_t pid; pid = wait( & status ); if( WIFEXITED( status ) ) { fprintf( stderr, "Proces%d wrocil z kodem %d.\n", pid, WEXITSTATUS( status ) ); } else if( WIFSIGNALED( status ) ) { fprintf( stderr, "Proces %d został zabity sygnałem %d.\n", pid, WTERMSIG( status ) ); } }
void sigchild_handler( int sig ); SSL_CTX * server_ssl_initialize_ctx();
int main( int argc, char ** argv ) { char * portbuff; int rv; BIO * listen_bio; SSL_CTX * ctx; SSL * ssl; char buf[ 1024 ]; int len; if( !( ctx = server_ssl_initialize_ctx() ) ) { fprintf( stderr, "Niestety.\n" ); exit( 1 ); } if( argc > 1 ) { portbuff = strdup( argv[ 1 ] ); } else { portbuff = strdup( DEFAULTPORT ); } signal( SIGCHLD, sigchild_handler ); listen_bio = BIO_new_accept( portbuff ); BIO_set_bind_mode( listen_bio, BIO_BIND_REUSEADDR ); if( BIO_do_accept( listen_bio ) <= 0 ) { fprintf( stderr, "Błąd w przygotowaniu do obsługi klientów.\n" ); ERR_print_errors_fp( stderr ); exit( 0 ); } while( 1 ) { BIO * client_bio = BIO_new_ssl( ctx, 0 ); BIO * buffered_bio; BIO_get_ssl( client_bio, & ssl ); if( !ssl ) { fprintf( stderr, "Błąd ssl.\n" ); ERR_print_errors_fp( stderr ); BIO_free_all( listen_bio ); SSL_CTX_free( ctx ); exit( 1 ); } SSL_set_verify( ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL ); SSL_set_mode( ssl, SSL_MODE_AUTO_RETRY ); BIO_set_accept_bios( listen_bio, client_bio ); if( BIO_do_accept( listen_bio ) <= 0 ) { fprintf( stderr, "Błąd podczas przyjmowania połączenia.\n" ); ERR_print_errors_fp( stderr ); continue; } client_bio = BIO_pop( listen_bio ); rv = fork(); if( rv > 0 ) { fprintf( stderr, "Mam mowego klienta, pid=%d\n", rv ); continue; } if( rv == - 1 ) { fprintf( stderr, "Błąd w tworzeniu nowego procesu: %s.\n", strerror( errno ) ); BIO_free( client_bio ); continue; } if( BIO_do_handshake( client_bio ) <= 0 ) { fprintf( stderr, "Błąd podczas SSL handshake.\n" ); ERR_print_errors_fp( stderr ); BIO_free_all( client_bio ); return 1; } buffered_bio = BIO_new( BIO_f_buffer() ); client_bio = BIO_push( buffered_bio, client_bio ); BIO_puts( client_bio, RESPONSE ); while( 1 ) { len = BIO_gets( client_bio, buf, 1024 ); if( len <= 0 ) { fprintf( stderr, "Błąd w czytaniu z gniazda.\n" ); ERR_print_errors_fp( stderr ); break; } BIO_write( client_bio, buf, len ); if(( buf[ 0 ] == '\r' ) ||( buf[ 0 ] == '\n' ) ) break; } BIO_puts( client_bio, "milo, ze wpadles.\r\n" ); rv = BIO_flush( client_bio ); BIO_free_all( client_bio ); exit( 0 ); } if( portbuff ) free( portbuff ); return 0; }
Jak poprawić ten przykład lub jak dodać BIO z tego przykładu do pierwszego? Pozdrawiam |
|
DejaVu |
» 2017-08-27 16:44:20 Sprawdź po prostu jakie dane wysyłasz. Jeżeli nie jest to jawny tekst to znaczy, że zaszyfrowałeś dane. |
|
mateczek |
» 2017-08-27 17:20:20 |
|
Breakermind Temat założony przez niniejszego użytkownika |
» 2017-08-27 19:02:33 Wysyła jakieś krzaczki nie tekst (lecz nie wykrywa Tlsv1.2 w Protocol w wiresharku jest tylko Tcp nie jak z przeglądarki Tlsv1.2 i na dole nie wyświetla Secure Sockets Layer)
|
|
Breakermind Temat założony przez niniejszego użytkownika |
» 2017-08-28 09:41:40 Wireshark ustawienia portów z obsługą TLS/SSL:
https://ask.wireshark.org/questions/34075/why-wireshark-cannot-display-tlsssl
:) |
|
Breakermind Temat założony przez niniejszego użytkownika |
» 2017-08-28 10:46:15 Qt C++ ssl socket server multiple connections: Zainstalować: apt-get install openssl libssl-dev Połączenie do servera openssl s_client -connect 127.0.0.1:3333
// SMTP server STARTTLS (-quiet enable lowercase commands, openssl s_client: R - command renegotiation ) openssl s_client -connect 127.0.0.1:25 -starttls smtp -quiet
// if renegotiation certificate error openssl s_client -connect 127.0.0.1:25 -starttls smtp -quiet
lub telnet-ssl -z ssl 127.0.0.1 3333
Z ca file openssl s_client -connect do-me-na.pl:3333 -CAfile /home/user/c++/server/ca_bundle.crt openssl s_client -connect 127.0.0.1:3333 -CAfile /etc/ssl/certs/ca-certificates.crt
Pokaż certyfikaty echo "" | openssl s_client -showcerts -connect 127.0.0.1:3333 -CAfile /home/user/c++/server/ca_bundle.crt
Wersja dla Qt QtServer.pro QT += core QT -= gui
TARGET = QtServer CONFIG += console CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
# LIBS += -L/path/to -lpsapi LIBS += - lssl - lcrypto
main.cpp #include <QCoreApplication>
#include <iostream> #include <algorithm> #include <stdio.h> #include <cstdio> #include <unistd.h> #include <string> #include <cstring> #include <sys/socket.h> #include <arpa/inet.h> #include <openssl/ssl.h> #include <openssl/err.h>
#include <pthread.h> #include <errno.h> #include <signal.h>
const int readSize = 8192;
char buffer[ 8192 ];
char end[] = "...";
int received, count = 0; int TotalReceived = 0;
int opt = 1;
pid_t pid; int currpid = 0;
#define PORT 3333 int create_socket( int port ) { int s; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons( port ); addr.sin_addr.s_addr = htonl( INADDR_ANY ); s = socket( AF_INET, SOCK_STREAM, 0 ); if( s < 0 ) { perror( "Unable to create socket" ); exit( EXIT_FAILURE ); } if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR,( char * ) & opt, sizeof( opt ) ) < 0 ) { perror( "setsockopt" ); exit( EXIT_FAILURE ); } if( bind( s,( struct sockaddr * ) & addr, sizeof( addr ) ) < 0 ) { perror( "Unable to bind" ); exit( EXIT_FAILURE ); } if( listen( s, 2 ) < 0 ) { perror( "Unable to listen" ); exit( EXIT_FAILURE ); } return s; }
void ShowCerts( SSL * ssl ) { X509 * cert; char * line; cert = SSL_get_peer_certificate( ssl ); if( cert != NULL ) { printf( "Server certificates:\n" ); line = X509_NAME_oneline( X509_get_subject_name( cert ), 0, 0 ); printf( "Subject: %s\n", line ); free( line ); line = X509_NAME_oneline( X509_get_issuer_name( cert ), 0, 0 ); printf( "Issuer: %s\n", line ); free( line ); X509_free( cert ); } else printf( "No certificates.\n" ); }
void init_openssl() { SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); }
void cleanup_openssl() { EVP_cleanup(); }
SSL_CTX * create_context() { const SSL_METHOD * method; SSL_CTX * ctx; method = SSLv23_server_method(); ctx = SSL_CTX_new( method ); if( !ctx ) { perror( "Unable to create SSL context" ); ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } SSL_CTX_set_options( ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION ); return ctx; }
void configure_context( SSL_CTX * ctx ) { SSL_CTX_set_ecdh_auto( ctx, 1 ); if( SSL_CTX_use_certificate_file( ctx, "/home/user/c++/qt/QtServer/certificate.crt", SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } if( SSL_CTX_use_PrivateKey_file( ctx, "/home/user/c++/qt/QtServer/private.key", SSL_FILETYPE_PEM ) <= 0 ) { ERR_print_errors_fp( stderr ); exit( EXIT_FAILURE ); } }
int main( int argc, char * argv[] ) { QCoreApplication a( argc, argv ); SSL_library_init(); int sock; SSL_CTX * ctx; init_openssl(); ctx = create_context(); configure_context( ctx ); sock = create_socket( PORT ); while( 1 ) { int users = 0; struct sockaddr_in addr; uint len = sizeof( addr ); SSL * ssl; const char reply[] = "220 Hello from server\n"; const char reply1[] = "250 Next Command MAIL FROM:\n"; int client = accept( sock,( struct sockaddr * ) & addr, & len ); printf( "Connection: %s:%d\n", inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) ); pid = fork(); if( pid > 0 ) { currpid = pid; fprintf( stderr, "Mam mowego klienta, pid=%d\n", currpid ); continue; } if( client < 0 ) { perror( "Unable to accept" ); exit( EXIT_FAILURE ); } ssl = SSL_new( ctx ); SSL_set_options( ssl, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION ); SSL_set_fd( ssl, client ); ShowCerts( ssl ); if( SSL_accept( ssl ) <= 0 ) { ERR_print_errors_fp( stderr ); } else { SSL_write( ssl, reply, strlen( reply ) ); } received = SSL_read( ssl, buffer, readSize ); if( received > 0 ) { TotalReceived += received; printf( "PID %i Buffsize - %i - %.*s \n", getpid(), received, received, buffer ); } int z = 1; while( z == 1 ) { SSL_write( ssl, reply1, strlen( reply1 ) ); received = SSL_read( ssl, buffer, readSize ); if( received > 0 ) { TotalReceived += received; printf( "PID %i Buffsize - %i - %.*s \n", getpid(), received, received, buffer ); } printf( "Client send: %s\n", buffer ); std::string buf = std::string( buffer ); std::string dot = std::string( end ); buf = buf.substr( 0, 3 ); dot = dot.substr( 0, 3 ); std::cout << "Compare " << buf.size() << " z " << dot.size() << " end "; std::cout << "Compare " << std::string( buffer ) << " z " << std::string( dot ) << " end "; if( std::string( end ) == std::string( buf ) ) { printf( "%s\n", "End connection " ); z = 0; SSL_shutdown( ssl ); } else { printf( "%s\n", "Working connection" ); } } printf( "SSL pid %s", getpid() ); SSL_free( ssl ); printf( "Client pid %s", getpid() ); close( client ); printf( "Kill pid %s", getpid() ); SSL_free( ssl ); close( client ); exit( 1 ); close( sock ); SSL_CTX_free( ctx ); cleanup_openssl(); } close( sock ); SSL_CTX_free( ctx ); cleanup_openssl(); return a.exec(); }
Pozdrawiam |
|
« 1 » 2 3 |