Перетворіть просту розетку в розетку 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.