diff --git a/README.md b/README.md index 024be0b..310327d 100644 --- a/README.md +++ b/README.md @@ -124,10 +124,14 @@ Run it from the nginx directory. This is a condition for using strict sni. [View issue.](https://github.com/hakasenyang/openssl-patch/issues/7#issuecomment-427664716) -- Strict SNI requires at least two ssl server (fake) settings (server { listen 443 ssl }). -- It does not matter what kind of certificate or duplicate. +- How to use nginx strict-sni? + - **ONLY USE IN http { }** + - strict_sni : nginx strict-sni ON/OFF toggle option. + - strict_sni_header : if you do not want to respond to invalid headers. (**only with strict_sni**) + - Strict SNI requires at least two ssl server (fake) settings (server { listen 443 ssl }). + - It does not matter what kind of certificate or duplicate. -Thanks [@JemmyLoveJenny](https://github.com/hakasenyang/openssl-patch/issues/1#issuecomment-427040319)! +Thanks [@JemmyLoveJenny](https://github.com/hakasenyang/openssl-patch/issues/1#issuecomment-427040319), [@NewBugger](https://github.com/hakasenyang/openssl-patch/issues/7#issuecomment-427831677)! ### nginx OpenSSL-1.1.x Renegotiation Bugfix diff --git a/nginx_strict-sni.patch b/nginx_strict-sni.patch index 3bee9be..12e0bd3 100644 --- a/nginx_strict-sni.patch +++ b/nginx_strict-sni.patch @@ -1,38 +1,8 @@ diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c -index 75129134..a41edeab 100644 +index 75129134..e9ea5231 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c -@@ -1455,6 +1455,14 @@ ngx_ssl_handshake(ngx_connection_t *c) - - c->read->error = 1; - -+#if (!defined SSL_R_CALLBACK_FAILED || !defined SSL_F_FINAL_SERVER_NAME) -+ if (sslerr == SSL_ERROR_SSL) { -+ ERR_peek_error(); -+ ERR_clear_error(); -+ return NGX_ERROR; -+ } -+#endif -+ - ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed"); - - return NGX_ERROR; -@@ -1568,6 +1576,14 @@ ngx_ssl_try_early_data(ngx_connection_t *c) - - c->read->error = 1; - -+#if (!defined SSL_R_CALLBACK_FAILED || !defined SSL_F_FINAL_SERVER_NAME) -+ if (sslerr == SSL_ERROR_SSL) { -+ ERR_peek_error(); -+ ERR_clear_error(); -+ return NGX_ERROR; -+ } -+#endif -+ - ngx_ssl_connection_error(c, sslerr, err, "SSL_read_early_data() failed"); - - return NGX_ERROR; -@@ -2547,6 +2563,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, +@@ -2547,6 +2547,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, char *text) { int n; @@ -42,18 +12,22 @@ index 75129134..a41edeab 100644 ngx_uint_t level; level = NGX_LOG_CRIT; -@@ -2583,6 +2602,20 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, +@@ -2583,6 +2586,24 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, n = ERR_GET_REASON(ERR_peek_error()); + /* Strict SNI Error Patch + * https://github.com/hakasenyang/openssl-patch/issues/1#issuecomment-427040319 ++ * https://github.com/hakasenyang/openssl-patch/issues/7#issuecomment-427872934 + */ +#if (defined SSL_R_CALLBACK_FAILED && defined SSL_F_FINAL_SERVER_NAME) + if (n == SSL_R_CALLBACK_FAILED) { + f = ERR_GET_FUNC(ERR_peek_error()); + if (f == SSL_F_FINAL_SERVER_NAME) { -+ ERR_peek_error(); ++ while (ERR_peek_error()) { ++ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, ++ "ignoring ssl error at STRICT SNI block"); ++ } + ERR_clear_error(); + return; + } @@ -63,34 +37,174 @@ index 75129134..a41edeab 100644 /* handshake failures */ if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC /* 103 */ #ifdef SSL_R_NO_SUITABLE_KEY_SHARE +diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c +index c57ec00c..a14d68a9 100644 +--- a/src/http/ngx_http_core_module.c ++++ b/src/http/ngx_http_core_module.c +@@ -441,6 +441,20 @@ static ngx_command_t ngx_http_core_commands[] = { + offsetof(ngx_http_core_loc_conf_t, directio_alignment), + NULL }, + ++ { ngx_string("strict_sni"), ++ NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_flag_slot, ++ NGX_HTTP_LOC_CONF_OFFSET, ++ offsetof(ngx_http_core_loc_conf_t, strict_sni), ++ NULL }, ++ ++ { ngx_string("strict_sni_header"), ++ NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, ++ ngx_conf_set_flag_slot, ++ NGX_HTTP_LOC_CONF_OFFSET, ++ offsetof(ngx_http_core_loc_conf_t, strict_sni_header), ++ NULL }, ++ + { ngx_string("tcp_nopush"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, +@@ -3387,6 +3401,8 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) + clcf->read_ahead = NGX_CONF_UNSET_SIZE; + clcf->directio = NGX_CONF_UNSET; + clcf->directio_alignment = NGX_CONF_UNSET; ++ clcf->strict_sni = NGX_CONF_UNSET; ++ clcf->strict_sni_header = NGX_CONF_UNSET; + clcf->tcp_nopush = NGX_CONF_UNSET; + clcf->tcp_nodelay = NGX_CONF_UNSET; + clcf->send_timeout = NGX_CONF_UNSET_MSEC; +@@ -3615,6 +3631,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) + NGX_OPEN_FILE_DIRECTIO_OFF); + ngx_conf_merge_off_value(conf->directio_alignment, prev->directio_alignment, + 512); ++ ngx_conf_merge_value(conf->strict_sni, prev->strict_sni, 0); ++ ngx_conf_merge_value(conf->strict_sni_header, prev->strict_sni_header, 0); + ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0); + ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); + +diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h +index 4c6da7c0..04e14d09 100644 +--- a/src/http/ngx_http_core_module.h ++++ b/src/http/ngx_http_core_module.h +@@ -382,6 +382,8 @@ struct ngx_http_core_loc_conf_s { + ngx_flag_t sendfile; /* sendfile */ + ngx_flag_t aio; /* aio */ + ngx_flag_t aio_write; /* aio_write */ ++ ngx_flag_t strict_sni; /* strict_sni */ ++ ngx_flag_t strict_sni_header; /* strict_sni_header */ + ngx_flag_t tcp_nopush; /* tcp_nopush */ + ngx_flag_t tcp_nodelay; /* tcp_nodelay */ + ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c -index 7dd28b8c..5e5bbed1 100644 +index 7dd28b8c..1901129d 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c -@@ -849,7 +849,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) +@@ -846,14 +846,18 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t *cscf; + ++ c = ngx_ssl_get_connection(ssl_conn); ++ ++ hc = c->data; ++ ++ clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); ++ servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); if (servername == NULL) { - return SSL_TLSEXT_ERR_NOACK; -+ return SSL_TLSEXT_ERR_ALERT_FATAL; ++ return (clcf->strict_sni) ? SSL_TLSEXT_ERR_ALERT_FATAL : SSL_TLSEXT_ERR_NOACK; } - c = ngx_ssl_get_connection(ssl_conn); -@@ -864,7 +864,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) +- c = ngx_ssl_get_connection(ssl_conn); +- + if (c->ssl->handshaked) { + return SSL_TLSEXT_ERR_NOACK; + } +@@ -864,7 +868,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) host.len = ngx_strlen(servername); if (host.len == 0) { - return SSL_TLSEXT_ERR_NOACK; -+ return SSL_TLSEXT_ERR_ALERT_FATAL; ++ return (clcf->strict_sni) ? SSL_TLSEXT_ERR_ALERT_FATAL : SSL_TLSEXT_ERR_NOACK; } host.data = (u_char *) servername; -@@ -879,7 +879,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) +@@ -873,13 +877,11 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) + return SSL_TLSEXT_ERR_NOACK; + } + +- hc = c->data; +- + if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host, NULL, &cscf) != NGX_OK) { - return SSL_TLSEXT_ERR_NOACK; -+ return SSL_TLSEXT_ERR_ALERT_FATAL; ++ return (clcf->strict_sni) ? SSL_TLSEXT_ERR_ALERT_FATAL : SSL_TLSEXT_ERR_NOACK; } hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t)); +@@ -891,8 +893,6 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) + + hc->conf_ctx = cscf->ctx; + +- clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module); +- + ngx_set_connection_log(c, clcf->error_log); + + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); +@@ -936,15 +936,18 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) + static void + ngx_http_process_request_line(ngx_event_t *rev) + { +- ssize_t n; +- ngx_int_t rc, rv; +- ngx_str_t host; +- ngx_connection_t *c; +- ngx_http_request_t *r; ++ ssize_t n; ++ ngx_int_t rc, rv; ++ ngx_str_t host; ++ ngx_connection_t *c; ++ ngx_http_core_loc_conf_t *clcf; ++ ngx_http_request_t *r; + + c = rev->data; + r = c->data; + ++ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ++ + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, + "http process request line"); + +@@ -1060,10 +1063,10 @@ ngx_http_process_request_line(ngx_event_t *rev) + ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]); + + if (rc == NGX_HTTP_PARSE_INVALID_VERSION) { +- ngx_http_finalize_request(r, NGX_HTTP_VERSION_NOT_SUPPORTED); ++ (r->http_connection->ssl && clcf->strict_sni && clcf->strict_sni_header) ? ngx_http_terminate_request(r, 0) : ngx_http_finalize_request(r, NGX_HTTP_VERSION_NOT_SUPPORTED); + + } else { +- ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ (r->http_connection->ssl && clcf->strict_sni && clcf->strict_sni_header) ? ngx_http_terminate_request(r, 0) : ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + } + + break; +@@ -1808,6 +1811,9 @@ ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_int_t + ngx_http_process_request_header(ngx_http_request_t *r) + { ++ ngx_http_core_loc_conf_t *clcf; ++ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ++ + if (r->headers_in.server.len == 0 + && ngx_http_set_virtual_server(r, &r->headers_in.server) + == NGX_ERROR) +@@ -1818,7 +1824,7 @@ ngx_http_process_request_header(ngx_http_request_t *r) + if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent HTTP/1.1 request without \"Host\" header"); +- ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ (r->http_connection->ssl && clcf->strict_sni && clcf->strict_sni_header) ? ngx_http_terminate_request(r, 0) : ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } +