cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: http proxy tunnel ... through a proxy

From: Prashant Ramanathan <prashant_at_netenrich.com>
Date: Thu, 22 Jun 2006 19:02:18 -0700

Hi Daniel,

I'm going to try again...

Yes, we go through two proxies and do two CONNECTs. The first proxy is a
normal proxy connection; the second is a proxy tunnel connection.

There are two new options that can be set by curl_easy_setopt():
1. CURLOPT_CONNECTTUNNEL (used to specify a proxy tunnel connection, but
can also be used in conjunction with CURLOPT_PROXY, in case we need to
go through another proxy server)
2. CURLOPT_FORCE_REUSE (used so that the connection made to the proxy
tunnel stays open)

There is one new option that is set by curl_easy_getinfo():
1. CURLINFO_CONNECTINDEX (used to reference the new connection, so that
we can directly access the socket connection)

Below are the diffs made on curl-7.15.4.

prashant.

=================================================
=================================================
cvs diff -r 1.1 -r 1.2 -u -- getinfo.c (in directory
C:\Source\netenrich\ra\curl-7.15.4\lib\)
Index: getinfo.c
===================================================================
RCS file: /cvs/netenrich/ra/curl-7.15.4/lib/getinfo.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- getinfo.c 13 Jun 2006 18:53:49 -0000 1.1
+++ getinfo.c 13 Jun 2006 21:28:03 -0000 1.2
@@ -18,7 +18,7 @@
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
OF ANY
  * KIND, either express or implied.
  *
- * $Id: getinfo.c,v 1.1 2006/06/13 18:53:49 ratna Exp $
+ * $Id: getinfo.c,v 1.2 2006/06/13 21:28:03 ratna Exp $
  
***************************************************************************/
 
 #include "setup.h"
@@ -197,6 +197,10 @@
        Callers must never free it themselves. */
     *param_charp = data->state.most_recent_ftp_entrypath;
     break;
