pippa, a network datapipe by b0z0/iKX, Padania 1998 What is pippa? -------------- pippa is a small network datapipe written in Perl. Basically pippa's work is to redirect a network connection from one site to another, thus hiding the identity of the real connection originator and exposing just the host where the datapipe is running. What should I do with it? ------------------------- Well, pretty obviously, when you would like to hide (of course this method of hiding yourself is just relatively secure) your connection from some third host making just the host running the datapipe to be exposed. This can be very useful when you don't want that other users see your provider's host on irc, when you would like to remain anonymous when sending mail, if you would like to conserve your privacy while hacking into other people's site or when you would like to make some packets to cross your country's border and then return in your country thus making some more problems to the local lawyers ;) How it works? ------------- Simple, it just gets the packets it receives in input (from some incoming connection) and send them to some desired target machine. So, with a small ascii art: /-----\ /-----\ /-----\ | A |------->| B |------->| C | | 789 |<-------| 456 |<-------| 678 | \-----/ \-----/ \-----/ You are host A, starting from port 789. On the host B pippa is supposed to run on port 456. You'll connect to the host B on port 456. Then you will be able to send (in either interactive or noninteractive mode) some data to the port 678 of the host C. Of course the host C will just think that someone is connecting from host B and won't care at all about host A. What has pippa to offer? ------------------------ pippa is a quite small network datapipe written in Perl, so it should be very easy to use on a lot of different platforms (mainly every system that has Perl installed, so all kind of unixes and windoze nt too) without the need of compiling or something (except some variables should have to be changed, but this changes too are easy to do and well documented in the system's include files). pippa is quite versatile, it can run in noninteractive mode (so it should just feed all the packets from the input to the desired fixed target) or in interactive mode (so you will have a small command prompt where you'll be able to select to which host/port to connect and so on), so it can be used for many puroposes without the need to be restarted each time. two or more interactive or noninteractive pippas can be used in chain thus making your work choices of the destination and such very easy without the need of restarting the datapipe or something. pippa has some small logging options. Starting pippa -------------- Start pippa with a '-h 1' parameter and you'll get a list of the possible pippa command line options. The cmdline options are selfexplanatory, so here come just a few samples of starting pippa. pippa -p 3456 & pippa will wait on port 3456 in interactive mode, so when someone will log on that port it will send the prompt 'pippa>' and wait for commands. pippa -p 3456 -b 1 & same as before, but in this case pippa will bind itself on all the adresses of the machine where pippa was started (while without the -b 1 it will bind just as the adress that results as the output of the hostname program). pippa -d 1 2>&1 > .pippalog & pippa will wait on the default 2345 port in interactive mode. All the connections to pippa and all the issued commands will be logged and everything redirected in the .pippalog file. (you should have to change the STDERR redirection to STDOUT according to the shell you're using) pippa -p 3456 -F 1 -P 6667 -H irc.ais.net & pippa will wait for connections on port 3456 and will redirect any incoming connection to the port 6667 of the server irc.ais.net. This is an easy example of the use of pippa for irc spoofing, since the irc server and the other irc users will actually see the user as if it is connecting from the datapipe host. People with a brain should notice that you have to pay attention at some IRC client things such as DCC, when your real connection could be revealed anyway. pippa -F 1 -P 3456 -H fakeirc.com -I 'open irc.ais.net 6667' & pippa will wait on the default 2345 port for connection in non interactive mode. Each time someone will connect pippa will redirect the connection to the fakeirc.com at port 3456 and will send as the first line the 'open irc.ais.net 6667'. This is very useful when chaining two or more pippa datapipes. Infact if pippa is running in interactive mode it should be a bit shitty to use it with and irc client. So you should just install a datapipe on your own host that will just pipe all the data to the interactive pipe outside but will additionally initialize it for use with IRC (this is, will send the string to open the connection to an IRC server). This way you can use an interactive datapipe as an uninteractive pipe, since there isn't any prob to install one pipe more on your local system. As you can see there will be some output (the pippa> prompt and the connecting status strings) sent to the second datapipe from the first uninteractive one when it will execute the initialization string, but IRC clients will treat this just as garbage and will work ok anyway, so don't worry. Using pippa in interactive mode ------------------------------- There isn't too much to say. By writing help at the prompt you'll get the command list. To connect to a site just write open where port can be the port number or the port name (from /etc/services). And then you can do what you want to. There is also a ping command that relies on the ping program of the host running pippa. This will just ping the desired site and send ya the output in case you would like to check if the site is up and running. Known problems -------------- There is one known problem with this datapipe that wasn't corrected because the datapipe should have been written with a quite different approach from the very beginning to leave out this problem. Basically when you connect to the telnet (23) port of a site running pippa in interactive mode with a telnet client, when you logout the telnet client should (some does, some don't) have strange behaviours, since the telnet client remains in a quite strange state for some commands the destination daemon sends. So in some cases you should just go to the telnet client command line (using the escape character, usually ^]) and then reput it in line mode (mode line), but more likely you'll have to exit from the telnet client and then reconnect to the datapipe once again for the next work. I hope this won't cause too much probs to ya. Anyway for a note, this should be corrected by rewriting all the pippa input routines with a char-by-char input strategy (so it should drastically change), by monitoring the finishing telnet sequences at the end of the connection (too lazy to write this) or even by restoring all the telnet settings at the end of the session (too much rfcs to browse :) ). The code -------- Here it comes. Just change the path to the perl interpreter (or delete it if ya are running it under windozes) and change the socket constants if needed. --------------------->8----------[cut here]----------8<---------------------- #!/usr/bin/perl # # pippa, a network datapipe # by b0z0/iKX, Padania april 1998 # # 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 # # Tested under Linux with Perl 5.004 # Tested under Digital Unix 4.0 with Perl 5.004 # Tested under SunOS 5 with Perl 5.003 use Socket; require "getopt.pl"; $SIG{'CHLD'}='IGNORE'; &Getopt('hpdbPHFI'); # 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; $port=2345 unless $port; # Some defaults $destport=25 unless $destport; $desthost="127.0.0.1" unless $desthost; 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\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 adress avaiable $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); 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; doopen() if $nonint; exit() if $nonint; while () { print STDOUT "nr=$con command: $_" if ($debug and !($nonint)); @command=split(' ',$_); $_=$command[0]; CMDLOOP: { if (/^open$/) { doopen(); 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 : connect to at \n"; print NS " ping : ping three times\n"; print NS " help : this shit\n"; print NS " quit : bail out\n"; print NS " exit : bail out\n\n"; last CMDLOOP; } if (/^$/) { 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 doopen { DOOPEN: { $outta= pack($sockaddr,$AF_INET,0,$thisaddr); socket(OUT,$AF_INET, $SOCK_STREAM, $proto) || die "socket: $!"; bind(OUT,$outta) || die "bind: $!"; $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; } ($name,$aliases,$type,$len,$targetaddr)=gethostbyname($command[1]); $_=$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; } $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"; } } }