본문 바로가기

backup

stunnel을 쓰지 않고 바로 openssl c 프로그래밍하기

FIX로 거래를 하려고 하면 흔히 ssl를 요구하게 됩니다. 그래서 쉽게 쓰게 되는데,

FIX제공해주는 업체에서 보통 쉽게 쓰는 방법으로 stunnel을 추천을 하게 됩니다.


stunnel은 openssl을 기반으로 해서 자기 컴퓨터에 일반 평문을 ssl로 자동으로 바꿔서 보내주는 중간 프락시 서버를 만드는 것입니다.

말이 어려운데

ssl을 요구하는 서버와 직접 통신 하는 것이 아니라, 내 컴퓨터에 심어져 있는 서버에다가 메세지를 보내면 그 중간 서버가 ssl을 요구하는 업체에다가 메세지를 암호화해서 보내고

다시 그 곳으로부터 오는 메세지를 암호를 풀어서 평문으로 해서 자신의 프로그램에서 쓸 수 있도록 해주는 것입니다.


참고로 openssl은 오픈소스쪽에서 무료로 만들어진 ssl 구현한 툴입니다.


stunnel 세팅하기도 쉽고, 그냥 프로그래밍도 똑같이 하고 간편히 쓰면 되어서 매우 유용한 프로그램이기는 한데

HFT를 위해서 하나라도 속도나는 것을 줄이려면 stunnel도 제거 대상입니다.


아무리 localhost로 데이터를 전송하고 받는다고 하지만 중간에 불필요한 네트워크 처리 과정이 들어가게 됩니다.

내 메세지가 네트워크 카드로 내려가서 다시 네트워크 카드가 수신을 하고 ssl로 암호화하고 다시 보내게 되는데,

네트워크 카드의 대기시간이 중간에 들어가게 되어 일반적인 네트워크 카드를 사용한 경우 최소 60~100 마이크로초의 지연이 추가로

발생하게 됩니다.


그래서 stunnel을 제거하려면 바로 openssl을 이용해서 프로그래밍할 수 있겠죠.

여러가기 구글링해보다가 그나마 간편하게 직관적으로 프로그래밍 잘해놓은것 찾아서 공유를 합니다.

참고하세요~









출처 : http://savetheions.com/2010/01/16/quickly-using-openssl-in-c/

#include
<sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

// Simple structure to keep track of the handle, and
// of what needs to be freed later.
typedef struct {
   
int socket;
    SSL
*sslHandle;
    SSL_CTX
*sslContext;
} connection;

// For this example, we'll be testing on openssl.org
#define SERVER  "www.openssl.org"
#define PORT 443

// Establish a regular tcp connection
int tcpConnect ()
{
 
int error, handle;
 
struct hostent *host;
 
struct sockaddr_in server;

  host
= gethostbyname (SERVER);
  handle
= socket (AF_INET, SOCK_STREAM, 0);
 
if (handle == -1)
   
{
      perror
("Socket");
      handle
= 0;
   
}
 
else
   
{
      server
.sin_family = AF_INET;
      server
.sin_port = htons (PORT);
      server
.sin_addr = *((struct in_addr *) host->h_addr);
      bzero
(&(server.sin_zero), 8);

      error
= connect (handle, (struct sockaddr *) &server,
                       
sizeof (struct sockaddr));
     
if (error == -1)
       
{
          perror
("Connect");
          handle
= 0;
       
}
   
}

 
return handle;
}

// Establish a connection using an SSL layer
connection
*sslConnect (void)
{
  connection
*c;

  c
= malloc (sizeof (connection));
  c
->sslHandle = NULL;
  c
->sslContext = NULL;

  c
->socket = tcpConnect ();
 
if (c->socket)
   
{
     
// Register the error strings for libcrypto & libssl
      SSL_load_error_strings
();
     
// Register the available ciphers and digests
      SSL_library_init
();

     
// New context saying we are a client, and using SSL 2 or 3
      c
->sslContext = SSL_CTX_new (SSLv23_client_method ());
     
if (c->sslContext == NULL)
        ERR_print_errors_fp
(stderr);

     
// Create an SSL struct for the connection
      c
->sslHandle = SSL_new (c->sslContext);
     
if (c->sslHandle == NULL)
        ERR_print_errors_fp
(stderr);

     
// Connect the SSL struct to our connection
     
if (!SSL_set_fd (c->sslHandle, c->socket))
        ERR_print_errors_fp
(stderr);

     
// Initiate SSL handshake
     
if (SSL_connect (c->sslHandle) != 1)
        ERR_print_errors_fp
(stderr);
   
}
 
else
   
{
      perror
("Connect failed");
   
}

 
return c;
}

// Disconnect & free connection struct
void sslDisconnect (connection *c)
{
 
if (c->socket)
    close
(c->socket);
 
if (c->sslHandle)
   
{
      SSL_shutdown
(c->sslHandle);
      SSL_free
(c->sslHandle);
   
}
 
if (c->sslContext)
    SSL_CTX_free
(c->sslContext);

  free
(c);
}

// Read all available text from the connection
char *sslRead (connection *c)
{
 
const int readSize = 1024;
 
char *rc = NULL;
 
int received, count = 0;
 
char buffer[1024];

 
if (c)
   
{
     
while (1)
       
{
         
if (!rc)
            rc
= malloc (readSize * sizeof (char) + 1);
         
else
            rc
= realloc (rc, (count + 1) *
                          readSize
* sizeof (char) + 1);

          received
= SSL_read (c->sslHandle, buffer, readSize);
          buffer
[received] = '\0';

         
if (received > 0)
            strcat
(rc, buffer);

         
if (received < readSize)
           
break;
          count
++;
       
}
   
}

 
return rc;
}

// Write text to the connection
void sslWrite (connection *c, char *text)
{
 
if (c)
    SSL_write
(c->sslHandle, text, strlen (text));
}

// Very basic main: we send GET / and print the response.
int main (int argc, char **argv)
{
  connection
*c;
 
char *response;

  c
= sslConnect ();

  sslWrite
(c, "GET /\r\n\r\n");
  response
= sslRead (c);

  printf
("%s\n", response);

  sslDisconnect
(c);
  free
(response);

 
return 0;
}