+ /* HTTP Tunneling - */
+ case CURLINFO_CONNECTINDEX:
+ *param_longp = data->info.connectindex;
+ break;
   case CURLINFO_LASTSOCKET:
     if((data->state.lastconnect != -1) &&
        (data->state.connects[data->state.lastconnect] != NULL)) {

=================================================
=================================================

cvs diff -r 1.1 -r 1.2 -u -- http.c (in directory
C:\Source\netenrich\ra\curl-7.15.4\lib\)
Index: http.c
===================================================================
RCS file: /cvs/netenrich/ra/curl-7.15.4/lib/http.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- http.c 13 Jun 2006 18:53:49 -0000 1.1
+++ http.c 13 Jun 2006 21:28:03 -0000 1.2
@@ -18,7 +18,7 @@
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
OF ANY
  * KIND, either express or implied.
  *
- * $Id: http.c,v 1.1 2006/06/13 18:53:49 ratna Exp $
+ * $Id: http.c,v 1.2 2006/06/13 21:28:03 ratna Exp $
  
***************************************************************************/
 
 #include "setup.h"
@@ -1616,6 +1616,9 @@
   /* Now set the 'request' pointer to the proper request string */
   if(data->set.customrequest)
     request = data->set.customrequest;
+ /* HTTP Tunneling - */
+ else if(data->set.tunneldest)
+ request = (char *)"CONNECT";
   else {
     if(conn->bits.no_body)
       request = (char *)"HEAD";
@@ -1938,6 +1941,46 @@
       return CURLE_OUT_OF_MEMORY;
 
     /* add the main request stuff */
+ /* HTTP Tunneling - */
+ if (data->set.tunneldest) {
+ result =
+ add_bufferf(req_buffer,
+ "%s " /* CONNECT */
+ "%s HTTP/%s\r\n" /* tunnel destination + HTTP version */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* host */
+ "%s" /* pragma */
+ "%s" /* accept */
+ "%s" /* accept-encoding */
+ "%s" /* referer */
+ "%s" /* Proxy-Connection */
+ "%s",/* transfer-encoding */
+
+ request,
+ data->set.tunneldest,
+ httpstring,
+ conn->allocptr.proxyuserpwd?
+ conn->allocptr.proxyuserpwd:"",
+ conn->allocptr.userpwd?conn->allocptr.userpwd:"",
+ (conn->bits.use_range && conn->allocptr.rangeline)?
+ conn->allocptr.rangeline:"",
+ (data->set.useragent && *data->set.useragent &&
conn->allocptr.uagent)?
+ conn->allocptr.uagent:"",
+ (conn->allocptr.host?conn->allocptr.host:""), /* Host:
host */
+ http->p_pragma?http->p_pragma:"",
+ http->p_accept?http->p_accept:"",
+ (data->set.encoding && *data->set.encoding &&
conn->allocptr.accept_encoding)?
+ conn->allocptr.accept_encoding:"",
+ (data->change.referer &&
conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> */,
+ (conn->bits.httpproxy && !conn->bits.tunnel_proxy)?
+ "Proxy-Connection: Keep-Alive\r\n":"",
+ te
+ );
+ }
+ else {
     result =
       add_bufferf(req_buffer,
                   "%s " /* GET/HEAD/POST/PUT */
@@ -1974,7 +2017,7 @@
                   "Proxy-Connection: Keep-Alive\r\n":"",
                 te
                 );
-
+ }
     if(result)
       return result;
 

=================================================
=================================================

cvs diff -r 1.1 -r 1.2 -u -- transfer.c (in directory
C:\Source\netenrich\ra\curl-7.15.4\lib\)
Index: transfer.c
===================================================================
RCS file: /cvs/netenrich/ra/curl-7.15.4/lib/transfer.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- transfer.c 13 Jun 2006 18:53:49 -0000 1.1
+++ transfer.c 13 Jun 2006 21:28:03 -0000 1.2
@@ -18,7 +18,7 @@
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
OF ANY
  * KIND, either express or implied.
  *
- * $Id: transfer.c,v 1.1 2006/06/13 18:53:49 ratna Exp $
+ * $Id: transfer.c,v 1.2 2006/06/13 21:28:03 ratna Exp $
  
***************************************************************************/
 
 #include "setup.h"
@@ -2196,7 +2196,9 @@
 
   do {
     res = Curl_connect_host(data, &conn); /* primary connection */
-
+ /* HTTP Tunneling - Remember the current connectindex */
+ if(res == CURLE_OK)
+ data->info.connectindex = conn->connectindex;
     if(res == CURLE_OK) {
       if (data->set.source_url) /* 3rd party transfer */
         res = Curl_second_connect(conn);

=================================================
=================================================

cvs diff -r 1.1 -r 1.2 -u -- url.c (in directory
C:\Source\netenrich\ra\curl-7.15.4\lib\)
Index: url.c
===================================================================
RCS file: /cvs/netenrich/ra/curl-7.15.4/lib/url.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- url.c 13 Jun 2006 18:53:49 -0000 1.1
+++ url.c 13 Jun 2006 21:28:03 -0000 1.2
@@ -18,7 +18,7 @@
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
OF ANY
  * KIND, either express or implied.
  *
- * $Id: url.c,v 1.1 2006/06/13 18:53:49 ratna Exp $
+ * $Id: url.c,v 1.2 2006/06/13 21:28:03 ratna Exp $
  
***************************************************************************/
 
 /* -- WIN32 approved -- */
@@ -498,6 +498,14 @@
      */
     data->set.reuse_forbid = va_arg(param, long)?TRUE:FALSE;
     break;
+ /* HTTP Tunneling - */
+ case CURLOPT_FORCE_REUSE:
+ /*
+ * When this transfer is done, the connection is forced to remain open
+ * (especially useful for HTTP CONNECT proxy tunnels)
+ */
+ data->set.reuse_force = va_arg(param, long)?TRUE:FALSE;
+ break;
   case CURLOPT_FRESH_CONNECT:
     /*
      * This transfer shall not use a previously cached connection but
@@ -898,6 +906,18 @@
        here, we continue as if we were using the already set type
        and this just changes the actual request keyword */
     break;
+ /* HTTP Tunneling - */
+ case CURLOPT_CONNECTTUNNEL:
+ /*
+ * Specifies a tcp tunnel using the CONNECT command. Sets the
+ * ipaddr:portnumber to tunnel to.
+ */
+ data->set.tunneldest = va_arg(param, char *);
+ /* we don't set
+ data->set.httpreq = HTTPREQ_CONNECTTUNNEL;
+ here, we continue as if we were using the already set type
+ and this just changes the actual request keyword */
+ break;
 
   case CURLOPT_PROXYPORT:
     /*
@@ -4068,7 +4088,8 @@
      if conn->bits.close is TRUE, it means that the connection should be
      closed in spite of all our efforts to be nice, due to protocol
      restrictions in our or the server's end */
- if(data->set.reuse_forbid || conn->bits.close) {
+ /* HTTP Tunneling - */
+ if(( data->set.reuse_forbid || conn->bits.close ) &&
(!(data->set.reuse_force))) {
     CURLcode res2;
     res2 = Curl_disconnect(conn); /* close the connection */
 
=================================================
=================================================

cvs diff -r 1.1 -r 1.2 -u -- urldata.h (in directory
C:\Source\netenrich\ra\curl-7.15.4\lib\)
Index: urldata.h
===================================================================
RCS file: /cvs/netenrich/ra/curl-7.15.4/lib/urldata.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- urldata.h 13 Jun 2006 18:53:49 -0000 1.1
+++ urldata.h 13 Jun 2006 21:28:03 -0000 1.2
@@ -20,7 +20,7 @@
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
OF ANY
  * KIND, either express or implied.
  *
- * $Id: urldata.h,v 1.1 2006/06/13 18:53:49 ratna Exp $
+ * $Id: urldata.h,v 1.2 2006/06/13 21:28:03 ratna Exp $
  
***************************************************************************/
 
 /* This file is for lib internal stuff */
@@ -793,6 +793,8 @@
   long numconnects; /* how many new connection did libcurl created */
 
   char *contenttype; /* the content type of the object */
+ /* HTTP Tunneling - */
+ long connectindex; /* the connectindex of the most recent connection */
 };
 
 
@@ -1066,6 +1068,8 @@
   curl_closepolicy closepolicy; /* connection cache close concept */
   Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
   char *customrequest; /* HTTP/FTP request to use */
+ /* HTTP Tunneling - */
+ char *tunneldest; /* destination ipaddr:port for tunnel, if using
HTTP CONNECT tunneling */
   long httpversion; /* when non-zero, a specific HTTP version requested to
                        be used in the library's request(s) */
   char *auth_host; /* if set, this is the allocated string to the host name
@@ -1128,6 +1132,8 @@
   bool verbose;
   bool krb4; /* kerberos4 connection requested */
   bool reuse_forbid; /* forbidden to be reused, close after use */
+ /* HTTP Tunneling - */
+ bool reuse_force; /* force to keep connection alive */
   bool reuse_fresh; /* do not re-use an existing connection */
   bool expect100header; /* TRUE if we added Expect: 100-continue */
   bool ftp_use_epsv; /* if EPSV is to be attempted or not */

=================================================
=================================================

cvs diff -r 1.1 -r 1.2 -u -- curl.h (in directory
C:\Source\netenrich\ra\curl-7.15.4\include\curl\)
Index: curl.h
===================================================================
RCS file: /cvs/netenrich/ra/curl-7.15.4/include/curl/curl.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- curl.h 13 Jun 2006 18:53:48 -0000 1.1
+++ curl.h 13 Jun 2006 21:28:03 -0000 1.2
@@ -20,7 +20,7 @@
  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
OF ANY
  * KIND, either express or implied.
  *
- * $Id: curl.h,v 1.1 2006/06/13 18:53:48 ratna Exp $
+ * $Id: curl.h,v 1.2 2006/06/13 21:28:03 ratna Exp $
  
***************************************************************************/
 
 /* If you have problems, all libcurl docs and details are found here:
@@ -963,6 +963,18 @@
      Note that this is used only for SSL certificate processing */
   CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
 
+ /* Set to explicitly force the upcoming transfer's connection to be
kept open
+ when done. Useful for HTTP CONNECT proxy tunnel connections
+ */
+ CINIT(FORCE_REUSE, LONG, 142),
+
+ /* Set to specify an http tunnel connection. The specified string
contains the
+ ip address and port (ie. "127.0.0.1:9900"). If NULL, then this
method is not
+ used. The result http message, for example, contains the header
+ "CONNECT 127.0.0.1:9900 HTTP/1.1"
+ */
+ CINIT(CONNECTTUNNEL, OBJECTPOINT, 143),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -1335,9 +1347,11 @@
   CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
   CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
   CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
+ CURLINFO_CONNECTINDEX = CURLINFO_LONG + 31,
+
   /* Fill in new entries below here! */
 
- CURLINFO_LASTONE = 30
+ CURLINFO_LASTONE = 31
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously
known as
Received on 2006-06-23