Project

General

Profile

Actions

Feature #2060

closed

mod_connect

Added by jmberg over 15 years ago. Updated over 7 years ago.

Status:
Missing Feedback
Priority:
Low
Category:
mod_proxy
Target version:
-
ASK QUESTIONS IN Forums:

Description

The attached code will add support for CONNECT requests, as such:

CONNECT foo.bar.example.com:443 HTTP/1.0

etc. It supports being configured to allow only certain hosts, ports, combinations. Additionally, it allows configuring paths, so that

CONNECT /path HTTP/1.0

goes to a certain pre-defined host/port. This is the use case that I currently need. When this is used, it is also possible to ask lighttpd to not send a 200 OK response so that the backend server can do that if it's prepared to -- this allows it to control the response header.

Its error handling sucks, and the entire architecture might not be very clean, comments appreciated.

This patch is against 1.4.x, it doesn't seem to apply on a newer version but that can be solved I suppose.


Files

mod-connect.patch (27.5 KB) mod-connect.patch jmberg, 2009-09-01 09:46
Actions #1

Updated by jmberg over 15 years ago

Since the patch viewer doesn't show the patch header, here's an example config:

connect.server          = (
    # finger kernel.org
    "/FINGER" => ( "host" => "204.152.191.37", "port" => 79 ),

    # connect to local echo server
    "/ECHO1" => ( "host" => "127.0.0.1", "port" => 7 ),

    # connect to local echo server, omit 200 response
    # the idea is that the server (echo doesn't of course)
    # will generate the 200 response to have control over it.
    "/ECHO2" => ( "host" => "127.0.0.1", "port" => 7, "noresponse" => 1 ),

    # connect to sipsolutions.net web server
    "/SIPS" => ( "host" => "83.246.72.84", "port" => 80 ),

    # w/o port: treat as http connection
    "83.246.72.84" => ( "port" => 80 ),

    # with any port: allow
    "83.246.72.84:*" => (),

    # allow connections anywhere to port 443
    "*:443" => (),
)
Actions #2

Updated by gstrauss over 8 years ago

  • Category set to 3rd party
Actions #3

Updated by gstrauss over 7 years ago

  • Status changed from New to Missing Feedback

(FYI, HTTP method CONNECT is HTTP/1.1, not HTTP/1.0)

lighttpd does not directly handle HTTP method CONNECT, but lighttpd can be used with HTTP method CONNECT.

If a file exists in the configured document root, e.g. /srv/htdocs/www/127.0.0.1:25, which matches the target authority (e.g. 127.0.01:25) in CONNECT, then dynamic handlers such as CGI, FastCGI, SCGI, proxy can be configured to handle the request, with minor modifications made to lighttpd (similar to those recently made to support HTTP Upgrade in mod_proxy). Care MUST be taken to require proper authentication and/or other restrictions before blindly passing data.

Here is an untested patch against mod_proxy for lighttpd 1.4.46 which might handle a CONNECT request, after the admin created the file in the document root (as above) and configured mod_proxy to explicitly connect to the specific target server and port. It does not support omitting the HTTP response to CONNECT (configurable in user-submitted patch attachment), as omitting the HTTP response header is a violation of the HTTP protocol.

--- a/src/mod_proxy.c
+++ b/src/mod_proxy.c
@@ -1182,11 +1182,23 @@ static void proxy_set_Forwarded(connection *con, const unsigned int flags) {

 static int proxy_create_env(server *srv, handler_ctx *hctx) {
        connection *con   = hctx->remote_conn;
-       buffer *b = buffer_init();
+       buffer *b;
        const int remap_headers = (NULL != hctx->remap_hdrs.urlpaths
                                   || NULL != hctx->remap_hdrs.hosts_request);
        const int upgrade = hctx->remap_hdrs.upgrade
                            && (NULL != array_get_element(con->request.headers, "Upgrade"));
+
+       /* XXX: should check if enabled by hctx->host property
+        *      (configured in proxy.server directive) */
+       if (con->request.http_method == HTTP_METHOD_CONNECT) {
+               con->http_status = 200; /* OK */
+               con->file_started = 1;
+               hctx->wb_reqlen = -1;
+               http_response_upgrade_read_body_unknown(srv, con);
+               return 0;
+       }
+
+       b = buffer_init();
        buffer_string_prepare_copy(b, 8192-1);

        /* build header */

If others find this useful, please add a note here, and we may consider adding this functionality to lighttpd mod_proxy, along with a config directive to enable this behavior. For now, this issue is being marked "Missing Feedback" as it is a very old request.

Actions #4

Updated by gstrauss over 7 years ago

  • Category changed from 3rd party to mod_proxy
Actions #5

Updated by stbuehler over 7 years ago

Just a few notes to keep in mind if one wants to support CONNECT:

  • CONNECT is also used with HTTP/1.0 as version (e.g. openssl s_client -proxy)
  • There are some clients which use "CONNECT ip:port\r\n" as connect request. I.e. possibly no empty line after the header (I think I saw this, but can't remember where), no HTTP version (older openssl s_client -proxy versions use no HTTP version, https://github.com/openssl/openssl/commit/8230f6c764f854190358cf40f0e7e7ca5647d8cd).
  • CONNECT requests probably don't include a "Host: "-header
Actions #6

Updated by gstrauss over 7 years ago

As I mentioned above, "CONNECT" is an HTTP/1.1 method, and HTTP/1.1 requires presence of Host: header.

While some broken clients might attempt CONNECT with HTTP/1.0, an HTTP/1.0 request might indicate an HTTP/1.0 proxy between client and server. Therefore, supporting CONNECT with HTTP/1.0 is not recommended.

If lighttpd 1.4.x is to consider supporting CONNECT method, then lighttpd 1.4.x will aim for compliance with HTTP/1.1 specification for CONNECT, and not for any of the broken clients alluded to in the previous post.

Actions

Also available in: Atom