nginx openssl 的集成代码流程

说明:
一、这里个人测试完全和nginx处理流程和返回的数据完全一致
二、这里做了只是做了简要抽取,如果作为服务器,能实现这些步骤整体ssl处理应该没有任何问题。
三、这里包含三个文件:NGXSSL.c 为主文件,source.h为头文件,source.c为部分代码文件。

source.h


点击(此处)折叠或打开

  1. /*
  2.  * source.h
  3.  *
  4.  * Created on: 2013-3-3
  5.  * Author: root
  6.  */

  7. #ifndef SOURCE_H_
  8. #define SOURCE_H_

  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <stdint.h>
  12. #include <unistd.h>
  13. #include <sys/types.h>
  14. #include <sys/epoll.h>

  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <arpa/inet.h>
  21. #include <sys/ioctl.h>
  22. #include <openssl/ssl.h>
  23. #include <openssl/err.h>
  24. #include <openssl/conf.h>
  25. #include <openssl/engine.h>
  26. #include <openssl/evp.h>

  27. //错误码的定义
  28. #define NGX_OK 0
  29. #define NGX_ERROR -1
  30. #define NGX_AGAIN -2
  31. #define NGX_BUSY -3
  32. #define NGX_DONE -4
  33. #define NGX_DECLINED -5
  34. #define NGX_ABORT -6
  35. #if (NGX_HAVE_ACCEPT4)
  36.     static ngx_uint_t use_accept4 = 1;
  37. #endif
  38. typedef int ngx_socket_t;

  39. int ngx_ssl_connection_index;
  40. int ngx_ssl_server_conf_index;
  41. int ngx_ssl_session_cache_index;

  42. #define NGX_SSL_SSLv2 0x0002
  43. #define NGX_SSL_SSLv3 0x0004
  44. #define NGX_SSL_TLSv1 0x0008
  45. #define NGX_SSL_TLSv1_1 0x0010
  46. #define NGX_SSL_TLSv1_2 0x0020

  47. #define ngx_ssl_get_connection(ssl_conn) 
  48.     SSL_get_ex_data(ssl_conn, ngx_ssl_connection_index)

  49. #define ngx_ssl_conn_t SSL

  50. #define ngx_close_socket close
  51. #define ngx_socket socket

  52. //错误吗的定义
  53. #define NGX_OK 0
  54. #define NGX_ERROR -1
  55. #define NGX_AGAIN -2
  56. #define NGX_BUSY -3
  57. #define NGX_DONE -4
  58. #define NGX_DECLINED -5
  59. #define NGX_ABORT -6

  60. typedef intptr_t ngx_int_t; //long int 定义
  61. typedef uintptr_t ngx_uint_t; //unsigned long int定义
  62. typedef intptr_t ngx_flag_t;

  63. typedef struct {
  64.     SSL_CTX *ctx;
  65. } ngx_ssl_t;

  66. RSA * ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length);
  67. int ngx_nonblocking(ngx_socket_t s);
  68. void ngx_http_ssl_handshake(int fd,ngx_ssl_conn_t *connection);
  69. ngx_int_t ngx_ssl_handshake(ngx_ssl_conn_t *connection);
  70. ngx_int_t ngx_ssl_shutdown(ngx_ssl_conn_t *connection);
  71. void ngx_ssl_clear_error();

  72. #endif /* SOURCE_H_ */
source.c

