Skip to content

Instantly share code, notes, and snippets.

@mendelgusmao
Created October 29, 2014 21:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mendelgusmao/a505ac85e893af98b800 to your computer and use it in GitHub Desktop.
Save mendelgusmao/a505ac85e893af98b800 to your computer and use it in GitHub Desktop.
diff -rupN nginx-1.6.2/auto/modules nginx-1.6.2-socks-upstream/auto/modules
--- nginx-1.6.2/auto/modules 2014-09-16 09:23:19.000000000 -0300
+++ nginx-1.6.2-socks-upstream/auto/modules 2014-10-29 19:28:26.451597644 -0200
@@ -381,6 +381,11 @@ if [ $HTTP_UPSTREAM_LEAST_CONN = YES ];
HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_LEAST_CONN_SRCS"
fi
+if [ $HTTP_UPSTREAM_SOCKS = YES ]; then
+ have=NGX_HTTP_UPSTREAM_SOCKS . auto/have
+ HTTP_SRCS="$HTTP_SRCS src/http/modules/ngx_http_upstream_socks_module.c"
+fi
+
if [ $HTTP_UPSTREAM_KEEPALIVE = YES ]; then
HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_KEEPALIVE_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_KEEPALIVE_SRCS"
diff -rupN nginx-1.6.2/auto/options nginx-1.6.2-socks-upstream/auto/options
--- nginx-1.6.2/auto/options 2014-09-16 09:23:19.000000000 -0300
+++ nginx-1.6.2-socks-upstream/auto/options 2014-10-29 19:27:46.835115534 -0200
@@ -101,6 +101,7 @@ HTTP_GZIP_STATIC=NO
HTTP_UPSTREAM_IP_HASH=YES
HTTP_UPSTREAM_LEAST_CONN=YES
HTTP_UPSTREAM_KEEPALIVE=YES
+HTTP_UPSTREAM_SOCKS=NO
# STUB
HTTP_STUB_STATUS=NO
@@ -220,7 +221,7 @@ do
--with-http_random_index_module) HTTP_RANDOM_INDEX=YES ;;
--with-http_secure_link_module) HTTP_SECURE_LINK=YES ;;
--with-http_degradation_module) HTTP_DEGRADATION=YES ;;
-
+ --with-http_upstream_socks_module) HTTP_UPSTREAM_SOCKS=YES ;;
--without-http_charset_module) HTTP_CHARSET=NO ;;
--without-http_gzip_module) HTTP_GZIP=NO ;;
--without-http_ssi_module) HTTP_SSI=NO ;;
@@ -370,6 +371,7 @@ cat << END
--with-http_secure_link_module enable ngx_http_secure_link_module
--with-http_degradation_module enable ngx_http_degradation_module
--with-http_stub_status_module enable ngx_http_stub_status_module
+ --with-http_upstream_socks_module enable SOCKS5 support for upstreams
--without-http_charset_module disable ngx_http_charset_module
--without-http_gzip_module disable ngx_http_gzip_module
diff -rupN nginx-1.6.2/src/event/ngx_event_connect.h nginx-1.6.2-socks-upstream/src/event/ngx_event_connect.h
--- nginx-1.6.2/src/event/ngx_event_connect.h 2014-09-16 09:23:19.000000000 -0300
+++ nginx-1.6.2-socks-upstream/src/event/ngx_event_connect.h 2014-10-29 19:26:18.106036150 -0200
@@ -52,6 +52,16 @@ struct ngx_peer_connection_s {
ngx_event_save_peer_session_pt save_session;
#endif
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ unsigned socks:1;
+ unsigned socks_handshake1_sent:1;
+ unsigned socks_handshake2_recv:1;
+ unsigned socks_handshake3_sent:1;
+ unsigned socks_handshake4_recv:1;
+ in_port_t socks_port;
+ ngx_str_t socks_hostname;
+#endif
+
#if (NGX_THREADS)
ngx_atomic_t *lock;
#endif
diff -rupN nginx-1.6.2/src/http/modules/ngx_http_upstream_socks_module.c nginx-1.6.2-socks-upstream/src/http/modules/ngx_http_upstream_socks_module.c
--- nginx-1.6.2/src/http/modules/ngx_http_upstream_socks_module.c 1969-12-31 21:00:00.000000000 -0300
+++ nginx-1.6.2-socks-upstream/src/http/modules/ngx_http_upstream_socks_module.c 2014-10-29 19:40:28.448401821 -0200
@@ -0,0 +1,132 @@
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+static void ngx_upstream_socks_write_handler(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
+static void ngx_upstream_socks_read_handler(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
+
+void
+ngx_upstream_socks_init_handshake(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
+{
+ u->next_write_event_handler = u->write_event_handler;
+ u->next_read_event_handler = u->read_event_handler;
+
+ u->write_event_handler = ngx_upstream_socks_write_handler;
+ u->read_event_handler = ngx_upstream_socks_read_handler;
+}
+
+static void
+ngx_upstream_socks_write_handler(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
+{
+ ngx_connection_t *c;
+
+ c = u->peer.connection;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http socks upstream handshake handler");
+
+ if (c->write->timedout) {
+ ngx_http_finalize_request(r, NGX_HTTP_GATEWAY_TIME_OUT);
+ return;
+ }
+
+ if (!u->peer.socks_handshake1_sent) {
+ u->peer.socks_handshake1_sent = 1;
+
+ // TODO, this is ugly
+ u_char handshake[] = {0x05, 0x01, 0x00};
+ c->send(c, handshake, 3);
+
+ } else if (u->peer.socks_handshake2_recv &&
+!u->peer.socks_handshake3_sent) {
+ u_char *handshake;
+ ngx_uint_t len;
+
+ len = 7 + u->peer.socks_hostname.len;
+
+ handshake = ngx_pnalloc(r->pool, len);
+
+ handshake[0] = 5; // version
+ handshake[1] = 1; // connect
+ handshake[2] = 0;
+ handshake[3] = 3; // specify dns
+ handshake[4] = (u_char)u->peer.socks_hostname.len;
+
+ // port
+ *(u_short*)(handshake+len-2) = ntohs(u->peer.socks_port);
+
+ ngx_memcpy(handshake+5, u->peer.socks_hostname.data,
+u->peer.socks_hostname.len);
+
+ c->send(c, handshake, len);
+
+ ngx_pfree(r->pool, handshake);
+
+ u->peer.socks_handshake3_sent = 1;
+ }
+}
+
+static void
+ngx_upstream_socks_read_handler(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
+{
+ ngx_connection_t *c;
+
+ c = u->peer.connection;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http socks upstream handshake recv handler");
+
+ if (c->read->timedout) {
+ ngx_http_finalize_request(r, NGX_HTTP_GATEWAY_TIME_OUT);
+ return;
+ }
+
+ if (!u->peer.socks_handshake2_recv) {
+ u_char buf[2];
+
+ u->peer.socks_handshake2_recv = 1;
+ c->recv(c, buf, 2);
+
+ if (buf[0] != 5 || buf[1] != 0) {
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
+ return;
+ }
+
+ } else if (u->peer.socks_handshake3_sent &&
+!u->peer.socks_handshake4_recv) {
+ u_char buf[22];
+
+ c->recv(c, buf, 5);
+
+ if (buf[0] != 5 || buf[1] != 0 || buf[2] != 0) {
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
+ return;
+ }
+
+ if (buf[3] == 1) {
+ c->recv(c, buf+5, 5);
+
+ } else if (buf[3] == 4) {
+ c->recv(c, buf+5, 17);
+
+ } else if (buf[3] == 3) {
+ u_char *hostname_and_port = ngx_pnalloc(r->pool,
+((size_t)buf[4]) + 2);
+ c->recv(c, hostname_and_port, ((size_t)buf[4]) + 2);
+ ngx_pfree(r->pool, hostname_and_port);
+ }
+
+ u->peer.socks_handshake4_recv = 1;
+
+ // restore previous handlers
+ u->write_event_handler = u->next_write_event_handler;
+ u->read_event_handler = u->next_read_event_handler;
+
+ u->write_event_handler(r, u);
+ }
+}
\ No newline at end of file
diff -rupN nginx-1.6.2/src/http/ngx_http_upstream.c nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream.c
--- nginx-1.6.2/src/http/ngx_http_upstream.c 2014-09-16 09:23:20.000000000 -0300
+++ nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream.c 2014-10-29 19:31:08.593571931 -0200
@@ -146,6 +146,11 @@ static char *ngx_http_upstream(ngx_conf_
static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+void ngx_upstream_socks_init_handshake(ngx_http_request_t *,
+ ngx_http_upstream_t *);
+#endif
+
static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,
ngx_http_upstream_local_t *local);
@@ -1312,6 +1317,13 @@ ngx_http_upstream_connect(ngx_http_reque
u->request_sent = 0;
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ if (u->peer.socks) {
+ ngx_upstream_socks_init_handshake(r, u);
+ return;
+ }
+#endif
+
if (rc == NGX_AGAIN) {
ngx_add_timer(c->write, u->conf->connect_timeout);
return;
@@ -4610,7 +4622,8 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_co
|NGX_HTTP_UPSTREAM_MAX_FAILS
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
|NGX_HTTP_UPSTREAM_DOWN
- |NGX_HTTP_UPSTREAM_BACKUP);
+ |NGX_HTTP_UPSTREAM_BACKUP
+ |NGX_HTTP_UPSTREAM_SOCKS_FLAG);
if (uscf == NULL) {
return NGX_CONF_ERROR;
}
@@ -4813,6 +4826,29 @@ ngx_http_upstream_server(ngx_conf_t *cf,
continue;
}
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ if (ngx_strncmp(value[i].data, "socks=", 6) == 0) {
+
+ if (!(uscf->flags & NGX_HTTP_UPSTREAM_SOCKS_FLAG)) {
+ goto invalid;
+ }
+
+ if (us->socks) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "duplicate socks proxy");
+
+ goto invalid;
+ }
+
+ us->socks = 1;
+ us->socks_port = 80;
+ us->socks_hostname.len = value[i].len - 6;
+ us->socks_hostname.data = value[i].data + 6;
+
+ continue;
+ }
+#endif
+
goto invalid;
}
diff -rupN nginx-1.6.2/src/http/ngx_http_upstream.h nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream.h
--- nginx-1.6.2/src/http/ngx_http_upstream.h 2014-09-16 09:23:20.000000000 -0300
+++ nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream.h 2014-10-29 19:23:43.580157692 -0200
@@ -95,6 +95,12 @@ typedef struct {
unsigned down:1;
unsigned backup:1;
+
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ unsigned socks:1;
+ in_port_t socks_port;
+ ngx_str_t socks_hostname;
+#endif
} ngx_http_upstream_server_t;
@@ -104,6 +110,7 @@ typedef struct {
#define NGX_HTTP_UPSTREAM_FAIL_TIMEOUT 0x0008
#define NGX_HTTP_UPSTREAM_DOWN 0x0010
#define NGX_HTTP_UPSTREAM_BACKUP 0x0020
+#define NGX_HTTP_UPSTREAM_SOCKS_FLAG 0x0040
struct ngx_http_upstream_srv_conf_s {
@@ -339,6 +346,11 @@ struct ngx_http_upstream_s {
unsigned request_sent:1;
unsigned header_sent:1;
+
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ ngx_http_upstream_handler_pt next_read_event_handler;
+ ngx_http_upstream_handler_pt next_write_event_handler;
+#endif
};
diff -rupN nginx-1.6.2/src/http/ngx_http_upstream_round_robin.c nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream_round_robin.c
--- nginx-1.6.2/src/http/ngx_http_upstream_round_robin.c 2014-09-16 09:23:20.000000000 -0300
+++ nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream_round_robin.c 2014-10-29 19:16:40.555024488 -0200
@@ -85,6 +85,12 @@ ngx_http_upstream_init_round_robin(ngx_c
peers->peer[n].max_fails = server[i].max_fails;
peers->peer[n].fail_timeout = server[i].fail_timeout;
peers->peer[n].down = server[i].down;
+
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ peers->peer[n].socks = server[i].socks;
+ peers->peer[n].socks_port = server[i].socks_port;
+ peers->peer[n].socks_hostname = server[i].socks_hostname;
+#endif
n++;
}
}
@@ -139,6 +145,12 @@ ngx_http_upstream_init_round_robin(ngx_c
backup->peer[n].max_fails = server[i].max_fails;
backup->peer[n].fail_timeout = server[i].fail_timeout;
backup->peer[n].down = server[i].down;
+
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ backup->peer[n].socks = server[i].socks;
+ backup->peer[n].socks_port = server[i].socks_port;
+ backup->peer[n].socks_hostname = server[i].socks_hostname;
+#endif
n++;
}
}
@@ -439,6 +451,12 @@ failed:
rrp->peers = peers->next;
pc->tries = rrp->peers->number;
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ pc->socks = peer->socks;
+ pc->socks_port = peer->socks_port;
+ pc->socks_hostname = peer->socks_hostname;
+#endif
+
n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
/ (8 * sizeof(uintptr_t));
diff -rupN nginx-1.6.2/src/http/ngx_http_upstream_round_robin.h nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream_round_robin.h
--- nginx-1.6.2/src/http/ngx_http_upstream_round_robin.h 2014-09-16 09:23:20.000000000 -0300
+++ nginx-1.6.2-socks-upstream/src/http/ngx_http_upstream_round_robin.h 2014-10-29 19:24:23.104637998 -0200
@@ -35,6 +35,12 @@ typedef struct {
#if (NGX_HTTP_SSL)
ngx_ssl_session_t *ssl_session; /* local to a process */
#endif
+
+#if (NGX_HTTP_UPSTREAM_SOCKS)
+ unsigned socks:1;
+ in_port_t socks_port;
+ ngx_str_t socks_hostname;
+#endif
} ngx_http_upstream_rr_peer_t;
@poshad
Copy link

poshad commented Mar 18, 2015

code is not work (

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment