Skip to content

Commit 3a5436e

Browse files
avidadenji
authored andcommitted
Add https support
1 parent 2a97041 commit 3a5436e

File tree

2 files changed

+121
-12
lines changed

2 files changed

+121
-12
lines changed

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ check
4343
-----
4444
* **syntax**: `check interval=milliseconds [fall=count] [rise=count]
4545
[timeout=milliseconds] [default_down=true|false]
46-
[type=tcp|http|ssl_hello|mysql|ajp|fastcgi]`
46+
[type=tcp|http|https|ssl_hello|mysql|ajp|fastcgi]`
4747
* **default**: `none` parameters are `interval=30000 fall=5 rise=2 timeout=1000 default_down=true type=tcp`
4848
* **context**: `upstream`
4949

@@ -60,15 +60,18 @@ The parameters' meanings are:
6060
Default the port is 0 and it means the same as the original backend server.
6161
* `type`: the check protocol type:
6262
1. `tcp` is a simple tcp socket connect and peek one byte.
63-
2. `sl_hello` sends a client ssl hello packet and receives the
63+
2. `ssl_hello` sends a client ssl hello packet and receives the
6464
server ssl hello packet.
6565
3. `http` sends a http request packet, receives and parses the http
6666
response to diagnose if the upstream server is alive.
67-
4. `mysql` connects to the mysql server, receives the greeting
67+
4. `https` establishes a https connection and sends a http request
68+
packet, receives and parses the http response to diagnose if the
69+
upstream server is alive.
70+
5. `mysql` connects to the mysql server, receives the greeting
6871
response to diagnose if the upstream server is alive.
69-
5. `ajp` sends a AJP Cping packet, receives and parses the AJP
72+
6. `ajp` sends a AJP Cping packet, receives and parses the AJP
7073
Cpong response to diagnose if the upstream server is alive.
71-
6. `fastcgi` send a fastcgi request, receives and parses the
74+
7. `fastcgi` send a fastcgi request, receives and parses the
7275
fastcgi response to diagnose if the upstream server is alive.
7376

7477

ngx_http_upstream_check_module.c

Lines changed: 113 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ struct ngx_http_upstream_check_srv_conf_s {
241241

242242
ngx_uint_t default_down;
243243

244+
#if (NGX_HTTP_SSL)
245+
ngx_ssl_t ssl;
246+
#endif
247+
244248
ngx_uint_t fast_upstream_init;
245249
};
246250

@@ -349,6 +353,11 @@ static ngx_int_t ngx_http_upstream_check_peek_one_byte(ngx_connection_t *c);
349353
static void ngx_http_upstream_check_begin_handler(ngx_event_t *event);
350354
static void ngx_http_upstream_check_connect_handler(ngx_event_t *event);
351355

356+
#if (NGX_HTTP_SSL)
357+
static void ngx_http_upstream_do_ssl_handshake(ngx_event_t *event);
358+
static void ngx_ups_ssl_handshake(ngx_connection_t *c);
359+
#endif
360+
352361
static void ngx_http_upstream_check_peek_handler(ngx_event_t *event);
353362

354363
static void ngx_http_upstream_check_send_handler(ngx_event_t *event);
@@ -696,19 +705,21 @@ static ngx_check_conf_t ngx_check_types[] = {
696705
1
697706
},
698707

708+
#if (NGX_HTTP_SSL)
699709
{
700710
NGX_HTTP_CHECK_HTTP,
701-
ngx_string("fastcgi"),
702-
ngx_null_string,
703-
0,
711+
ngx_string("https"),
712+
ngx_string("GET / HTTP/1.0\r\n\r\n"),
713+
NGX_CONF_BITMASK_SET | NGX_CHECK_HTTP_2XX | NGX_CHECK_HTTP_3XX,
704714
ngx_http_upstream_check_send_handler,
705715
ngx_http_upstream_check_recv_handler,
706716
ngx_http_upstream_check_http_init,
707-
ngx_http_upstream_check_fastcgi_parse,
717+
ngx_http_upstream_check_http_parse,
708718
ngx_http_upstream_check_http_reinit,
709719
1,
710-
0
720+
1
711721
},
722+
#endif
712723

713724
{
714725
NGX_HTTP_CHECK_SSL_HELLO,
@@ -752,6 +763,20 @@ static ngx_check_conf_t ngx_check_types[] = {
752763
0
753764
},
754765

766+
{
767+
NGX_HTTP_CHECK_HTTP,
768+
ngx_string("fastcgi"),
769+
ngx_null_string,
770+
0,
771+
ngx_http_upstream_check_send_handler,
772+
ngx_http_upstream_check_recv_handler,
773+
ngx_http_upstream_check_http_init,
774+
ngx_http_upstream_check_fastcgi_parse,
775+
ngx_http_upstream_check_http_reinit,
776+
1,
777+
0
778+
},
779+
755780
{
756781
0,
757782
ngx_null_string,
@@ -1189,6 +1214,7 @@ ngx_http_upstream_check_connect_handler(ngx_event_t *event) {
11891214

11901215
peer = event->data;
11911216
ucscf = peer->conf;
1217+
int is_https_check_type = strcmp((const char *)peer->conf->check_type_conf->name.data, "https") == 0;
11921218

11931219
if (peer->pc.connection != NULL) {
11941220
c = peer->pc.connection;
@@ -1233,12 +1259,20 @@ ngx_http_upstream_check_connect_handler(ngx_event_t *event) {
12331259
c->read->log = c->log;
12341260
c->write->log = c->log;
12351261
c->pool = peer->pool;
1262+
#if (NGX_HTTP_SSL)
1263+
if (is_https_check_type && rc == NGX_AGAIN) {
1264+
c->write->handler = ngx_http_upstream_do_ssl_handshake;
1265+
c->read->handler = ngx_http_upstream_do_ssl_handshake;
1266+
}
1267+
#endif
12361268

12371269
upstream_check_connect_done:
12381270
peer->state = NGX_HTTP_CHECK_CONNECT_DONE;
12391271

1240-
c->write->handler = peer->send_handler;
1241-
c->read->handler = peer->recv_handler;
1272+
if (!is_https_check_type) {
1273+
c->write->handler = peer->send_handler;
1274+
c->read->handler = peer->recv_handler;
1275+
}
12421276

12431277
ngx_add_timer(&peer->check_timeout_ev, ucscf->check_timeout);
12441278

@@ -1248,6 +1282,67 @@ ngx_http_upstream_check_connect_handler(ngx_event_t *event) {
12481282
}
12491283
}
12501284

1285+
#if (NGX_HTTP_SSL)
1286+
static void ngx_http_upstream_do_ssl_handshake(ngx_event_t *event) {
1287+
long rc;
1288+
ngx_connection_t *c;
1289+
ngx_http_upstream_check_peer_t *peer;
1290+
ngx_http_upstream_check_srv_conf_t *ucscf;
1291+
c = event->data;
1292+
peer = c -> data;
1293+
ucscf = peer->conf;
1294+
ucscf->ssl.buffer_size = NGX_SSL_BUFSIZE;
1295+
ucscf->ssl.ctx = SSL_CTX_new(SSLv23_method());
1296+
rc = ngx_ssl_create_connection(&ucscf->ssl, c, NGX_SSL_BUFFER|NGX_SSL_CLIENT);
1297+
if (rc != NGX_OK) {
1298+
return;
1299+
}
1300+
int tcp_nodelay = 1;
1301+
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
1302+
(const void *) &tcp_nodelay, sizeof(int)) == -1) {
1303+
ngx_connection_error(c, ngx_socket_errno,
1304+
"setsockopt(TCP_NODELAY) failed");
1305+
return;
1306+
}
1307+
c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1308+
rc = ngx_ssl_handshake(c);
1309+
if (rc != NGX_OK && rc != NGX_AGAIN) {
1310+
ngx_ssl_shutdown(peer->pc.connection);
1311+
SSL_CTX_free(ucscf->ssl.ctx);
1312+
ucscf->ssl.ctx = NULL;
1313+
return;
1314+
}
1315+
if (rc == NGX_AGAIN) {
1316+
if (!c->write->timer_set) {
1317+
ngx_add_timer(c->write, ucscf->check_timeout);
1318+
}
1319+
c->ssl->handler = ngx_ups_ssl_handshake;
1320+
} else {
1321+
ngx_ups_ssl_handshake(c);
1322+
}
1323+
}
1324+
1325+
static void
1326+
ngx_ups_ssl_handshake(ngx_connection_t *c) {
1327+
long rc;
1328+
ngx_http_upstream_check_peer_t *peer;
1329+
peer = c->data;
1330+
if (c->ssl && c->ssl->handshaked) {
1331+
rc = SSL_get_verify_result(c->ssl->connection);
1332+
if (rc != X509_V_OK) {
1333+
ngx_log_error(NGX_LOG_ERR, c->log, 0,
1334+
"upstream SSL certificate verify error: (%l:%s)",
1335+
rc, X509_verify_cert_error_string(rc));
1336+
}
1337+
}
1338+
peer->state = NGX_HTTP_CHECK_CONNECT_DONE;
1339+
c->write->handler = peer->send_handler;
1340+
c->read->handler = peer->recv_handler;
1341+
/* the kqueue's loop interface needs it. */
1342+
c->write->handler(c->write);
1343+
}
1344+
#endif
1345+
12511346
static ngx_int_t
12521347
ngx_http_upstream_check_peek_one_byte(ngx_connection_t *c) {
12531348
char buf[1];
@@ -2663,6 +2758,17 @@ ngx_http_upstream_check_status_update(ngx_http_upstream_check_peer_t *peer,
26632758
}
26642759
}
26652760

2761+
#if (NGX_HTTP_SSL)
2762+
int is_https_check_type = strcmp((const char *)peer->conf->check_type_conf->name.data, "https") == 0;
2763+
if (is_https_check_type) {
2764+
ngx_http_upstream_check_srv_conf_t *ucscf;
2765+
ucscf = peer->conf;
2766+
if (ucscf->ssl.ctx) {
2767+
ngx_ssl_shutdown(peer->pc.connection);
2768+
SSL_CTX_free(ucscf->ssl.ctx);
2769+
}
2770+
}
2771+
#endif
26662772
peer->shm->access_time = ngx_current_msec;
26672773
}
26682774

0 commit comments

Comments
 (0)