Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ngx_http_proxy_connect_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
297 changes: 297 additions & 0 deletions patch/proxy_connect_rewrite_103001.patch
Original file line number Diff line number Diff line change
@@ -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 },