Virtual Box에서 내부 내트워크와 외부 네트워크와의 통신 문제 해결…

학교 과제문제때문에 Virtual Box로 다음과 같은 네트워크를 구성하였다.

사용자 삽입 이미지
 net0 이 바로 Virtual Box에서 구성한 Bridge 구성이고, 나머지 net1 과 net2 는 실습을 위한 내부 네트워크 이다.

 이 네트워크를 구축할 때, 나는 공유기를 사용하고 있었다.

 그리고 라우팅 테이블을 수정해서 모든 노드가 서로 통신이 가능하게끔 하였다.

 그런데 문제가 발생했다.

 바로 외부 네트워크(인터넷)의 연결 부분이었다.

 MyNote, Debian_0, Debian_Another 은 인터넷이 가능하였다. 하지만, Debian_1, Debian_2 은 인터넷이 되지 않았던것….

 이상한 일이었다.

 심지어 인터넷이 안되는 두개의 호스트는 공유기로의 ping도 되지 않았다. 공유기와 같은 네트워크에 있는 net0 에 있는 모든 노드와는 통신이 되는데, 유독 공유기와는 연결이 되지 않았다.

 이유는 다음과 같았다.

 바로 공유기에서 문제가 있었다.

 공유기에서의 라우팅 셋팅을 하지 않았던 것.

 당연한 것이다. 하지만….. 나름 공유기를 믿고 있었는데…자동으로 라우팅 테이블을 작성할 줄 알았던 것이다.(너무 바랬다….)

 공유기에서의 static routing table을 다음과 같이 수정하니 인터넷과 통신이 매우 잘 되었다.

사용자 삽입 이미지
 게이트웨이 192.168.1.7 의 주소는 Debian_0 의 주소이다.

Openssl을 이용한 암호화 통신

 Openssl을 이용한 암호화 통신

 서버는 암호화 통신을 위하여 가장 먼저 SSL_CTX와 SSL 구조체를 선언하여 암호화 통신을 위한 정보를 관리할 수 있도록 한다. 그리고, SSL 세션을 시작하기 위한 초기값을 설정하고, SSL_CTX_new() 함수를 이용하여 SSL 컨텍스트를 생성한다.

 다음 단계는 인증서를 이용하여 서버와 클라이언트 간의 인증을 수행할 경우 SS_CTX_use_certificate_file()를 이요하여 인증서 파일을 생성하며, SSL_CTX_use_PrivateKey_file()를 이용하여 개인 키를 생성한다.

 이런 준비 단계 후에 SSL_new() 함수를 이용하여 SSL 세션을 생성하고, 이후의 단계는 기존의 소켓 서버와 유사한 방법으로 처리를 수행할 수 있다. SSL을 이용한 송수신은 SSL_accept(), SSL_read(), SSL_write() 등의 함수를 이용할 수 있으며, 이 과정은 기종의 소켓 프로그래밍과 유사한 방법으로 수행된다.