点击(此处)折叠或打开

  1. /*
  2.  * source.c
  3.  *
  4.  * Created on: 2013-3-3
  5.  * Author: root
  6.  */

  7. #include "source.h"

  8. //设置一个临时的RSA,在出口算法中,有规定需要这么做的
  9. RSA * ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length) {
  10.     static RSA *key;

  11.     if (key_length == 512) {
  12.         if (key == NULL) {
  13.             key = RSA_generate_key(512, RSA_F4, NULL, NULL);
  14.         }
  15.     }

  16.     return key;
  17. }

  18. //
  19. int ngx_nonblocking(ngx_socket_t s) {
  20.     int nb;

  21.     nb = 1;

  22.     return ioctl(s, FIONBIO, &nb);
  23. }

  24. void ngx_http_ssl_handshake(int fd,ngx_ssl_conn_t *connection) {
  25.     u_char buf[1];
  26.     ssize_t n;
  27.     ngx_int_t rc;

  28.     //如果在recv的时候,flag字段设置了MSG_PEEK,则读取数据包的时候,不会把该数据包从缓存队列中删除;下次读取时还是这个数据包
  29.     n = recv(fd, (char *) buf, 1, MSG_PEEK);

  30.     if (== 1) {
  31.         if (buf[0] & 0x80 /* SSLv2 */|| buf[0] == 0x16 /* SSLv3/TLSv1 */) { //对不同加密协议进行判断
  32.             rc = ngx_ssl_handshake(connection); //处理握手和单向认证
  33.             if (rc == NGX_AGAIN) {
  34.                 return;
  35.             }
  36.             return;
  37.         }else
  38.         {
  39.             //http 平台的请求,如果是http平台的请求,就走一般流程返回错我信息
  40.             return;
  41.         }
  42.     }
  43.     return;
  44. }

  45. ngx_int_t ngx_ssl_handshake(ngx_ssl_conn_t *connection) {
  46.     int n, sslerr;
  47.     n = SSL_do_handshake(connection); //这里会试着握手,由于上次recv之后,会有数据正在写入,返回-1
  48.     if (== 1) {
  49.         /* initial handshake done, disable renegotiation (CVE-2009-3555) */
  50.         if (connection->s3) {
  51.             connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
  52.         }
  53.         return NGX_OK;
  54.     }
  55.     sslerr = SSL_get_error(connection, n);

  56.     //这里应该再重新接收一次和NGINX一样,等待下一次循环(epoll)再进行,同时设置读写句柄,以便下次读取的时候直接进行握手
  57.      if (sslerr == SSL_ERROR_WANT_READ) {
  58.          n = SSL_do_handshake(connection);
  59.              if (== 1) {
  60.                  /* initial handshake done, disable renegotiation (CVE-2009-3555) */
  61.                  if (connection->s3) {
  62.                      connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
  63.                  }
  64.                  return NGX_OK;//握手成功,就可以读取了
  65.              }
  66.      }

  67.     return NGX_AGAIN;
  68. }

  69. //ret->quiet_shutdown=1;默认的是ret->quiet_shutdown=0;他相当于SSL_set_shutdown函数将参数设置为SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN
  70. // 当设置为1时,假如关闭后,不通知对方,这样不适合TLS标准
  71. ngx_int_t ngx_ssl_shutdown(ngx_ssl_conn_t *connection) {

  72.     //这里是对认证正确的处理方式简要地关闭处理
  73.     int n, sslerr, mode;
  74. //    ngx_err_t err;

  75. //    if (c->timedout) { //超时,可能是读取或写入超时导致
  76.     if(0){
  77.         mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
  78.         SSL_set_quiet_shutdown(connection, 1); //设置为1时,假如关闭后,不通知对方

  79.     } else {
  80.         mode = SSL_get_shutdown(connection);

  81. //        if (c->ssl->no_wait_shutdown) {
  82.             mode |= SSL_RECEIVED_SHUTDOWN;
  83. //        }

  84. //        if (c->ssl->no_send_shutdown) {
  85.             mode |= SSL_SENT_SHUTDOWN;
  86. //        }

  87. //        if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
  88.             SSL_set_quiet_shutdown(connection, 1);
  89. //        }
  90.     }

  91.     SSL_set_shutdown(connection, mode);

  92.     ngx_ssl_clear_error();

  93.     n = SSL_shutdown(connection);//关闭SSL套接字


  94.     sslerr = 0;

  95. //    /* SSL_shutdown() never returns -1, on error it returns 0 */
  96. //    if (== 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
  97.         SSL_free(connection); //释放SSL套接字
  98. //        c->ssl = NULL;

  99.         return NGX_OK; //到这里结束了
  100. //    }
  101. //
  102. // return NGX_OK;
  103. }

  104. void ngx_ssl_clear_error() { //对错误信息的清理工作
  105.     while (ERR_peek_error()) {
  106.     }

  107.     ERR_clear_error();
  108. }


  109. //
  110. //ngx_int_t ngx_ssl_init(void) {
  111. //    OPENSSL_config(NULL);
  112. //
  113. //    SSL_library_init();
  114. //    SSL_load_error_strings();
  115. //
  116. //    OpenSSL_add_all_algorithms();
  117. //
  118. //    ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
  119. //
  120. //    if (ngx_ssl_connection_index == -1) {
  121. //        printf("SSL_get_ex_new_index() failed");
  122. //        return NGX_ERROR;
  123. //    }
  124. //
  125. //    ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
  126. //            NULL);
  127. //    if (ngx_ssl_server_conf_index == -1) {
  128. //        printf("SSL_CTX_get_ex_new_index() failed");
  129. //        return NGX_ERROR;
  130. //    }
  131. //
  132. //    ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
  133. //            NULL);
  134. //    if (ngx_ssl_session_cache_index == -1) {
  135. //        printf("SSL_CTX_get_ex_new_index() failed");
  136. //        return NGX_ERROR;
  137. //    }
  138. //
  139. //    return NGX_OK;
  140. //}
  141. //
  142. static void *
  143. ngx_openssl_create_conf(ngx_cycle_t *cycle)
  144. {
  145. ngx_openssl_conf_t *oscf;

  146. oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
  147.  if (oscf == NULL) {
  148. return NULL;
  149. }

  150. /*
  151.  * set by ngx_pcalloc():
  152.  *
  153.  * oscf->engine = 0;
  154.  */

  155. return oscf;
  156. }

  157. static void *
  158. ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
  159. {
  160. ngx_http_ssl_srv_conf_t *sscf;

  161. sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
  162.  if (sscf == NULL) {
  163. return NULL;
  164. }

  165. /*
  166.  * set by ngx_pcalloc():
  167.  *
  168.  * sscf->protocols = 0;
  169.  * sscf->certificate = { 0, NULL };
  170.  * sscf->certificate_key = { 0, NULL };
  171.  * sscf->dhparam = { 0, NULL };
  172.  * sscf->ecdh_curve = { 0, NULL };
  173.  * sscf->client_certificate = { 0, NULL };
  174.  * sscf->crl = { 0, NULL };
  175.  * sscf->ciphers = { 0, NULL };
  176.  * sscf->shm_zone = NULL;
  177.  */

  178. sscf->enable = NGX_CONF_UNSET;
  179. sscf->prefer_server_ciphers = NGX_CONF_UNSET;
  180. sscf->verify = NGX_CONF_UNSET_UINT;
  181. sscf->verify_depth = NGX_CONF_UNSET_UINT;
  182. sscf->builtin_session_cache = NGX_CONF_UNSET;
  183. sscf->session_timeout = NGX_CONF_UNSET;

  184. return sscf;
  185. }

  186. static ngx_int_t
  187. ngx_http_ssl_add_variables(ngx_conf_t *cf)
  188. {
  189. ngx_http_variable_t *var, *v;

  190.  for (= ngx_http_ssl_vars; v->name.len; v++) {
  191. var = ngx_http_add_variable(cf, &v->name, v->flags);
  192.  if (var == NULL) {
  193. return NGX_ERROR;
  194. }

  195. var->get_handler = v->get_handler;
  196. var->data = v->data;
  197. }

  198. return NGX_OK;
  199. }

  200. static void *
  201. ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
  202. {
  203. ngx_http_ssl_srv_conf_t *sscf;

  204. sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
  205.  if (sscf == NULL) {
  206. return NULL;
  207. }

  208. /*
  209.  * set by ngx_pcalloc():
  210.  *
  211.  * sscf->protocols = 0;
  212.  * sscf->certificate = { 0, NULL };
  213.  * sscf->certificate_key = { 0, NULL };
  214.  * sscf->dhparam = { 0, NULL };
  215.  * sscf->ecdh_curve = { 0, NULL };
  216.  * sscf->client_certificate = { 0, NULL };
  217.  * sscf->crl = { 0, NULL };
  218.  * sscf->ciphers = { 0, NULL };
  219.  * sscf->shm_zone = NULL;
  220.  */

  221. sscf->enable = NGX_CONF_UNSET;
  222. sscf->prefer_server_ciphers = NGX_CONF_UNSET;
  223. sscf->verify = NGX_CONF_UNSET_UINT;
  224. sscf->verify_depth = NGX_CONF_UNSET_UINT;
  225. sscf->builtin_session_cache = NGX_CONF_UNSET;
  226. sscf->session_timeout = NGX_CONF_UNSET;

  227. return sscf;
  228. }


  229. //ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) {
  230. //    ssl->ctx = SSL_CTX_new(SSLv23_method());
  231. //
  232. //    if (ssl->ctx == NULL) {
  233. //        printf("SSL_CTX_new() failed");
  234. //        return NGX_ERROR;
  235. //    }
  236. //
  237. //    if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
  238. //        printf("SSL_CTX_set_ex_data() failed");
  239. //        return NGX_ERROR;
  240. //    }
  241. //
  242. //    /* client side options */
  243. //
  244. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
  245. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
  246. //
  247. //    /* server side options */
  248. //
  249. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
  250. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
  251. //
  252. //    /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
  253. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
  254. //
  255. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
  256. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
  257. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
  258. //
  259. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
  260. //
  261. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
  262. //
  263. //    if (!(protocols & NGX_SSL_SSLv2)) {
  264. //        SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
  265. //    }
  266. //    if (!(protocols & NGX_SSL_SSLv3)) {
  267. //        SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
  268. //    }
  269. //    if (!(protocols & NGX_SSL_TLSv1)) {
  270. //        SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
  271. //    }
  272. //
  273. //#ifdef SSL_OP_NO_COMPRESSION
  274. //    SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
  275. //#endif
  276. //
  277. //#ifdef SSL_MODE_RELEASE_BUFFERS
  278. //    SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
  279. //#endif
  280. //
  281. //    SSL_CTX_set_read_ahead(ssl->ctx, 1);
  282. //
  283. //    SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
  284. //
  285. //    return NGX_OK;
  286. //}
  287. //
  288. //void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) {
  289. //    //    void *c;
  290. //    //
  291. //    // if (where & SSL_CB_HANDSHAKE_START) {
  292. //    // c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
  293. //    //
  294. //    // if (c) {
  295. //    // printf("SSL renegotiation");
  296. //    // }
  297. //    // }
  298. //
  299. //    printf("SSL renegotiation");
  300. //}
  301. //
  302. //int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) {
  303. //    const char *servername;
  304. //
  305. //    servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
  306. //
  307. //    if (servername == NULL) {
  308. //        return SSL_TLSEXT_ERR_NOACK;
  309. //    }
  310. //
  311. //    c = ngx_ssl_get_connection(ssl_conn);
  312. //
  313. //    printf("SSL server name: "%s"", servername);
  314. //
  315. //    return SSL_TLSEXT_ERR_OK;
  316. //}
  317. //
  318. //ngx_int_t ngx_ssl_certificate(ngx_ssl_t *ssl, const char *cert, const char *key) {
  319. //    if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert) == 0) {
  320. //        printf("SSL_CTX_use_certificate_chain_file("%s") failed", cert);
  321. //        return NGX_ERROR;
  322. //    }
  323. //
  324. //    if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key, SSL_FILETYPE_PEM)
  325. //            == 0) {
  326. //        printf("SSL_CTX_use_PrivateKey_file("%s") failed", key);
  327. //        return NGX_ERROR;
  328. //    }
  329. //
  330. //    return NGX_OK;
  331. //}
  332. //

  333. //
  334. //ngx_ssl_conn_t * ngx_ssl_create_connection(ngx_ssl_t *ssl, int socketid) {
  335. //    c = malloc(1024);
  336. //    ngx_ssl_conn_t *connection;
  337. //
  338. //    connection = SSL_new(ssl->ctx);
  339. //
  340. //    if (connection == NULL) {
  341. //        return NULL;
  342. //    }
  343. //
  344. //    if (SSL_set_fd(connection, socketid) == 0) {
  345. //        return NULL;
  346. //    }
  347. //    SSL_set_accept_state(connection);
  348. //    if (SSL_set_ex_data(connection, ngx_ssl_connection_index, c) == 0) {
  349. //        return NULL;
  350. //    }
  351. //
  352. //    return connection;
  353. //}
  354. //
  355. //
  356. //ngx_int_t ngx_ssl_dhparam(ngx_ssl_t *ssl, const char *file) {
  357. //    DH *dh;
  358. //    BIO *bio;
  359. //
  360. //    /*
  361. //     * -----BEGIN DH PARAMETERS-----
  362. //     * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
  363. //     * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
  364. //     * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
  365. //     * -----END DH PARAMETERS-----
  366. //     */
  367. //
  368. //    static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46,
  369. //            0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, 0xD9,
  370. //            0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, 0x08, 0xEE, 0xD4, 0xEB,
  371. //            0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, 0xE7, 0x10, 0x80,
  372. //            0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, 0xBE, 0xEC,
  373. //            0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, 0x9B,
  374. //            0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
  375. //            0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5,
  376. //            0xDF, 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC,
  377. //            0x9A, 0x50, 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A,
  378. //            0x63, 0xAB, 0x1E, 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D,
  379. //            0x14, 0x67, 0x57, 0xDA, 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B,
  380. //            0x9B };
  381. //
  382. //    static unsigned char dh1024_g[] = { 0x02 };
  383. //
  384. //    if (!file) {
  385. //
  386. //        dh = DH_new();
  387. //        if (dh == NULL) {
  388. //            return NGX_ERROR;
  389. //        }
  390. //
  391. //        dh->= BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
  392. //        dh->= BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
  393. //
  394. //        if (dh->== NULL || dh->== NULL) {
  395. //            DH_free(dh);
  396. //            return NGX_ERROR;
  397. //        }
  398. //
  399. //        SSL_CTX_set_tmp_dh(ssl->ctx, dh);
  400. //
  401. //        DH_free(dh);
  402. //
  403. //        return NGX_OK;
  404. //    }
  405. //
  406. //    bio = BIO_new_file((char *) file, "r");
  407. //    if (bio == NULL) {
  408. //        return NGX_ERROR;
  409. //    }
  410. //
  411. //    dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
  412. //    if (dh == NULL) {
  413. //        BIO_free(bio);
  414. //        return NGX_ERROR;
  415. //    }
  416. //
  417. //    SSL_CTX_set_tmp_dh(ssl->ctx, dh);
  418. //
  419. //    DH_free(dh);
  420. //    BIO_free(bio);
  421. //
  422. //    return NGX_OK;
  423. //}
  424. //
  425. //ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, const char *sess_ctx,
  426. //        ssize_t builtin_session_cache, time_t timeout) {
  427. //    SSL_CTX_set_session_id_context(ssl->ctx, (const unsigned char *) sess_ctx,strlen(sess_ctx));
  428. //
  429. //    SSL_CTX_set_session_cache_mode(ssl->ctx,
  430. //            SSL_SESS_CACHE_SERVER
  431. //            |SSL_SESS_CACHE_NO_AUTO_CLEAR
  432. //            |SSL_SESS_CACHE_NO_INTERNAL_STORE);
  433. //
  434. //    SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
  435. //
  436. //    return NGX_OK;
  437. //
  438. //}

  439. //打开监听到接口,只绑定了一个
  440. ngx_socket_t ngx_open_listening_sockets() {
  441.     int reuseaddr;
  442.     ngx_socket_t s;
  443.     reuseaddr = 1; //重用地址
  444.     struct sockaddr_in addr;

  445.     s = ngx_socket(AF_INET, SOCK_STREAM, 0); //创建套接口
  446.     if (== -1) {
  447.         return NGX_ERROR;
  448.     }

  449.     /* 填写sockaddr_in结构*/
  450.     bzero(&addr, sizeof(addr));
  451.     addr.sin_family = AF_INET;
  452.     addr.sin_port = htons(443);
  453.     addr.sin_addr.s_addr = inet_addr("127.0.0.1");

  454.     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuseaddr,
  455.             sizeof(int)) == -1) {
  456.         if (ngx_close_socket(s) == -1) { //出错就把它关闭
  457.         }
  458.         return NGX_ERROR;
  459.     }

  460.     if (ngx_nonblocking(s) == -1) { //堵塞失败调用
  461.         if (ngx_close_socket(s) == -1) { //关闭套接字
  462.         }
  463.         return NGX_ERROR;
  464.     }

  465.     if (bind(s, (struct sockaddr*) &addr, sizeof(addr)) == -1) { //绑定
  466.         return NGX_ERROR;
  467.     }

  468.     if (listen(s, 5) == -1) { //监听套接口
  469.         if (ngx_close_socket(s) == -1) {
  470.         }
  471.         return NGX_ERROR;
  472.     }

  473.     return s;
  474. }
