sockproxy: Do not validate ALPN protocols
With the use of sockproxy, it is not desirable to reject connections that do not advertise ALPN protocols related to HTTP (e.g. h2, http/1.1), since the backend might not be related to HTTP (for example, an IRC server).
lighttpd should not advertise any ALPN protocol with sockproxy and thus let TLS handshake succeed even if they advertise unknown ALPN protocols:
Servers that receive a ClientHello containing the
"application_layer_protocol_negotiation" extension MAY return a
suitable protocol selection response to the client. The server will
ignore any protocol name that it does not recognize.
In a second phase, the sockproxy module could be configurable to filter connections according to the advertised ALPN protocol, allowing HTTPS and other TLS-based protocols to be handled on the same port?
- Tracker changed from Bug to Feature
lighttpd, first and foremost, is an HTTP server. "httpd" is part of the name "lighttpd".
It appears that you had trouble distinguishing between a bug and a feature request attempting to extend lighttpd, despite the wording of your post.
The lighttpd hook
handle_connection_accept, which is used by mod_sockproxy, occurs when the connection is accepted, and before the TLS Client Hello. Other hooks in lighttpd occur after the HTTP request header has received so that lighttpd can configure the request based on the contents of the HTTP request headers. These other hooks would be too late to select mod_sockproxy, since if using mod_sockproxy, an HTTP request header is probably not present.
FYI: There is a recent security discussion around ALPN enforcement in Go, and was mentioned on the Apache httpd mailing list. Neither Go nor Apache strictly enforce the ALPN if an attempt is made to negotiate ALPN. lighttpd, on the other hand, does.
Stefan Eissing (an Apache httpd developer) wrote (about Apache httpd):
In short: there is the possibility of a middle-man tricking a client into accepting the response from another TLS server, if it uses the same certificate. This seems to be in the open, so we can talk about it here.
People think about how to prevent this and enforce stricter ALPN negotiation. But it is hairy since ALPN has been deployed for over 5 years. Breakage may ensue.
Our server is also 'relaxed' about this. If you look at ssl_engine_kernel.c#2760, if no protocol overlap was found, we continue the handshake as if no ALPN was supplied at all.
golang ticket: https://github.com/golang/go/issues/46310
Twitter thread: https://twitter.com/icing/status/1402943686619639818
side note: The issue stems from a user of my (go) IRC client that struggled to make it connect to a bouncer behind lighttpd. However I'm not interested in making a patch nor having this issue fixed/feature implemented. If you don't need/want this feature this ticket can be closed. Sorry for the inconvenience.
Basically lighttpd needs to enforce ALPN like it does right now and this issue is invalid as-is. However, mod_sockproxy requires HTTP from clients that advertise ALPN and thus prevents any non-HTTP service to these clients.
I guess the feature to add here is a "protocols" option that lists ALPN codes supported by the backend?
I am not against extending lighttpd per se, though I have noted that this feature request reaches somewhat outside the scope of an HTTP server, just as mod_sockproxy does, too.
Presumably, you would like to use some features of lighttpd, such as TLS termination, or else you would more simply have your backend listen on a specific IP and port instead of lighttpd. Perhaps you are multiplexing over a single IP and port and would like to use SNI and ALPN for application-level, virtual-host-based routing via protocol. Perhaps you are not very concerned with ALPN and merely want it disabled or non-fatal when using mod_sockproxy. From your comments, I think I understand your request to be the latter.
Currently, lighttpd modules are by-and-large independent of one another, and do not control one another. If you are willing to test some patches, I may experiment with some low-impact changes to see if mod_sockproxy can leave a bread crumb for lighttpd TLS modules to find while processing the TLS ClientHello.
- Status changed from New to Patch Pending
- Target version changed from 1.4.x to 1.4.60
The following (UNTESTED) patch does not error out if ALPN is submitted by the client, but does not match ALPN protocols known to lighttpd mod_openssl, AND the request already has a handler, e.g. mod_sockproxy, which can only be a connection handler since the request has not yet been read if TLS Client Hello is being processed during TLS connection setup negotiation.
--- a/src/mod_openssl.c +++ b/src/mod_openssl.c @@ -1847,7 +1847,9 @@ mod_openssl_alpn_select_cb (SSL *ssl, const unsigned char **out, unsigned char * #if OPENSSL_VERSION_NUMBER < 0x10100000L return SSL_TLSEXT_ERR_NOACK; #else - return SSL_TLSEXT_ERR_ALERT_FATAL; + return hctx->r->handler_module /*(e.g. mod_sockproxy)*/ + ? SSL_TLSEXT_ERR_NOACK + : SSL_TLSEXT_ERR_ALERT_FATAL; #endif }
Also available in: Atom