Proxytunnel 1.9.0 enhanced
Post
Cancel

Proxytunnel 1.9.0 enhanced

I recently discovered Proxytunnel, a great tool to build tunnels through HTTP and/or HTTPS proxies, which is even able to chain two proxies. It can seem a bit overkill at first sight, but it’s really useful in some configurations. This tool is well documented on its homepage and a very nice use case is detailed SSH HTTP Tunneling.

I made a patch (named -sl1) against the latest version (1.9.0), which brings the following changes:

  • A command-line option to use HTTP/1.1 CONNECT instead of HTTP/1.0. This also adds the required Host: header. This is needed for some corporate proxies that refuse to serve HTTP/1.0 CONNECT requests and is the primary reason I made this patch.
  • Under Cygwin, the “verbose” switch now outputs to stderr, instead of trying to use syslog, which doesn’t seem to work or make sense under Cygwin
  • Compilation with FORTIFY_SOURCE, which secures some potentially dangerous libc functions, for the gcc’s that support it.
  • Cygwin autodetection at compile time, manually editing the Makefile is no longer needed.

Edit: Released version -sl2, now HTTP/1.0 vs HTTP/1.1 is properly enforced in all cases (one or two proxies, with or without SSL).

Share and enjoy. :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
diff -ruN proxytunnel-1.9.0/cmdline.c proxytunnel-1.9.0-sl2/cmdline.c
--- proxytunnel-1.9.0/cmdline.c 2008-03-03 23:06:28.000000000 +0100
+++ proxytunnel-1.9.0-sl2/cmdline.c     2009-09-23 10:49:42.000000000 +0200
@@ -75,6 +75,7 @@
 #ifdef SETPROCTITLE
 " -x, --proctitle=STRING    Use a different process title\n"
 #endif
+" -1, --http11              Use HTTP/1.1 instead of 1.0, and add 'Host:' header\n"
 "\n"
 "Miscellaneous options:\n"
 " -v, --verbose             Turn on verbosity\n"
@@ -132,6 +133,7 @@
        args_info->encryptproxy_given = 0;
        args_info->encryptremproxy_given = 0;
        args_info->proctitle_given = 0;
+       args_info->http_minorversion = 0;
 /* No... we can't make this a function... -- Maniac */
 #define clear_args() \
@@ -157,6 +159,7 @@
        args_info->encryptproxy_flag = 0; \
        args_info->encryptremproxy_flag = 0; \
        args_info->proctitle_arg = NULL; \
+       args_info->http_minorversion = 0; \
 } 
        clear_args();
@@ -198,12 +201,13 @@
                        { "encrypt",            0, NULL, 'e' },
                        { "encrypt-proxy",      0, NULL, 'E' },
                        { "encrypt-remproxy",0,NULL, 'X' },
+                       { "http11",         0, NULL, '1' },
                        { NULL,                         0, NULL, 0 }
                };
-               c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq", long_options, &option_index);
+               c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq1", long_options, &option_index);
 #else
-               c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq" );
+               c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXq1" );
 #endif
                if (c == -1)
@@ -403,6 +407,10 @@
                                args_info->quiet_flag = !(args_info->quiet_flag);
                                break;
+                       case '1':       /* use HTTP/1.1 instead of HTTP/1.0 */
+                               args_info->http_minorversion = 1;
+                               break;
+
                        case 0: /* Long option with no short option */
                        case '?':       /* Invalid option.  */
@@ -418,7 +426,7 @@
        } /* while */
 /* For Windows quiet is the default output. -- Dag */
-#ifdef CYGWIN
+#ifdef __CYGWIN__
        if (! args_info->verbose_flag ) {
                args_info->quiet_flag = 1;
        }
diff -ruN proxytunnel-1.9.0/cmdline.h proxytunnel-1.9.0-sl2/cmdline.h
--- proxytunnel-1.9.0/cmdline.h 2008-02-22 22:25:02.000000000 +0100
+++ proxytunnel-1.9.0-sl2/cmdline.h     2009-09-23 09:39:00.000000000 +0200
@@ -71,6 +71,7 @@
        int encryptproxy_given; /* Whether encrypt was given */
        int encryptremproxy_given;   /* Whether encrypt was given */
        int proctitle_given;    /* Whether to override process title */
+       int http_minorversion;  /* Whether to use HTTP/1.1 or 1.0 for CONNECT */
 };
 int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *args_info );
diff -ruN proxytunnel-1.9.0/config.h proxytunnel-1.9.0-sl2/config.h
--- proxytunnel-1.9.0/config.h  2008-03-03 22:50:32.000000000 +0100
+++ proxytunnel-1.9.0-sl2/config.h      2009-09-23 09:39:00.000000000 +0200
@@ -17,7 +17,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
-#define VERSION "1.9.0"
+#define VERSION "1.9.0-sl1"
 #define PACKAGE "proxytunnel"
 #define PURPOSE "Build generic tunnels through HTTPS proxies"
 #define AUTHORS "Jos Visser (Muppet) <josv@osp.nl>, Mark Janssen (Maniac) <maniac@maniac.nl>"
diff -ruN proxytunnel-1.9.0/http.c proxytunnel-1.9.0-sl2/http.c
--- proxytunnel-1.9.0/http.c    2008-02-27 00:31:01.000000000 +0100
+++ proxytunnel-1.9.0-sl2/http.c        2009-09-23 12:11:12.000000000 +0200
@@ -97,6 +97,19 @@
 }
 /*
+ * Return the "host" portion of a "host:port" string
+ * Don't forget to free() the returned string!
+ */
+
+char *get_host_only(const char *hostport) {
+       if( !hostport ) { return NULL; }
+       char *hostonly = strdup( hostport );
+       char *sep = strstr( hostonly, ":" );
+       if( sep ) { *sep = 0; } // end the string before the ':'
+       return hostonly;
+}
+
+/*
  * Execute the basic proxy protocol of CONNECT and response, until the
  * last line of the response has been read. The tunnel is then open.
  */
