Skip to content

Commit

Permalink
Merge pull request #174 from chobits/for_pull_request
Browse files Browse the repository at this point in the history
Feature: modify CONNECT response via proxy_connect_response directive
  • Loading branch information
chobits committed Dec 22, 2020
2 parents 3cc43d0 + 2847f79 commit cb4dcd5
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
43 changes: 42 additions & 1 deletion README.md
Expand Up @@ -28,6 +28,7 @@ Table of Contents
* [proxy_connect_send_timeout](#proxy_connect_send_timeout)
* [proxy_connect_address](#proxy_connect_address)
* [proxy_connect_bind](#proxy_connect_bind)
* [proxy_connect_response](#proxy_connect_response)
* [Variables](#variables)
* [$connect_host](#connect_host)
* [$connect_port](#connect_port)
Expand All @@ -37,7 +38,7 @@ Table of Contents
* [$proxy_connect_send_timeout](#proxy_connect_send_timeout-1)
* [$proxy_connect_resolve_time](#proxy_connect_resolve_time)
* [$proxy_connect_connect_time](#proxy_connect_connect_time)
* [$proxy_connect_response](#proxy_connect_response)
* [$proxy_connect_response](#proxy_connect_response-1)
* [Compatibility](#compatibility)
* [Nginx Compatibility](#nginx-compatibility)
* [OpenResty Compatibility](#openresty-compatibility)
Expand Down Expand Up @@ -367,6 +368,44 @@ In order for this parameter to work, it is usually necessary to run nginx worker

NOTE: If using `set $<nginx variable>` and `proxy_connect_bind $<nginx variable>` together, you should use `proxy_connect_rewrite.patch` instead, see [Install](#install) for more details.

proxy_connect_response
----------------------

Syntax: **proxy_connect_response `CONNECT response`**
Default: `HTTP/1.1 200 Connection Established\r\nProxy-agent: nginx\r\n\r\n`
Context: `server`

Set the response of CONNECT request.

Note that it is only used for CONNECT request, it cannot modify the data flow over CONNECT tunnel.

For example:

```
proxy_connect_response "HTTP/1.1 200 Connection Established\r\nProxy-agent: nginx\r\nX-Proxy-Connected-Addr: $connect_addr\r\n\r\n";
```

The `curl` command test case with above config is as following:

```
$ curl https://github.com -sv -x localhost:3128
* Connected to localhost (127.0.0.1) port 3128 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to github.com:443
> CONNECT github.com:443 HTTP/1.1
> Host: github.com:443
> User-Agent: curl/7.64.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection Established --.
< Proxy-agent: nginx | custom CONNECT response
< X-Proxy-Connected-Addr: 13.229.188.59:443 --'
...
```


Variables
=========

Expand Down Expand Up @@ -465,6 +504,8 @@ rewrite_by_lua '
';
```

Also note that `set` or `rewrite_by_lua*` directive is run during the REWRITE phase, which is ahead of dns resolving phase. It cannot get right value of some variables, for example, `$connect_addr` value is `nil`. In such case, you should use [`proxy_connect_response` directive](#proxy_connect_response) instead.


Compatibility
=============
Expand Down
25 changes: 25 additions & 0 deletions ngx_http_proxy_connect_module.c
Expand Up @@ -37,6 +37,8 @@ typedef struct {

ngx_http_complex_value_t *address;
ngx_http_proxy_connect_address_t *local;

ngx_http_complex_value_t *response;
} ngx_http_proxy_connect_loc_conf_t;


Expand Down Expand Up @@ -201,6 +203,12 @@ static ngx_command_t ngx_http_proxy_connect_commands[] = {
offsetof(ngx_http_proxy_connect_loc_conf_t, local),
NULL },

{ ngx_string("proxy_connect_response"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
ngx_http_set_complex_value_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_proxy_connect_loc_conf_t, response),
NULL },

ngx_null_command
};
Expand Down Expand Up @@ -530,6 +538,23 @@ ngx_http_proxy_connect_send_connection_established(ngx_http_request_t *r)

b = &ctx->buf;

/* modify CONNECT response via proxy_connect_response directive */
{
ngx_str_t resp;
ngx_http_proxy_connect_loc_conf_t *plcf;

plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_connect_module);

if (plcf->response
&& ngx_http_complex_value(r, plcf->response, &resp) == NGX_OK)
{
if (resp.len > 0) {
b->pos = resp.data;
b->last = b->pos + resp.len;
}
}
}

ctx->send_established = 1;

for (;;) {
Expand Down
46 changes: 46 additions & 0 deletions t/http_proxy_connect.t
Expand Up @@ -346,6 +346,52 @@ if ($test_enable_rewrite_phase) {

$t->stop();

###############################################################################

$t->write_file_expand('nginx.conf', <<'EOF');
%%TEST_GLOBALS%%
daemon off;
events {
}
http {
%%TEST_GLOBALS_HTTP%%
access_log off;
resolver 127.0.0.1:18085 ipv6=off; # NOTE: cannot connect ipv6 address ::1 in mac os x.
server {
listen 127.0.0.1:8080;
proxy_connect;
proxy_connect_allow all;
proxy_connect_response "HTTP/1.1 200 Connection Established\r\nProxy-agent: nginx\r\nX-Proxy-Connected-Addr: $connect_addr\r\n\r\n";
}
server {
listen 8081;
location / {
return 200 "backend";
}
}
}
EOF

# test proxy_connect_response directive

$t->run();

if ($test_enable_rewrite_phase) {
like(http_connect_request('set-response-header.com', '8081', '/'), qr/X-Proxy-Connected-Addr: 127.0.0.1:8081\r/, 'added header "Foo: bar" to CONNECT response');
}

$t->stop();



# --- stop DNS server ---
Expand Down

0 comments on commit cb4dcd5

Please sign in to comment.