| #!/usr/bin/env python |
| |
| """This starts an SSH tunnel to a given host. If the SSH process ever dies then |
| this script will detect that and restart it. I use this under Cygwin to keep |
| open encrypted tunnels to port 25 (SMTP), port 143 (IMAP4), and port 110 |
| (POP3). I set my mail client to talk to localhost and I keep this script |
| running in the background. |
| |
| Note that this is a rather stupid script at the moment because it just looks to |
| see if any ssh process is running. It should really make sure that our specific |
| ssh process is running. The problem is that ssh is missing a very useful |
| feature. It has no way to report the process id of the background daemon that |
| it creates with the -f command. This would be a really useful script if I could |
| figure a way around this problem. """ |
| |
| import pexpect |
| import getpass |
| import time |
| |
| # SMTP:25 IMAP4:143 POP3:110 |
| tunnel_command = 'ssh -C -N -f -L 25:127.0.0.1:25 -L 143:127.0.0.1:143 -L 110:127.0.0.1:110 %(user)@%(host)' |
| host = raw_input('Hostname: ') |
| user = raw_input('Username: ') |
| X = getpass.getpass('Password: ') |
| |
| |
| def get_process_info(): |
| |
| # This seems to work on both Linux and BSD, but should otherwise be |
| # considered highly UNportable. |
| |
| ps = pexpect.run('ps ax -O ppid') |
| pass |
| |
| |
| def start_tunnel(): |
| try: |
| ssh_tunnel = pexpect.spawn(tunnel_command % globals()) |
| ssh_tunnel.expect('password:') |
| time.sleep(0.1) |
| ssh_tunnel.sendline(X) |
| time.sleep(60) # Cygwin is slow to update process status. |
| ssh_tunnel.expect(pexpect.EOF) |
| |
| except Exception, e: |
| print str(e) |
| |
| |
| def main(): |
| |
| while True: |
| ps = pexpect.spawn('ps') |
| time.sleep(1) |
| index = ps.expect(['/usr/bin/ssh', pexpect.EOF, pexpect.TIMEOUT]) |
| if index == 2: |
| print 'TIMEOUT in ps command...' |
| print str(ps) |
| time.sleep(13) |
| if index == 1: |
| print time.asctime(), |
| print 'restarting tunnel' |
| start_tunnel() |
| time.sleep(11) |
| print 'tunnel OK' |
| else: |
| # print 'tunnel OK' |
| time.sleep(7) |
| |
| if __name__ == '__main__': |
| main() |
| |
| # This was for older SSH versions that didn't have -f option |
| #tunnel_command = 'ssh -C -n -L 25:%(host)s:25 -L 110:%(host)s:110 %(user)s@%(host)s -f nothing.sh' |
| # nothing_script = """#!/bin/sh |
| # while true; do sleep 53; done |
| #""" |