serv.c (Language : c)
  1. /*
  2. *      serv.c
  3. *     
  4. *      Copyright 2008 Kim Sung-tae <pchero21@gmail.com>
  5. *     
  6. *      This program is free software; you can redistribute it and/or modify
  7. *      it under the terms of the GNU General Public License as published by
  8. *      the Free Software Foundation; either version 2 of the License, or
  9. *      (at your option) any later version.
  10. *     
  11. *      This program is distributed in the hope that it will be useful,
  12. *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. *      GNU General Public License for more details.
  15. *     
  16. *      You should have received a copy of the GNU General Public License
  17. *      along with this program; if not, write to the Free Software
  18. *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. *      MA 02110-1301, USA.
  20. */
  21.  
  22.  
  23. #include <stdio.h>
  24. #include <unistd.h>
  25. #include <stdlib.h>
  26. #include <memory.h>
  27. #include <errno.h>
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <netinet/in.h>
  31. #include <arpa/inet.h>
  32. #include <netdb.h>
  33.  
  34. /*
  35. * openssl 관련 헤더 파일을 include 한다.
  36. */
  37. #include <openssl/rsa.h>        /* SSLeay stuff */
  38. #include <openssl/crypto.h>
  39. #include <openssl/x509.h>
  40. #include <openssl/pem.h>
  41. #include <openssl/ssl.h>
  42. #include <openssl/err.h>
  43.  
  44. /* define HOME to be dir for key and cert files…. */
  45. #define HOME “./”
  46.  
  47. /* Make these what you want for cert & key files */
  48. #define CERTF HOME “server.crt”
  49. #define KEYF HOME “server.key”
  50.  
  51. #define CHK_NULL(x) if((x) == NULL) exit(1);
  52. #define CHK_ERR(err, s) if((err) == -1) { perror(s); exit(1); }
  53. #define CHK_SSL(err) if((err) == -1) { ERR_print_errors_fp(stderr); exit(2); }
  54.  
  55.  
  56. int main(void)
  57. {
  58.     int err;
  59.     int listen_sd;
  60.     int sd;
  61.     struct sockaddr_in sa_serv;
  62.     struct sockaddr_in sa_cli;
  63.     size_t client_len;
  64.    
  65.     /* SSL Context 및 관련 구조체를 선언한다. */
  66.     SSL_CTX  *ctx;
  67.     SSL    *ssl;
  68.     X509                *client_cert;
  69.     char                *str;
  70.     char                buf[4096];
  71.     SSL_METHOD  *meth;
  72.    
  73.     /* SSL 관련 초기화 작업을 수행한다. */
  74.     SSL_load_error_strings();
  75.     SSLeay_add_ssl_algorithms();
  76.     meth = SSLv23_server_method();    // 서버 메소드.
  77.     ctx = SSL_CTX_new(meth);                // 지정된 초기 값을 이용하여 SSL Context를 생성한다.
  78.    
  79.     if(!ctx) {
  80.         ERR_print_errors_fp(stderr);
  81.         exit(2);
  82.     }
  83.    
  84.     /* 사용하게 되는 인증서 파일을 설정한다. */
  85.     if(SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {      // 인증서를 파일로 부터 로딩할때 사용함.
  86.         ERR_print_errors_fp(stderr);
  87.         exit(3);
  88.     }
  89.    
  90.     /* 암호화 통신을 위해서 이용하는 개인 키를 설정한다. */
  91.     if(SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
  92.         ERR_print_errors_fp(stderr);
  93.         exit(4);
  94.     }
  95.    
  96.     /* 개인 키가 사용 가능한 것인지 확인한다. */
  97.     if(!SSL_CTX_check_private_key(ctx)) {
  98.         fprintf(stderr, “Private key does not match the certificate public keyn);
  99.         exit(5);
  100.     }
  101.    
  102.     /* Prepare TCP socket for receiving connections */
  103.     listen_sd = socket(AF_INET, SOCK_STREAM, 0);
  104.     CHK_ERR(listen_sd, “socket”);
  105.    
  106.     memset(&sa_serv, , sizeof(sa_serv));
  107.     sa_serv.sin_family = AF_INET;
  108.     sa_serv.sin_addr.s_addr = INADDR_ANY;
  109.     sa_serv.sin_port = htons(1111); /* Server Port number */
  110.  
  111.     err = bind(listen_sd, (struct sockaddr*)&sa_serv, sizeof(sa_serv));
  112.     CHK_ERR(err, “bimd”);
  113.    
  114.     /* Receive a TCP connection. */
  115.      err = listen(listen_sd, 5);
  116.      CHK_ERR(err, “listen”);
  117.     
  118.      client_len = sizeof(sa_cli);
  119.      sd = accept(listen_sd, (struct sockaddr*)&sa_cli, &client_len);
  120.      CHK_ERR(sd, “accept”);
  121.      close(listen_sd);
  122.     
  123.      printf(“Connection from %1x, port %xn, sa_cli.sin_addr.s_addr, sa_cli.sin_port);
  124.     
  125.      /* TCP connection is ready. Do server side SSL. */
  126.     ssl = SSL_new(ctx); // 설정된 Context를 이용하여 SSL 세션의 초기화 작업을 수행한다.
  127.     CHK_NULL(ssl);
  128.     SSL_set_fd(ssl, sd);
  129.     err = SSL_accept(ssl);    // SSL 세션을 통해 클라이언트의 접속을 대기한다.
  130.     CHK_SSL(err);
  131.    
  132.     /* Get the cipher – opt */
  133.     printf(“SSL connection using %sn, SSL_get_cipher(ssl));
  134.    
  135.     /* 클라이언트의 인증서를 받음 – opt */
  136.     client_cert = SSL_get_peer_certificate(ssl);
  137.     if(client_cert != NULL) {
  138.         printf(“Client certificate:n);
  139.        
  140.         str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0);
  141.         CHK_NULL(str);
  142.         printf(t subject: %sn, str);
  143.         OPENSSL_free(str);
  144.        
  145.         str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0);
  146.         CHK_NULL(str);
  147.         printf(t issuer: %sn, str);
  148.         OPENSSL_free(str);
  149.        
  150.         /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */
  151.         X509_free(client_cert);
  152.     } else {
  153.         printf(“Client does not have certificate.n);
  154.     }
  155.    
  156.     /* SSL 세션을 통해서 클라이언트와 데이터를 송수신한다. */
  157.     err = SSL_read(ssl, buf, sizeof(buf)1);
  158.     CHK_SSL(err);
  159.     buf[err] = ;
  160.     printf(“Got %d chars: ‘%s’n, err, buf);
  161.    
  162.     err = SSL_write(ssl, “I hear you/”, strlen(“I hear you.”));
  163.     CHK_SSL(err);
  164.    
  165.     /* 설정한 자원을 반환하고 종료한다. */
  166.     close(sd);
  167.     SSL_free(ssl);
  168.     SSL_CTX_free(ctx);
  169.    
  170.     return(0);
  171. }
  172.  

