관리 메뉴

사과하는 제라스

17. OpenSSL(TLS 서버 구축) 본문

대학 전공 공부/네트워크 프로그래밍

17. OpenSSL(TLS 서버 구축)

Xerath(제라스) 2022. 6. 9. 13:58

목차

    728x90
    반응형

    - 어떤 서버를 구축함에 있어서 인증서가 중요함.

     

    - 인증서의 chain

    사용자가 서버 인증서와 서명값을 받음 - 이 인증서의 IssuerDN인 CA1에게 감 - CA1의 IssuerDN인 RootCA에 감

    - CA1 인증서에 서명된 걸 노란 키로 인증, 서버 인증서에 서명된 걸 파란 키로 인증, 초록 키 받아서 인증

     

    - 각국의 RootCA들끼리는 peer-to-peer로 믿어줌.

     

    - TLS 서버를 구축하려면 서버에 인증서와 개인키를 생성해야 함.

     

    //SSL-Server.c
    #include <errno.h>
    #include <unistd.h>
    #include <malloc.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <resolv.h>
    #include "openssl/ssl.h"
    #include "openssl/err.h"
    
    #define FAIL    -1
    
    int OpenListener(int port)
    {   int sd;
        struct sockaddr_in addr;
    
        sd = socket(PF_INET, SOCK_STREAM, 0);
        bzero(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = INADDR_ANY;
        if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
        {
            perror("can't bind port");
            abort();
        }
        if ( listen(sd, 10) != 0 )
        {
            perror("Can't configure listening port");
            abort();
        }
        return sd;
    }
    
    SSL_CTX* InitServerCTX(void)
    {
    	const SSL_METHOD *method;
        SSL_CTX *ctx;
    
        OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */
        SSL_load_error_strings();   /* load all error messages */
        
    	method = TLSv1_2_server_method();
        ctx = SSL_CTX_new(method);   /* create new context from method */
        if(ctx == NULL)
        {
            ERR_print_errors_fp(stderr);
            abort();
        }
    	
    	SSL_CTX_set_cipher_list(ctx, "ALL:eNULL");
        
    	return ctx;
    }
    
    void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
    {
        //New lines 
        if (SSL_CTX_load_verify_locations(ctx, CertFile, KeyFile) != 1)
            ERR_print_errors_fp(stderr);
    
        if (SSL_CTX_set_default_verify_paths(ctx) != 1)
            ERR_print_errors_fp(stderr);
        //End new lines
    
        /* set the local certificate from CertFile */
        if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0)
        {
            ERR_print_errors_fp(stderr);
            abort();
        }
        /* set the private key from KeyFile (may be the same as CertFile) */
    	SSL_CTX_set_default_passwd_cb_userdata(ctx, "12345678");
        if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0)
        {
            ERR_print_errors_fp(stderr);
            abort();
        }
        /* verify private key */
        if (!SSL_CTX_check_private_key(ctx))
        {
            fprintf(stderr, "Private key does not match the public certificate\n");
            abort();
        }
    
        //New lines - Force the client-side have a certificate
        //SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
        //SSL_CTX_set_verify_depth(ctx, 4);
        //End new lines
    }
    
    void ShowCerts(SSL* ssl)
    {
    	X509 *cert;
    	char *line;
    
    	cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
    	if ( cert != NULL )
    	{
    		printf("Server certificates:\n");
    		line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
    		printf("Subject: %s\n", line);
    		free(line);
    		line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
    		printf("Issuer: %s\n", line);
    		free(line);
    		X509_free(cert);
    	}
    	else
    		printf("No certificates.\n");
    }
    
    void Servlet(SSL* ssl) /* Serve the connection -- threadable */
    {
    	char buf[1024];
    	int sd, bytes;
    	
    	char enter[3] = { 0x0d, 0x0a, 0x00 };
    	
    	char output[1024];
    	strcpy(output, "HTTP/1.1 200 OK");
    	strcat(output, enter);
    	strcat(output, "Content-Type: text/html");
    	strcat(output, enter);
    	strcat(output, "Content-Length: 47");
    	strcat(output, enter);
    	strcat(output, enter);
    	strcat(output, "<html><body><h1>Hello World!</h1></body></html>");
    	
    	if ( SSL_accept(ssl) == FAIL )     /* do SSL-protocol accept */
    		ERR_print_errors_fp(stderr);
    	else
    	{
    		ShowCerts(ssl);        /* get any certificates */
    		bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
    		if ( bytes > 0 )
    		{
    			buf[bytes] = 0;
    			printf("Client msg: \"%s", buf);
    			SSL_write(ssl, output, strlen(output)); /* send reply */
    		}
    		else
    			ERR_print_errors_fp(stderr);
    	}
    	sd = SSL_get_fd(ssl);       /* get socket connection */
    	SSL_free(ssl);         /* release SSL state */
    	close(sd);          /* close connection */
    }
    
    int main(int argc, char **argv)
    {
    	SSL_CTX *ctx; // TLS 서버 구축을 위해 ctx 메모리 포인터 선언
    	int server;
    	char portnum[]="5000"; //port 번호 할당
    
    	char CertFile[] = "key/certificate.crt"; //인증성 세팅
        char KeyFile[] = "key/private_key.pem"; //개인키 세팅
    
    	SSL_library_init(); //OpenSSL 라이브러리 초기화
    
    	ctx = InitServerCTX();        /* initialize SSL */
    	LoadCertificates(ctx, CertFile, KeyFile); /* load certs */
    	server = OpenListener(atoi(portnum));    /* create server socket */
    	while (1)
    	{
    		struct sockaddr_in addr;
    		socklen_t len = sizeof(addr);
    		SSL *ssl;
    
    		int client = accept(server, (struct sockaddr*)&addr, &len);  /* accept connection as usual */
    		printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    		ssl = SSL_new(ctx);              /* get new SSL state with context */
    		SSL_set_fd(ssl, client);      /* set connection socket to SSL state */
    		Servlet(ssl);         /* service connection */
    	}
    	close(server);          /* close server socket */
    	SSL_CTX_free(ctx);         /* release context */
    }

     

    728x90
    반응형

    '대학 전공 공부 > 네트워크 프로그래밍' 카테고리의 다른 글

    16. Basic OpenSSL  (0) 2022.06.08
    15. 네트워크 보안  (0) 2022.06.08
    14강. 보안 기본 개념  (0) 2022.05.21
    13강. HTTP and Web Client  (0) 2022.05.13
    12강. DNS  (0) 2022.05.13