pippa v2, di b0z0/iKX



d) cos'e' pippa v2?
r) come non si deduce dal nome, pippa v2 e' un datapipe, ovvero un
   programma che ridireziona tutti i pacchetti tcp diretti ad una porta su
   una macchina ad un altra porta su un altra (o stessa) macchina.

d) a che serve?
r) pippa v2 puo' essere usato per mascherare la vera provvenienza di certi
   pacchetti facendoli passare sempre per un altra macchina. questo
   chiaramente puo' essere usato per diversi scopi, dal far passare i
   pacchetti per altre nazioni per complicare il lavoro di chi vorra'
   venire a cercarvi, per mantenere relativamente + segreta la vostra
   identita' su irc o semplicemente per ridirezionare delle porte da
   qualche parte (utilizzabile su gateway per reti interne o cose simili).

d) xche' usare pippa v2 e non m$datapipe o altri?
r) perche':
    -) e' scritto in perl, quindi usabile su moltissime piattaforme
       (su tutti gli unix like e anche sui winblows) senza dover
       modificare nulla (a meno di una costante e la path all'interprete).
    -) la destinazione dei pacchetti puo' essere fissa (usando il modo non
       interattivo) o cambiata al volo al momento dell'uso (con il modo 
       interattivo) senza dover far ripartire ogni volta il datapipe.
    -) ha il supporto per i proxy server socks (v4 e v5) modificabili
       anche al volo nel modo interattivo.
    -) due o piu' pippa v2 in modo interattivo e non possono essere
       collegati facilmente in serie (anche poi via un socks
       proxy) rendendo la ricerca della sorgente dei pacchetti +
       complicata.
    -) pippa v2 ha un po' di opzioni di logging delle connesioni.
    -) dovrebbe funzionare e hai il source per aggiungerci quello che
       vuoi senza perdere molto tempo.

d) requisiti?
r) il sistema deve avere installato il perl5. per poter usare il supporto
   per server socks si dovra' disporre anche del socks perl module
   (reperibile al http://www.perl.com/CPAN/modules/by-module/Net/). per
   pingare una macchina dal modo interattivo inoltre pippa v2 usera' un
   comando 'ping' che si suppone sia presente sulla macchina.
 
d) come si usa? 
r) beh, per avere una schermata di tutte le possibili opzioni alla command
   line basta lanciare pippa v2 con un '-h 1'. ecco qualche spiegazione
   per ogni comando cmq:
     -p xxxx       : specifica la porta sulla quale pippa v2 aspetta
                     eventuali connessioni.
     -d 1          : saranno visualizzate sull'output tutte le connessioni
                     avvenute.
     -b 1          : pippa v2 si binda (attacca? va be', da bind) su tutti
                     gli indirizzi della macchina (in caso contrario si
                     binda solo su quello ottenuto da `hostname`)
     -F 1          : usa il modo non interattivo. in questo caso pippa v2
                     semplicemente mandera' tutti i pacchetti alla
                     destinazione desiderata scelta dalle opzioni -P e -H
                     ed eventualmente potra' mandare il comando -I.
     -P xxxx       : porta alla quale connettersi (se usato con -F)
     -H xxxx       : host al quale connettersi (se usato con -F)
     -I xxxx       : stringa da mandare all'inizio della connessione (se
                     usato con -F)
     -S 1          : usa il socks proxy specificato dalle opzioni -s, -t,
                     -v, -u e -k.
     -s xxxx       : socks proxy da usare
     -t xxxx       : porta del socks proxy da usare
     -v x          : protocol version del socks proxy (4 o 5)
     -u xxxx       : utente sul proxy socks (di default anonimo)
     -k xxxx       : password sul proxy socks
   se lanciato in modo interattivo il pippa v2 puo' essere comandato
   dall'esterno. connettendovi alla porta del host sulla quale avete
   lanciato pippa vi verra' un prompt "pippa>". con 'help' avrete qualche
   suggerimento. + esattamente i comandi sono:
     open <host> <port>       : connettiti alla porta <port> del <host>
     prox <host> <port>       : setta il socks proxy al sito <host> alla
                                porta <port>. se usato senza parametri il
                                comando disabilita l'uso del socks proxy.
     pvar <user> <pass> <ver> : setta l'utente, la password e la versione
                                del socks proxy. se usato senza parametri
                                toglie l'uso dell'autentificazione con
                                user/pass.
     ping <host>              : esegue tre ping al host desiderato.
     stop                     : esegue la chiusura del pippa v2,
                                principale, lasciando pur sempre attiva 
                                la connessione attuale.
     exit,quit                : chiude la sessione attuale.
     help                     : un riassunto dei comandi.

