diff --git a/changelog b/changelog
index 99758be421d5925ba9708518ed76eae7fb5a9abe..602a9bb98c5c997d690cd942622889a0d6fd2b8f 100644
--- a/changelog
+++ b/changelog
@@ -20,6 +20,12 @@ processing is protected by a 5s timeout.
 The chunks are stored in a malloc'd buffer of size protocols[0].rx_buffer_size.
 
 
+New server option you can enable from user code
+LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT allows non-SSL connections to
+also be accepted on an SSL listening port.  It's disabled unless you enable
+it explicitly.
+
+
 User api changes
 ----------------
 
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 7342e9baccde80fa11bb89c8b0b2b24fa0176be7..8b2fec52b3a8a11485b08f8049b93340c0d6a4a0 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -1892,6 +1892,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 
 #ifdef LWS_OPENSSL_SUPPORT
 	context->use_ssl = 0;
+	context->allow_non_ssl_on_ssl_port = 0;
 	context->ssl_ctx = NULL;
 	context->ssl_client_ctx = NULL;
 	openssl_websocket_private_data_index = 0;
@@ -2135,6 +2136,11 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
 						     context->ssl_ctx, NULL, 0);
 	}
 
+	if(info->options & LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT) {
+		/* Normally SSL listener rejects non-ssl, optionally allow */
+		context->allow_non_ssl_on_ssl_port = 1;
+	}
+
 	if (context->use_ssl) {
 
 		/* openssl init for server sockets */
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index cfd1f8c58bb19502d8bc41ca2555ca01e007dc46..b2ba359491980e49309c583b2b12db48aeae5a2a 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -138,6 +138,7 @@ LWS_VISIBLE LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
 enum libwebsocket_context_options {
 	LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2,
 	LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4,
+	LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT = 8
 };
 
 enum libwebsocket_callback_reasons {
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 12b8d5a8b3e9beba15e29a8d9af90dd67c2e6ec1..ea68f4bc34a5e97b903fd49552c1e134ea8d949d 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -289,6 +289,7 @@ struct libwebsocket_context {
 
 #ifdef LWS_OPENSSL_SUPPORT
 	int use_ssl;
+	int allow_non_ssl_on_ssl_port;
 	SSL_CTX *ssl_ctx;
 	SSL_CTX *ssl_client_ctx;
 #endif
diff --git a/lib/server.c b/lib/server.c
index 6c35c98ed145287d01a68ef23e0d20ed48294c27..700a6e286f620024dd4e7580dd47d009c03929a1 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -354,6 +354,37 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 			wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
 
 		lws_latency_pre(context, wsi);
+
+		n = recv(wsi->sock, context->service_buffer,
+			sizeof(context->service_buffer), MSG_PEEK);
+
+		/*
+		 * optionally allow non-SSL connect on SSL listening socket
+		 * This is disabled by default, if enabled it goes around any
+		 * SSL-level access control (eg, client-side certs) so leave
+		 * it disabled unless you know it's not a problem for you
+		 */
+
+		if (context->allow_non_ssl_on_ssl_port && n >= 1 &&
+					context->service_buffer[0] >= ' ') {
+			/*
+			 * TLS content-type for Handshake is 0x16
+			 * TLS content-type for ChangeCipherSpec Record is 0x14
+			 *
+			 * A non-ssl session will start with the HTTP method in
+			 * ASCII.  If we see it's not a legit SSL handshake
+			 * kill the SSL for this connection and try to handle
+			 * as a HTTP connection upgrade directly.
+			 */
+			wsi->use_ssl = 0;
+			SSL_shutdown(wsi->ssl);
+			SSL_free(wsi->ssl);
+			wsi->ssl = NULL;
+			goto accepted;
+		}
+
+		/* normal SSL connection processing path */
+
 		n = SSL_accept(wsi->ssl);
 		lws_latency(context, wsi,
 			"SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
@@ -378,7 +409,6 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 			if (m == SSL_ERROR_WANT_WRITE) {
 				context->fds[
 				  wsi->position_in_fds_table].events |= POLLOUT;
-
 				/* external POLL support via protocol 0 */
 				context->protocols[0].callback(context, wsi,
 					LWS_CALLBACK_SET_MODE_POLL_FD,
@@ -387,13 +417,14 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 				break;
 			}
 			lwsl_debug("SSL_accept failed skt %u: %s\n",
-			      pollfd->fd,
-			      ERR_error_string(m, NULL));
+				  pollfd->fd,
+				  ERR_error_string(m, NULL));
 			libwebsocket_close_and_free_session(context, wsi,
-						     LWS_CLOSE_STATUS_NOSTATUS);
+						 LWS_CLOSE_STATUS_NOSTATUS);
 			break;
 		}
 
+accepted:
 		/* OK, we are accepted */
 
 		libwebsocket_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
diff --git a/test-server/test-server.c b/test-server/test-server.c
index 0a32ba08e9250d217ebe91bf5a26017cc0e30c50..f82cd0c5a4b913c9846b6cbc48669b499b68650a 100644
--- a/test-server/test-server.c
+++ b/test-server/test-server.c
@@ -715,6 +715,7 @@ static struct option options[] = {
 	{ "debug",	required_argument,	NULL, 'd' },
 	{ "port",	required_argument,	NULL, 'p' },
 	{ "ssl",	no_argument,		NULL, 's' },
+	{ "allow-non-ssl",	no_argument,		NULL, 'a' },
 	{ "interface",  required_argument,	NULL, 'i' },
 	{ "closetest",  no_argument,		NULL, 'c' },
 #ifndef LWS_NO_DAEMONIZE
@@ -749,7 +750,7 @@ int main(int argc, char **argv)
 	info.port = 7681;
 
 	while (n >= 0) {
-		n = getopt_long(argc, argv, "ci:hsp:d:Dr:", options, NULL);
+		n = getopt_long(argc, argv, "ci:hsap:d:Dr:", options, NULL);
 		if (n < 0)
 			continue;
 		switch (n) {
@@ -767,6 +768,9 @@ int main(int argc, char **argv)
 		case 's':
 			use_ssl = 1;
 			break;
+		case 'a':
+			opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
+			break;
 		case 'p':
 			info.port = atoi(optarg);
 			break;