Skip to content

Commit

Permalink
Introduce socks_set_host directive
Browse files Browse the repository at this point in the history
  • Loading branch information
dannote committed Oct 17, 2016
1 parent bbe2b3c commit 94118c3
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 21 deletions.
46 changes: 34 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@ An `nginx_http_proxy_module` fork with SOCKS5 support

## Building

`nginx` >= **1.9.1** is supported.
nginx >= **1.9.1** is supported.

```bash
sudo apt-get install git build-essential zlib1g-dev libpcre3 libpcre3-dev unzip
# apt-get install git build-essential zlib1g-dev libpcre3 libpcre3-dev unzip

git clone https://github.com/dannote/socks-nginx-module
wget http://nginx.org/download/nginx-1.9.15.tar.gz
$ git clone https://github.com/dannote/socks-nginx-module
$ wget http://nginx.org/download/nginx-1.9.15.tar.gz

tar -xzvf nginx-1.9.15.tar.gz
$ tar -xzvf nginx-1.9.15.tar.gz

cd nginx-1.9.15
$ cd nginx-1.9.15

# See http://nginx.org/en/docs/configure.html for more configuration options
./configure --add-module=../socks-nginx-module
$ ./configure --add-module=../socks-nginx-module

make
sudo make install
$ make
# make install
```

## Configuring

Sample configuration:
Sample HTTP to SOCKS5 proxy configuration:

```
location / {
Expand All @@ -49,9 +49,11 @@ All [ngx_http_proxy_module](http://nginx.org/en/docs/http/ngx_http_proxy_module.

### socks_tunnel_header

As `nginx` HTTP parser doesn't support HTTP CONNECT method, a special header can be set to indicate tunnel connection.
Context: `http`, `server`, `location`

This directive can be exploited with the following `HAProxy` configuration:
As nginx HTTP parser doesn't support HTTP CONNECT method, a special header can be set to indicate tunnel connection.

This directive can be exploited with the following HAProxy configuration:

```
frontend local
Expand All @@ -65,4 +67,24 @@ frontend local
backend nginx
mode http
server proxy 127.0.0.1:8080 maxconn 100000
```

### socks_set_host

Context: `http`, `server`, `location`

Default: `proxy_set_host $http_host;`

Overrides the endpoint server.

This example will proxy requests to `ipinfo.io` via local Tor daemon:

```
location /ip {
socks_pass socks5://127.0.0.1:9050;
socks_set_host ipinfo.io;
socks_set_header Host ipinfo.io;
socks_redirect off;
socks_http_version 1.1;
}
```
51 changes: 50 additions & 1 deletion src/ngx_http_socks_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ static ngx_int_t ngx_http_socks_rewrite_regex(ngx_conf_t *cf,

static void ngx_http_socks_set_vars(ngx_url_t *u, ngx_http_socks_vars_t *v);
static char *ngx_http_socks_tunnel_header(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
void *conf);
static char *ngx_http_socks_set_host(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);


static ngx_conf_post_t ngx_http_socks_lowat_post =
Expand Down Expand Up @@ -493,6 +495,13 @@ static ngx_command_t ngx_http_socks_commands[] = {
offsetof(ngx_http_socks_loc_conf_t, tunnel_header),
NULL },

{ ngx_string("socks_set_host"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_socks_set_host,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_socks_loc_conf_t, host),
NULL },

ngx_null_command
};

Expand Down Expand Up @@ -1060,6 +1069,15 @@ ngx_http_socks_create_request(ngx_http_request_t *r)
}
}

if (slcf->host.value.data) {
if (ngx_http_complex_value(r, &slcf->host, &ctx->host) != NGX_OK) {
return NGX_ERROR;
}
} else {
ctx->host.len = r->headers_in.host->value.len;
ctx->host.data = r->headers_in.host->value.data;
}

if (slcf->upstream.pass_request_headers) {
part = &r->headers_in.headers.part;
header = part->elts;
Expand Down Expand Up @@ -2977,6 +2995,10 @@ ngx_http_socks_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->tunnel_header,
prev->tunnel_header, "");

if (conf->host.value.data == NULL) {
conf->host = prev->host;
}

ngx_conf_merge_value(conf->redirect, prev->redirect, 1);

if (conf->redirect) {
Expand Down Expand Up @@ -4040,4 +4062,31 @@ ngx_http_socks_tunnel_header(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
slcf->tunnel_header = value[1];

return NGX_CONF_OK;
}

static char *
ngx_http_socks_set_host(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_socks_loc_conf_t *slcf = conf;

ngx_str_t *value;
ngx_http_compile_complex_value_t ccv;

value = cf->args->elts;

if (slcf->host.value.data) {
return "is duplicate";
}

ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));

ccv.cf = cf;
ccv.value = &value[1];
ccv.complex_value = &slcf->host;

if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
}

return NGX_CONF_OK;
}
4 changes: 4 additions & 0 deletions src/ngx_http_socks_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ typedef struct {
ngx_str_t location;
ngx_str_t url;

ngx_http_complex_value_t host;

#if (NGX_HTTP_CACHE)
ngx_http_complex_value_t cache_key;
#endif
Expand All @@ -113,6 +115,8 @@ typedef struct {
ngx_chain_t *free;
ngx_chain_t *busy;

ngx_str_t host;

unsigned head:1;
unsigned internal_chunked:1;
unsigned header_sent:1;
Expand Down
16 changes: 8 additions & 8 deletions src/ngx_http_socks_upstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -2039,7 +2039,6 @@ ngx_http_socks_upstream_write_handler(ngx_http_request_t *r,
ngx_connection_t *c;
u_char *buf, host_len, i;
ngx_uint_t len;
ngx_str_t *host;
ngx_uint_t port;
ngx_http_socks_ctx_t *ctx;

Expand All @@ -2062,19 +2061,20 @@ ngx_http_socks_upstream_write_handler(ngx_http_request_t *r,
break;

case socks_connect:
if (!r->headers_in.host || r->headers_in.host->value.len > 0xFF) {
if (!ctx->host.len || ctx->host.len > 0xFF) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"invalid target host");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return;
}

host = &r->headers_in.host->value;
host_len = (u_char) host->len;
host_len = (u_char) ctx->host.len;
port = ctx->tunnel ? 443 : 80;

for (i = 0; i < host_len; i++) {
if (host->data[host_len - i - 1] == ':') {
host_len = host->len - i - 1;
port = ngx_atoi(host->data + host_len + 1, i);
if (ctx->host.data[host_len - i - 1] == ':') {
host_len = ctx->host.len - i - 1;
port = ngx_atoi(ctx->host.data + host_len + 1, i);
break;
}
}
Expand All @@ -2089,7 +2089,7 @@ ngx_http_socks_upstream_write_handler(ngx_http_request_t *r,
buf[3] = NGX_HTTP_SOCKS_ADDR_DOMAIN_NAME;
buf[4] = host_len;
*(u_short*) (buf + len - 2) = ntohs(port);
ngx_memcpy(buf + 5, host->data, host_len);
ngx_memcpy(buf + 5, ctx->host.data, host_len);

c->send(c, buf, len);

Expand Down

0 comments on commit 94118c3

Please sign in to comment.