[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

checking ssh tunnels: best practices?



Hi, all.

I've got a laptop (yes, I'm on this list, duh).  I take it
to a jobsite with me, I take it home, I take it to the
office.  Some places I can connect to the mailserver
directly, but at other places I have to ssh through a leased
line back to the office.

I've got ssh set up with tunnels for one smtp port,
three POP ports, a VNC session, etc.  I set up exim 
to send its mail through the tunnel smtp, and set up 
fetchmail to fetch through the tunnel.

The problem is that sometimes these programs don't work
right and hassle ensues if I start them up without starting
up my ssh session first, or if the ssh session has dropped
someplace along the way.  A lot of the time I'm working
locally, so I might not notice that the tunnel went away,
and exim will tell me that the message couldn't be
delivered, etc.

The hack I've done is to make a little script,
port_is_connected, so I can have my mutt-starter script
abort with a line like this:

    port_is_connected $MAIL1SMTP localhost || exit 1

...or less tersely...

    if ! port_is_connected $MAIL1SMTP localhost 
    then
      echo "check the ssh tunnel, dammit!"
      exit 1
    fi

Does this approach make sense, overall?

It took me a while to figure out how to do port_is_connected, but 
eventually I located nmap.  This does the job pretty well
and is pretty fast:

    nmap -p $MAIL1SMTP localhost | grep -q open

I had been using something like this...

    ps -ef | grep "ssh.*$MAIL1SMTP"

... but I don't like that much for a variety of reasons.

So this is what I came up with for port_is_connected:

    #!/bin/sh
    
    port=""
    host=""
    err=""
    
    while [ -n "$1" ]
    do
    
      case "$1" in
    
      -*) 
        err="$err\nunexpected opt"
        ;;
    
      *)
        if [ -z "$port" ]
        then
          case "$1" in
          [0-9]*)
            port="$1"
            ;;
          *)
            err="$err\nhuh? [$1]"
            ;;
          esac
        elif [ -z "$host" ]
        then
          host="$1"
        else
          err="$err\ntoo many args [$1]"
        fi
        ;;
    
      esac
    
      shift
    
    done
    
    if [ -n "$err" ]; then printf "ERR$err\n"; exit 2; fi
    
    if [ -z "$port" ]; then err="$err\nno port specified"; fi
    
    if [ -n "$err" ]; then printf "ERR$err\n"; exit 2; fi
    
    if [ -z "$host" ]; then 
      host=localhost
      printf "no host given; assuming host[$host]\n" >&2
    fi
    
    if nmap -p $port $host | grep -q open 
    then
      printf "port $host:$port is open: exit 0\n" >&2
      exit 0
    else
      printf "port $host:$port is closed: exit 1\n" >&2
      exit 1
    fi
    
So, comments please.  Is this a good way to do it, or am I
missing a better, obvious way?  Comments on style are also
welcome.  

Tony 
 



Reply to: