From bf693b0afc8672265dd69fe6a6202a471757b20d Mon Sep 17 00:00:00 2001 From: Mark Janssen Date: Mon, 6 Feb 2006 14:40:42 +0000 Subject: [PATCH] Very cool... we now do SSL encryption in the connection. This will fool protocol-inspecting proxies (requires stunnel or other ssl wrapper on the server side) git-svn-id: https://proxytunnel.svn.sourceforge.net/svnroot/proxytunnel/trunk/proxytunnel@94 bc163920-b10d-0410-b2c5-a5491ca2ceef --- CHANGES | 2 + CREDITS | 1 + Makefile | 2 +- README | 7 +++ cmdline.c | 17 ++++++- cmdline.h | 2 + io.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++---- proxytunnel.c | 28 +++++++++++ proxytunnel.h | 13 +++++ 9 files changed, 191 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index d712be4..345f4cf 100755 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,8 @@ Changes to proxytunnel version 1.6.0 -- Mon Feb 6 17:00:00 CET 2006 - Makefile vars now no longer override environment versions - Added proxy-bouncing support, courtesy of Dag Wieers, authentication only works on the FIRST proxy, not on a second proxy !! +- Added SSL encryption to the data-layer to fool proxies that do deep- + packet inspection, by: Alex Peuchert proxytunnel@peuchert.de Changes to proxytunnel version 1.5.2 -- Fri Dec 16 09:27:11 CET 2005 diff --git a/CREDITS b/CREDITS index f5e5c20..aa7d0ba 100644 --- a/CREDITS +++ b/CREDITS @@ -17,6 +17,7 @@ people. Roberto Veldhoven at atosorigin.com - Tandem compile fix Stephane Engel at macchiati.org - Fix for broken proxy Mike Frysinger - Makefile fix, 64bit fix + Alex Peuchert proxytunnel@peuchert.de - SSL/Encrypt support Furthermore we would like to thank the wonderful people at SourceForge diff --git a/Makefile b/Makefile index 35ec0da..623caaa 100755 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Please uncomment the appropriate settings CC ?= gcc -CFLAGS += -Wall -DHAVE_GETOPT_LONG +CFLAGS += -Wall -DHAVE_GETOPT_LONG -DUSE_SSL LDFLAGS += -lssl BINDIR = /usr/local/bin INSTALLPATH = $(DESTDIR)/$(BINDIR) diff --git a/README b/README index 0617ac1..e0b0e60 100755 --- a/README +++ b/README @@ -34,6 +34,7 @@ Usage: Proxytunnel [OPTIONS]... -V --version Print version and exit -i --inetd Run from inetd (default=off) -a INT --standalone=INT Run as standalone daemon on specified port + -e --encrypt encrypt the communication using SSL -p STRING --proxy=STRING Proxy host:port combination to connect to -d STRING --dest=STRING Destination host:port to built the tunnel to @@ -104,6 +105,12 @@ requested destination. Note that authentication doesn't (yet) work on this remote proxy. For more information regarding this feature, check out http://dag.wieers.com/howto/ssh-http-tunneling/ +If your proxy is more advanced, and does protocol inspection it will +detect that your connection is not a real HTTPS/SSL connection. You +can enable SSL encryption (using -e), which will work around this +problem, however, you need to setup stunnel4 on the other side, or +connect to a process that understands SSL itself. + When all this is in place, execute an "ssh foobar" and you're in business! Share and Enjoy! diff --git a/cmdline.c b/cmdline.c index 842c825..2db6bad 100755 --- a/cmdline.c +++ b/cmdline.c @@ -57,6 +57,9 @@ cmdline_parser_print_help (void) #if 0 " -f --nobackground Don't for to background in standalone mode (FIXME)\n" #endif +#ifdef USE_SSL +" -e --encrypt encrypt the communication using SSL\n" +#endif " -p STRING --proxy=STRING Proxy host:port combination to connect to\n" " -d STRING --dest=STRING Destination host:port to built the tunnel to\n" "\nParameters for proxy-authentication (not needed for plain proxies):\n" @@ -125,6 +128,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar args_info->quiet_given = 0; args_info->header_given = 0; args_info->domain_given = 0; + args_info->encrypt_given = 0; /* No... we can't make this a function... -- Maniac */ #define clear_args() \ @@ -142,6 +146,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar args_info->inetd_flag = 0; \ args_info->quiet_flag = 0; \ args_info->standalone_arg = 0; \ + args_info->encrypt_flag = 0; \ } clear_args(); @@ -179,12 +184,13 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar { "inetd", 0, NULL, 'i' }, { "standalone", 1, NULL, 'a' }, { "quiet", 0, NULL, 'q' }, + { "encrypt", 0, NULL, 'e' }, { NULL, 0, NULL, 0 } }; - c = getopt_long (argc, argv, "hVia:u:s:t:U:S:p:r:g:G:d:D:H:nvNq", long_options, &option_index); + c = getopt_long (argc, argv, "hVia:u:s:t:U:S:p:r:d:H:nvNeq", long_options, &option_index); #else - c = getopt( argc, argv, "hVia:u:s:t:U:S:p:r:g:G:d:D:H:nvNq" ); + c = getopt( argc, argv, "hVia:u:s:t:U:S:p:r:d:H:nvNeq" ); #endif if (c == -1) break; /* Exit from `while (1)' loop. */ @@ -196,6 +202,13 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar cmdline_parser_print_help (); exit (0); +#ifdef USE_SSL + case 'e': /* Turn on SSL encryption */ + args_info->encrypt_flag = !(args_info->encrypt_flag); + fprintf (stderr, "SSL enabled\n"); + break; +#endif + case 'i': /* Run from inetd. */ if ( args_info->standalone_arg > 0 ) { diff --git a/cmdline.h b/cmdline.h index 430e309..f531412 100755 --- a/cmdline.h +++ b/cmdline.h @@ -38,6 +38,7 @@ struct gengetopt_args_info { int inetd_flag; /* Turn on inetd (default=off). */ int quiet_flag; /* Turn on quiet mode (default=off). */ int standalone_arg; /* Turn on stdalone (-a) on port */ + int encrypt_flag; /* Turn on SSL encryption (default=off). */ int help_given; /* Whether help was given. */ int version_given; /* Whether version was given. */ @@ -54,6 +55,7 @@ struct gengetopt_args_info { int inetd_given; /* Whether inetd was given. */ int quiet_given; /* Whether quiet mode was given. */ int header_given; /* Whenther extra headers are given */ + int encrypt_given; /* Whether encrypt was given */ } ; int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *args_info ); diff --git a/io.c b/io.c index 94dec78..b3db3ac 100644 --- a/io.c +++ b/io.c @@ -29,6 +29,14 @@ #include "proxytunnel.h" #include "io.h" +#ifdef USE_SSL /* Override copy functions */ +#define COPY_TO(fd) copy_to_SSL(fd, ssl) +#define COPY_FROM(fd) copy_from_SSL(ssl, fd) +#else +#define COPY_TO(fd) copy(fd, sd) +#define COPY_FROM(fd) copy(sd, fd) +#endif + /* * Read one line of data from the tunnel. Line is terminated by a * newline character. Result is stored in buf. @@ -100,6 +108,76 @@ int copy(int from, int to) return 0; } +int copy_to_SSL(int from, SSL* to) +{ + int n; + + /* + * Read a buffer from the source socket + */ + if ( ( n = read( from, buf, SIZE ) ) < 0 ) + { + my_perror( "Socket read error" ); + exit( 1 ); + } + + /* + * If we have read 0 bytes, there is an EOF on src + */ + if( n==0 ) + return 1; + + /* + * Write the buffer to the destination socket + */ + if ( SSL_write( to, buf, n ) != n ) + { + my_perror( "Socket write error" ); + exit( 1 ); + } + + /* + * We're not yet at EOF + */ + return 0; +} + +int copy_from_SSL(SSL* from, int to) +{ + int n; + + /* + * Read a buffer from the source socket + */ + if ( ( n = SSL_read( from, buf, SIZE ) ) < 0 ) + { + my_perror( "Socket read error" ); + exit( 1 ); + } + + /* + * If we have read 0 bytes, there is an EOF on src + */ + if( n==0 ) + return 1; + + /* + * Write the buffer to the destination socket + */ + if ( write( to, buf, n ) != n ) + { + my_perror( "Socket write error" ); + exit( 1 ); + } + + /* + * We're not yet at EOF + */ + return 0; +} + + + /* * Move into a loop of copying data to and from the tunnel. * stdin (fd 0) and stdout (fd 1) are the file descriptors @@ -112,12 +190,22 @@ void cpio() fd_set writefds; fd_set exceptfds; int max_fd; + int out_fd; + +#ifdef USE_SSL + if( args_info.encrypt_flag ) + out_fd = SSL_get_fd(ssl); + else + out_fd = sd; +#else + out_fd = sd; +#endif /* * Find the biggest file descriptor for select() */ max_fd = MAX( read_fd,write_fd ); - max_fd = MAX( max_fd,sd ); + max_fd = MAX( max_fd, out_fd ); /* @@ -144,16 +232,16 @@ void cpio() /* * We want to know whether stdin or sd is ready for reading */ - FD_SET( read_fd,&readfds ); - FD_SET( sd,&readfds ); + FD_SET( read_fd, &readfds ); + FD_SET( out_fd, &readfds ); /* * And we want to know about exceptional conditions on either * stdin, stdout or the tunnel */ - FD_SET( read_fd,&exceptfds ); - FD_SET( write_fd,&exceptfds ); - FD_SET( sd,&exceptfds ); + FD_SET( read_fd, &exceptfds ); + FD_SET( write_fd, &exceptfds ); + FD_SET( out_fd, &exceptfds ); /* * Wait until something happens on one of the registered @@ -175,13 +263,29 @@ void cpio() */ if ( FD_ISSET( read_fd, &readfds ) ) { - if ( copy( read_fd, sd ) ) - break; + if( args_info.encrypt_flag ) + { + if ( COPY_TO(read_fd ) ) + break; + } + else + { + if ( copy(read_fd, sd ) ) + break; + } } else if( FD_ISSET( sd, &readfds ) ) { - if( copy(sd,write_fd ) ) - break; + if( args_info.encrypt_flag ) + { + if( COPY_FROM(write_fd ) ) + break; + } + else + { + if( copy(sd,write_fd ) ) + break; + } } else { @@ -194,7 +298,15 @@ void cpio() * Close all files we deal with */ close( read_fd ); +#ifdef USE_SSL + if( args_info.encrypt_flag ) + { + SSL_free (ssl); + SSL_CTX_free (ctx); + } +#else close( sd ); +#endif if( read_fd != write_fd ) /* When not running from inetd */ { diff --git a/proxytunnel.c b/proxytunnel.c index 3fe756c..aeab1bd 100755 --- a/proxytunnel.c +++ b/proxytunnel.c @@ -49,6 +49,11 @@ int read_fd=0; /* The file descriptor to read from */ int write_fd=1; /* The file destriptor to write to */ +#ifdef USE_SSL +SSL_CTX* ctx; +SSL* ssl; +SSL_METHOD *meth; +#endif /* * Kill the program (signal handler) @@ -129,6 +134,25 @@ void tunnel_connect() { signal(SIGHUP,signal_handler); } +#ifdef USE_SSL +/* + * Do the SSL handshake. + */ +void do_ssl() +{ + SSLeay_add_ssl_algorithms(); + meth = SSLv2_client_method(); + SSL_load_error_strings(); + + ctx = SSL_CTX_new (meth); + + ssl = SSL_new (ctx); + + SSL_set_fd (ssl, sd); + SSL_connect (ssl); +} +#endif + /* * Leave a goodbye message */ @@ -320,6 +344,10 @@ int main( int argc, char *argv[] ) /* Main processing */ tunnel_connect(); proxy_protocol(); +#ifdef USE_SSL + if( args_info.encrypt_flag ) + do_ssl(); +#endif cpio(); } diff --git a/proxytunnel.h b/proxytunnel.h index 66db2b4..dbde5ec 100644 --- a/proxytunnel.h +++ b/proxytunnel.h @@ -19,6 +19,13 @@ /* proxytunnel.h */ +#ifdef USE_SSL +#include +#include +#include +#include +#endif + #include "cmdline.h" void message( char *s, ... ); @@ -27,6 +34,7 @@ void signal_handler( int signal ); void tunnel_connect(); void analyze_HTTP(); void proxy_protocol(); +void do_ssl(); void einde(); void do_daemon(); int main( int argc, char *argv[] ); @@ -38,6 +46,11 @@ int write_fd; /* The file destriptor to write to */ char *program_name; /* Guess what? */ int i_am_daemon; /* Also... */ +#ifdef USE_SSL +SSL_CTX* ctx; +SSL* ssl; +#endif + /* * All the command line options */