差不多花了一周的时间,研究了下https,研究的不算深入,顶多算是入门,先做个记录,遗留问题再抽时间研究
https可以看成是http+ssl或tls,tls它的前身是ssl,这里简单介绍下ssl
位置:ssl介于http和tcp之间
协议:握手协议、记录协议、报警协议
协议大致过程如上图所示
阶段一、client通过client hello将client支持的ssl最高version、32字节随机数、密码套件(包括秘钥交换算法、加密算法、散列算法)、压缩算法发送给server、server通过server hello将ssl version、32字节随机数、从client中选择的密码套件、压缩算法发送给client,通过阶段一,client和server双方协商确认了ssl版本、秘钥交换算法、对称加密算法、散列算法、压缩算法、秘钥生成的两个随机数(client和server一边一个)
阶段二、server端发送证书,秘钥交换(基于秘钥交换算法),客户端证书请求(可选,如果server段需要验证client的话,则发送)
阶段三、client端发送证书(可选,如果server段需要的话),client端秘钥交换,server端证书验证(可选,如果需要验证,需要第三方认证机构)
阶段四、两端互相发送改变密码规格值,握手完成
握手协议完成之后,可以开始正式的数据传输,通过对称加密算法对传输的数据进行加密,通过散列算法来保证数据的完整性。
客户机和服务器发现错误时,向对方发送一个警报消息。如果是致命错误,则算法立即关闭SSL连接
https可以看做是http+ssl(tls),http本身明文传输,而https却通过ssl解决了3个问题
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;
ssl_session_tickets on; ssl_session_ticket_key /usr/local/cdn_cache/nginx/conf/ticket.key;
keepalive_timeout 65s; keepalive_requests 1000;
1、编译nginx,./configure时加上--with-http_ssl_module,即./configure --with-http_ssl_module......
2、安装openssl
#yum install openssl #yum install openssl-devel
3、生成server端ca证书
#cd /usr/local/cdn_cache/nginx/conf #openssl genrsa -des3 -out server.key 1024 #openssl req -new -key server.key -out server.csr #openssl rsa -in server.key -out server_nopwd.key #openssl x509 -req -days 365 -in server.csr -signkey server_nopwd.key -out server.crt
4、nginx配置文件
init_by_lua 'cjson = require "cjson"'; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_session_tickets on; ssl_session_ticket_key /usr/local/cdn_cache/nginx/conf/ticket.key; server { listen 443; ssl on; ssl_certificate /usr/local/cdn_cache/nginx/conf/server.crt; ssl_certificate_key /usr/local/cdn_cache/nginx/conf/server_nopwd.key; location /shen_post { content_by_lua ' ngx.req.read_body() local data = cjson.decode(ngx.req.get_body_data()) local chnlid = data.chnlid local bps = data.bps local name = data.name ret = {} ret["cid"] = chnlid ret["bps"] = bps ret["name"] = name ngx.say(cjson.encode(ret)) '; } location /shen_get { content_by_lua ' ret = {} ret["cid"] = "10000" ret["bps"] = 500 ret["name"] = "xxxx" ngx.say(cjson.encode(ret)) '; } }
通过libevent+libcurl谢了一个https client,代码如下:
#include <unistd.h> #include <event.h> #include <curl/curl.h> #include <stdio.h> #include <stdlib.h> #define inter_t 10*1000 #ifndef false #define false 0 #endif #ifndef true #define true 1 #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif typedef unsigned char bool; struct timeval tv_get; struct event ev_get; struct timeval tv_post; struct event ev_post; struct event_base* base = NULL; typedef struct private_ { CURL * curl; CURLM * multi_handle; bool data_valid; int running_count; }private_t; static size_t handle_recv_header(void *ptr, size_t size, size_t nmemb, void *private) { size_t total = size * nmemb; printf("handle_recv_header---%s\n", ptr); return total; } static size_t handle_recv_data(void *ptr, size_t size, size_t nmemb, void *private) { private_t * pri = (private_t *)private; size_t total = size * nmemb; pri->data_valid = true; printf("handle_recv_data---%s\n", ptr); return total; } size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { printf("%s\n", buffer); return size * nmemb; } void get_timeout_cb(int fd, short event, void *arg) { private_t * pri = (private_t *)arg; while(1) { pri->data_valid = false; CURLMcode curl_rc = curl_multi_perform(pri->multi_handle, &(pri->running_count)); if((curl_rc != CURLM_CALL_MULTI_PERFORM && curl_rc != CURLM_OK)) { printf("curl_multi_perform err happened, jump out loop, curl_rc=%d\n", curl_rc); break; } if (false == pri->data_valid) { break; } } if (pri->running_count) { printf("get_timeout_cb, running_count[%d]\n", pri->running_count); evtimer_add(&ev_get, &tv_get); return; } sleep(15); curl_multi_remove_handle(pri->multi_handle, pri->curl); curl_multi_add_handle(pri->multi_handle, pri->curl); evtimer_add(&ev_get, &tv_get); return; } void post_timeout_cb(int fd, short event, void *arg) { private_t * pri = (private_t *)arg; CURLMcode curl_rc = curl_multi_perform(pri->multi_handle, &(pri->running_count)); if((curl_rc != CURLM_CALL_MULTI_PERFORM && curl_rc != CURLM_OK)) { printf("curl_multi_perform err happened, jump out loop, curl_rc=%d\n", curl_rc); return; } if (pri->running_count) { printf("post_timeout_cb, running_count[%d]\n", pri->running_count); evtimer_add(&ev_post, &tv_post); return; } curl_multi_remove_handle(pri->multi_handle, pri->curl); curl_multi_add_handle(pri->multi_handle, pri->curl); evtimer_add(&ev_post, &tv_post); return; } int curl_get(char * url) { private_t * pri = calloc(1, sizeof(private_t)); CURL * curl = curl_easy_init(); if (NULL == curl) { printf("failed in curl_easy_init.\n"); return -1; } CURLM * multi_handle = curl_multi_init(); if (NULL == multi_handle) { curl_easy_cleanup(curl); printf("failed in curl_multi_init\n"); return -1; } curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_recv_data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)pri); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, handle_recv_header); curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)pri); //curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, on_set_sock_fd); //curl_easy_setopt(curl, CURLOPT_SOCKOPTDATA, (void *)pri); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 10); curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); CURLcode xx = curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 1L); if (CURLE_OK != xx) { printf("xxxxxx\n"); } if (curl_multi_add_handle(multi_handle, curl) != CURLM_OK) { printf("failed in curl_multi_add_handle. "); curl_easy_cleanup(curl); curl_multi_cleanup(multi_handle); return -1; } pri->curl = curl; pri->multi_handle = multi_handle; pri->running_count = 1; tv_get.tv_sec = 0; tv_get.tv_usec = inter_t; //event_set(&ev_appget, -1, EV_PERSIST|EV_TIMEOUT, timeout_cb, pri); evtimer_set(&ev_get, get_timeout_cb, pri); event_base_set(base, &ev_get); evtimer_add(&ev_get, &tv_get); } int curl_post(char * url) { private_t * pri = calloc(1, sizeof(private_t)); char * post_content = "{\ \"chnlid\":\"shen\",\ \"bps\":555,\ \"name\":\"shen\"\ }"; CURL * curl = curl_easy_init(); CURLM * multi_handle = curl_multi_init(); //char *list = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_content); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); //curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, list); curl_multi_add_handle(multi_handle, curl); pri->curl = curl; pri->multi_handle = multi_handle; pri->running_count = 1; tv_post.tv_sec = 0; tv_post.tv_usec = inter_t; evtimer_set(&ev_post, post_timeout_cb, pri); event_base_set(base, &ev_post); evtimer_add(&ev_post, &tv_post); } int main(int argc, char *argv[]) { base = event_base_new(); if (0 == strcmp("get", argv[1])) { curl_get(argv[2]); } else if (0 == strcmp("post", argv[1])) { curl_post(argv[2]); } event_base_dispatch(base); return 0; }
编译:gcc -levent -lcurl -g -o lt lbe_curl.c
执行:./lt get "https://10.10.73.18/shen_get"或./lt post "https://10.10.73.18/shen_post"
ssl:
http://www.cnblogs.com/zhuqil/archive/2012/10/06/ssl_detail.html
http://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy.html
https://www.openssl.org/docs/manmaster/apps/ciphers.html
https性能调优:
http://blog.httpwatch.com/2009/01/15/https-performance-tuning/(强烈推荐)
http://www.mahaixiang.cn/seoyjy/1422.html
http://blog.jobbole.com/78042/
http://www.admin10000.com/document/6236.html
http2:
http://chimera.labs.oreilly.com/books/1230000000545/ch12.html(强烈推荐)
http://io.upyun.com/2015/05/13/http2/?utm_source=tuicool&utm_medium=referral
nginx配置:
http://nginx.org/en/docs/http/configuring_https_servers.html(强烈推荐)
http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets(强烈推荐)