[c] 간단한 소켓을 SSL 소켓으로 전환

소켓 ( ‘클라이언트’와 ‘서버’)을 사용하는 간단한 C 프로그램을 작성했습니다. (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 을 추가하려고했지만 원하는 것을 구현하는 쉬운 방법을 찾을 수 없습니다.



답변

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

이제 대부분의 기능에 대해 설명합니다. 연결에 while 루프를 추가 할 수 있습니다.

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_new 설명

TLS_method (), TLS_server_method (), TLS_client_method ().
이는 범용 버전 유연성 SSL / TLS 방법입니다. 사용되는 실제 프로토콜 버전은 클라이언트와 서버가 상호 지원하는 가장 높은 버전으로 협상됩니다. 지원되는 프로토콜은 SSLv3, TLSv1, TLSv1.1, TLSv1.2 및 TLSv1.3입니다.


답변

OpenSSL은 매우 어렵습니다. 협상을 정확하게 수행하지 않으면 실수로 모든 보안을 포기하기 쉽습니다. (Heck, 저는 curl이 OpenSSL 경고를 정확하게 읽지 못하고 일부 사이트와 대화 할 수없는 버그에 개인적으로 물었습니다.)

정말 빠르고 간단하게하고 싶다면 프로그램 앞에 스터드 를 넣어 하루에 전화하세요. 다른 프로세스에서 SSL을 사용한다고해서 속도가 느려지지 않습니다. http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html


답변

나 같은 다른 사람 :

한때 디렉토리의 SSL 소스 demos/ssl/에 C ++의 예제 코드가있는 예제가있었습니다. 이제 기록을 통해서만 사용할 수 있습니다 :
https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

아마도 작동하는 버전을 찾아야 할 것입니다. 저는 원래이 답변을 2015 년 11 월 6 일에 게시했습니다. 그리고 소스를 편집해야했습니다.

인증서 : .pem in demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps


답변

여기 내 예제 ssl 소켓 서버 스레드 (다중 연결) 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;
}


답변