diff --git a/ngx_http_proxy_connect_module.c b/ngx_http_proxy_connect_module.c index cd7e517..b3a629a 100644 --- a/ngx_http_proxy_connect_module.c +++ b/ngx_http_proxy_connect_module.c @@ -1759,11 +1759,17 @@ static char * ngx_http_proxy_connect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t *cscf; ngx_http_proxy_connect_loc_conf_t *pclcf; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_proxy_connect_handler; + cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); + if (cscf != NULL) { + cscf->allow_connect = 1; + } + pclcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_proxy_connect_module); pclcf->accept_connect = 1; diff --git a/patch/proxy_connect_rewrite_103001.patch b/patch/proxy_connect_rewrite_103001.patch new file mode 100644 index 0000000..76fc15c --- /dev/null +++ b/patch/proxy_connect_rewrite_103001.patch @@ -0,0 +1,297 @@ +diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c +index 53ddf39bb..b5e46de01 100644 +--- a/src/http/ngx_http_core_module.c ++++ b/src/http/ngx_http_core_module.c +@@ -978,6 +978,14 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, + r->content_handler = NULL; + r->uri_changed = 0; + ++#if (NGX_HTTP_PROXY_CONNECT) ++ if (r->method == NGX_HTTP_CONNECT) { ++ ngx_http_update_location_config(r); ++ r->phase_handler++; ++ return NGX_AGAIN; ++ } ++#endif ++ + rc = ngx_http_core_find_location(r); + + if (rc == NGX_ERROR) { +diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c +index 81f689e5b..152f98835 100644 +--- a/src/http/ngx_http_parse.c ++++ b/src/http/ngx_http_parse.c +@@ -111,6 +111,14 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) + enum { + sw_start = 0, + sw_method, ++#if (NGX_HTTP_PROXY_CONNECT) ++ sw_spaces_before_connect_host, ++ sw_connect_host_start, ++ sw_connect_host, ++ sw_connect_host_end, ++ sw_connect_host_ip_literal, ++ sw_connect_port, ++#endif + sw_spaces_before_uri, + sw_schema, + sw_schema_slash, +@@ -253,7 +261,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) + if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' ')) + { + r->method = NGX_HTTP_CONNECT; ++#if (NGX_HTTP_PROXY_CONNECT) ++ state = sw_spaces_before_connect_host; ++#else + state = sw_spaces_before_host; ++#endif + } + + break; +@@ -285,6 +297,111 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) + + break; + ++#if (NGX_HTTP_PROXY_CONNECT) ++ case sw_spaces_before_connect_host: ++ ++ if (ch == ' ') { ++ break; ++ } ++ ++ /* fall through */ ++ ++ case sw_connect_host_start: ++ ++ r->connect_host_start = p; ++ ++ if (ch == '[') { ++ state = sw_connect_host_ip_literal; ++ break; ++ } ++ ++ state = sw_connect_host; ++ ++ /* fall through */ ++ ++ case sw_connect_host: ++ ++ c = (u_char) (ch | 0x20); ++ if (c >= 'a' && c <= 'z') { ++ break; ++ } ++ ++ if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') { ++ break; ++ } ++ ++ /* fall through */ ++ ++ case sw_connect_host_end: ++ ++ r->connect_host_end = p; ++ ++ switch (ch) { ++ case ':': ++ state = sw_connect_port; ++ break; ++ default: ++ return NGX_HTTP_PARSE_INVALID_REQUEST; ++ } ++ break; ++ ++ case sw_connect_host_ip_literal: ++ ++ if (ch >= '0' && ch <= '9') { ++ break; ++ } ++ ++ c = (u_char) (ch | 0x20); ++ if (c >= 'a' && c <= 'z') { ++ break; ++ } ++ ++ switch (ch) { ++ case ':': ++ break; ++ case ']': ++ state = sw_connect_host_end; ++ break; ++ case '-': ++ case '.': ++ case '_': ++ case '~': ++ /* unreserved */ ++ break; ++ case '!': ++ case '$': ++ case '&': ++ case '\'': ++ case '(': ++ case ')': ++ case '*': ++ case '+': ++ case ',': ++ case ';': ++ case '=': ++ /* sub-delims */ ++ break; ++ default: ++ return NGX_HTTP_PARSE_INVALID_REQUEST; ++ } ++ break; ++ ++ case sw_connect_port: ++ if (ch >= '0' && ch <= '9') { ++ break; ++ } ++ ++ switch (ch) { ++ case ' ': ++ r->connect_port_end = p; ++ state = sw_http_09; ++ break; ++ default: ++ return NGX_HTTP_PARSE_INVALID_REQUEST; ++ } ++ break; ++#endif ++ + /* space* before URI */ + case sw_spaces_before_uri: + +diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c +index a9573a620..dbc6bc663 100644 +--- a/src/http/ngx_http_request.c ++++ b/src/http/ngx_http_request.c +@@ -1160,6 +1160,55 @@ ngx_http_process_request_line(ngx_event_t *rev) + r->http_protocol.len = r->request_end - r->http_protocol.data; + } + ++#if (NGX_HTTP_PROXY_CONNECT) ++ ++ if (r->connect_host_start && r->connect_host_end) { ++ ++ host.len = r->connect_host_end - r->connect_host_start; ++ host.data = r->connect_host_start; ++ rc = ngx_http_validate_host(&host, &r->connect_port_n, r->pool, 0); ++ ++ if (rc == NGX_DECLINED) { ++ ngx_log_error(NGX_LOG_INFO, c->log, 0, ++ "client sent invalid host in request line"); ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return; ++ } ++ ++ if (rc == NGX_ERROR) { ++ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); ++ return; ++ } ++ ++ r->connect_host = host; ++ ++ if (!r->connect_port_end) { ++ ngx_log_error(NGX_LOG_INFO, c->log, 0, ++ "client sent no port in request line"); ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return; ++ } ++ ++ r->connect_port.data = r->connect_host_end + 1; ++ r->connect_port.len = r->connect_port_end ++ - r->connect_host_end - 1; ++ ++ ngx_int_t port; ++ ++ port = ngx_atoi(r->connect_port.data, r->connect_port.len); ++ if (port == NGX_ERROR || port < 1 || port > 65535) { ++ ngx_log_error(NGX_LOG_INFO, c->log, 0, ++ "client sent invalid port in request line"); ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return; ++ } ++ ++ r->connect_port_n = port; ++ ++ /* skip processing request uri */ ++ } else ++#endif ++ + if (ngx_http_process_request_uri(r) != NGX_OK) { + break; + } +@@ -1774,6 +1823,19 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, + } + } + ++#if (NGX_HTTP_PROXY_CONNECT) ++ if (r->connect_host_start) { ++ r->connect_host_start = new + (r->connect_host_start - old); ++ if (r->connect_host_end) { ++ r->connect_host_end = new + (r->connect_host_end - old); ++ } ++ ++ if (r->connect_port_end) { ++ r->connect_port_end = new + (r->connect_port_end - old); ++ } ++ } ++#endif ++ + if (r->host_start) { + r->host_start = new + (r->host_start - old); + if (r->host_end) { +@@ -2074,6 +2136,15 @@ ngx_http_process_request_header(ngx_http_request_t *r) + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + ++#if (NGX_HTTP_PROXY_CONNECT) ++ if (r->method == NGX_HTTP_CONNECT && r->connect_host_start == NULL) { ++ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ++ "client sent CONNECT method without target"); ++ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); ++ return NGX_ERROR; ++ } ++#endif ++ + if (r->method == NGX_HTTP_CONNECT + && (r->http_version != NGX_HTTP_VERSION_11 || !cscf->allow_connect)) + { +diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h +index 48eb43eb0..35175e5ed 100644 +--- a/src/http/ngx_http_request.h ++++ b/src/http/ngx_http_request.h +@@ -424,6 +424,15 @@ struct ngx_http_request_s { + ngx_str_t exten; + ngx_str_t unparsed_uri; + ++#if (NGX_HTTP_PROXY_CONNECT) ++ ngx_str_t connect_host; ++ ngx_str_t connect_port; ++ in_port_t connect_port_n; ++ u_char *connect_host_start; ++ u_char *connect_host_end; ++ u_char *connect_port_end; ++#endif ++ + ngx_str_t method_name; + ngx_str_t http_protocol; + ngx_str_t schema; +diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c +index 37cd0d287..20661df36 100644 +--- a/src/http/ngx_http_variables.c ++++ b/src/http/ngx_http_variables.c +@@ -167,6 +167,14 @@ static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r, + + static ngx_http_variable_t ngx_http_core_variables[] = { + ++#if (NGX_HTTP_PROXY_CONNECT) ++ { ngx_string("connect_host"), NULL, ngx_http_variable_request, ++ offsetof(ngx_http_request_t, connect_host), 0, 0 }, ++ ++ { ngx_string("connect_port"), NULL, ngx_http_variable_request, ++ offsetof(ngx_http_request_t, connect_port), 0, 0 }, ++#endif ++ + { ngx_string("http_host"), NULL, ngx_http_variable_header, + offsetof(ngx_http_request_t, headers_in.host), 0, 0 }, +