cli.c (Language : c)
  1. /*
  2. *      cli.c
  3. *     
  4. *      Copyright 2008 Kim Sung-tae <pchero21@gmail.com>
  5. *     
  6. *      This program is free software; you can redistribute it and/or modify
  7. *      it under the terms of the GNU General Public License as published by
  8. *      the Free Software Foundation; either version 2 of the License, or
  9. *      (at your option) any later version.
  10. *     
  11. *      This program is distributed in the hope that it will be useful,
  12. *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. *      GNU General Public License for more details.
  15. *     
  16. *      You should have received a copy of the GNU General Public License
  17. *      along with this program; if not, write to the Free Software
  18. *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. *      MA 02110-1301, USA.
  20. */
  21.  
  22.  
  23. #include <stdio.h>
  24. #include <memory.h>
  25. #include <errno.h>
  26. #include <sys/types.h>
  27. #include <sys/socket.h>
  28. #include <netinet/in.h>
  29. #include <arpa/inet.h>
  30. #include <netdb.h>
  31.  
  32. #include <openssl/crypto.h>
  33. #include <openssl/x509.h>
  34. #include <openssl/pem.h>
  35. #include <openssl/ssl.h>
  36. #include <openssl/err.h>
  37.  
  38. #define CHK_NULL(x) if((x) == NULL) exit(1);
  39. #define CHK_ERR(err, s) if((err) == -1) { perror(s); exit(1); }
  40. #define CHK_SSL(err) if((err) == -1) { ERR_print_errors_fp(stderr); exit(2); }
  41.  
  42.  
  43. int main(void)
  44. {
  45.     int err;
  46.     int sd;
  47.     struct sockaddr_in sa;
  48.    
  49.     /* SSL 관련 정보를 관리할 구조체를 선언한다. */
  50.     SSL_CTX   *ctx;
  51.     SSL     *ssl;
  52.     X509                    *server_cert;
  53.     char                    *str;
  54.     char                    buf[4096];
  55.     SSL_METHOD    *meth;
  56.    
  57.     /* 암호화 통신을 위한 초기화 작업을 수행한다. */
  58.     SSL_load_error_strings();
  59.     SSLeay_add_ssl_algorithms();
  60.     meth = SSLv3_client_method();
  61.     ctx = SSL_CTX_new(meth);
  62.     CHK_NULL(ctx);
  63.    
  64.     /* 사용하게 되는 인증서 파일을 설정한다. – opt*/
  65.     if(SSL_CTX_use_certificate_file(ctx, “./client.crt”, SSL_FILETYPE_PEM) <= 0) {    // 인증서를 파일로 부터 로딩할때 사용함.
  66.         ERR_print_errors_fp(stderr);
  67.         exit(3);
  68.     }
  69.    
  70.     /* 암호화 통신을 위해서 이용하는 개인 키를 설정한다. – opt */
  71.     if(SSL_CTX_use_PrivateKey_file(ctx, “./client.key”, SSL_FILETYPE_PEM) <= 0) {
  72.         ERR_print_errors_fp(stderr);
  73.         exit(4);
  74.     }
  75.    
  76.     /* 개인 키가 사용 가능한 것인지 확인한다. – opt */
  77.     if(!SSL_CTX_check_private_key(ctx)) {
  78.         fprintf(stderr, “Private key does not match the certificate public keyn);
  79.         exit(5);
  80.     }
  81.    
  82.     //CHK_SSL(err);
  83.    
  84.     /* Create a socket and connect to server using normal socket calls. */
  85.     sd = socket(AF_INET, SOCK_STREAM, 0);
  86.     CHK_ERR(sd, “socket”);
  87.    
  88.     memset(&sa, , sizeof(sa));
  89.     sa.sin_family = AF_INET;
  90.     sa.sin_addr.s_addr = inet_addr(“127.0.0.1”);        // Server IP Address
  91.     sa.sin_port = htons(1111);                // Server Port Number
  92.    
  93.     err = connect(sd, (struct sockaddr*)&sa, sizeof(sa));
  94.     CHK_ERR(err, “connect”);
  95.    
  96.     /* Now we have TCP connection. Start SSL negotiation. */
  97.     ssl = SSL_new(ctx);  // 세션을 위한 자원을 할당받는다.
  98.     CHK_NULL(ssl);
  99.    
  100.     SSL_set_fd(ssl, sd);
  101.     err = SSL_connect(ssl); // 기존의 connect() 함수 대신 사용하여 서버로 접속한다.
  102.     CHK_NULL(err);
  103.    
  104.     /* Following two steps are optional and not required for data exchange to be successful. */
  105.    
  106.     /* Get the Cipher – opt */
  107.     printf(“SSL connection using %sn, SSL_get_cipher(ssl));
  108.    
  109.     /* Get server’s certificate (note: beware of dynamic allocation) – opt */
  110.     /* 서버의 인증서를 받는다. */
  111.     server_cert = SSL_get_peer_certificate(ssl);
  112.     CHK_NULL(server_cert);
  113.     printf(“Server certificate:n);
  114.    
  115.     /* 인증서의 이름을 출력한다. */
  116.     str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0);
  117.     CHK_NULL(str);
  118.     printf(t subject: %sn, str);
  119.     OPENSSL_free(str);
  120.    
  121.     /* 인증서의 issuer를 출력한다. */
  122.     str = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0);
  123.     CHK_NULL(str);
  124.     printf(t issuer: %sn, str);
  125.     OPENSSL_free(str);
  126.    
  127.     /* We could do all sorts of certificate verification stuff here before deallocating the certificate */
  128.     X509_free(server_cert);
  129.    
  130.     /* 서버와 데이터를 송수신 한다. */
  131.     err = SSL_write(ssl, “Hello World!”, strlen(“Hello World!”));
  132.     CHK_SSL(err);
  133.    
  134.     err = SSL_read(ssl, buf, sizeof(buf)1);
  135.     CHK_SSL(err);
  136.     buf[err] = ;
  137.     printf(“Got %d chars: ‘%s’n, err, buf);
  138.     SSL_shutdown(ssl);    // SSL로 연결된 접속을 해지한다.
  139.    
  140.     /* 할당된 자원을 반환하고 종료한다. */
  141.     close(sd);
  142.     SSL_free(ssl);
  143.     SSL_CTX_free(ctx);
  144.    
  145.     return 0;
  146. }
  147.  
  148.  

