Basit bir soketi bir SSL soketine dönüştürün


115

Soketler ('istemci' ve 'sunucu') kullanan basit C programları yazdım. (UNIX / Linux kullanımı)

Sunucu tarafı basitçe bir soket oluşturur:

sockfd = socket(AF_INET, SOCK_STREAM, 0);

Ve sonra onu sockaddr'ye bağlar:

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

Ve dinler (ve kabul eder ve okur):

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

İstemci soketi yaratır ve sonra ona yazar.

Şimdi, bu basit bağlantıyı en basit, en pastoral, en temiz ve en hızlı şekilde bir SSL bağlantısına dönüştürmek istiyorum.

OpenSSL'yi projeme eklemeye çalıştım , ancak istediğimi uygulamanın kolay bir yolunu bulamıyorum.


Özellikle SSL yerine "güvenli bir bağlantı" arıyorsanız , uygulamanızın dışında bulunan proxychains.sourceforge.net gibi bir şeye bakabilir ve bunu bir SSH bağlantısı üzerinden trafik gönderecek şekilde ayarlayabilirsiniz. Uygulama içi SSL'ye gelince, SSL / TLS'nin nasıl çalışması gerektiğini anlarsanız OpenSSL oldukça kolaydır. Bir alternatif istiyorsanız yaSSL veya gnuTLS'yi deneyin.
Borealid

3
'Kolay yolu' tanımlayın. OpenSSl, C programcıları için standarttır. Bununla ilgili zorluk yaşıyorsanız, bunu sormalısınız.
Lorne Markisi

Bunu kontrol edin OpenSSL Programlamaya Giriş (Bölüm I) . Bölüm II benim için çok ileri ve zor. Ancak part2 bir göz atmaya değer.
Rick

Ayrıca OpenSSL API ile Güvenli programlamayı kontrol edin . Ama Açıksl'ın ne kadar kötü olduğu ve denemeye değer diğer alternatifler hakkında yeni fikirler duydum.
Rick

Diğer bir seçenek ise stunnel, stunnel4paketin Debian tabanlı dağıtımlarda olması ve kullanımı kolay olması gibi harici bir SSL sarma aracı kullanmaktır. Sunucunuza uygun SSL desteği eklemeye kıyasla bazı sınırlamalar vardır, ancak hızlı bir çözüm için iyi olabilir. Stunnel'ı seviyorum çünkü UNIX yazılım araçları yaklaşımına uygun görünüyor.
Sam Watkins

Yanıtlar:


150

OpenSSL kullanırken birkaç adım vardır. Özel anahtara sahip sertifikayı içerebilecek bir SSL sertifikasına sahip olmalısınız, sertifikanın tam konumunu belirttiğinizden emin olun (bu örnekte, kökte vardır). Orada birçok iyi öğretici var.

Bazıları şunları içerir:

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

OpenSSL'yi başlatmanız gerekecek:

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

Şimdi işlevselliğin büyük kısmı için. Bağlantılara bir while döngüsü eklemek isteyebilirsiniz.

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

Daha sonra aşağıdakileri kullanarak okuyabilir veya yazabilirsiniz:

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

GüncellemeSSL_CTX_new sırayla ihtiyaçlarını en uygun yerine, güvenlik yeni sürümlerini desteklemek için bu TLS yöntemi ile çağrılmalıdır SSLv23_server_method(). Bkz: OpenSSL SSL_CTX_new açıklama

TLS_method (), TLS_server_method (), TLS_client_method (). Bunlar genel amaçlı sürüm esnek SSL / TLS yöntemleridir. Kullanılan gerçek protokol sürümü, istemci ve sunucu tarafından karşılıklı olarak desteklenen en yüksek sürüme göre müzakere edilecektir. Desteklenen protokoller SSLv3, TLSv1, TLSv1.1, TLSv1.2 ve TLSv1.3'tür.


9
sandığım kadar "basit" değil, ama sonunda (Tanrıya şükür!) Bazı kodlar görüyorum. Bu çapraz platform mu yoksa sadece unix / unix benzeri sistemler için mi?
juliomalegria

3
Birden çok platformda benzer kod kullandım: arm, linux ve windows.
CaptainBli

2
Son ifyanlış olsa. Ancak if (ssl_err <= 0) {o zaman bu bir hata olmalı . başarı, "kontrollü başarısızlık" ve "ölümcül başarısızlık" üzerine SSL_accept()geri döner . Man sayfasına bakın. 10-1
Jite

2
Ayrıca, DH şifreleri SSL_CTX_set_tmp_dh[_callback]()çağrılmazsa çalışmayacaktır . Sadece BOŞ şifrelerin onsuz çalışmamasının zor yolunu keşfettim ve 40 numaralı uyarı üretildi.
Roman Dmitrienko

5
@DevNull SSLv23_server_method()Sunucunun SSLv2 ve v3'ü anladığını ve artık kullanımdan kaldırıldığını belirtir. TLS 1.1 ve 1.2'yi desteklemek için bu yöntemi TLS_server_method(). kaynak
ezPaint

17

OpenSSL oldukça zordur. Müzakereyi tam olarak doğru yapmayarak kazara tüm güvenliğinizi çöpe atmak kolaydır. (Kahretsin, curl'nin OpenSSL uyarılarını tam olarak doğru okumadığı ve bazı sitelerle konuşamadığım bir hata tarafından şahsen ısırıldım.)

Gerçekten hızlı ve basit istiyorsanız, stud'ı programınızın önüne koyun ve bir gün arayın. SSL'nin farklı bir süreçte olması sizi yavaşlatmaz: http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html


11
Bu pratik bir cevap, ancak soruyu gerçekten cevaplamıyor.
İsviçre

4
STUD 2016'da terk edildi. Benioku önerisi: github.com/varnish/hitch
Charles

7

Benim gibi diğerleri için:

Bir zamanlar dizindeki SSL kaynağında demos/ssl/C ++ 'da örnek kodlu bir örnek vardı. Artık yalnızca geçmiş aracılığıyla kullanılabilir: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

Muhtemelen çalışan bir versiyon bulmanız gerekecek, bu cevabı ilk olarak 6 Kasım 2015'te gönderdim. Ve kaynağı düzenlemem gerekiyordu - çok değil.

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


-1

İşte benim örnek ssl soket sunucu konuları (çoklu bağlantı) 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;
}

Lütfen çözümü doğrudan SO gönderinize ekleyin.
Maciej Jureczko
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.