comparison src/http/modules/ngx_http_ssl_module.c @ 7732:59e1c73fe02b

SSL: ssl_reject_handshake directive (ticket #195). In some cases it might be needed to reject SSL handshake based on SNI server name provided, for example, to make sure an invalid certificate is not returned to clients trying to contact a name-based virtual server without SSL configured. Previously, a "ssl_ciphers aNULL;" was used for this. This workaround, however, is not compatible with TLSv1.3, in particular, when using BoringSSL, where it is not possible to configure TLSv1.3 ciphers at all. With this change, the ssl_reject_handshake directive is introduced, which instructs nginx to reject SSL handshakes with an "unrecognized_name" alert in a particular server block. For example, to reject handshake with names other than example.com, one can use the following configuration: server { listen 443 ssl; ssl_reject_handshake on; } server { listen 443 ssl; server_name example.com; ssl_certificate example.com.crt; ssl_certificate_key example.com.key; } The following configuration can be used to reject all SSL handshakes without SNI server name provided: server { listen 443 ssl; ssl_reject_handshake on; } server { listen 443 ssl; server_name ~^; ssl_certificate example.crt; ssl_certificate_key example.key; } Additionally, the ssl_reject_handshake directive makes configuring certificates for the default server block optional. If no certificates are configured in the default server for a given listening socket, certificates must be defined in all non-default server blocks with the listening socket in question.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 22 Oct 2020 18:02:28 +0300
parents 3bff3f397c05
children 7ce28b4cc57e 71b7453fb11f
comparison
equal deleted inserted replaced
7731:fd0b2226919b 7732:59e1c73fe02b
291 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2, 291 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
292 ngx_conf_set_keyval_slot, 292 ngx_conf_set_keyval_slot,
293 NGX_HTTP_SRV_CONF_OFFSET, 293 NGX_HTTP_SRV_CONF_OFFSET,
294 offsetof(ngx_http_ssl_srv_conf_t, conf_commands), 294 offsetof(ngx_http_ssl_srv_conf_t, conf_commands),
295 &ngx_http_ssl_conf_command_post }, 295 &ngx_http_ssl_conf_command_post },
296
297 { ngx_string("ssl_reject_handshake"),
298 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
299 ngx_conf_set_flag_slot,
300 NGX_HTTP_SRV_CONF_OFFSET,
301 offsetof(ngx_http_ssl_srv_conf_t, reject_handshake),
302 NULL },
296 303
297 ngx_null_command 304 ngx_null_command
298 }; 305 };
299 306
300 307
612 */ 619 */
613 620
614 sscf->enable = NGX_CONF_UNSET; 621 sscf->enable = NGX_CONF_UNSET;
615 sscf->prefer_server_ciphers = NGX_CONF_UNSET; 622 sscf->prefer_server_ciphers = NGX_CONF_UNSET;
616 sscf->early_data = NGX_CONF_UNSET; 623 sscf->early_data = NGX_CONF_UNSET;
624 sscf->reject_handshake = NGX_CONF_UNSET;
617 sscf->buffer_size = NGX_CONF_UNSET_SIZE; 625 sscf->buffer_size = NGX_CONF_UNSET_SIZE;
618 sscf->verify = NGX_CONF_UNSET_UINT; 626 sscf->verify = NGX_CONF_UNSET_UINT;
619 sscf->verify_depth = NGX_CONF_UNSET_UINT; 627 sscf->verify_depth = NGX_CONF_UNSET_UINT;
620 sscf->certificates = NGX_CONF_UNSET_PTR; 628 sscf->certificates = NGX_CONF_UNSET_PTR;
621 sscf->certificate_keys = NGX_CONF_UNSET_PTR; 629 sscf->certificate_keys = NGX_CONF_UNSET_PTR;
658 666
659 ngx_conf_merge_value(conf->prefer_server_ciphers, 667 ngx_conf_merge_value(conf->prefer_server_ciphers,
660 prev->prefer_server_ciphers, 0); 668 prev->prefer_server_ciphers, 0);
661 669
662 ngx_conf_merge_value(conf->early_data, prev->early_data, 0); 670 ngx_conf_merge_value(conf->early_data, prev->early_data, 0);
671 ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
663 672
664 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, 673 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
665 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 674 (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
666 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); 675 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
667 676
705 714
706 conf->ssl.log = cf->log; 715 conf->ssl.log = cf->log;
707 716
708 if (conf->enable) { 717 if (conf->enable) {
709 718
710 if (conf->certificates == NULL) { 719 if (conf->certificates) {
720 if (conf->certificate_keys == NULL) {
721 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
722 "no \"ssl_certificate_key\" is defined for "
723 "the \"ssl\" directive in %s:%ui",
724 conf->file, conf->line);
725 return NGX_CONF_ERROR;
726 }
727
728 if (conf->certificate_keys->nelts < conf->certificates->nelts) {
729 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
730 "no \"ssl_certificate_key\" is defined "
731 "for certificate \"%V\" and "
732 "the \"ssl\" directive in %s:%ui",
733 ((ngx_str_t *) conf->certificates->elts)
734 + conf->certificates->nelts - 1,
735 conf->file, conf->line);
736 return NGX_CONF_ERROR;
737 }
738
739 } else if (!conf->reject_handshake) {
711 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 740 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
712 "no \"ssl_certificate\" is defined for " 741 "no \"ssl_certificate\" is defined for "
713 "the \"ssl\" directive in %s:%ui", 742 "the \"ssl\" directive in %s:%ui",
714 conf->file, conf->line); 743 conf->file, conf->line);
715 return NGX_CONF_ERROR; 744 return NGX_CONF_ERROR;
716 } 745 }
717 746
718 if (conf->certificate_keys == NULL) { 747 } else if (conf->certificates) {
719 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
720 "no \"ssl_certificate_key\" is defined for "
721 "the \"ssl\" directive in %s:%ui",
722 conf->file, conf->line);
723 return NGX_CONF_ERROR;
724 }
725
726 if (conf->certificate_keys->nelts < conf->certificates->nelts) {
727 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
728 "no \"ssl_certificate_key\" is defined "
729 "for certificate \"%V\" and "
730 "the \"ssl\" directive in %s:%ui",
731 ((ngx_str_t *) conf->certificates->elts)
732 + conf->certificates->nelts - 1,
733 conf->file, conf->line);
734 return NGX_CONF_ERROR;
735 }
736
737 } else {
738
739 if (conf->certificates == NULL) {
740 return NGX_CONF_OK;
741 }
742 748
743 if (conf->certificate_keys == NULL 749 if (conf->certificate_keys == NULL
744 || conf->certificate_keys->nelts < conf->certificates->nelts) 750 || conf->certificate_keys->nelts < conf->certificates->nelts)
745 { 751 {
746 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 752 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
748 "for certificate \"%V\"", 754 "for certificate \"%V\"",
749 ((ngx_str_t *) conf->certificates->elts) 755 ((ngx_str_t *) conf->certificates->elts)
750 + conf->certificates->nelts - 1); 756 + conf->certificates->nelts - 1);
751 return NGX_CONF_ERROR; 757 return NGX_CONF_ERROR;
752 } 758 }
759
760 } else if (!conf->reject_handshake) {
761 return NGX_CONF_OK;
753 } 762 }
754 763
755 if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { 764 if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
756 return NGX_CONF_ERROR; 765 return NGX_CONF_ERROR;
757 } 766 }
806 "\"ssl_certificate\" and \"ssl_certificate_key\" " 815 "\"ssl_certificate\" and \"ssl_certificate_key\" "
807 "directives are not supported on this platform"); 816 "directives are not supported on this platform");
808 return NGX_CONF_ERROR; 817 return NGX_CONF_ERROR;
809 #endif 818 #endif
810 819
811 } else { 820 } else if (conf->certificates) {
812 821
813 /* configure certificates */ 822 /* configure certificates */
814 823
815 if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, 824 if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
816 conf->certificate_keys, conf->passwords) 825 conf->certificate_keys, conf->passwords)
944 { 953 {
945 ngx_str_t *cert, *key; 954 ngx_str_t *cert, *key;
946 ngx_uint_t i, nelts; 955 ngx_uint_t i, nelts;
947 ngx_http_complex_value_t *cv; 956 ngx_http_complex_value_t *cv;
948 ngx_http_compile_complex_value_t ccv; 957 ngx_http_compile_complex_value_t ccv;
958
959 if (conf->certificates == NULL) {
960 return NGX_OK;
961 }
949 962
950 cert = conf->certificates->elts; 963 cert = conf->certificates->elts;
951 key = conf->certificate_keys->elts; 964 key = conf->certificate_keys->elts;
952 nelts = conf->certificates->nelts; 965 nelts = conf->certificates->nelts;
953 966
1325 } 1338 }
1326 1339
1327 cscf = addr[a].default_server; 1340 cscf = addr[a].default_server;
1328 sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; 1341 sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
1329 1342
1330 if (sscf->certificates == NULL) { 1343 if (sscf->certificates) {
1344 continue;
1345 }
1346
1347 if (!sscf->reject_handshake) {
1331 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 1348 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1332 "no \"ssl_certificate\" is defined for " 1349 "no \"ssl_certificate\" is defined for "
1333 "the \"listen ... ssl\" directive in %s:%ui", 1350 "the \"listen ... ssl\" directive in %s:%ui",
1334 cscf->file_name, cscf->line); 1351 cscf->file_name, cscf->line);
1335 return NGX_ERROR; 1352 return NGX_ERROR;
1336 } 1353 }
1354
1355 /*
1356 * if no certificates are defined in the default server,
1357 * check all non-default server blocks
1358 */
1359
1360 cscfp = addr[a].servers.elts;
1361 for (s = 0; s < addr[a].servers.nelts; s++) {
1362
1363 cscf = cscfp[s];
1364 sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
1365
1366 if (sscf->certificates || sscf->reject_handshake) {
1367 continue;
1368 }
1369
1370 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1371 "no \"ssl_certificate\" is defined for "
1372 "the \"listen ... ssl\" directive in %s:%ui",
1373 cscf->file_name, cscf->line);
1374 return NGX_ERROR;
1375 }
1337 } 1376 }
1338 } 1377 }
1339 1378
1340 return NGX_OK; 1379 return NGX_OK;
1341 } 1380 }