SSL 라이브러리의 활용

  SSL 라이브러리의 활용

 SSL 라이브러리의 가장 중요한 기능은 암호화 채널을 통한 통신이다. 이를 위해서 각각의 통신은 인증서를 필요한 경우가 있으며, 실제 전자상거래나 증권 거래 등에서 이용하는 인증서인 경우 공인 인증기관에서 발급받는다.

 하지만 제한적인 범위 내에서는 자체적으로 인증서를 생성하여 이용할 수 있으며, 이러한 기능은 openssl 라이브러리에서 기본적인 명령으로 제공한다.

 1) 인증서 만들기
 인 증서(Certificate)는 서버와 클라이언트 간에 통신을 수행하는 과정에서 서로의 신원을 보증하는 일종의 보증서 역할을 한다. 은증서는 공인된 인증기관에서 개인의 신원 확인을 거쳐서 발급하며 주식거래, 전자상거래 같은 금융 거래에서 주로 이용한다. 인증서를 발급하는 기관을 CA(Certificate Authority)라고 하며, 이러한 기관에서 발급한 인증서는 기본적으로 다음과 같은 정보를 포함한다.

 – 소유자 이름 : 주민등록증의 이름과 동일한 기능
 – 일련 번호 : 주민등록증에 비교할 때 주민등록번호의 역할
 – 소유자의 공개 키 : 해당 인증서를 소유한 사람의 공개 키
 – 인증 기관의 전자 서명 : 인증서를 발급한 기관의 전자 서명

 하 지만 개발자 입장에서 제한된 시스템과 응용 프로그램을 대상으로 하는 경우에는 자체적인 인증서를 발급하고 이를 이용하여 응용 프로그램에서 이용할 수도 있는데, 이러한 기능을 수행하는 시스템을 ‘self-signed’ 서버라고 한다. 이를 위해 openssl은 기본적인 명령어로 인증서를 발급하는 기능을 갖추고 있다.

 * 비밀 키 생성
 인증서를 만들 때 가장 먼저 하는 작업으로 비밀 키를 생성한다. 비밀 키는 자신만이 알 수 있게 주의해서 관리해야 하는 정보다. 따라서 가능하면 누구도 알 수 없게 비밀스럽게 생성하고 관리해야 한다. 이 과정에서 가장 먼저 하는 작업은 DSA Parameter를 만드는 과정으로 다음과 같은 명령으로 수행한다.

     # openssl dsaparam 1024 -out dsaparam1024.pem

 이 명령은 1024 비트 크기로 DSA Parameter를 만드는 기능을 수행하며, DSA 키를 만드는 데 사용한다.

 다음 명령은 각각 암호화된 DSA 또는 암호화 되지 않은 DSA 키를 생성하는 기능을 한다. 처음의 것이 암호화되지 않은 키를 생성하는 명령이고, 두번째 명령이 암호화 된 DSA 키를 생성하는 명령이다.

     # openssl gendsa -out dsa1024.pem -des dsaparam1024.pem
     # openssl gendsa -out dsa1024.pem dsaparam1024.pem

 RSA 키를 생성하려면 다음과 같은 형식으로 명령을 이용하면 된다. DSA 키의 생성과 마찬가지로 암호 알고리즘 지정 여부에 따라 암호화 된 키 또는 암호화되지 않은 키를 생성할 수 있다.

     # openssl genrsa -out rsa1024.key -des3 1024
     # openssl genrsa -out rsa1024.key 1024

 DH 파라미터는 다음과 같은 명령으로 생성한다.

     # openssl gendh -out dh1024.pem 1024

 * CSR 생성
 CSR(Certificate Signing Request)은 인증서를 만들기 위해서 CA(Certificate Autority)로 보내는 문서를 말한다. 실제로 이러한 서비스는 사설 인증 업체에서 수행하는 경우가 많기 때문에 개인적으로 CSR을 생성하고 이를 이용해서 인증서를 신청하는 작업이 조금 어려울 수도 있다. openssl에서 제공하는 다음 명령을 이용해서 CSR을 생성할 수 있다.

     # openssl req -new -config /etc/ssl/openssl.cnf -days 365 -key rsa1024.key > server.scr

 이 명령은 RSA 1024비트 키로 CSR을 만들며, 명령 수행 과정에서 openssl.cnf 파일을 필요로 한다. 실제로 이 명령을 수행할 때는 라이브러리와 함께 설치된 openssl.cnf 파일을 적절히 수정해서 사용하자. 이 명령은 앞 단계에서 만든 RSA 키를 이용하는 명령이며, DSA를 이용해서 생성할 수도 있다. 이 경우 위의 명령에서 rsa1024.key를 DSA 키 파일인 dsa1024.key로 대치하여 수행하면 된다.

 * CRT 생성
 이 과정은 앞에서 생성한 CSR을 이용해서 인증서를 만드는 과정이다. 실제로 이 과정은 CSR을 받은 공인 인증 기관을 통해서 수행하지만, 한정된 범위에서 암호화 통신 기능을 위해서 사용하는 정도라면 자신이 가지고 있는 키로 서명해서 이용할 수도 있다. 이러한 경우를 self-signing이라고 한다. 이 과정은 다음 명령을 통해서 수행한다.

     # openssl x509 -req -days 365 -in server.csr -signkey rsa1024.key -out server.crt

 만일 가상적으로 CA 서버를 만들고 싶다면, 이 과정을 응용해서 CA 서버를 구축하고 운영할 수도 있다.

