#!/usr/bin/perl -w # # $Id: ssh-ppp 356 2011-09-24 23:25:47Z svnuser $ # # $Log: ssh-ppp,v $ # Revision 1.9 1999/07/06 22:22:27 merlin # Name option is really an option now # Removed full pathnames # # Revision 1.8 1999/06/17 00:42:51 merlin # Added -n option, and added SIGTERM to the list of signals after which we # cleanup (Doh!) # # Revision 1.7 1999/06/15 00:34:21 merlin # Boy, this works sooo much better if you run ssh in the child and ppp in the # father. # I also made the script a little more robust # # Revision 1.6 1999/06/14 22:15:22 merlin # Lots of minor changes as I was chasing an annoying bug my($d)=@_ vs my $d=@_ # but now this script works again. # # Revision 1.5 1999/06/10 18:13:51 merlin # Added lock detection # # Revision 1.4 1999/06/09 18:32:50 merlin # Cleaned up, added some more debugging stuff and a sample call command line # # Revision 1.3 1998/07/10 06:42:17 merlin # Erased useless fifo # # Revision 1.2 1998/05/25 19:19:40 merlin # A bunch of modifications and hacks to make it work # # Revision 1.1 1998/05/24 05:23:44 merlin # First version checked in CVS # # Start an ssh connection and a pppd running on top of it. # by Olaf Titz, July 1996 # # Lots of modifications by Marc Merlin , more than # half done on VA Linux Systems' time (http://www.valinux.com/) # # Sample call: # ssh-ppp -v -d -l remotepppuser distanthost require "getopts.pl"; require "sys/syscall.ph"; use FileHandle; STDIN->autoflush(1); STDOUT->autoflush(1); STDERR->autoflush(1); # I know, most of those should never happen, but I like to be safe :-) $SIG{'HUP'} = $SIG{'INT'} = $SIG{'QUIT'} = $SIG{'ILL'} = $SIG{'TRAP'} = $SIG{'ABRT'} = $SIG {'FPE'} = $SIG {'BUS'} = $SIG {'SEGV'} = $SIG {'PIPE'} = $SIG {'ALRM'} = $SIG{'QUIT'} = 'sighld'; # disable escape, and compress #$ssh="ssh -c blowfish -e none -C -v -P"; $ssh="ssh -c idea -e none -C -v -P"; $pppd="pppd nodetach noipdefault lcp-echo-failure 2"; # defaults # It's safer to put a script in the remote user that starts ppp #$opt_c="pppd"; $opt_c=""; chomp($opt_l=`whoami`); $opt_n=""; $opt_p="22"; $opt_d=0; $opt_v=0; Getopts("p:c:l:n:d:v"); $pppd =~ s/pppd/pppd name $opt_n/ if ($opt_n); $debug=$opt_d; $verbose=$opt_v; $opt_l="-l $opt_l"; $opt_p="-p $opt_p"; $pppd =~ s/pppd/pppd debug/ if $verbose; $opt_c =~ s/pppd/pppd debug/ if $verbose; ($host=shift) or die "usage: $0 [-v] [-d file] [-p port] [-l user] [-n local ppp hostname/username] [-c command] host"; if ($debug) { open(CONSOLE, ">>$debug") or die "Can't open debugging file/device $debug: $!"; # Used by the father of the next fork to warn bugdaemon before starting ppp CONSOLE->autoflush(1); } srand(time); $fifofile="/tmp/ssh_ppp.$$".rand(99999); system "mkfifo -m 600 $fifofile"; foreach $maj ("p".."s") { foreach $min ("0".."9", "a".."f") { tryopen("$maj$min"); } } die "Couldn't alloc master pty\n"; sub tryopen { my ($d)=@_; $master=sprintf("/dev/pty%s", $d); $slave=sprintf("/dev/tty%s", $d); if (open(PTY, "+<$master")) { $pid=fork; defined($pid) or die "can't fork: $!"; if ($pid) { close PTY; print CONSOLE "Father: reading from fifo while waiting for child to complete ssh connection\n" if $debug; open(FIFO, "$fifofile") or die "Can't open fifo: $!"; FIFO->autoflush(1); while () { print CONSOLE "Child sent: $_" if $debug; last if /Entering interactive session./; last if /Permission denied./; last if /Host key not found from the list of known hosts/; last if /Selected cipher type .* not supported by server./; # If you find something to add here, let me know -- Marc } if (! defined($_) or ! /Entering interactive session./) { $_="\n[unexpected output from ssh. Rerun in debug mode and look at log file]" if (! defined($_)); print CONSOLE "Father: connection aborted: $_\n" if $debug; print CONSOLE "Father: killing child (pid $pid)\n" if $debug; kill (15, $pid); die "connection aborted, ssh returned: $_\n"; } print CONSOLE "Father: ssh has connected\n" if $debug; unlink($fifofile) or die "can't unlink $fifofile: $!"; open(STDIN, "+<$slave") or die "Can't open slave: $!"; open(STDOUT, ">&STDIN") or die "Can't dup2 STDOUT: $!"; # Yeah, it's a dirty kludge: ssh needs to be kicked for the ppp # packets to be able to ride over it. Don't ask me why -- Marc kill ("STOP", $pid); sleep 1; kill ("CONT", $pid); print CONSOLE "Father: Going to run $pppd on $slave\n" if $debug; exec $pppd; die "Father: can't exec $pppd: $!"; } else { print CONSOLE "Child: running on $master; ssh=$$, pppd=".getppid."\n" if $debug; open(STDIN, "<&PTY") or die "Can't dup2 STDIN: $!"; open(STDOUT, ">&PTY") or die "Can't dup2 STDOUT: $!"; close PTY; open(FIFO, ">$fifofile") or die "Can't open $fifofile for writing: $!"; open(STDERR, ">&FIFO") or die "Can't dup2 STDERR: $!"; print CONSOLE "Child: about to run $ssh -t $opt_p $opt_l $opt_c $host\n" if $debug; exec "$ssh -t $opt_p $opt_l $opt_c $host"; die "Child can't exec $ssh: $!"; } } } sub sighld { # Do some cleanup. It might get called by the father and the child, but # I don't care. unlink($fifofile); exit 0; }