d) qualche esempio di uso?
r) massi'..
    pippa -p 3456 &
      fa partire pippa v2 in modo interattivo sulla porta 3456
    pippa -p 3456 -b 1 &
      come prima ma pippa v2 si bindera' su tutti gli indirizzi del host
    pippa -p 3456 -b 1 -d 1  2>&1 > pippalog &
      come prima ma le connessioni verranno loggate nel file pippalog
    pippa -F 1 -P 6667 -H irc.ais.net &
      ridireziona tutti i pacchetti in entrata (sulla porta di default
      2345) al sito irc.ais.net alla porta 6667. questo e' un esempio di
      come usare pippa v2 x irc mostrando cosi' solo l'ip dove e' stato
      installato pippa.
    pippa -F 1 -P 23 -H un.wingate.com -I 'open irc.ais.net 6667' &
      qui i pacchetti in entrata verranno ridirezionati al sito
      un.wingate.com alla porta 23. all'inizio di ogni connessione verra'
      mandata la stringa 'open irc.ais.net 6667'. questo e' un tipico modo
      per usare un wingate per andare su irc (in questo caso il pippa v2
      potete eseguirlo sulla vostra macchina locale e settare il server
      per il vostro client irc alla porta 2345 della vostra macchina).
      chiaramente le risposte del wingate non saranno chiare al vostro
      client irc, ma fa nulla, dopo un po' gli passa.
    pippa -F 1 -P 6667 -H irc.ais.net -S 1 -s socks.proxy.com -t 1080
      qui i pacchetti in entrata vengono mandati al sito irc.ais.net alla
      porta 6667 usando il socks proxy socks.proxy.com piazziato sulla
      porta 1080. questo e' un tipico modo per usare un socks proxy per
      andare su irc quando il vostro client non ha il supporto socks gia'
      integrato. anche qui fate girare pippa v2 sul vostro pc e settate il
      server irc del vostro client sulla porta 2345 della vostra macchina. 
   come esempi di cmdline credo bastino, non e' poi cosi' difficile credo.
   per quanto riguarda il modo inteattivo non c'e' molto da fare esempi
   se effetivamente sapete cosa vogliate fare. 

d) problemi conosciuti?
r) connettendosi alla porta 23 (telnet) via pippa v2 in modo interattivo
   con alcuni client telnet all'uscita si potrebbe verificare un strano
   comportamento xche' gli ultimi comandi mandati dal demone non saranno
   interpretati. in caso succeda vi basta rimettere il client telnet in
   line mode o chiuderlo e riaprirlo.

d) quanto costa?
r) ma nulla, se trovate pippa v2 di qualche utilita' mandatemi una mail a
   b0z0@realitylimited.com o intrattenetemi su irc.

d) dediche, saluti o altro?
r) finalmente (forse) non dovro' + ascoltare i problemi impossibili delle
   troppe xsone che vogliono usare un socks proxy ma dicono che bitchx non
   compila e/o che non riescono ad installare/configurare socks5.
   saluti generici a tutti i fratelli e le sorelle, soprattutto quelli/e 
   che mi tirano su di morale di tanto in tanto.

d) allora dov'e'?
r) ecco...

---------->8------------------------------------------8<---------------------
#!/usr/bin/perl

#
# pippa v2, a network datapipe
# by b0z0/iKX, late 1998
# contacts: b0z0@realitylimited.com
#
# start it with the -h 1 option to get some help
# write help at the pippa> prompt to get some help on the interactive mode
#
# this has been tested.
#

$socks_installed=1;		# set this to 0 if ya don't have socks pm

use Socket;
require "getopt.pl";
if ($socks_installed) {use Net::SOCKS;}

$SIG{'CHLD'}='IGNORE';

