说明:
一、这里个人测试完全和nginx处理流程和返回的数据完全一致
二、这里做了只是做了简要抽取,如果作为服务器,能实现这些步骤整体ssl处理应该没有任何问题。
三、这里包含三个文件:NGXSSL.c 为主文件,source.h为头文件,source.c为部分代码文件。
source.h
source.c
NGXSSL.c
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自带的接收和链接函数
一、这里个人测试完全和nginx处理流程和返回的数据完全一致
二、这里做了只是做了简要抽取,如果作为服务器,能实现这些步骤整体ssl处理应该没有任何问题。
三、这里包含三个文件:NGXSSL.c 为主文件,source.h为头文件,source.c为部分代码文件。
source.h
点击(此处)折叠或打开
- /*
- * source.h
- *
- * Created on: 2013-3-3
- * Author: root
- */
-
- #ifndef SOURCE_H_
- #define SOURCE_H_
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/epoll.h>
-
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <sys/ioctl.h>
- #include <openssl/ssl.h>
- #include <openssl/err.h>
- #include <openssl/conf.h>
- #include <openssl/engine.h>
- #include <openssl/evp.h>
-
- //错误码的定义
- #define NGX_OK 0
- #define NGX_ERROR -1
- #define NGX_AGAIN -2
- #define NGX_BUSY -3
- #define NGX_DONE -4
- #define NGX_DECLINED -5
- #define NGX_ABORT -6
- #if (NGX_HAVE_ACCEPT4)
- static ngx_uint_t use_accept4 = 1;
- #endif
- typedef int ngx_socket_t;
-
- int ngx_ssl_connection_index;
- int ngx_ssl_server_conf_index;
- int ngx_ssl_session_cache_index;
-
- #define NGX_SSL_SSLv2 0x0002
- #define NGX_SSL_SSLv3 0x0004
- #define NGX_SSL_TLSv1 0x0008
- #define NGX_SSL_TLSv1_1 0x0010
- #define NGX_SSL_TLSv1_2 0x0020
-
- #define ngx_ssl_get_connection(ssl_conn)
- SSL_get_ex_data(ssl_conn, ngx_ssl_connection_index)
-
- #define ngx_ssl_conn_t SSL
-
- #define ngx_close_socket close
- #define ngx_socket socket
-
- //错误吗的定义
- #define NGX_OK 0
- #define NGX_ERROR -1
- #define NGX_AGAIN -2
- #define NGX_BUSY -3
- #define NGX_DONE -4
- #define NGX_DECLINED -5
- #define NGX_ABORT -6
-
- typedef intptr_t ngx_int_t; //long int 定义
- typedef uintptr_t ngx_uint_t; //unsigned long int定义
- typedef intptr_t ngx_flag_t;
-
- typedef struct {
- SSL_CTX *ctx;
- } ngx_ssl_t;
-
- RSA * ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length);
- int ngx_nonblocking(ngx_socket_t s);
- void ngx_http_ssl_handshake(int fd,ngx_ssl_conn_t *connection);
- ngx_int_t ngx_ssl_handshake(ngx_ssl_conn_t *connection);
- ngx_int_t ngx_ssl_shutdown(ngx_ssl_conn_t *connection);
- void ngx_ssl_clear_error();
-
- #endif /* SOURCE_H_ */
点击(此处)折叠或打开
- /*
- * source.c
- *
- * Created on: 2013-3-3
- * Author: root
- */
-
- #include "source.h"
-
- //设置一个临时的RSA,在出口算法中,有规定需要这么做的
- RSA * ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length) {
- static RSA *key;
-
- if (key_length == 512) {
- if (key == NULL) {
- key = RSA_generate_key(512, RSA_F4, NULL, NULL);
- }
- }
-
- return key;
- }
-
- //
- int ngx_nonblocking(ngx_socket_t s) {
- int nb;
-
- nb = 1;
-
- return ioctl(s, FIONBIO, &nb);
- }
-
- void ngx_http_ssl_handshake(int fd,ngx_ssl_conn_t *connection) {
- u_char buf[1];
- ssize_t n;
- ngx_int_t rc;
-
- //如果在recv的时候,flag字段设置了MSG_PEEK,则读取数据包的时候,不会把该数据包从缓存队列中删除;下次读取时还是这个数据包
- n = recv(fd, (char *) buf, 1, MSG_PEEK);
-
- if (n == 1) {
- if (buf[0] & 0x80 /* SSLv2 */|| buf[0] == 0x16 /* SSLv3/TLSv1 */) { //对不同加密协议进行判断
- rc = ngx_ssl_handshake(connection); //处理握手和单向认证
- if (rc == NGX_AGAIN) {
- return;
- }
- return;
- }else
- {
- //http 平台的请求,如果是http平台的请求,就走一般流程返回错我信息
- return;
- }
- }
- return;
- }
-
- ngx_int_t ngx_ssl_handshake(ngx_ssl_conn_t *connection) {
- int n, sslerr;
- n = SSL_do_handshake(connection); //这里会试着握手,由于上次recv之后,会有数据正在写入,返回-1
- if (n == 1) {
- /* initial handshake done, disable renegotiation (CVE-2009-3555) */
- if (connection->s3) {
- connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
- }
- return NGX_OK;
- }
- sslerr = SSL_get_error(connection, n);
-
- //这里应该再重新接收一次和NGINX一样,等待下一次循环(epoll)再进行,同时设置读写句柄,以便下次读取的时候直接进行握手
- if (sslerr == SSL_ERROR_WANT_READ) {
- n = SSL_do_handshake(connection);
- if (n == 1) {
- /* initial handshake done, disable renegotiation (CVE-2009-3555) */
- if (connection->s3) {
- connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
- }
- return NGX_OK;//握手成功,就可以读取了
- }
- }
-
- return NGX_AGAIN;
- }
-
- //ret->quiet_shutdown=1;默认的是ret->quiet_shutdown=0;他相当于SSL_set_shutdown函数将参数设置为SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN
- // 当设置为1时,假如关闭后,不通知对方,这样不适合TLS标准
- ngx_int_t ngx_ssl_shutdown(ngx_ssl_conn_t *connection) {
-
- //这里是对认证正确的处理方式简要地关闭处理
- int n, sslerr, mode;
- // ngx_err_t err;
-
- // if (c->timedout) { //超时,可能是读取或写入超时导致
- if(0){
- mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
- SSL_set_quiet_shutdown(connection, 1); //设置为1时,假如关闭后,不通知对方
-
- } else {
- mode = SSL_get_shutdown(connection);
-
- // if (c->ssl->no_wait_shutdown) {
- mode |= SSL_RECEIVED_SHUTDOWN;
- // }
-
- // if (c->ssl->no_send_shutdown) {
- mode |= SSL_SENT_SHUTDOWN;
- // }
-
- // if (c->ssl->no_wait_shutdown && c->ssl->no_send_shutdown) {
- SSL_set_quiet_shutdown(connection, 1);
- // }
- }
-
- SSL_set_shutdown(connection, mode);
-
- ngx_ssl_clear_error();
-
- n = SSL_shutdown(connection);//关闭SSL套接字
-
-
- sslerr = 0;
-
- // /* SSL_shutdown() never returns -1, on error it returns 0 */
- // if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
- SSL_free(connection); //释放SSL套接字
- // c->ssl = NULL;
-
- return NGX_OK; //到这里结束了
- // }
- //
- // return NGX_OK;
- }
-
- void ngx_ssl_clear_error() { //对错误信息的清理工作
- while (ERR_peek_error()) {
- }
-
- ERR_clear_error();
- }
-
-
- //
- //ngx_int_t ngx_ssl_init(void) {
- // OPENSSL_config(NULL);
- //
- // SSL_library_init();
- // SSL_load_error_strings();
- //
- // OpenSSL_add_all_algorithms();
- //
- // ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- //
- // if (ngx_ssl_connection_index == -1) {
- // printf("SSL_get_ex_new_index() failed");
- // return NGX_ERROR;
- // }
- //
- // ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
- // NULL);
- // if (ngx_ssl_server_conf_index == -1) {
- // printf("SSL_CTX_get_ex_new_index() failed");
- // return NGX_ERROR;
- // }
- //
- // ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
- // NULL);
- // if (ngx_ssl_session_cache_index == -1) {
- // printf("SSL_CTX_get_ex_new_index() failed");
- // return NGX_ERROR;
- // }
- //
- // return NGX_OK;
- //}
- //
- static void *
- ngx_openssl_create_conf(ngx_cycle_t *cycle)
- {
- ngx_openssl_conf_t *oscf;
-
- oscf = ngx_pcalloc(cycle->pool, sizeof(ngx_openssl_conf_t));
- if (oscf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * oscf->engine = 0;
- */
-
- return oscf;
- }
-
- static void *
- ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
- {
- ngx_http_ssl_srv_conf_t *sscf;
-
- sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
- if (sscf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * sscf->protocols = 0;
- * sscf->certificate = { 0, NULL };
- * sscf->certificate_key = { 0, NULL };
- * sscf->dhparam = { 0, NULL };
- * sscf->ecdh_curve = { 0, NULL };
- * sscf->client_certificate = { 0, NULL };
- * sscf->crl = { 0, NULL };
- * sscf->ciphers = { 0, NULL };
- * sscf->shm_zone = NULL;
- */
-
- sscf->enable = NGX_CONF_UNSET;
- sscf->prefer_server_ciphers = NGX_CONF_UNSET;
- sscf->verify = NGX_CONF_UNSET_UINT;
- sscf->verify_depth = NGX_CONF_UNSET_UINT;
- sscf->builtin_session_cache = NGX_CONF_UNSET;
- sscf->session_timeout = NGX_CONF_UNSET;
-
- return sscf;
- }
-
- static ngx_int_t
- ngx_http_ssl_add_variables(ngx_conf_t *cf)
- {
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_ssl_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
- }
-
- static void *
- ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
- {
- ngx_http_ssl_srv_conf_t *sscf;
-
- sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
- if (sscf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * sscf->protocols = 0;
- * sscf->certificate = { 0, NULL };
- * sscf->certificate_key = { 0, NULL };
- * sscf->dhparam = { 0, NULL };
- * sscf->ecdh_curve = { 0, NULL };
- * sscf->client_certificate = { 0, NULL };
- * sscf->crl = { 0, NULL };
- * sscf->ciphers = { 0, NULL };
- * sscf->shm_zone = NULL;
- */
-
- sscf->enable = NGX_CONF_UNSET;
- sscf->prefer_server_ciphers = NGX_CONF_UNSET;
- sscf->verify = NGX_CONF_UNSET_UINT;
- sscf->verify_depth = NGX_CONF_UNSET_UINT;
- sscf->builtin_session_cache = NGX_CONF_UNSET;
- sscf->session_timeout = NGX_CONF_UNSET;
-
- return sscf;
- }
-
-
- //ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) {
- // ssl->ctx = SSL_CTX_new(SSLv23_method());
- //
- // if (ssl->ctx == NULL) {
- // printf("SSL_CTX_new() failed");
- // return NGX_ERROR;
- // }
- //
- // if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {
- // printf("SSL_CTX_set_ex_data() failed");
- // return NGX_ERROR;
- // }
- //
- // /* client side options */
- //
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
- //
- // /* server side options */
- //
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
- //
- // /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
- //
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_D5_BUG);
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
- //
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
- //
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
- //
- // if (!(protocols & NGX_SSL_SSLv2)) {
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv2);
- // }
- // if (!(protocols & NGX_SSL_SSLv3)) {
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_SSLv3);
- // }
- // if (!(protocols & NGX_SSL_TLSv1)) {
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1);
- // }
- //
- //#ifdef SSL_OP_NO_COMPRESSION
- // SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
- //#endif
- //
- //#ifdef SSL_MODE_RELEASE_BUFFERS
- // SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS);
- //#endif
- //
- // SSL_CTX_set_read_ahead(ssl->ctx, 1);
- //
- // SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
- //
- // return NGX_OK;
- //}
- //
- //void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) {
- // // void *c;
- // //
- // // if (where & SSL_CB_HANDSHAKE_START) {
- // // c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
- // //
- // // if (c) {
- // // printf("SSL renegotiation");
- // // }
- // // }
- //
- // printf("SSL renegotiation");
- //}
- //
- //int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) {
- // const char *servername;
- //
- // servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
- //
- // if (servername == NULL) {
- // return SSL_TLSEXT_ERR_NOACK;
- // }
- //
- // c = ngx_ssl_get_connection(ssl_conn);
- //
- // printf("SSL server name: "%s"", servername);
- //
- // return SSL_TLSEXT_ERR_OK;
- //}
- //
- //ngx_int_t ngx_ssl_certificate(ngx_ssl_t *ssl, const char *cert, const char *key) {
- // if (SSL_CTX_use_certificate_chain_file(ssl->ctx, (char *) cert) == 0) {
- // printf("SSL_CTX_use_certificate_chain_file("%s") failed", cert);
- // return NGX_ERROR;
- // }
- //
- // if (SSL_CTX_use_PrivateKey_file(ssl->ctx, (char *) key, SSL_FILETYPE_PEM)
- // == 0) {
- // printf("SSL_CTX_use_PrivateKey_file("%s") failed", key);
- // return NGX_ERROR;
- // }
- //
- // return NGX_OK;
- //}
- //
-
- //
- //ngx_ssl_conn_t * ngx_ssl_create_connection(ngx_ssl_t *ssl, int socketid) {
- // c = malloc(1024);
- // ngx_ssl_conn_t *connection;
- //
- // connection = SSL_new(ssl->ctx);
- //
- // if (connection == NULL) {
- // return NULL;
- // }
- //
- // if (SSL_set_fd(connection, socketid) == 0) {
- // return NULL;
- // }
- // SSL_set_accept_state(connection);
- // if (SSL_set_ex_data(connection, ngx_ssl_connection_index, c) == 0) {
- // return NULL;
- // }
- //
- // return connection;
- //}
- //
- //
- //ngx_int_t ngx_ssl_dhparam(ngx_ssl_t *ssl, const char *file) {
- // DH *dh;
- // BIO *bio;
- //
- // /*
- // * -----BEGIN DH PARAMETERS-----
- // * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc
- // * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl
- // * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC
- // * -----END DH PARAMETERS-----
- // */
- //
- // static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46,
- // 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, 0xD9,
- // 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, 0x08, 0xEE, 0xD4, 0xEB,
- // 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, 0xE7, 0x10, 0x80,
- // 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, 0xBE, 0xEC,
- // 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, 0x9B,
- // 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
- // 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5,
- // 0xDF, 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC,
- // 0x9A, 0x50, 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A,
- // 0x63, 0xAB, 0x1E, 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D,
- // 0x14, 0x67, 0x57, 0xDA, 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B,
- // 0x9B };
- //
- // static unsigned char dh1024_g[] = { 0x02 };
- //
- // if (!file) {
- //
- // dh = DH_new();
- // if (dh == NULL) {
- // return NGX_ERROR;
- // }
- //
- // dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
- // dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
- //
- // if (dh->p == NULL || dh->g == NULL) {
- // DH_free(dh);
- // return NGX_ERROR;
- // }
- //
- // SSL_CTX_set_tmp_dh(ssl->ctx, dh);
- //
- // DH_free(dh);
- //
- // return NGX_OK;
- // }
- //
- // bio = BIO_new_file((char *) file, "r");
- // if (bio == NULL) {
- // return NGX_ERROR;
- // }
- //
- // dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
- // if (dh == NULL) {
- // BIO_free(bio);
- // return NGX_ERROR;
- // }
- //
- // SSL_CTX_set_tmp_dh(ssl->ctx, dh);
- //
- // DH_free(dh);
- // BIO_free(bio);
- //
- // return NGX_OK;
- //}
- //
- //ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, const char *sess_ctx,
- // ssize_t builtin_session_cache, time_t timeout) {
- // SSL_CTX_set_session_id_context(ssl->ctx, (const unsigned char *) sess_ctx,strlen(sess_ctx));
- //
- // SSL_CTX_set_session_cache_mode(ssl->ctx,
- // SSL_SESS_CACHE_SERVER
- // |SSL_SESS_CACHE_NO_AUTO_CLEAR
- // |SSL_SESS_CACHE_NO_INTERNAL_STORE);
- //
- // SSL_CTX_sess_set_cache_size(ssl->ctx, 1);
- //
- // return NGX_OK;
- //
- //}
-
- //打开监听到接口,只绑定了一个
- ngx_socket_t ngx_open_listening_sockets() {
- int reuseaddr;
- ngx_socket_t s;
- reuseaddr = 1; //重用地址
- struct sockaddr_in addr;
-
- s = ngx_socket(AF_INET, SOCK_STREAM, 0); //创建套接口
- if (s == -1) {
- return NGX_ERROR;
- }
-
- /* 填写sockaddr_in结构*/
- bzero(&addr, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(443);
- addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuseaddr,
- sizeof(int)) == -1) {
- if (ngx_close_socket(s) == -1) { //出错就把它关闭
- }
- return NGX_ERROR;
- }
-
- if (ngx_nonblocking(s) == -1) { //堵塞失败调用
- if (ngx_close_socket(s) == -1) { //关闭套接字
- }
- return NGX_ERROR;
- }
-
- if (bind(s, (struct sockaddr*) &addr, sizeof(addr)) == -1) { //绑定
- return NGX_ERROR;
- }
-
- if (listen(s, 5) == -1) { //监听套接口
- if (ngx_close_socket(s) == -1) {
- }
- return NGX_ERROR;
- }
-
- return s;
- }
点击(此处)折叠或打开
- /*
- ============================================================================
- Name : NGXSSL.c
- Author : xiangrongcheng
- Version :
- Copyright : Your copyright notice
- Description : Ansi-style
- ============================================================================
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include "source.h"
-
- int epfd;
-
- int main(void) {
-
- // void *data = NULL;
-
- //认证和密钥目录
- const char * certificate = "/usr/local/nginx/conf/api.bz.crt";
- const char * certificate_key = "/usr/local/nginx/conf/api.bz_nopass.key";
-
- //这里模拟nginx初始化
- // ngx_ssl_init(); //初始化ssl
- OPENSSL_config(NULL); //加载openssl的配置信息,不知道对否
- SSL_library_init(); //加载ssl库函数
- SSL_load_error_strings(); //格式化错误日志信息
- OpenSSL_add_all_algorithms(); //load所有的SSL算法
-
- // //这里没有必要,是做为缓存,会话和连接池处理的
- // ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
- // if (ngx_ssl_connection_index == -1) {
- // printf("SSL_get_ex_new_index() failed");
- // return NGX_ERROR;
- // }
- //
- // ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,NULL);
- // if (ngx_ssl_server_conf_index == -1) {
- // printf("SSL_CTX_get_ex_new_index() failed");
- // return NGX_ERROR;
- // }
- //
- // ngx_ssl_session_cache_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,NULL);
- // if (ngx_ssl_session_cache_index == -1) {
- // printf("SSL_CTX_get_ex_new_index() failed");
- // return NGX_ERROR;
- // }
-
- //创建ssl
- ngx_ssl_t ssl;
- ngx_uint_t protocols = 61;
- // ngx_ssl_create(ssl, protocols, data);
- ssl.ctx = SSL_CTX_new(SSLv23_method()); //通过SSL所用方法新建SSL_CTX上下文信息
- if (ssl.ctx == NULL) {
- printf("SSL_CTX_new() failed");
- return NGX_ERROR;
- }
-
- // //设置上下文信息的数据,保存扩展数据(应该不是很需要)
- // if (SSL_CTX_set_ex_data(ssl.ctx, ngx_ssl_server_conf_index, data) == 0) {
- // printf("SSL_CTX_set_ex_data() failed");
- // return NGX_ERROR;
- // }
-
- //客户端服务器选项的设定,具体查看具体参数吧,可以看一下英文
- /* client side options */
- SSL_CTX_set_options(ssl.ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
- SSL_CTX_set_options(ssl.ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
-
- /* server side options */
- SSL_CTX_set_options(ssl.ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
- SSL_CTX_set_options(ssl.ctx, SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
-
- /* this option allow a potential SSL 2.0 rollback (CAN-2005-2969) */
- SSL_CTX_set_options(ssl.ctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
- SSL_CTX_set_options(ssl.ctx, SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
- SSL_CTX_set_options(ssl.ctx, SSL_OP_TLS_D5_BUG);
- SSL_CTX_set_options(ssl.ctx, SSL_OP_TLS_BLOCK_PADDING_BUG);
- SSL_CTX_set_options(ssl.ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
- SSL_CTX_set_options(ssl.ctx, SSL_OP_SINGLE_DH_USE);
-
- if (!(protocols & NGX_SSL_SSLv2)) {
- SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_SSLv2);
- }
- if (!(protocols & NGX_SSL_SSLv3)) {
- SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_SSLv3);
- }
- if (!(protocols & NGX_SSL_TLSv1)) {
- SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_TLSv1);
- }
-
- #ifdef SSL_OP_NO_COMPRESSION
- SSL_CTX_set_options(ssl.ctx, SSL_OP_NO_COMPRESSION);
- #endif
-
- #ifdef SSL_MODE_RELEASE_BUFFERS
- SSL_CTX_set_mode(ssl.ctx, SSL_MODE_RELEASE_BUFFERS);
- #endif
-
- //这里一定需要,设置读取头一个字节,作为判断协议,如果不设定那么将使得n = SSL_read(connection, buffer, 512);少读前一个字节,因为读取第一个字节作为判断字节
- SSL_CTX_set_read_ahead(ssl.ctx, 1);
-
- //下面也不是必要的
- // SSL_CTX_set_info_callback(ssl.ctx, ngx_ssl_info_callback);
- // SSL_CTX_set_tlsext_servername_callback(ssl.ctx,ngx_http_ssl_servername);
-
- // ngx_ssl_certificate(ssl, certificate, certificate_key);
-
- // SSL_CTX_load_verify_locations用于加载受信任的CA证书,CAfile如果不为NULL,则他指向的文件包含PEM编码格式的一个或多个证书,可以用e.g.来简要介绍证书内容
- // CApath如果不为NULL,则它指向一个包含PEM格式的CA证书的目录,目录中每个文件包含一份CA证书,文件名是证书中CA名的HASH值
- // 可以用c-rehash来建立该目录,如cd /some/where/certs(包含了很多可信任的CA证书) c_rehash .。返回一成功,0 失败。SSL_CTX_set_default_verify_paths找寻默认的验证路径,在这里肯定找不到的。
- // 这里主要set cert_store
- // char *CAfile=NULL,*CApath=NULL;
- // SSL_CTX_load_verify_locations(ctx,CAfile,CApath);
- // 当需要客户端验证的时候,服务器把CAfile里面的可信任CA证书发往客户端。
- // if(CAfile !=NULL )SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
- // 设置最大的验证用户证书的上级数。
- // SSL_CTX_set_verify_depth(ctx,10);
-
- //设置加载服务器的证书和私钥
- if (SSL_CTX_use_certificate_chain_file(ssl.ctx, (char *) certificate) == 0) {
- printf("SSL_CTX_use_certificate_chain_file("%s") failed", certificate);
- }
- if (SSL_CTX_use_PrivateKey_file(ssl.ctx, (char *) certificate_key, SSL_FILETYPE_PEM)== 0) { //类型测试好像无所谓,应该是SSL_FILETYPE_ASN1?
- printf("SSL_CTX_use_PrivateKey_file("%s") failed", certificate_key);
- }
-
- SSL_CTX_set_cipher_list(ssl.ctx, "HIGH:!aNULL:!MD5"); //设置密码链表,具体看密码 ciphers(1)指令吧
- SSL_CTX_set_tmp_rsa_callback(ssl.ctx, ngx_ssl_rsa512_key_callback); //设置键改变时调用,握手时的处理
-
- //如果是双向认证还得做下面这几件事情
- // SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER, ngx_http_ssl_verify_callback);
- // SSL_CTX_set_verify_depth(ssl->ctx, depth);
- // SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL);
- // SSL_load_client_CA_file((char *) cert->data);
- // ERR_clear_error();
- // SSL_CTX_set_client_CA_list(ssl->ctx, list);
- // SSL_CTX_get_cert_store(ssl->ctx);
- // X509_STORE_add_lookup(store, X509_LOOKUP_file();
- // X509_LOOKUP_load_file(lookup, (char *) crl->data, X509_FILETYPE_PEM);
- // X509_STORE_set_flags(store,X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
-
- //ngx_ssl_dhparam(ssl, "");
- // 当使用RSA算法鉴别的时候,会有一个临时的DH密钥磋商发生。这样会话数据将用这个临时的密钥加密,而证书中的密钥中做为签名。
- // 所以这样增强了安全性,临时密钥是在会话结束消失的,所以就是获取了全部信息也无法把通信内容给解密出来。
-
- // 实现 openssl 提供的默认的 DH_METHOD,实现了根据密钥参数生成 DH 公私钥,以及根据 DH 公钥(一方)以及 DH 私钥(另一方)来生成一个共享密钥,用于密钥交换。
- //DH密钥磋商设置
- DH *dh;
- static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46,
- 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, 0xD9,
- 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, 0x08, 0xEE, 0xD4, 0xEB,
- 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, 0xE7, 0x10, 0x80,
- 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, 0xBE, 0xEC,
- 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, 0x9B,
- 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04,
- 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5,
- 0xDF, 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC,
- 0x9A, 0x50, 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A,
- 0x63, 0xAB, 0x1E, 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D,
- 0x14, 0x67, 0x57, 0xDA, 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B,
- 0x9B };
-
- static unsigned char dh1024_g[] = { 0x02 };
- dh = DH_new();
- if (dh == NULL) {
- }
-
- dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
- dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
-
- if (dh->p == NULL || dh->g == NULL) {
- DH_free(dh);
- }
- SSL_CTX_set_tmp_dh(ssl.ctx, dh);
- DH_free(dh);
-
- // ngx_ssl_session_cache(ssl, "HTTP", 0, 0);
- //下面只是会话的设置
- SSL_CTX_set_session_id_context(ssl.ctx, (const unsigned char *) "HTTP",strlen("HTTP"));
- SSL_CTX_set_session_cache_mode(ssl.ctx,
- SSL_SESS_CACHE_SERVER
- |SSL_SESS_CACHE_NO_AUTO_CLEAR
- |SSL_SESS_CACHE_NO_INTERNAL_STORE);
-
- // 设置cache的大小,默认的为1024*20=20000,这个也就是可以存多少个session_id,一般都不需要更改的。假如为0的话将是无限
- SSL_CTX_sess_set_cache_size(ssl.ctx, 1);
-
- //下面是网络模块
- socklen_t sin_len = sizeof(struct sockaddr_in);
- int fd, opt = 1;
- struct epoll_event ev;
- struct sockaddr_in sin, cin;
-
- epfd = epoll_create(1024);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) <= 0) {
- fprintf(stderr, "socket failed/n");
- return -1;
- }
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &opt, sizeof(opt));
-
- memset(&sin, 0, sizeof(struct sockaddr_in));
- sin.sin_family = AF_INET;
- sin.sin_port = htons((short) (443));
- sin.sin_addr.s_addr = INADDR_ANY;
- if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
- fprintf(stderr, "bind failed/n");
- return -1;
- }
- if (listen(fd, 32) != 0) {
- fprintf(stderr, "listen failed/n");
- return -1;
- }
-
- int i, cfd, n, nfds;
-
- struct epoll_event events[1024];
- char buffer[512];
-
- ev.data.fd = fd;
- ev.events = EPOLLIN | EPOLLET; //设置要处理的事件类型
- epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
-
- while (1) {
- nfds = epoll_wait(epfd, events, 1024, -1);
- printf("nfds ........... %d/n", nfds);
- for (i = 0; i < nfds; i++) {
- if (events[i].data.fd == fd) {
- cfd = accept(fd, (struct sockaddr *) &cin, &sin_len);
- ngx_nonblocking(cfd); //把客户端的socket设置为非阻塞方式
- ev.data.fd = cfd;
- ev.events = EPOLLIN | EPOLLET;
- epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &ev);
- } else {
- if (events[i].events & EPOLLIN) {
- cfd = events[i].data.fd;
-
- //这里模拟nginx接收
- // ngx_ssl_create_connection(ssl, cfd);
- ngx_ssl_conn_t *connection = SSL_new(ssl.ctx); //根据上下文,建立ssl套接口或链接
- if (connection == NULL) {
- }
-
- if (SSL_set_fd(connection, cfd) == 0) { //设置处理的id进入上下文里面
- }
- SSL_set_accept_state(connection); //设置接收状态
-
- // if (SSL_set_ex_data(connection, ngx_ssl_connection_index, c) == 0) {
- // }
-
- //进行握手处理
- ngx_http_ssl_handshake(cfd,connection);
-
- //正确处理
- for (;;) {
- n = SSL_read(connection, buffer, 512); //会读取好几次把之前读取的第一个字节也读取回来
- if (n > 0) {
- } else {
- break;
- }
- continue;
- }
-
- //这里是,对请求的相关处理,省略掉了
-
- //ngx_http_process_request_headers(rev);
-
- //给客户端发送数据
- const char *data = "HTTP/1.1 200 OKrnServer: nginx/1.0.12rnDate: Sun, 03 Mar 2013 12:38:48 GMTrnContent- ...";
- n = SSL_write(connection, data, sizeof(data));
-
- //关闭请求链接;如果验证通过是不会走这里的(而等到超时的时候才处理);对于验证不通过或http请求则直接调用关闭链接。
- ngx_ssl_shutdown(connection);
- SSL_CTX_free(ssl.ctx);//释放SSL环境
- close(fd);
-
- // ret = recv(cfd, buffer, sizeof(buffer), 0);
- // printf("read ret..........= %d/n", ret);
- //
- // ev.data.fd = cfd;
- // ev.events = EPOLLOUT | EPOLLET;
- // epoll_ctl(epfd, EPOLL_CTL_MOD, cfd, &ev);
- } else if (events[i].events & EPOLLOUT) {
- cfd = events[i].data.fd;
-
- ev.data.fd = cfd;
- epoll_ctl(epfd, EPOLL_CTL_DEL, cfd, &ev);
- close(cfd);
-
- }
- }
- }
- }
-
- if (fd > 0)
- close(fd);
- return 0;
- }
-
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自带的接收和链接函数