Перетворіть просту розетку в розетку SSL


115

Я написав прості програми на C, які використовують сокети ('client' та 'server'). (Використання UNIX / Linux)

Сторона сервера просто створює сокет:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

А потім прив'язує його до sockaddr:

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

І слухає (і приймає, і читає):

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

Клієнт створює сокет, а потім пише в нього.

Тепер я хочу перетворити це просте з'єднання в SSL-з'єднання, в найпростіший, ідилічний, найшвидший і швидкий спосіб.

Я намагався додати OpenSSL до свого проекту, але не можу знайти простий спосіб реалізувати те, що я хочу.


Якщо ви шукаєте "безпечне з'єднання", а не SSL зокрема, ви можете подивитися на щось на зразок proxychains.sourceforge.net, яке знаходиться за межами вашої програми, і налаштувати його на надсилання трафіку через SSH-з'єднання. Що стосується вбудованого SSL, OpenSSL досить простий, якщо ви розумієте, як повинен працювати SSL / TLS. Якщо ви хочете альтернативи, спробуйте yaSSL або gnuTLS.
Borealid

3
Визначте «простий шлях». OpenSSl - стандарт для програмістів на C. Якщо у вас виникають труднощі з цим, вам слід запитати про це.
Маркіз Лорнський

Перевірте це Вступ до програмування OpenSSL (Par t I) . Частина II для мене занадто передова і складна. Але part2 варто поглянути.
Рік

Також перевірте безпечне програмування за допомогою API OpenSSL . Але я щойно почув думку про те, наскільки поганий Openssl та інші альтернативи, які варто спробувати.
Рік

Іншим варіантом є використання зовнішнього інструмента для обгортки SSL, наприклад stunnel, stunnel4пакет знаходиться в дистрибутивах на базі Debian, і він простий у використанні. Існують деякі обмеження порівняно з додаванням належної підтримки SSL на вашому сервері, але це може бути корисним для швидкого вирішення. Мені подобається оглушення, тому що він, здається, підходить до підходу програмних засобів UNIX.
Сем Уоткінс

Відповіді:


150

При використанні OpenSSL є кілька кроків. У вас повинен бути зроблений сертифікат SSL, який може містити сертифікат із приватним ключем, обов'язково вкажіть точне місце розташування сертифіката (цей приклад містить його в корені). Там багато хороших навчальних посібників.

Деякі включають:

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

Вам потрібно буде ініціалізувати OpenSSL:

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);
}

Тепер про основну частину функціональності. Ви можете додати цикл часу під час з'єднань.

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();
}

Потім ви можете читати чи писати, використовуючи:

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

ОновленняSSL_CTX_new повинно бути викликано за допомогою методу TLS , який найкраще відповідає вашим потребам з метою підтримки нових версій безпеки, замість SSLv23_server_method(). Дивіться: OpenSSL SSL_CTX_новий опис

TLS_method (), TLS_server_method (), TLS_client_method (). Це універсальні гнучкі до версії методи SSL / TLS. Фактична версія протоколу, що використовується, буде узгоджена з найвищою версією, яка взаємно підтримується клієнтом і сервером. Підтримувані протоколи: SSLv3, TLSv1, TLSv1.1, TLSv1.2 та TLSv1.3.


9
не такий "простий", як я думав, але нарешті (слава Богу!) я бачу якийсь код. Це крос-платформа чи просто для unix / unix-подібних систем?
juliomalegria

3
Я використовував подібний код на багатьох платформах: arm, linux та Windows.
КапітанBli

2
Останній ifпомиляється, хоча. Це повинно бути if (ssl_err <= 0) {лише тоді це помилка. SSL_accept()повертається 1на успіх, 0на «контрольований збій» та -1на «фатальний збій». Див. Сторінку чоловіка.
Джит

2
Також шифри DH не працюватимуть, якщо SSL_CTX_set_tmp_dh[_callback]()їх не викликають. Щойно виявив важкий шлях, що шифри ANULL не працюватимуть без цього, створюючи попередження № 40.
Роман Дмитрієнко

5
@DevNull Заявляє, SSLv23_server_method()що сервер розуміє SSLv2 та v3 і тепер застарілий. Для підтримки TLS 1.1 та 1.2 замініть цей метод на TLS_server_method(). джерело
ezPaint

17

OpenSSL досить складно. Легко випадково викинути всю свою безпеку, не зробивши переговори абсолютно правильно. (Чорт, мене особисто вкусила помилка, де Curl не правильно читав сповіщення OpenSSL і не міг поговорити з деякими сайтами.)

Якщо ви дійсно хочете швидко та просто, поставте шпильку перед програмою, зателефонуйте їй щодня. Включення SSL в інший процес не сповільнить вас: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html


11
Це практична відповідь, але насправді не відповідає на питання.
Швейцарія

4
STUD був відмовлений у 2016 році. Рекомендується: Рекомендуємо: github.com/varnish/hitch
Чарльз

7

Для таких, як я:

Був колись приклад у джерелі SSL у каталозі demos/ssl/з кодом з прикладом у C ++. Тепер це доступно лише через історію: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

Напевно, вам доведеться знайти робочу версію, я спочатку опублікував цю відповідь 6 листопада 2015 року. І мені довелося редагувати джерело - не дуже багато.

Сертифікати: .pem demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps


-1

Ось мій приклад потоків сервера socket sos (декілька з'єднань) 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;
}

Будь ласка, включіть це рішення безпосередньо у свою посаду про те
Мацей Юречко
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.