&Getopt('hpdbPHFISstvuk');		# Get some needed cmdline options
$help=$opt_h;
$port=$opt_p;
$bindany=$opt_b;
$debug=$opt_d;
$destport=$opt_P;
$desthost=$opt_H;
$nonint=$opt_F;
$initstr=$opt_I;
$usesocks=$opt_S;
$sockserver=$opt_s;
$sockport=$opt_t;
$sockversion=$opt_v;
$sockuser=$opt_u;
$sockpass=$opt_k;

$port=2345 unless $port;	# some defaults
$destport=25 unless $destport;
$desthost="127.0.0.1" unless $desthost;
$sockport=1080 unless $sockport;
$sockversion=4 unless $sockversion;
$usesocks=0 unless (($usesocks) and ($socks_installed));

if ($help) {
 print "pippa usage:\n";
 print "  -h 1           = help\n";
 print "  -p xxxx        = run pippa on port xxxx\n";
 print "  -d 1           = output debug infos\n";
 print "  -b 1           = bind to any adress of the machine\n";
 print "  -F 1           = non interactive mode, just pipe to -H -P\n";
 print "     -P xxxx     = fix destination port to xxxx\n";
 print "     -H xxxx     = fix destination host to xxxx\n";
 print "     -I xxxxx    = send string xxxxx at beginning\n";
 if ($socks_installed){
  print "  -S 1           = use a socks proxy for connections \n";
  print "     -s xxxx     = socks proxy to use\n";
  print "     -t xxxx     = socks proxy port (default 1080)\n";
  print "     -v x        = socks proxy protocol version (default 4)\n";
  print "     -u xxxx     = socks proxy username (default anon login)\n";
  print "     -k xxxx     = socks proxy password (default anon login)\n\n";
 }
 exit();
}

$AF_INET=2;

# This should very probably change for some operating systems
# Check the socket include files (sys/socket.h) for this value

$SOCK_STREAM=1;		# should be 2 for SunOS

$sockaddr='S n a4 x8';

chop($hostname=`hostname`);	# Infos on machine running pippa
($name,$aliases,$type,$len,$thisaddr)= gethostbyname($hostname) if $hostname;


($name,$aliases,$proto)=getprotobyname('tcp');
if($port !~ /^\d+$/) {
   ($name, $aliases, $port) = getservbyname($port,'tcp');
}

$thisaddr=INADDR_ANY if ($bindany or !($thisaddr));  # bind to any address

$this= pack($sockaddr,$AF_INET,$port,$thisaddr);
select(NS); $|=1; select(STDOUT); $|=1;

socket(S,$AF_INET, $SOCK_STREAM, $proto) || die "socket: $!";
bind(S,$this) || die "bind: $!";
listen(S,5) || die "connect: $!";	# Stay on port and wait for conns

select(S); $|=1; select(STDOUT);

for ($con=1;;$con++) {
 ($addr=accept(NS,S)) || die $!;
 if (($child=fork())==0) {
   ($af,$port,$inetaddr)=unpack($sockaddr,$addr);
   @inetaddr=unpack('C4',$inetaddr);

   @datetime=localtime(time);
   $datetime[4]++;
   print "$datetime[3]/$datetime[4]/$datetime[5] " if $debug; 
   print "$datetime[2]:$datetime[1]:$datetime[0] from " if $debug;
   print "$inetaddr[0].$inetaddr[1].$inetaddr[2].$inetaddr[3]" if $debug;
   print ":$port connection nr=$con\n" if $debug;
    	
   print NS "pippa> " if !($nonint);
   select(S); $|=1; select(STDOUT); $|=1;

   openconn() if ($nonint);
   exit() if $nonint;
   while (<NS>) {
    print STDOUT "nr=$con command: $_" if ($debug and !($nonint));
    @command=split(' ',$_);
    $_=$command[0];
    CMDLOOP: {
     if (/^open$/) {
           ::openconn();
           last CMDLOOP;
       }

     if (/^prox$/) {
           $command[2]=1080 if (!($command[2]));
           $sockserver=$command[1];
           $sockport=$command[2];
           $usesocks=0;
           $usesocks=1 if (($command[1]) and ($socks_installed));
           last CMDLOOP;
     }

     if (/^pvar$/) {
           $command[3]=4 if (!($command[3] == 5));
           $sockuser=$command[1];
           $sockpass=$command[2];
           $sockversion=$command[3];
           last CMDLOOP;
     }

     if (/^ping$/) {
       if (!($command[1]) or ($command[2])) {
          print NS "bad ping params\n";
       }
       elsif (!($command[1] =~ /^(\w+\.*)+$/)) {
          print NS "nice params\n";
       }
       else {
          open(SAVEOUT,">&STDOUT");
          open(SAVEERR,">&STDERR");

          open(STDOUT,">&NS");
          open(STDERR,">&STDOUT");
          system("ping -c 3 $command[1]");
          close(STDOUT);
          close(STDERR);

          open(STDOUT,">&SAVEOUT");
          open(STDERR,">&SAVEERR");
       }
       last CMDLOOP;
     }

     if (/^help$/) {
       print NS "avaiable commands:\n";
       print NS "  open <host> <port>       : connect to <host> at <port>\n";
       print NS "  prox <host> <port>       : use socks proxy <host>:<port>\n";
       print NS "  pvar <user> <pass> <ver> : proxy auth: user, pass and ver\n";
       print NS "  ping <host>              : ping <host> three times\n";
       print NS "  help                     : this shit\n";
       print NS "  stop                     : stop main pippa\n";
       print NS "  quit, exit               : bail out\n\n";
       last CMDLOOP;
     }
 
     if (/^$/) { last CMDLOOP; }

     if (/^stop$/) {
       kill 15, getppid();
       last CMDLOOP;
     }

     if ((/^quit$/) or (/^exit$/)) {
       close(NS);
       exit();
     }
     print NS "bad command\n";
    }
   print NS "pippa> " if !($nonint);
   exit() if $nonint;
   }
 close(NS);
 exit();
 }
close(NS);
}