NGXSSL.c


点击(此处)折叠或打开

  1. /*
  2.  ============================================================================
  3.  Name : NGXSSL.c
  4.  Author : xiangrongcheng
  5.  Version :
  6.  Copyright : Your copyright notice
  7.  Description :  Ansi-style
  8.  ============================================================================
  9.  */

  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include "source.h"

  13. int epfd;

  14. int main(void) {

  15. //    void *data = NULL;

  16.     //认证和密钥目录
  17.     const char * certificate = "/usr/local/nginx/conf/api.bz.crt";
  18.     const char * certificate_key = "/usr/local/nginx/conf/api.bz_nopass.key";

  19.     //这里模拟nginx初始化
  20.     //    ngx_ssl_init(); //初始化ssl
  21.     OPENSSL_config(NULL); //加载openssl的配置信息,不知道对否
  22.     SSL_library_init(); //加载ssl库函数
  23.     SSL_load_error_strings(); //格式化错误日志信息
  24.     OpenSSL_add_all_algorithms(); //load所有的SSL算法

  25. //    //这里没有必要,是做为缓存,会话和连接池处理的
  26. //    ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
  27. //    if (ngx_ssl_connection_index == -1) {
  28. //        printf("SSL_get_ex_new_index() failed");
  29. //        return NGX_ERROR;
  30. //    }
  31. //
  32. //    ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,NULL);
  33. //    if (ngx_ssl_server_conf_index == -1) {
  34. //        printf("SSL_CTX_get_ex_new_index() failed");
  35. //        return NGX_ERROR;
  36. //    }
  37. //
  38. //    ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,NULL);
  39. //    if (ngx_ssl_session_cache_index == -1) {
  40. //        printf("SSL_CTX_get_ex_new_index() failed");
  41. //        return NGX_ERROR;
  42. //    }

  43.     //创建ssl
  44.     ngx_ssl_t ssl;
  45.     ngx_uint_t protocols = 61;
  46. //    ngx_ssl_create(ssl, protocols, data);
  47.     ssl.ctx = SSL_CTX_new(SSLv23_method()); //通过SSL所用方法新建SSL_CTX上下文信息
  48.     if (ssl.ctx == NULL) {
  49.         printf("SSL_CTX_new() failed");
  50.         return NGX_ERROR;
  51.     }

  52. //    //设置上下文信息的数据,保存扩展数据(应该不是很需要)
  53. //    if (SSL_CTX_set_ex_data(ssl.ctx, ngx_ssl_server_conf_index, data) == 0) {
  54. //        printf("SSL_CTX_set_ex_data() failed");
  55. //        return NGX_ERROR;
  56. //    }

  57.     //客户端服务器选项的设定,具体查看具体参数吧,可以看一下英文
  58.     /* client side options */
  59.     SSL_CTX_set_options(ssl.ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
  60.     SSL_CTX_set_options(ssl.ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);

  61.     /* server side options */
  62.     SSL_CTX_set_options(ssl.ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
  63.     SSL_CTX_set_options(ssl.ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);

  64.     /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
  65.     SSL_CTX_set_options(ssl.ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
  66.     SSL_CTX_set_options(ssl.ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
  67.     SSL_CTX_set_options(ssl.ctx, SSL_OP_TLS_D5_BUG);
  68.     SSL_CTX_set_options(ssl.ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
  69.     SSL_CTX_set_options(ssl.ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
  70.     SSL_CTX_set_options(ssl.ctx, SSL_OP_SINGLE_DH_USE);

  71.     if (!(protocols & NGX_SSL_SSLv2)) {
  72.         SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_SSLv2);
  73.     }
  74.     if (!(protocols & NGX_SSL_SSLv3)) {
  75.         SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_SSLv3);
  76.     }
  77.     if (!(protocols & NGX_SSL_TLSv1)) {
  78.         SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_TLSv1);
  79.     }

  80. #ifdef SSL_OP_NO_COMPRESSION
  81.     SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_COMPRESSION);
  82. #endif

  83. #ifdef SSL_MODE_RELEASE_BUFFERS
  84.     SSL_CTX_set_mode(ssl.ctx, SSL_MODE_RELEASE_BUFFERS);
  85. #endif

  86.     //这里一定需要,设置读取头一个字节,作为判断协议,如果不设定那么将使得n = SSL_read(connection, buffer, 512);少读前一个字节,因为读取第一个字节作为判断字节
  87.     SSL_CTX_set_read_ahead(ssl.ctx, 1);

  88.     //下面也不是必要的
  89. //    SSL_CTX_set_info_callback(ssl.ctx, ngx_ssl_info_callback);
  90. //    SSL_CTX_set_tlsext_servername_callback(ssl.ctx,ngx_http_ssl_servername);

  91. //    ngx_ssl_certificate(ssl, certificate, certificate_key);

  92. //     SSL_CTX_load_verify_locations用于加载受信任的CA证书,CAfile如果不为NULL,则他指向的文件包含PEM编码格式的一个或多个证书,可以用e.g.来简要介绍证书内容
  93. //      CApath如果不为NULL,则它指向一个包含PEM格式的CA证书的目录,目录中每个文件包含一份CA证书,文件名是证书中CA名的HASH值
  94. //      可以用c-rehash来建立该目录,如cd /some/where/certs(包含了很多可信任的CA证书) c_rehash .。返回一成功,0 失败。SSL_CTX_set_default_verify_paths找寻默认的验证路径,在这里肯定找不到的。
  95. //      这里主要set cert_store
  96. //      char *CAfile=NULL,*CApath=NULL;
  97. //      SSL_CTX_load_verify_locations(ctx,CAfile,CApath);
  98. //      当需要客户端验证的时候,服务器把CAfile里面的可信任CA证书发往客户端。
  99. //      if(CAfile !=NULL )SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
  100. //      设置最大的验证用户证书的上级数。
  101. //      SSL_CTX_set_verify_depth(ctx,10);

  102.     //设置加载服务器的证书和私钥
  103.     if (SSL_CTX_use_certificate_chain_file(ssl.ctx, (char *) certificate) == 0) {
  104.         printf("SSL_CTX_use_certificate_chain_file("%s") failed", certificate);
  105.     }
  106.     if (SSL_CTX_use_PrivateKey_file(ssl.ctx, (char *) certificate_key, SSL_FILETYPE_PEM)== 0) { //类型测试好像无所谓,应该是SSL_FILETYPE_ASN1?
  107.         printf("SSL_CTX_use_PrivateKey_file("%s") failed", certificate_key);
  108.     }

  109.     SSL_CTX_set_cipher_list(ssl.ctx, "HIGH:!aNULL:!MD5"); //设置密码链表,具体看密码    ciphers(1)指令吧
  110.     SSL_CTX_set_tmp_rsa_callback(ssl.ctx, ngx_ssl_rsa512_key_callback); //设置键改变时调用,握手时的处理

  111.     //如果是双向认证还得做下面这几件事情
  112. //     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
  113. // SSL_CTX_set_verify_depth(ssl->ctx, depth);
  114. //     SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL);
  115. //     SSL_load_client_CA_file((char *) cert->data);
  116. //     ERR_clear_error();
  117. //     SSL_CTX_set_client_CA_list(ssl->ctx, list);
  118. //     SSL_CTX_get_cert_store(ssl->ctx);
  119. // X509_STORE_add_lookup(store, X509_LOOKUP_file();
  120. // X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM);
  121. // X509_STORE_set_flags(store,X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);

  122.     //ngx_ssl_dhparam(ssl, "");
  123. //    当使用RSA算法鉴别的时候,会有一个临时的DH密钥磋商发生。这样会话数据将用这个临时的密钥加密,而证书中的密钥中做为签名。
  124. //    所以这样增强了安全性,临时密钥是在会话结束消失的,所以就是获取了全部信息也无法把通信内容给解密出来。

  125. //    实现 openssl 提供的默认的 DH_METHOD,实现了根据密钥参数生成 DH 公私钥,以及根据 DH 公钥(一方)以及 DH 私钥(另一方)来生成一个共享密钥,用于密钥交换。
  126.     //DH密钥磋商设置
  127.     DH *dh;
  128.     static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46,
  129.             0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, 0xD9,
  130.             0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, 0x08, 0xEE, 0xD4, 0xEB,
  131.             0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, 0xE7, 0x10, 0x80,
  132.             0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, 0xBE, 0xEC,
  133.             0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, 0x9B,
  134.             0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
  135.             0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5,
  136.             0xDF, 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC,
  137.             0x9A, 0x50, 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A,
  138.             0x63, 0xAB, 0x1E, 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D,
  139.             0x14, 0x67, 0x57, 0xDA, 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B,
  140.             0x9B };

  141.     static unsigned char dh1024_g[] = { 0x02 };
  142.     dh = DH_new();
  143.     if (dh == NULL) {
  144.     }

  145.     dh->= BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
  146.     dh->= BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);

  147.     if (dh->== NULL || dh->== NULL) {
  148.         DH_free(dh);
  149.     }
  150.     SSL_CTX_set_tmp_dh(ssl.ctx, dh);
  151.     DH_free(dh);

  152. //    ngx_ssl_session_cache(ssl, "HTTP", 0, 0);
  153.     //下面只是会话的设置
  154.     SSL_CTX_set_session_id_context(ssl.ctx, (const unsigned char *) "HTTP",strlen("HTTP"));
  155.     SSL_CTX_set_session_cache_mode(ssl.ctx,
  156.             SSL_SESS_CACHE_SERVER
  157.             |SSL_SESS_CACHE_NO_AUTO_CLEAR
  158.             |SSL_SESS_CACHE_NO_INTERNAL_STORE);

  159. //    设置cache的大小,默认的为1024*20=20000,这个也就是可以存多少个session_id,一般都不需要更改的。假如为0的话将是无限
  160.     SSL_CTX_sess_set_cache_size(ssl.ctx, 1);

  161.     //下面是网络模块
  162.     socklen_t sin_len = sizeof(struct sockaddr_in);
  163.     int fd, opt = 1;
  164.     struct epoll_event ev;
  165.     struct sockaddr_in sin, cin;

  166.     epfd = epoll_create(1024);
  167.     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) <= 0) {
  168.         fprintf(stderr, "socket failed/n");
  169.         return -1;
  170.     }
  171.     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &opt, sizeof(opt));

  172.     memset(&sin, 0, sizeof(struct sockaddr_in));
  173.     sin.sin_family = AF_INET;
  174.     sin.sin_port = htons((short) (443));
  175.     sin.sin_addr.s_addr = INADDR_ANY;
  176.     if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
  177.         fprintf(stderr, "bind failed/n");
  178.         return -1;
  179.     }
  180.     if (listen(fd, 32) != 0) {
  181.         fprintf(stderr, "listen failed/n");
  182.         return -1;
  183.     }

  184.     int i, cfd, n, nfds;

  185.     struct epoll_event events[1024];
  186.     char buffer[512];

  187.     ev.data.fd = fd;
  188.     ev.events = EPOLLIN | EPOLLET; //设置要处理的事件类型
  189.     epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);

  190.     while (1) {
  191.         nfds = epoll_wait(epfd, events, 1024, -1);
  192.         printf("nfds ........... %d/n", nfds);
  193.         for (= 0; i < nfds; i++) {
  194.             if (events[i].data.fd == fd) {
  195.                 cfd = accept(fd, (struct sockaddr *) &cin, &sin_len);
  196.                 ngx_nonblocking(cfd); //把客户端的socket设置为非阻塞方式
  197.                 ev.data.fd = cfd;
  198.                 ev.events = EPOLLIN | EPOLLET;
  199.                 epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
  200.             } else {
  201.                 if (events[i].events & EPOLLIN) {
  202.                     cfd = events[i].data.fd;

  203.                     //这里模拟nginx接收
  204. //                    ngx_ssl_create_connection(ssl, cfd);
  205.                     ngx_ssl_conn_t *connection = SSL_new(ssl.ctx); //根据上下文,建立ssl套接口或链接
  206.                     if (connection == NULL) {
  207.                     }

  208.                     if (SSL_set_fd(connection, cfd) == 0) { //设置处理的id进入上下文里面
  209.                     }
  210.                     SSL_set_accept_state(connection); //设置接收状态

  211. //                    if (SSL_set_ex_data(connection, ngx_ssl_connection_index, c) == 0) {
  212. //                    }

  213.                     //进行握手处理
  214.                     ngx_http_ssl_handshake(cfd,connection);

  215.                     //正确处理
  216.                     for (;;) {
  217.                         n = SSL_read(connection, buffer, 512); //会读取好几次把之前读取的第一个字节也读取回来
  218.                         if (> 0) {
  219.                         } else {
  220.                             break;
  221.                         }
  222.                         continue;
  223.                     }

  224.                     //这里是,对请求的相关处理,省略掉了

  225.                     //ngx_http_process_request_headers(rev);

  226.                     //给客户端发送数据
  227.                     const char *data = "HTTP/1.1 200 OKrnServer: nginx/1.0.12rnDate: Sun, 03 Mar 2013 12:38:48 GMTrnContent- ...";
  228.                     n = SSL_write(connection, data, sizeof(data));

  229.                     //关闭请求链接;如果验证通过是不会走这里的(而等到超时的时候才处理);对于验证不通过或http请求则直接调用关闭链接。
  230.                     ngx_ssl_shutdown(connection);
  231.                     SSL_CTX_free(ssl.ctx);//释放SSL环境
  232.                     close(fd);

  233.                     //                    ret = recv(cfd, buffer, sizeof(buffer), 0);
  234.                     //                    printf("read ret..........= %d/n", ret);
  235.                     //
  236.                     //                    ev.data.fd = cfd;
  237.                     //                    ev.events = EPOLLOUT | EPOLLET;
  238.                     //                    epoll_ctl(epfd, EPOLL_CTL_MOD, cfd, &ev);
  239.                 } else if (events[i].events & EPOLLOUT) {
  240.                     cfd = events[i].data.fd;

  241.                     ev.data.fd = cfd;
  242.                     epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, &ev);
  243.                     close(cfd);

  244.                 }
  245.             }
  246.         }
  247.     }

  248.     if (fd > 0)
  249.         close(fd);
  250.     return 0;
  251. }




openssl nginx 处理流程总结:

一、初始化工作
1、通过SSL所用方法新建SSL_CTX上下文信息
2、客户端服务器选项的ssl上下文设定
3、设置读取第一个字节读取设定
4、设置服务器的CA证书和私钥
5、DH密钥磋商设定,加强数据安全性
6、如果是双向认证还得做一些事情
7、设置密码链表
8、设置键改变时调用,握手时的处理
9、网络模块的建立

二、当请求到来时
1、通过ssl的上下文建立ssl链接
2、设置链接状态和描述符
3、进行握手处理
4、读取一个字节,进行协议判断,如果协议不正确做退出等操作
5、协议正确,会进行握手操作(SSL_do_handshake),握手里面做了三件事:加密算法保持一致,确认所使用的算法中的加密密钥,对客户端进行认证。
6、握手成功后SSL_read 在“记录层”进行数据读取
7、数据处理
8、对客户端进行写入操作,也在“记录层”进行处理。
9、最后进行数据的关闭等操作

SSL_read 和 SSL_write 都是根据记录层,进行数据加密/解密传输所得的正确数据
当然实现还可有使用 SSL自带的接收和链接函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值