SSL의 구조

 * SSL의 구조
 SSL은 가장 다양한 분야에서 적용하고 있는 암호 프로토콜 중 하나다. TCP/IP는 기본적으로 보안을 고려하지 않으므로 전자상거래를 비롯한 다양한 온라인 서비스를 활성화하려면 서비스 상호간의 인증, 암호와 통신을 비롯한 문제점을 해결해야 한다.

 * SSL의 개념
 SSL은 ‘Secure Socket Layer’의 약자로 넷스케이프(Netscape)에서 처음 개발하여 넷스케이프 네이게이터(Netscape Navigator)에 처음 적용한 보안 프로토콜이다. 기본적인 아이디어는 기본의 TCP/IP에서 고려하지 않은 보안 세션을 추가하여 통신 상호 간의 전송 메시지에 대한 암호화와 상호 인증을 수행하는 프로토콜이다.

사용자 삽입 이미지
 그림과 같이 SSL은 기존의 TCP/IP에서 응용 계층과 TCP 계층 사이에 추가된 보안 계층으로 동작한다. TCP 계층은 응용 계층의 프로톨 간의 인터페이스를 위하여 소켓을 이용하며, SSL은 각 소켓으로 연결된 상호 간의 통신 채널을 안전하게 관리하는 기능을 한다. 클라이언트와 서버 간의 안전한 통신을 위하여 SSL은 다음과 같은 기능을 제공한다.