sub openconn {
 DOOPEN: {
   $command[1]=$desthost if $nonint;
   $command[2]=$destport if $nonint;
          
   if ((!($command[1])) or (!($command[2])) or $command[3]) {
      print NS "bad params\n";
      last DOOPEN;
   }
   $_=$command[2];

   if($_ !~ /^\d+$/) {
     ($name, $aliases, $port) = getservbyname($command[2],'tcp');
     print NS "bad port\n" if !($port);
     last DOOPEN if !($port);
     $command[2]=$port;
   }
   elsif ($command[2] > 65535) {
      print NS "port > 65535? cool\n";
      last DOOPEN;
   }
   ::doopen() if (!($usesocks));
   ::doopensocks() if ($usesocks);
 }
}


sub doopen {
   $outta= pack($sockaddr,$AF_INET,0,$thisaddr);
   socket(OUT,$AF_INET, $SOCK_STREAM, $proto) || die "socket: $!";
   bind(OUT,$outta) || die "bind: $!";

   ($name,$aliases,$type,$len,$targetaddr)=gethostbyname($command[1]);
      
   $that=pack($sockaddr, $AF_INET, $command[2],$targetaddr);

   print NS "ok, connecting... \n" if !($nonint);
   if (connect(OUT,$that)) {
      print NS "ok, connected!\n" if !($nonint);
      select(OUT); $|=1; select(STDOUT);
      print OUT "$initstr\n" if ($nonint and $initstr);
      if ($child_c=fork()){
         while (read(OUT,$buf,1)) { print NS $buf;}         
         sleep 3;
         kill 9,$child_c if $child_c;
      }
      else { 
         while (read(NS,$buffo,1)) { print OUT $buffo;}
      }
   }
   else { print NS "error: $!\n"; }
}

sub doopensocks {
   $forzo=0;
   $forzo=1 if ($sockuser and $sockpass);
   my $sock = new Net::SOCKS(socks_addr => $sockserver,
                socks_port => $sockport,
                user_id => $sockuser,
                user_password => $sockpass,
                force_nonanonymous => $forzo,
                protocol_version => $sockversion);

   my $f= $sock->connect(peer_addr => $command[1], peer_port => $command[2]);

   $s_num=$sock->param('status_num');
   if ($s_num == SOCKS_OKAY) {
      if ($child_c=fork()){
         while (read($f,$buf,1)) { print NS $buf;}
         sleep 3;
         $sock->close();
         kill 9,$child_c if $child_c;
      }
      else {
         while (read(NS,$buffo,1)) { print $f $buffo;}
      }
   }
   else {
     $s_err=Net::SOCKS::status_message($s_num);
     print NS "Socks error: $s_err\n";
   }
}