Created
July 6, 2012 14:27
-
-
Save mrgriscom/3060466 to your computer and use it in GitHub Desktop.
reverse ssh tunnel script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import os.path | |
import re | |
import time | |
import json | |
# script to create an ssh tunnel from a public server back to a private (firewalled/NATted) machine; a poor man's VPN, basically | |
# how it works: | |
# private machine run this script at regular intervals, which attempts to ssh into public server; if successful, it | |
# sets up a number of port forwards back to private machine so you can access it from public server | |
# to use: | |
# 1) configure the settings below | |
# 2) set up key-based auth for private machine to log into public server | |
# 3) set up cron on private machine to run the script at frequent intervals (<= 5 minutes) | |
# 4) when the tunnel is up, access private machine via: | |
# ssh -l PORT youracct@localhost (from public server) | |
# ssh -l PORT youracct@publicserver (from internet at large, if you made the ssh-forward publicly hittable) | |
def mk_port_forward(listen_at, local_port, remote_port, public=False): | |
pattern = { | |
'forward': '-L %(public)s%(local)d:localhost:%(remote)d', | |
'reverse': '-R %(public)s%(remote)d:localhost:%(local)d', | |
}[listen_at] | |
return pattern % { | |
'public': '*:' if public else '', | |
'local': local_port, | |
'remote': remote_port, | |
} | |
def mk_port_forwards(port_forwards): | |
return ' '.join(mk_port_forward(*f) for f in port_forwards) | |
def mk_tunnel_cmd(user, server, forwards, compression=True, keyfile=None): | |
options = [ | |
'BatchMode yes', # abort if any interactive prompt (e.g., password) shown | |
'ExitOnForwardFailure yes', # abort if port forwards unavailable (usually means tunnel is already up) | |
'ServerAliveInterval 60', # use keep-alive pings to prevent stale sessions | |
] | |
return 'ssh %s@%s -N %s %s %s %s' % (user, server, '-C' if compression else '', '-i %s' % keyfile if keyfile else '', | |
mk_port_forwards(forwards), ' '.join('-o "%s"' % opt for opt in options)) | |
if __name__ == "__main__": | |
# public server as resolvable from private machine | |
SERVER = 'example.com' | |
# user that private machine will log into public server as | |
USER = 'user' | |
# port of the reverse-ssh endpoint | |
PORT = '2222' | |
# private keyfile used to log into USER@SERVER. if None, ssh will search in the default places. | |
# note that key-based auth is required! password-based auth will not work, as there is no one | |
# to type in the password | |
KEYFILE = None | |
PORT_FORWARDS = [ | |
('reverse', 22, PORT, True), #reverse ssh | |
# add additional port forwards here | |
] | |
# probably enable for mobile-tethered connections | |
USE_COMPRESSION = False | |
os.popen(mk_tunnel_cmd(USER, SERVER, PORT_FORWARDS, USE_COMPRESSION, KEYFILE)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment