if its too loud, turn it down

Thursday, October 15, 2009

Use Perl and Expect to auto-connect, and maintain connection, to a proxy

There are a number of reason to use a proxy, security and privacy being the two biggest for me. I use Cotse.net and am very happy with it. There is one downside to Cotse (and alot of similar services I suppose) is that you must manually connect to the proxy server, using something like SSH Tunnel Manager. Kind of a pain.

So I wrote a script that manages the connection using perl and expect. It runs as a cronjob to always make sure you're connected to the proxy when an internet connection is available.

Installation
  1. Step 1: Install the Expect.pm perl module. As root, type this:
    # perl -MCPAN -e 'install Expect'
    
  2. Step 2: Edit this script and put in your /Users/user/bin/ directory as "proxy.pl".
    # check if we are connected to the proxy.  If not, connect.
    my $pid = &checkAlive($command);
    if (!$pid) {
    
     # check if we even have internet before trying to connect to proxy
     my $result = &checkInternet($ext_host,$timeout);
     if ($result > 0) {
      print "Not connected. Connecting to $command\n";
      &connect($password,$command,$timeout);
     } else {
      print "No internet available.\n";
     }
     
    } else {
     # we do have internet, and are connected toi proxy.
     print "connected to $command\n";
    }
    
    sub connect {
     # connect to the proxy and login using expect
     
     my ($password,$command,$timeout) = @_;
     
     # Create the Expect object
     my $exp = Expect->spawn($command) or die "Cannot spawn ssh command\n";
     $exp->expect($timeout,
      ["Password Authentication"],
      ["Are you sure you want to continue connecting", sub {my $self = shift; $self->send("yes\n");}]
      );
     # answer the password
     $exp->expect($timeout,
      [ qr/Password:/ => sub { my $exp = shift; $exp->send("$password\n"); exp_continue; } ],
      [ qr/Password:/ => sub { my $exp = shift; $exp->send("$password\n"); } ], 
      );
     # wait forever for nothing...basically, stay connected
     $exp->expect(undef);
     
    } # end sub connect
    
    sub checkInternet {
     # check if the internet is up by pinging external host
     # sends back packets received, so if the return val
     # is > 0 then we have internet
    
     my ($host,$timeout) = @_;
     my $packets = 0;
     
     my $pingcmd = "/sbin/ping -q -t $timeout -c 1 $ext_host";
     #print "checking for running program with $pingcmd\n";
     my @raw = `$pingcmd`;
     chomp(@raw);
     foreach my $line (@raw) {
      if ($line =~ /([0-9]{0,2}) packets received/) {
       $packets = $1;
      }
     } # end foreach
     return ($packets);
     
    } # end sub checkInternet
    
    sub checkAlive {
     # gets the PID of the process that matches a SINGLE criteria 
    
     my ($text) = shift;
     my $return_pid = "";
     
     my $pidgetter = "/bin/ps ax -o pid,command | grep '$text' | grep -v 'grep' | grep -v 'sh -c'";
     #print "checking for running program with $pidgetter\n";
     my @raw_pids = `$pidgetter`;
     chomp(@raw_pids);
     
     foreach my $raw_pid (@raw_pids) {
      $raw_pid =~ s/^\s+//;
      $raw_pid =~ /^(\d+)\s/;
      $raw_pid = $1;
      my $pid = stripNonNumber($raw_pid);
      my $exists = kill("0",$pid);
      if ($exists) {
       my $message = "checking for any program operating on $text. I found one with pid ${pid}. ";
       $return_pid = $pid
      }
     } # end foreach
     
     return ($return_pid);
    
    } # end sub checkAlive
    
    sub stripNonNumber {
    
     my($text) = shift;
     $text =~ s/([^0-9])//g;
     return ($text);
    
    } # end sub strip non number
    
    Then type this:
    cd ~/bin ; chmod 755 proxy.pl;
    
  3. Step 3: Add to cron. Type
    crontab -e
    . Add this line (you will need to edit where it says "user"):
    * * * * * /Users/user/bin/proxy.pl  > /dev/null 2>&1
    

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.