@@ -105,13 +118,28 @@
        if (args_info.remproxy_given ) {
                if( args_info.verbose_flag )
                        message( "\nTunneling to %s (remote proxy)\n", args_info.remproxy_arg );
-               sprintf( buf, "CONNECT %s HTTP/1.0\r\n", args_info.remproxy_arg );
+               sprintf( buf, "CONNECT %s HTTP/1.%d\r\n", args_info.remproxy_arg, args_info.http_minorversion );
+               if( args_info.http_minorversion == 1 ) {
+                       char *hostonly = get_host_only( args_info.remproxy_arg );
+                       if( hostonly ) {
+                               strzcat( buf, "Host: %s\r\n", hostonly );
+                               free( hostonly );
+                       }
+               }
+
        } else {
                if( args_info.verbose_flag )
                        message( "\nTunneling to %s (destination)\n", args_info.dest_arg );
-               sprintf( buf, "CONNECT %s HTTP/1.0\r\n", args_info.dest_arg );
+               sprintf( buf, "CONNECT %s HTTP/1.%d\r\n", args_info.dest_arg, args_info.http_minorversion );
+               if( args_info.http_minorversion == 1 ) {
+                       char *hostonly = get_host_only( args_info.dest_arg );
+                       if( hostonly ) {
+                               strzcat( buf, "Host: %s\r\n", hostonly );
+                               free( hostonly );
+                       }
+               }
        }
-
+
        if ( args_info.user_given && args_info.pass_given ) {
                /* Create connect string including the authorization part */
                if (args_info.ntlm_flag) {
@@ -163,7 +191,15 @@
                if( args_info.verbose_flag )
                        message( "\nTunneling to %s (destination)\n", args_info.dest_arg );
-               sprintf( buf, "CONNECT %s HTTP/1.0\r\n", args_info.dest_arg);
+               sprintf( buf, "CONNECT %s HTTP/1.%d\r\n", args_info.dest_arg, args_info.http_minorversion );
+
+               if( args_info.http_minorversion == 1 ) {
+                       char *hostonly = get_host_only( args_info.dest_arg );
+                       if( hostonly ) {
+                               strzcat( buf, "Host: %s\r\n", hostonly );
+                               free( hostonly );
+                       }
+               }
                if ( args_info.remuser_given && args_info.rempass_given )
                        strzcat( buf, "Proxy-Authorization: Basic %s\r\n", basicauth(args_info.remuser_arg, args_info.rempass_arg ));
diff -ruN proxytunnel-1.9.0/Makefile proxytunnel-1.9.0-sl2/Makefile
--- proxytunnel-1.9.0/Makefile  2008-02-27 00:31:08.000000000 +0100
+++ proxytunnel-1.9.0-sl2/Makefile      2009-09-23 10:50:28.000000000 +0200
@@ -3,7 +3,7 @@
 # Please uncomment the appropriate settings
 CC ?= cc
-CFLAGS ?= -Wall -O2 -ggdb
+CFLAGS ?= -Wall -O2 -ggdb -D_FORTIFY_SOURCE=2
 OPTFLAGS = -DREV=$(shell ./getrev.sh)
@@ -28,6 +28,7 @@
 # DARWIN
 #OPTFLAGS += -DDARWIN
+# No longer needed, Cygwin is now autodetected
 # CYGWIN
 #OPTFLAGS += -DCYGWIN
diff -ruN proxytunnel-1.9.0/messages.c proxytunnel-1.9.0-sl2/messages.c
--- proxytunnel-1.9.0/messages.c        2008-02-22 22:20:41.000000000 +0100
+++ proxytunnel-1.9.0-sl2/messages.c    2009-09-23 10:49:45.000000000 +0200
@@ -35,9 +35,11 @@
        vsnprintf( (char *)buf, sizeof( buf ), s, ap );
        va_end( ap );
+#ifndef __CYGWIN__
        if ( i_am_daemon )
                syslog( LOG_NOTICE, "%s", buf );
        else
+#endif
                fputs( buf, stderr );
 }
diff -ruN proxytunnel-1.9.0/proxytunnel.c proxytunnel-1.9.0-sl2/proxytunnel.c
--- proxytunnel-1.9.0/proxytunnel.c     2008-02-22 22:27:57.000000000 +0100
+++ proxytunnel-1.9.0-sl2/proxytunnel.c 2009-09-23 10:50:05.000000000 +0200
@@ -137,7 +137,7 @@
 /* Leave a goodbye message */
 void closeall() {
-#ifndef CYGWIN
+#ifndef __CYGWIN__
        closelog();
 #endif
@@ -210,7 +210,7 @@
  * Also so we can put logging there, since there's no syslog on cygwin (AFAIK)
  *     -- Maniac
  */
-#ifndef CYGWIN
+#ifndef __CYGWIN__
 /*
        if ( ( pid = fork( ) ) < 0 ) {
                my_perror( "Cannot fork into the background" );
@@ -223,7 +223,7 @@
        openlog( program_name, LOG_CONS|LOG_PID,LOG_DAEMON );
        i_am_daemon = 1;
-#endif /* CYGWIN */
+#endif /* __CYGWIN__ */
        atexit( closeall );
        listen( listen_sd, 8 );
This post is licensed under CC BY 4.0 by the author.