==================================================================================================
기능            | 설명
==================================================================================================
상호인증       | 클라이언트/서버 간의 인증을 위한 세션 키를 생성하고 “Hello”라는 메시지를 교환함으로써
                | 상호 인증을 한다.
————————————————————————————————–
기밀성         | 전송되는 메시지에 대한 다양한 형식의 암호화를 통해서 타인에게 메시지의 내용을 노출하
                | 지 않도록 한다.
————————————————————————————————–
무결성         | 전송 메시지의 변조를 방지할 수 있도록 MD5를 비롯한 알고리즘을 이용하여 전자 서명을 한다.
==================================================================================================

 기밀성이나 무결성 등의 암호학적 기능을 제공하기 위해서는 국제적으로 표준화되고 있는 암호 알고리즘의 지원이 따라야 한다. SSL은 표준화되어 있는 주요 암호 알고리즘을 비롯하여 현재 주로 이용하는 다양한 암호 알고리즘을 지원하고 있다.

==================================================================================================
기능          | 적용 알고리즘
==================================================================================================
기밀성        | DES, 3DES, IDEA, RC2, RC4
————————————————————————————————–
무결성        | MD5
————————————————————————————————–
서버 인증     | RSA, X509
————————————————————————————————–
클라이언트 인증 | 현재 대부분의 웹 브라우저에서 클라이언트 인증을 제공함
==================================================================================================

 * SSL의 구조 및 통신 절차
 SSL은 다수의 프로토콜로 구성되어 있는 프로토콜 집합이라고 할 수 있으며, 패킷 분할, 세션 관리 등의 기본적인 통신과 관련된 처리를 수행하는 부분과 데이터의 암호화, 복호화, 메시지 인증 같은 보안 서비스를 담당하고 있는 부분으로 구분할 수 있다.

사용자 삽입 이미지
 그림에서 SSL 핸드쉐이크 프로토콜, SSL 변겸 암호 스펙, SSL 경고 프로토콜이 SSL의 세션 관리 및 동작을 처리하는 부분이며, 메시지의 암호화 및 무결성 등의 보안 서비스는 SSL 레코드 프로토콜에서 담당한다.

 * SSL 핸드쉐이크 프로토콜
 클라이언트와 서버 간의 통신을 수행하기 위한 첫번째 단계는 상호 간의 통신을 위한 세션(Session)을 설정하는 과정이다. 세션은 데이터 전송을 위한 논리적인 경로로, 실제로는 여러 개의 커넥션(Connection)이 포함이 되어 클라이언트와 서버 간의 논리적인 관계를 표시하는 정보를 포함하고 있다. SSL에서 세션 상태 연결을 수행하는 것이 SSL 핸드쉐이크 프로토콜(SSL Handshake Protocol)이며 한 세션 동안 이용되는 암호 매개 변수를 생성하여 클라이언트와 서버 간에 공유하기 위해서 사용한다.

 SSL 핸드쉐이크 프로토콜은 SSL 레코드 프로토콜(Record Protocol)에 의해서 메시지의 송수신을 위한 작업보다 먼저 수행이 되어 다음과 같은 세션 정보들을 생성하게 된다.

 세션 식별자(Session Identifier) : 활동 또는 보류 중인 세션을 식별하기 위해서 서버가 임의로 설정한 식별자
 인증서(peer certification) : 서버와 클라이언트 주체의 X.509 인증서
 Cipher Spec : 다량의 데이터에 대해 수행되는 압축 알고리즘과 MAC 알고리즘에 대한 규격
 압축 방법(Compression method) : 암호화 이전에 데이터 압축을 위해 사용하는 알고리즘
 Master secret : 클라이언트와 서버 간에 공유하는 48비트 길이의 비밀 값
 재사용 여부 : 세션이 새로운 연결에 사용 가능한지 여부를 나타내는 플래그

 세션이 설정된 후 해당 세션 내에 수행되는 각 커넥션에서 메시지는 세션 정보의 Master secret과 클라이언트의 난수를 통해서 각 커넥션마다 다르게 생성된 비밀 키에 의해서 암호화된다. 따라서 공격자는 스니핑을 통해서 전송 내용을 도청하더라도 전송되는 메시지를 복호화하기 위한 정보를 얻어내기 어렵게 된다.

