summaryrefslogtreecommitdiffhomepage
path: root/src/reqs.c
diff options
context:
space:
mode:
authorGonzalo Tornaria <tornaria@math.utexas.edu>2016-12-20 21:30:43 +0000
committerrofl0r <rofl0r@users.noreply.github.com>2018-02-06 16:11:39 +0000
commit8906b0734e5c61016d9d4090507f010b2006292d (patch)
tree73eea974f5a292516e1ffd85ed44ddeae1b34764 /src/reqs.c
parent116e59e93346ddbe08f56f8c7e8bd648690c0242 (diff)
add SOCKS upstream proxy support (socks4/socks5)
original patch submitted in 2006 to debian mailing list: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=392848%29#12 this version was rebased to git and updated by Russ Dill <russ.dill@gmail.com> in 2015 (the original patch used a different config file format). as discussed in #40. commit message by @rofl0r.
Diffstat (limited to 'src/reqs.c')
-rw-r--r--src/reqs.c93
1 files changed, 90 insertions, 3 deletions
diff --git a/src/reqs.c b/src/reqs.c
index 990152a..a3d8162 100644
--- a/src/reqs.c
+++ b/src/reqs.c
@@ -61,9 +61,11 @@
#ifdef UPSTREAM_SUPPORT
# define UPSTREAM_CONFIGURED() (config.upstream_list != NULL)
# define UPSTREAM_HOST(host) upstream_get(host, config.upstream_list)
+# define UPSTREAM_IS_HTTP(conn) (conn->upstream_proxy != NULL && conn->upstream_proxy->type == HTTP_TYPE)
#else
# define UPSTREAM_CONFIGURED() (0)
# define UPSTREAM_HOST(host) (NULL)
+# define UPSTREAM_IS_HTTP(up) (0)
#endif
/*
@@ -853,10 +855,10 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
/*
* Don't send headers if there's already an error, if the request was
* a stats request, or if this was a CONNECT method (unless upstream
- * proxy is in use.)
+ * http proxy is in use.)
*/
if (connptr->server_fd == -1 || connptr->show_stats
- || (connptr->connect_method && (connptr->upstream_proxy == NULL))) {
+ || (connptr->connect_method && ! UPSTREAM_IS_HTTP(connptr))) {
log_message (LOG_INFO,
"Not sending client headers to remote machine");
return 0;
@@ -1265,6 +1267,88 @@ static void relay_connection (struct conn_s *connptr)
return;
}
+static int
+connect_to_upstream_proxy(struct conn_s *connptr, struct request_s *request)
+{
+ int len;
+ char buff[512]; /* won't use more than 7 + 255 */
+ unsigned short port;
+ struct hostent *host;
+ struct upstream *cur_upstream = connptr->upstream_proxy;
+
+ log_message(LOG_CONN,
+ "Established connection to %s proxy \"%s\" using file descriptor %d.",
+ proxy_type_name(cur_upstream->type), cur_upstream->host, connptr->server_fd);
+
+ if (cur_upstream->type == SOCKS4_TYPE) {
+
+ buff[0] = 4; /* socks version */
+ buff[1] = 1; /* connect command */
+ port = htons(request->port);
+ memcpy(&buff[2], &port, 2); /* dest port */
+ host = gethostbyname(request->host);
+ memcpy(&buff[4], host->h_addr_list[0], 4); /* dest ip */
+ buff[8] = 0; /* user */
+ if (9 != safe_write(connptr->server_fd, buff, 9))
+ return -1;
+ if (8 != safe_read(connptr->server_fd, buff, 8))
+ return -1;
+ if (buff[0]!=0 || buff[1]!=90)
+ return -1;
+
+ } else if (cur_upstream->type == SOCKS5_TYPE) {
+
+ /* init */
+ buff[0] = 5; /* socks version */
+ buff[1] = 1; /* number of methods */
+ buff[2] = 0; /* no auth method */
+ if (3 != safe_write(connptr->server_fd, buff, 3))
+ return -1;
+ if (2 != safe_read(connptr->server_fd, buff, 2))
+ return -1;
+ if (buff[0]!=5 || buff[1]!=0)
+ return -1;
+ /* connect */
+ buff[0] = 5; /* socks version */
+ buff[1] = 1; /* connect */
+ buff[2] = 0; /* reserved */
+ buff[3] = 3; /* domainname */
+ len=strlen(request->host);
+ if(len>255)
+ return -1;
+ buff[4] = len; /* length of domainname */
+ memcpy(&buff[5], request->host, len); /* dest ip */
+ port = htons(request->port);
+ memcpy(&buff[5+len], &port, 2); /* dest port */
+ if (7+len != safe_write(connptr->server_fd, buff, 7+len))
+ return -1;
+ if (4 != safe_read(connptr->server_fd, buff, 4))
+ return -1;
+ if (buff[0]!=5 || buff[1]!=0)
+ return -1;
+ switch(buff[3]) {
+ case 1: len=4; break; /* ip v4 */
+ case 4: len=16; break; /* ip v6 */
+ case 3: /* domainname */
+ if (1 != safe_read(connptr->server_fd, buff, 1))
+ return -1;
+ len = buff[0]; /* max = 255 */
+ break;
+ default: return -1;
+ }
+ if (2+len != safe_read(connptr->server_fd, buff, 2+len))
+ return -1;
+ } else {
+ return -1;
+ }
+
+ if (connptr->connect_method)
+ return 0;
+
+ return establish_http_connection(connptr, request);
+}
+
+
/*
* Establish a connection to the upstream proxy server.
*/
@@ -1308,6 +1392,9 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
return -1;
}
+ if (cur_upstream->type != HTTP_TYPE)
+ return connect_to_upstream_proxy(connptr, request);
+
log_message (LOG_CONN,
"Established connection to upstream proxy \"%s\" "
"using file descriptor %d.",
@@ -1527,7 +1614,7 @@ void handle_connection (int fd)
goto fail;
}
- if (!(connptr->connect_method && (connptr->upstream_proxy == NULL))) {
+ if (!connptr->connect_method || UPSTREAM_IS_HTTP(connptr)) {
if (process_server_headers (connptr) < 0) {
update_stats (STAT_BADCONN);
goto fail;