1 緣起
??前面的《nginx upstream server主動健康檢測模塊ngx_http_upstream_check_module 使用和源碼分析》系列已經(jīng)分析了ngx_http_upstream_check_module的實現(xiàn)原理,并且在借助這個模塊的框架實現(xiàn)了一個udp健康檢測的新功能。
??但是ngx_http_upstream_check_module還缺乏基于https監(jiān)測上游服務(wù)器健康狀況的能力,始終是一個缺憾,因此,本文基于《nginx upstream server主動健康檢測模塊ngx_http_upstream_check_module 使用和源碼分析》和《nginx stream proxy 模塊的ssl連接源碼分析》兩篇博文的分析成果,來實現(xiàn)一個基于https的上游服務(wù)器健康檢測的能力。
1.1 功能定義
??本次支持的功能:
- 支持向上游服務(wù)器發(fā)起https請求功能
- 請求的報文復(fù)用原有的http檢測的請求報文定義
- 響應(yīng)的狀態(tài)碼檢測復(fù)用原有的http檢測的響應(yīng)碼的定義
- 支持ssl握手過程中添加sni擴展信息
- 支持ssl握手協(xié)議類型的配置
- 支持ssl握手協(xié)議加密套件的配置
??暫時不支持的功能:
- 不支持ssl會話復(fù)用(會話復(fù)用可以降低上游服務(wù)器的ssl握手壓力)
- 不支持ssl證書雙向驗證
- 不支持服務(wù)器端證書有效性驗證
&ems;? 由于本次主要是檢驗https的鏈接握手流程,對一些不是特別關(guān)鍵的ssl握手特性暫時不支持主要是為了簡化代碼邏輯,但是不影響業(yè)務(wù)流程,這樣也便于在本文中將整個實現(xiàn)流程進行闡述。后續(xù)可以參照ngx_stream_proxy_module中的實現(xiàn),繼續(xù)將這些特性進行完善,以臻于完美。
2. 實現(xiàn)后的效果
??首先來看一下實現(xià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 hostname
check_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塊中定義了一個https的健康檢測類型, check_http_send復(fù)用了http的定義,而check_ssl_server_name是新增的指令,用來配置ssl握手設(shè)置sni擴展信息中的主機host信息。
2.2 運行效果
??啟動tengine后,可以通過查看nginx的error.log日志進行觀察, 可以看到如下信息:
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中的前面兩條因為服務(wù)器響應(yīng)403報了錯誤,對應(yīng)在配置了“check_http_expect_alive http_2xx http_3xx;”的情況。如果配置改成“check_http_expect_alive http_2xx http_3xx http_4xx;” 則報后面那條上游服務(wù)器enable的信息。證明https的檢測功能已經(jīng)可用了。
??另外我們可以通過wireshark抓包觀察交互的情況,抓包如下:
??從上述抓包的內(nèi)容可以看到ssl的握手交互的過程都已經(jīng)有了。關(guān)于如何進行ssl握手的內(nèi)容不在本文的討論范圍之內(nèi),可以參考HTTPS篇之SSL握手過程詳解 或者通過Wireshark分析HTTPS握手過程與協(xié)議概述
3. 代碼實現(xiàn)
??由于https進行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ù)器進行ssl握手時候采用的sni擴展host名字,如果不設(shè)置并且upstream塊中的server是用域名設(shè)置的,那么默認就采用設(shè)置的服務(wù)器名字。 - check_ssl_verify:[on/off]
????是否校驗服務(wù)器的證書有效性。(待后續(xù)實現(xiàn)) - check_ssl_session_reuse: [on/off]
????和上游服務(wù)器進行ssl握手的時候是否復(fù)用ssl會話信息。(待后續(xù)實現(xiàn))
3.1.2 配置指令結(jié)構(gòu)體:
?? 為了對上述定義的配置指令進行保存,需要在ngx_http_upstream_check_srv_conf_s結(jié)構(gòu)體中增加對應(yīng)的參數(shù),包括ssl_ciphers、ssl_protocols、ssl_server_name和ssl四個參數(shù),其中ssl參數(shù)用來保存ssl協(xié)議配置上下文。文章來源:http://www.zghlxwxcb.cn/news/detail-825618.html
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)容從哪個字節(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擴展hostname */
#endif
};
??以上添加的ssl_protocols參數(shù)在ngx_http_upstream_check_create_srv_conf函數(shù)中需要將其設(shè)置為NGX_CONF_UNSET_UINT,避免nginx在解析配置文件的時候出現(xiàn)參數(shù)重復(fù)的報錯。文章來源地址http://www.zghlxwxcb.cn/news/detail-825618.html
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
到了這里,關(guān)于nginx upstream server主動健康檢測模塊添加https檢測功能[完整版]的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!