From ea1124f5af4c17cb917bae403c9108563d0e4ff8 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Fri, 7 Dec 2012 12:45:20 +0000 Subject: [PATCH] Add support for Tor's optimistic-data SOCKS extension .. which can reduce the latency for requests on newly created connections. Currently only the headers are sent optimistically and only if the client request has already been read completely which rules out requests with large bodies. --- cgi.c | 5 ++++- cgisimple.c | 5 ++++- filters.c | 7 ++++++- gateway.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- jcc.c | 10 ++++++++-- loadcfg.c | 11 +++++++++-- project.h | 4 +++- 7 files changed, 76 insertions(+), 10 deletions(-) diff --git a/cgi.c b/cgi.c index 950d885b..f81443ee 100644 --- a/cgi.c +++ b/cgi.c @@ -1,4 +1,4 @@ -const char cgi_rcs[] = "$Id: cgi.c,v 1.156 2012/10/21 12:54:15 fabiankeil Exp $"; +const char cgi_rcs[] = "$Id: cgi.c,v 1.157 2012/11/09 10:47:42 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgi.c,v $ @@ -978,6 +978,9 @@ struct http_response *error_response(struct client_state *csp, case SOCKS_5: socks_type = "socks5-"; break; + case SOCKS_5T: + socks_type = "socks5t-"; + break; default: log_error(LOG_LEVEL_FATAL, "Unknown socks type: %d.", fwd->type); } diff --git a/cgisimple.c b/cgisimple.c index c1758b97..7855fa02 100644 --- a/cgisimple.c +++ b/cgisimple.c @@ -1,4 +1,4 @@ -const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.116 2012/10/21 12:39:27 fabiankeil Exp $"; +const char cgisimple_rcs[] = "$Id: cgisimple.c,v 1.117 2012/10/21 12:55:29 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/cgisimple.c,v $ @@ -1408,6 +1408,9 @@ jb_err cgi_show_url_info(struct client_state *csp, case SOCKS_5: socks_type = "socks5"; break; + case SOCKS_5T: + socks_type = "socks5t"; + break; default: log_error(LOG_LEVEL_FATAL, "Unknown socks type: %d.", fwd->type); } diff --git a/filters.c b/filters.c index a7f622a9..60d420fa 100644 --- a/filters.c +++ b/filters.c @@ -1,4 +1,4 @@ -const char filters_rcs[] = "$Id: filters.c,v 1.174 2012/10/21 12:35:15 fabiankeil Exp $"; +const char filters_rcs[] = "$Id: filters.c,v 1.175 2012/10/21 12:58:03 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/filters.c,v $ @@ -2158,6 +2158,11 @@ const static struct forward_spec *get_forward_override_settings(struct client_st fwd->type = SOCKS_5; socks_proxy = vec[1]; } + else if (!strcasecmp(vec[0], "forward-socks5t")) + { + fwd->type = SOCKS_5T; + socks_proxy = vec[1]; + } if (NULL != socks_proxy) { diff --git a/gateway.c b/gateway.c index ae706cfa..81b9b81a 100644 --- a/gateway.c +++ b/gateway.c @@ -1,4 +1,4 @@ -const char gateway_rcs[] = "$Id: gateway.c,v 1.91 2012/10/21 12:56:38 fabiankeil Exp $"; +const char gateway_rcs[] = "$Id: gateway.c,v 1.92 2012/10/23 10:16:52 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/gateway.c,v $ @@ -66,6 +66,8 @@ const char gateway_rcs[] = "$Id: gateway.c,v 1.91 2012/10/21 12:56:38 fabiankeil #include "jbsockets.h" #include "gateway.h" #include "miscutil.h" +#include "list.h" + #ifdef FEATURE_CONNECTION_KEEP_ALIVE #ifdef HAVE_POLL #ifdef __GLIBC__ @@ -639,6 +641,7 @@ jb_socket forwarded_connect(const struct forward_spec * fwd, sfd = socks4_connect(fwd, dest_host, dest_port, csp); break; case SOCKS_5: + case SOCKS_5T: sfd = socks5_connect(fwd, dest_host, dest_port, csp); break; default: @@ -964,7 +967,7 @@ static jb_socket socks5_connect(const struct forward_spec *fwd, err = 1; } - if (fwd->type != SOCKS_5) + if ((fwd->type != SOCKS_5) && (fwd->type != SOCKS_5T)) { /* Should never get here */ log_error(LOG_LEVEL_FATAL, @@ -1078,6 +1081,43 @@ static jb_socket socks5_connect(const struct forward_spec *fwd, return(JB_INVALID_SOCKET); } + /* + * Optimistically send the request headers with the initial + * request if the user requested use of Tor extensions, the + * CONNECT method isn't being used (in which case the client + * doesn't send data until it gets our 200 response) and the + * client request has been already read completely. + * + * Not optimistically sending the request body (if there is one) + * makes it easier to implement, but isn't an actual requirement. + */ + if ((fwd->type == SOCKS_5T) && (csp->http->ssl == 0) + && (csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ)) + { + char *client_headers = list_to_text(csp->headers); + size_t header_length; + + if (client_headers == NULL) + { + log_error(LOG_LEVEL_FATAL, "Out of memory rebuilding client headers"); + } + list_remove_all(csp->headers); + header_length= strlen(client_headers); + + log_error(LOG_LEVEL_CONNECT, + "Optimistically sending %d bytes of client headers intended for %s", + header_length, csp->http->hostport); + + if (write_socket(sfd, client_headers, header_length)) + { + log_error(LOG_LEVEL_CONNECT, + "optimistically writing header to: %s failed: %E", csp->http->hostport); + freez(client_headers); + return(JB_INVALID_SOCKET); + } + freez(client_headers); + } + server_size = read_socket(sfd, sbuf, sizeof(sbuf)); if (server_size != sizeof(sbuf)) { diff --git a/jcc.c b/jcc.c index 6967ad8d..33e406e8 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.418 2012/12/07 12:43:05 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.419 2012/12/07 12:43:55 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -1920,7 +1920,12 @@ static void chat(struct client_state *csp) csp->server_connection.requests_sent_total++; - if (fwd->forward_host || (http->ssl == 0)) + if ((fwd->type == SOCKS_5T) && (NULL == csp->headers->first)) + { + /* Client headers have been sent optimistically */ + assert(csp->headers->last == NULL); + } + else if (fwd->forward_host || (http->ssl == 0)) { int write_failure; hdr = list_to_text(csp->headers); @@ -1978,6 +1983,7 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); + /* XXX: should the time start earlier for optimistically sent data? */ csp->server_connection.request_sent = time(NULL); maxfd = (csp->cfd > csp->server_connection.sfd) ? diff --git a/loadcfg.c b/loadcfg.c index f3bec214..a5bc55d5 100644 --- a/loadcfg.c +++ b/loadcfg.c @@ -1,4 +1,4 @@ -const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.133 2012/10/21 12:32:21 fabiankeil Exp $"; +const char loadcfg_rcs[] = "$Id: loadcfg.c,v 1.134 2012/10/21 12:53:33 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/loadcfg.c,v $ @@ -140,6 +140,7 @@ static struct file_list *current_configfile = NULL; #define hash_forward_socks4 3963965521U /* "forward-socks4" */ #define hash_forward_socks4a 2639958518U /* "forward-socks4a" */ #define hash_forward_socks5 3963965522U /* "forward-socks5" */ +#define hash_forward_socks5t 2639958542U /* "forward-socks5t" */ #define hash_forwarded_connect_retries 101465292U /* "forwarded-connect-retries" */ #define hash_handle_as_empty_returns_ok 1444873247U /* "handle-as-empty-doc-returns-ok" */ #define hash_hostname 10308071U /* "hostname" */ @@ -1013,6 +1014,7 @@ struct configuration_spec * load_config(void) * *************************************************************************/ case hash_forward_socks4a: case hash_forward_socks5: + case hash_forward_socks5t: strlcpy(tmp, arg, sizeof(tmp)); vec_count = ssplit(tmp, " \t", vec, SZ(vec)); @@ -1039,10 +1041,15 @@ struct configuration_spec * load_config(void) { cur_fwd->type = SOCKS_4A; } - else + else if (directive_hash == hash_forward_socks5) { cur_fwd->type = SOCKS_5; } + else + { + assert(directive_hash == hash_forward_socks5t); + cur_fwd->type = SOCKS_5T; + } /* Save the URL pattern */ if (create_url_spec(cur_fwd->url, vec[0])) diff --git a/project.h b/project.h index eba76a6f..b880241c 100644 --- a/project.h +++ b/project.h @@ -1,7 +1,7 @@ #ifndef PROJECT_H_INCLUDED #define PROJECT_H_INCLUDED /** Version string. */ -#define PROJECT_H_VERSION "$Id: project.h,v 1.193 2012/11/24 13:55:51 fabiankeil Exp $" +#define PROJECT_H_VERSION "$Id: project.h,v 1.194 2012/12/07 12:43:55 fabiankeil Exp $" /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/project.h,v $ @@ -645,6 +645,8 @@ enum forwarder_type { SOCKS_4A = 41, /**< SOCKS 5 with hostnames, DNS resolution is done by the SOCKS server */ SOCKS_5 = 50, + /**< Like SOCKS5, but uses non-standard Tor extensions (currently only optimistic data) */ + SOCKS_5T, }; /* -- 2.39.2