NoPaste Service
DOWNLOAD
Language: C
Author: Matrix86
Description: Silent Http Proxy
Date: 02/09/08 21:09
  1. /**************************************************************************
  2.                                                         SILENT HTTP PROXY
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 3 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16.  
  17.    Coded By Matrix86 ----> matrix86 {AT} tuxmealux {DOT} net
  18.    http://www.tuxmealux.net
  19.    
  20.    (Thx to Evilsocket for his advice)
  21. ****************************************************************************/
  22.  
  23. #include <arpa/inet.h>
  24. #include <sys/types.h>
  25. #include <sys/time.h>
  26. #include <sys/socket.h>
  27. #include <netinet/in.h>
  28. #include <netdb.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <errno.h>
  32. #include <signal.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <fcntl.h>
  36. #include <sys/wait.h>
  37. #include <pthread.h>
  38. #include <time.h>
  39.  
  40. #define LISTENPORT      8080
  41. #define HTTPPORT        80
  42. #define BACKLOG         10
  43.  
  44. #define VERSION         "0.1 alpha"
  45. #define AUTHOR          "Matrix86"
  46. #define SITE            "http://www.tuxmealux.net"
  47.  
  48. int     shp_exit        = 1;
  49. FILE    *logfile        = NULL;
  50. FILE    *logpkt         = NULL;
  51. int     view            = 0;
  52. int             dm                      = 0;
  53.  
  54. typedef struct context {
  55.         int sock;
  56.         struct sockaddr_in client;
  57.         char req[BUFSIZ];
  58. } shp_context;
  59.  
  60. void shp_banner(){
  61.         printf("*****************************************\n");
  62.         printf("*           HTTP SILENT PROXY           *\n");
  63.         printf("*                                       *\n");
  64.         printf("* VERSION: %s                    *\n",VERSION);
  65.         printf("* Author:  %s                     *\n",AUTHOR);
  66.         printf("* Site:    %s     *\n",SITE);
  67.         printf("*                                       *\n");
  68.         printf("*****************************************\n\n");
  69. }
  70.  
  71. void shp_usage( char * ex){
  72.         printf( "Usage : %s <options>\n", ex );
  73.         printf( "\tOptions : \n" );
  74.         printf( "\t\t-o <namefile>  : write on logfile only http request\n" );
  75.         printf( "\t\t-p <namefile>  : write on another logfile request and packet\n" );
  76.         printf( "\t\t-v             : realtime view http packet.\n\n" );
  77.         printf( "\t\t-d             : daemon mode.\n\n" );
  78. }
  79.  
  80. void shp_die( char *ms )
  81. {
  82.   fprintf( stdout, "[ERROR] %s\n", ms );
  83.   exit( 1 );
  84. }
  85.  
  86. void shp_quit( int sig ){
  87.         shp_exit = 0;
  88. }
  89.  
  90. void set_timeout( int sd ){
  91.         int y = 1;
  92.         struct timeval tv;
  93.         tv.tv_sec       = 1;
  94.         tv.tv_usec      = 0;
  95.        
  96.         setsockopt( sd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval) );
  97.         setsockopt( sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval) );
  98.         setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int) );
  99. }
  100.  
  101. int shp_connection( char *address, int port )
  102. {
  103.         int sock;
  104.         struct sockaddr_in host;
  105.         struct hostent *data;
  106.         char ip[INET6_ADDRSTRLEN];
  107.  
  108.         if ((sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
  109.         {
  110.         printf( "[WARNING] Failed to create socket." );
  111.         return -1;
  112.         }
  113.  
  114.         memset( (void *) &host, 0, sizeof( host ) );
  115.         host.sin_family = AF_INET;
  116.         host.sin_port = htons( port );
  117.  
  118.         if ( ( data = gethostbyname( address ) ) == NULL ) return -1;
  119.        
  120.         inet_ntop( data->h_addrtype, data->h_addr, ip, sizeof( ip ) );
  121.  
  122.         host.sin_addr.s_addr = inet_addr( ip );
  123.         if( connect ( sock, (struct sockaddr *) &host, sizeof( struct sockaddr ) ) < 0 )
  124.         {
  125.         return -1;
  126.         }
  127.  
  128.         set_timeout( sock );
  129.         return sock;
  130. }
  131.  
  132. void showpkt( char * pkt ) {
  133.         char *p;
  134.         p = pkt;
  135.        
  136.         while( *p != '\0' ){
  137.                 if(*p == '\r') printf("\\r");
  138.                 else if(*p == '\n') printf("\\n\n");
  139.                 else printf("%c",*p);
  140.                 p++;
  141.         }
  142.        
  143.         return;
  144. }
  145.  
  146. int shp_forge_pkt( char * pkt, shp_context * ctx ){
  147.         char *p1, *p2, *end;
  148.         int offset;
  149.        
  150.         // Extract only first line from http request
  151.         if( ( offset = (int) strpbrk( pkt, "\r\n" ) ) ){
  152.                 offset -= (int) pkt;
  153.                 strncpy( ctx->req, pkt, offset );
  154.         }
  155.         ctx->req[offset] = '\0';
  156.        
  157.         if( ( p2 = strstr( ctx->req, "http://" ) ) != NULL ){
  158.                 p1 = ( p2 - ctx->req ) + pkt + strlen( "http://" );
  159.  
  160.                 while( *p1 != '/' ) p1++;
  161.                
  162.                 end  = strstr( pkt, "\r\n\r\n" );
  163.                 end += strlen( "\r\n\r\n" );
  164.                
  165.                 while( p1 != end ){
  166.                         *p2 = *p1;
  167.                         p1++;
  168.                         p2++;
  169.                 }
  170.                 *p2 = *p1;
  171.                
  172.                 return 0;
  173.         }
  174.         else return 1
  175. }
  176.  
  177. void shp_pipeline ( shp_context * ctx ) {
  178.         char *p, *p1, host[BUFSIZ] = { 0 }, buffer[BUFSIZ] = { 0 }, timebuf[BUFSIZ] = { 0 };
  179.         int outsock, mslen;
  180.         time_t curtime = time( NULL );
  181.         struct tm *loctime;
  182.        
  183.         loctime = localtime (&curtime);
  184.         strftime (timebuf, BUFSIZ, "[ %d/%m/%y %H:%M ]", loctime);
  185.        
  186.         if( ( p = strstr( ctx->req, "Host: " ) ) != NULL ) {
  187.                 p += strlen( "Host: " );
  188.                 p1 = host;
  189.                
  190.                 while( *p != '\r' && *( p + 1 ) != '\n' ) {
  191.                         *p1 = *p;
  192.                         p1++;
  193.                         p++;
  194.                 }
  195.                 if( dm ) fprintf (stdout, "%s HTTP request from: %s to: %s\n", timebuf, inet_ntoa (ctx->client.sin_addr), host);
  196.                
  197.                 if( logpkt != NULL ) {
  198.                         fprintf (logpkt, "%s HTTP request from: %s to: %s\n", timebuf, inet_ntoa (ctx->client.sin_addr), host);
  199.                         fprintf (logpkt, "%s\n",ctx->req);
  200.                 }
  201.                
  202.                 if( view && dm ) showpkt( ctx->req );
  203.                
  204.                 if( logfile != NULL ) fprintf (logfile, "%s HTTP request from: %s to: %s\n", timebuf, inet_ntoa (ctx->client.sin_addr), host);
  205.                
  206.                 if ( ( outsock = shp_connection( host, HTTPPORT ) ) < 0 ){
  207.                         if( dm ) fprintf( stdout, "Impossible to connect to host %s\n", host );
  208.                 }
  209.                 else {
  210.                         write( outsock, ctx->req, strlen( ctx->req ) );
  211.                        
  212.                         while( ( mslen = read( outsock, buffer, BUFSIZ ) ) > 0 ) {
  213.                                 write ( ctx->sock, buffer, mslen );
  214.                                 memset( buffer, 0, BUFSIZ );
  215.                         }
  216.                         close( outsock );
  217.                 }
  218.                
  219.         }
  220.         return;
  221. }
  222.  
  223. void * shp_req_manage( void * context ) {
  224.         shp_context *ctx = (shp_context *) context;
  225.         char buffer[BUFSIZ] = { 0 };
  226.         int mslen;
  227.        
  228.         if( ( mslen = read ( ctx->sock, buffer, BUFSIZ ) ) < 0 ){
  229.                 free( ctx );
  230.                 shp_die( "Problem with read function." );
  231.         }
  232.        
  233.         if( shp_forge_pkt( buffer, ctx ) == 0 ) {
  234.                 shp_pipeline( ctx );
  235.         } else {
  236.                 strncpy( ctx->req, buffer, BUFSIZ );
  237.                 shp_pipeline( ctx );
  238.         }
  239.        
  240.         close( ctx->sock );
  241.         free( ctx );
  242.         pthread_exit(NULL);
  243. }
  244.  
  245. int main( int argc, char *argv[] ){     
  246.         struct sockaddr_in      si;
  247.         struct sockaddr_in      client;
  248.         struct timeval          tv;
  249.         int sock1, in_con, c;
  250.        
  251.         while( ( c = getopt( argc, argv, "dvo:p:" ) ) != -1 ){
  252.                 switch(c){
  253.                         case 'o' : logfile = fopen( optarg, "a+" ); break;
  254.                         case 'p' : logpkt  = fopen( optarg, "a+" ); break;
  255.                         case 'v' : view    = 1; break;
  256.                         case 'd' : dm      = 1; break;
  257.                         default  :
  258.                                            shp_usage(strdup(argv[0]));
  259.                                            return -1;
  260.                 }
  261.         }
  262.        
  263.         if( dm ) daemon(1,0);
  264.        
  265.         signal( SIGINT, shp_quit );
  266.         signal( SIGKILL, shp_quit );
  267.  
  268.         sock1  = socket( AF_INET, SOCK_STREAM, 0 );
  269.  
  270.         if ( sock1 < 0 ) shp_die( "Failed to create socket." );
  271.  
  272.         tv.tv_sec       = 2;
  273.         tv.tv_usec      = 0;
  274.         set_timeout( sock1 );
  275.  
  276.         memset( (void *) &si, 0, sizeof( si ) );
  277.         si.sin_family           = AF_INET;
  278.         si.sin_port             = htons ( LISTENPORT );
  279.         si.sin_addr.s_addr      = htonl ( INADDR_ANY );
  280.  
  281.         if( bind ( sock1, (struct sockaddr *) &si, sizeof ( si ) ) < 0 )
  282.         {
  283.                 close ( sock1 );
  284.                 shp_die( "Binding socket." );
  285.         }
  286.         if( listen ( sock1, BACKLOG ) < 0 )
  287.         {
  288.                 close ( sock1 );
  289.                 shp_die( "Could not listen on socket." );
  290.         }
  291.        
  292.         shp_banner();
  293.        
  294.         if( dm ) fprintf( stdout, "Press CTRL-C to exit.\n" );
  295.        
  296.         while( shp_exit ){
  297.                 socklen_t addrlen = sizeof( client );
  298.  
  299.                 while ( ( in_con = accept( sock1, (struct sockaddr *) &client, &addrlen ) ) < 0 && ( errno == EINTR ) );
  300.  
  301.                 if( in_con > 0 ){
  302.                         //printf( "Http request.\n" );
  303.                         set_timeout( in_con );
  304.                
  305.                         pthread_t       thread;
  306.                         shp_context *context;
  307.                         context = (shp_context *) calloc( sizeof(shp_context), 1 );
  308.                        
  309.                         context->sock   = in_con;
  310.                         context->client = client;
  311.                        
  312.                         pthread_create( &thread, 0, shp_req_manage, (void *) context );
  313.                        
  314.         }
  315.         }
  316.        
  317.         if( logpkt != NULL ) fclose(logpkt);
  318.         if( logfile != NULL ) fclose(logfile);
  319.        
  320.         if( dm ) printf( "Power off.\n" );
  321.         fflush(stdout);
  322.         close( sock1 );
  323.         return 0;
  324. }
  325.