사용자 삽입 이미지
  세션을 설정하는 첫번째 단계로 클라이언트와 서버는 Hello 메시지를 교환하며, 이 과정을 통해서 SSL 프로토콜 보존, 세션 ID, 암호 알고리즘, 압축 방법을 설정하고 ClientHello.random과 ServerHello.random을 생성, 교환하게 된다. ClientHello 메시지를 받은 서버는 클라이언트의 인증서를 요구할 수 있으며, 이 경우 서버 자신의 인증서를 보내며 그렇지 않을 경우 ServerKeyExchange를 응답에 포함하여, CertificateRequest를 보내고, Hello 절차가 완료됨을 알리는 ServerHelloDone 메시지를 클라이언트로 보내어 응답한다.

 클라이언트는 Hello에 대한 응답을 받아서 클라이언트의 인증서 또는 ClientKeyExchange와 클라이언트가 사용할 ChangeCipherSpec 메시지를 보내고 뒤이어 CipherSpec에 맞추어 작성된 finished 메시지를 서버로 보낸다.

서버는 ChangeCipherSpec 메시지와 이를 이용해서 만들어진 Finished 메시지를 받은 후 서버가 사용할 CihpherSpec을 ChangeCipherSpec 메시지와 Finished 메시지를 보내고 이후에는 합의된 내용으로 Application Data의 교환이 이루어지게 된다.

 * 세션(Session)과 커넥션(Connection)
 커넥션은 실제로 데이터이 송 수신이 이루어지는 단위를 말하며, Peer-to-Peer 관계가 성립하는 개념이다. 이에 비해서 세션은 논리적인 개념에 가까우며 컴퓨터 사용 시부터 종료 시까지의 개념을 포함한다. 실제로 한 세션은 여러 커넥션을 포함할 수 있다.

 
 * SSL 레코드 프로토콜
 SSL 레코드 프로토콜은 상호 송수신을 위한 암호화 스펙이 SSL 핸드쉐이크 프로토콜에 의해 공유된 후 이러한 스펙에 따라 실제로 전송하는 데이터를 TCP 패킷으로 변환하기 위한 기능을 수행한다. SSL 레코드 프로토콜은 이를 위해 먼저 전송하는 메시지를 일정한 단위의 조각으로 분리하는 Fragmentation, 레코드 압축과 해제, 메시지 인증 및 암호화, 복호화 기능을 수행한다.

사용자 삽입 이미지
 SSL 레코드 프로토콜은 각 메시지에 대해 다음과 같은 절차를 통해서 전송을 수행한다. 먼저 전송할 메시지를 일정한 크기의 레코드 프로토콜 유닛(Record Protocol Unit)으로 분해하고, 각 유닛을 SSL 핸드쉐이크 프로토콜로 사전에 협의한 규칙에 맞게 압축한다. 다음으로 압축된 유닛마다 해시를 이용한 MAC을 생성한 후 이것을 포함하여 암호화한 후 전송한다.

 이 과정에서 사전에 클라이언트와 서버 간에 협의한 스펙에 따라 암호화, MAC 생성, 압축 방식 등을 수행하므로, 메시지를 수신한 측에서도 정상적으로 해독할 수 있다.

 * 변경 암호 스펙 프로토콜
 SSL 변경 암호 스펙(Change Cipher Spec) 메시지는 이후에 전송되는 레코드에 대해서 암호 스켁(Cipher Spec)에 정의된 알고리즘과 키를 이용해서 보호할 수 있도록 수신측에 알려주는 용도로 사용한다. 간단히 요약하면 송수신하는 데 사용하는 암호화 알고리즘, MAC, 압축 방식 등을 요약하고 있는 암호 스펙을 변경하는 데 이용한다.

 클라이언트는 키 교환 메시지와 인증서 확인 메시지를 전송한 후 보내며, 서버는 클라이언트에서 받은 키 교환 메시지를 성공적으로 처리한 후 보내게 된다.

 * SSL 경고 프로토콜
 SSL 경고 프로토콜(SSL Alert Protocol)은 SSL의 동작 과정에서 발생할 수 있는 문제 상황에 대해 경고를 전달하기 위해서 사용한다. 전송하는 경고 정보는 SSL 스펙에 정의되어 있는 치명적은 경고 목록과 메시지의 심각성을 나타내는 2바이트 데이터로 구성된다.

네트워크 관련 RFC 문서 정리

