From f5e1dcc4718e20dccb2d5a2f7741f158a9319399 Mon Sep 17 00:00:00 2001 From: daum3ns <23260410+daum3ns@users.noreply.github.com> Date: Tue, 18 Mar 2025 11:44:19 +0100 Subject: [PATCH] mod_ssl: directly abort connection when receiving HTTP requests Shutdown the ssl filter and abort the connection instead of disabling is and pass a fake request to the core handler. The current implementation allows to exhaust workers by sendin HTTP request to HTTPS port. Additionally the Openssl lib doesn't detect the http methods PATCH, DELETE, OPTIONS and TRACE. So the current implementation only works partially. See openssl PR: https://github.com/openssl/openssl/pull/26968 --- modules/ssl/ssl_engine_io.c | 66 ++++--------------------------------- modules/ssl/ssl_private.h | 2 -- 2 files changed, 6 insertions(+), 62 deletions(-) diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c index 3a2e841ae02..9091a99cecf 100644 --- a/modules/ssl/ssl_engine_io.c +++ b/modules/ssl/ssl_engine_io.c @@ -935,25 +935,6 @@ static apr_status_t ssl_filter_write(ap_filter_t *f, return outctx->rc; } -/* Just use a simple request. Any request will work for this, because - * we use a flag in the conn_rec->conn_vector now. The fake request just - * gets the request back to the Apache core so that a response can be sent. - * Since we use an HTTP/1.x request, we also have to inject the empty line - * that terminates the headers, or the core will read more data from the - * socket. - */ -#define HTTP_ON_HTTPS_PORT \ - "GET / HTTP/1.0" CRLF - -#define HTTP_ON_HTTPS_PORT_BUCKET(alloc) \ - apr_bucket_immortal_create(HTTP_ON_HTTPS_PORT, \ - sizeof(HTTP_ON_HTTPS_PORT) - 1, \ - alloc) - -/* Custom apr_status_t error code, used when a plain HTTP request is - * received on an SSL port. */ -#define MODSSL_ERROR_HTTP_ON_HTTPS (APR_OS_START_USERERR + 0) - /* Custom apr_status_t error code, used when the proxy cannot * establish an outgoing SSL connection. */ #define MODSSL_ERROR_BAD_GATEWAY (APR_OS_START_USERERR + 1) @@ -978,26 +959,6 @@ static apr_status_t ssl_io_filter_error(bio_filter_in_ctx_t *inctx, int send_eos = 1; switch (status) { - case MODSSL_ERROR_HTTP_ON_HTTPS: - /* log the situation */ - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, APLOGNO(01996) - "SSL handshake failed: HTTP spoken on HTTPS port; " - "trying to send HTML error page"); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server); - - ssl_io_filter_disable(sslconn, inctx); - f->c->keepalive = AP_CONN_CLOSE; - if (is_init) { - sslconn->non_ssl_request = NON_SSL_SEND_REQLINE; - return AP_FILTER_ERROR; - } - sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP; - - /* fake the request line */ - bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); - send_eos = 0; - break; - case MODSSL_ERROR_BAD_GATEWAY: ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, APLOGNO(01997) "SSL handshake failed: sending 502"); @@ -1436,10 +1397,12 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx) /* * The case where OpenSSL has recognized a HTTP request: * This means the client speaks plain HTTP on our HTTPS port. - * ssl_io_filter_error will disable the ssl filters when it - * sees this status code. + * Log the situation and shutdown ssl filter. */ - return MODSSL_ERROR_HTTP_ON_HTTPS; + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c, APLOGNO(01996) + "SSL handshake failed: HTTP spoken on HTTPS port; " + "aborting connection"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server); } else if (ssl_err == SSL_ERROR_SYSCALL) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rc, c, APLOGNO(02007) @@ -1564,24 +1527,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, } if (!inctx->ssl) { - SSLConnRec *sslconn = myConnConfig(f->c); - if (sslconn->non_ssl_request == NON_SSL_SEND_REQLINE) { - bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, bucket); - if (mode != AP_MODE_SPECULATIVE) { - sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP; - } - return APR_SUCCESS; - } - if (sslconn->non_ssl_request == NON_SSL_SEND_HDR_SEP) { - bucket = apr_bucket_immortal_create(CRLF, 2, f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, bucket); - if (mode != AP_MODE_SPECULATIVE) { - sslconn->non_ssl_request = NON_SSL_SET_ERROR_MSG; - } - return APR_SUCCESS; - } - return ap_get_brigade(f->next, bb, mode, block, readbytes); + return APR_ECONNABORTED; } /* XXX: we don't currently support anything other than these modes. */ diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index e3e41b7dff9..5f74aeb4915 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -609,8 +609,6 @@ typedef struct { int disabled; enum { NON_SSL_OK = 0, /* is SSL request, or error handling completed */ - NON_SSL_SEND_REQLINE, /* Need to send the fake request line */ - NON_SSL_SEND_HDR_SEP, /* Need to send the header separator */ NON_SSL_SET_ERROR_MSG /* Need to set the error message */ } non_ssl_request;