網(wǎng)站同時(shí)做競價(jià)和seo寧波百度seo排名優(yōu)化
目錄
- 1 緣起
- 1.1 功能定義
- 2. 實(shí)現(xiàn)后的效果
- 2.1 配置文件
- 2.2 運(yùn)行效果
- 3. 代碼實(shí)現(xiàn)
- 3.1 配置指令
- 3.1.1 配置指令定義:
- 3.1.2 配置指令結(jié)構(gòu)體:
- 3.1.3 配置指令源碼定義:
- 3.2 模塊的初始化
- 3.3 添加新的健康檢測類型的定義
- 3.4 握手完成后的處理
- 3. 5 發(fā)送http請求
- 3.6 接收http響應(yīng)
- 3.7 連接關(guān)閉
- 3.8 ssl上下文的釋放
1 緣起
??前面的《nginx upstream server主動健康檢測模塊ngx_http_upstream_check_module 使用和源碼分析》系列已經(jīng)分析了ngx_http_upstream_check_module的實(shí)現(xiàn)原理,并且在借助這個(gè)模塊的框架實(shí)現(xiàn)了一個(gè)udp健康檢測的新功能。
??但是ngx_http_upstream_check_module還缺乏基于https監(jiān)測上游服務(wù)器健康狀況的能力,始終是一個(gè)缺憾,因此,本文基于《nginx upstream server主動健康檢測模塊ngx_http_upstream_check_module 使用和源碼分析》和《nginx stream proxy 模塊的ssl連接源碼分析》兩篇博文的分析成果,來實(shí)現(xiàn)一個(gè)基于https的上游服務(wù)器健康檢測的能力。
1.1 功能定義
??本次支持的功能:
- 支持向上游服務(wù)器發(fā)起https請求功能
- 請求的報(bào)文復(fù)用原有的http檢測的請求報(bào)文定義
- 響應(yīng)的狀態(tài)碼檢測復(fù)用原有的http檢測的響應(yīng)碼的定義
- 支持ssl握手過程中添加sni擴(kuò)展信息
- 支持ssl握手協(xié)議類型的配置
- 支持ssl握手協(xié)議加密套件的配置
??暫時(shí)不支持的功能:
- 不支持ssl會話復(fù)用(會話復(fù)用可以降低上游服務(wù)器的ssl握手壓力)
- 不支持ssl證書雙向驗(yàn)證
- 不支持服務(wù)器端證書有效性驗(yàn)證
&ems;? 由于本次主要是檢驗(yàn)https的鏈接握手流程,對一些不是特別關(guān)鍵的ssl握手特性暫時(shí)不支持主要是為了簡化代碼邏輯,但是不影響業(yè)務(wù)流程,這樣也便于在本文中將整個(gè)實(shí)現(xiàn)流程進(jìn)行闡述。后續(xù)可以參照ngx_stream_proxy_module中的實(shí)現(xiàn),繼續(xù)將這些特性進(jìn)行完善,以臻于完美。
2. 實(shí)現(xiàn)后的效果
??首先來看一下實(shí)現(xiàn)后的效果,有一些感性的認(rèn)識。
2.1 配置文件
#user nobody;
worker_processes 1;
daemon off;
master_process off;error_log logs/error.log;
pid logs/nginx.pid;load_module objs/ngx_http_upstream_check_module.so;events {worker_connections 1024;
}http {include mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log logs/access.log main;sendfile on;keepalive_timeout 65;upstream backend {# 開啟https健康檢測check type=https interval=3000 rise=2 fall=5 timeout=1000 port=443;check_http_send "GET / HTTP/1.1\r\nHost: www.baidu.com\r\n\r\n";check_http_expect_alive http_2xx http_3xx;# 設(shè)置sni hostnamecheck_ssl_server_name www.baidu.com;server 183.240.99.24:443;}server {listen 9080;server_name localhost;# 開啟本模塊的狀態(tài)查詢接口 location /status {check_status html;}location / {proxy_pass http://backend;}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
}
?? 這里假設(shè)將www.baidu.com作為被代理的上游服務(wù)器,以上配置文件中的upstream塊中定義了一個(gè)https的健康檢測類型, check_http_send復(fù)用了http的定義,而check_ssl_server_name是新增的指令,用來配置ssl握手設(shè)置sni擴(kuò)展信息中的主機(jī)host信息。
2.2 運(yùn)行效果
??啟動tengine后,可以通過查看nginx的error.log日志進(jìn)行觀察, 可以看到如下信息:
2024/02/16 09:31:33 [error] 23638#0: https check failed with return code: 403
2024/02/16 09:31:33 [error] 23638#0: check protocol https error with peer: 192.168.0.1:443
2024/02/16 09:31:45 [info] 23663#0: enable check peer: 192.168.0.1:443
error.log中的前面兩條因?yàn)榉?wù)器響應(yīng)403報(bào)了錯(cuò)誤,對應(yīng)在配置了“check_http_expect_alive http_2xx http_3xx;”的情況。如果配置改成“check_http_expect_alive http_2xx http_3xx http_4xx;” 則報(bào)后面那條上游服務(wù)器enable的信息。證明https的檢測功能已經(jīng)可用了。
??另外我們可以通過wireshark抓包觀察交互的情況,抓包如下:
??從上述抓包的內(nèi)容可以看到ssl的握手交互的過程都已經(jīng)有了。關(guān)于如何進(jìn)行ssl握手的內(nèi)容不在本文的討論范圍之內(nèi),可以參考HTTPS篇之SSL握手過程詳解 或者通過Wireshark分析HTTPS握手過程與協(xié)議概述
3. 代碼實(shí)現(xiàn)
??由于https進(jìn)行ssl握手,需要一些額外的參數(shù),因此在nginx的配置文件http.upstream塊中需要新增一些配置指定定義。
3.1 配置指令
3.1.1 配置指令定義:
支持的配置指令如下:
- check_ssl_ciphers:
????配置加密套件,格式參考proxy_ssl_ciphers - check_ssl_protocols:
????和服務(wù)器交互采用的ssl協(xié)議版本,如TLSv1.1 TLSv1.2等,格式參考proxy_ssl_protocols。 - check_ssl_server_name:
????和服務(wù)器進(jìn)行ssl握手時(shí)候采用的sni擴(kuò)展host名字,如果不設(shè)置并且upstream塊中的server是用域名設(shè)置的,那么默認(rèn)就采用設(shè)置的服務(wù)器名字。 - check_ssl_verify:[on/off]
????是否校驗(yàn)服務(wù)器的證書有效性。(待后續(xù)實(shí)現(xiàn)) - check_ssl_session_reuse: [on/off]
????和上游服務(wù)器進(jìn)行ssl握手的時(shí)候是否復(fù)用ssl會話信息。(待后續(xù)實(shí)現(xiàn))
3.1.2 配置指令結(jié)構(gòu)體:
?? 為了對上述定義的配置指令進(jìn)行保存,需要在ngx_http_upstream_check_srv_conf_s結(jié)構(gòu)體中增加對應(yīng)的參數(shù),包括ssl_ciphers、ssl_protocols、ssl_server_name和ssl四個(gè)參數(shù),其中ssl參數(shù)用來保存ssl協(xié)議配置上下文。
struct ngx_http_upstream_check_srv_conf_s {ngx_uint_t port;ngx_uint_t fall_count;ngx_uint_t rise_count;ngx_msec_t check_interval;ngx_msec_t check_timeout;ngx_uint_t check_keepalive_requests;ngx_check_conf_t *check_type_conf;ngx_str_t send;union {ngx_uint_t return_code;ngx_uint_t status_alive;} code;ngx_array_t *fastcgi_params;ngx_uint_t default_down;ngx_uint_t unique;ngx_uint_t udp : 1; /* 是否udp socket */ngx_int_t match_part : 1; /* 是否只要部分匹配就可以了 */ngx_int_t match_offset; /* udp響應(yīng)期望的內(nèi)容從哪個(gè)字節(jié)開始匹配 */ngx_str_t expect; /* udp響應(yīng)的期望內(nèi)容 */#if (NGX_HTTP_SSL)ngx_ssl_t *ssl; /* ssl 配置上下文 */ngx_str_t ssl_ciphers; /* ssl 加密套件 */ngx_uint_t ssl_protocols; /* 采用的ssl協(xié)議 */ngx_str_t ssl_server_name; /* ssl握手的sni擴(kuò)展hostname */
#endif
};
??以上添加的ssl_protocols參數(shù)在ngx_http_upstream_check_create_srv_conf函數(shù)中需要將其設(shè)置為NGX_CONF_UNSET_UINT,避免nginx在解析配置文件的時(shí)候出現(xiàn)參數(shù)重復(fù)的報(bào)錯(cuò)。
3.1.3 配置指令源碼定義:
#if (NGX_HTTP_SSL){ ngx_string("check_ssl_ciphers"),NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,ngx_conf_set_str_slot,NGX_HTTP_SRV_CONF_OFFSET,offsetof(ngx_http_upstream_check_srv_conf_t, ssl_ciphers),NULL },{ ngx_string("check_ssl_protocols"),NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,ngx_conf_set_bitmask_slot,NGX_HTTP_SRV_CONF_OFFSET,offsetof(ngx_http_upstream_check_srv_conf_t, ssl_protocols),&ngx_upstream_check_ssl_protocols },{ ngx_string("check_ssl_server_name"),NGX_HTTP_UPS_CONF|NGX_CONF_FLAG,ngx_conf_set_str_slot,NGX_HTTP_SRV_CONF_OFFSET,offsetof(ngx_http_upstream_check_srv_conf_t