developer tip

간단한 소켓을 SSL 소켓으로 전환

optionbox 2020. 8. 12. 08:08
반응형

간단한 소켓을 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 is quite difficult. It's easy to accidentally throw away all your security by not doing negotiation exactly right. (Heck, I've been personally bitten by a bug where curl wasn't reading the OpenSSL alerts exactly right, and couldn't talk to some sites.)

If you really want quick and simple, put stud in front of your program an call it a day. Having SSL in a different process won't slow you down: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html


For others like me:

There was once an example in the SSL source in the directory demos/ssl/ with example code in C++. Now it's available only via the history: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

You probably will have to find a working version, I originally posted this answer at Nov 6 2015. And I had to edit the source -- not much.

Certificates: .pem in demos/certs/apps/: https://github.com/openssl/openssl/tree/master/demos/certs/apps


Here my example ssl socket server threads (multiple connection) 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;
}

참고URL : https://stackoverflow.com/questions/7698488/turn-a-simple-socket-into-an-ssl-socket

반응형