IP 주소 관련 RFC 문서
*RFC 1174 –
IAB Recommended Policy on Distributing Internet Identifier Assignment and
IAB Recommended Policy Change to Internet “Connected” Status
작성자 : V. Cerf (CNRI) / 작성년도 : 1990. 8

*RFC 1366 – Guidelines for Management of IP Address Space
작성자 : E. Gerich (Merit) / 작성년도 : 1992. 10

*RFC 1466 – Guideline for Management of IP Address Space
작성자 : E. Gerich (Merit) / 작성년도 : 1993. 5 / 구버전 : RFC 1366

*RFC 2050 – Internet Registry IP Allocation Guidelines
작성자 : K. Hubbard, M. Kosters(InterNIC), D. Conrad(APNIC), D. Karrenberg(RIPE),
J. Postel(ISI)
작성년도 : 1996. 11 / 구버전 : RFC 1466 / 카테고리 : Best Current Practice(12)

*RFC 2402 – IP Authentication Header (IP 인증 헤더)
*RFC 2406 – IP Encapsulating Security Payload (ESP) (IP 캡슐화 보안 페이로드(ESP))
*RFC 1852 – IP Authentication using Keyed SHA (키가 있는 SHA를 이용한 IP 인증)
*RFC 1886 – DNS Extensions to support IP version 6 (IP 버전 6을 지원하기 위한 DNS 확장)
*RFC 1812 – Requirements for IP Version 4 Routers (IP 버전 4 라우터 요구 사항)
*RFC 1828 – IP Authentication using Keyed MD5 (키가 있는 MD5를 이용한 IP 인증)
*RFC 1518 – An Architecture for IP Address Allocation with CIDR (CIDR을 이용한 IP 주소 할당 아키텍처)
*RFC 1188 – Proposed Standard for the Transmission of IP Datagrams over FDDI Networks
(FDDI를 통한 IP)
*RFC 1201 – Transmitting IP traffic over ARCNET networks (ARCNET을 통한 IP)
*RFC 1042 – Standard for the transmission of IP datagrams over IEEE 802 networks
(IEEE 802 네트워크를 통한 IP 데이터그램 전송 표준)
*RFC 1055 – Nonstandard for transmission of IP datagrams over serial lines: SLIP
(직렬 회선을 통한 IP(IP-SLIP) 전송)
*RFC 894 – A Standard for the Transmission of IP Datagrams over Ethernet Networks
(이더넷을 통한 IP)
*RFC 919 – Broadcasting Internet Datagrams (IP 브로드캐스트 데이터그램)
*RFC 922 – Broadcasting Internet datagrams in the presence of subnets (서브넷 브로드캐스팅)
*RFC 791 – Internet Protocol (인터넷 프로토콜)

사설 주소(네트워크)와 관련된 RFC 문서
*RFC 1918 – Address Allocation for Private Internets
작성자 : Y. Rekhter(Cisco Systems), B. Moskowitz(Chrysler Corp.),
D. Karrenberg, G. J. de Groo,(RIPE NCC), E. Leart(Silicon Graphics, Inc.)
작성년도 : 1996. 2 / 구버전 : 1627, 1597 / 카테고리 : Category: Best Current Practice(5)

*RFC 1631 – The IP Network Address Translator (NAT)
작성자 : K. Egevang(Cray Communications), P. Francis(NTT) / 작성년도 : 1994. 5
카테고리 : Informational

번역본 출처 : 한국인터넷진흥원

(참
고로 ietf 란 RFC (논평 요구서:Request For Comment) 표준안을 평가하는 Internet
Engineering Task Force (주요 인터넷 표준안 제안기관:*역자주) 를 의미합니다. 사실상 RFC1294 나
RFC1490 모두 동일 기관에서 제안된 것이기 때문에 1294 모드에만 ietf 키워드를 쓰는 것은 약간 어폐가 있긴 하지만,
1490 이 보다 최근에 발표된 초기 표준안 (DS:Draft Standard) 으로 좀더 일반성을 띠는 반면, 1294는
그보다 한단계 낮은 표준 제안서이고 언젠가는 폐기될 것이기 때문에 1294에만 키워드를 붙인 것입니다.)

broadcast 주소와 관련된 RFC
*RFC 1700

루프백 주소와 관련된 RFC
*RFC 1700 [page 4, 5]
*RFC 3330

클래스 없는 주소지정과 관련된 RFC 문서

*RFC 1519 – 클래스 없는 도메인 간 라우팅(사이더)주소 할당 및 합침 방법.
*RFC 1518 – 사이더를 이용한 IP 주소 할당을 위한 구조
*RFC 2373 – IPv6 주소 구조

출처 : http://aspell00.egloos.com/187566