ssh tunneling vs dynamic dns
Nick Demou
ndemou at gmail.com
Wed Oct 26 16:47:32 EEST 2011
2011/10/26 Antonis Christofides <anthony at itia.ntua.gr>:
> Γεια σας,
>
> θυμάμαι ότι παλιά είχα φτιάξει ένα μηχάνημα (A) πίσω από adsl να
> διατηρεί ανοιχτή μια σύνδεση ssh με ένα server (B) και να την
> ξανασηκώνει αν πέσει, η οποία σύνδεση προσέφερε κι ένα τουνελάκι για
> μπορώ να κάνω ssh στο A μέσω του Β. Η λύση αυτή δούλευε ωραία και
> αξιόπιστα.
>
> Σε σχέση με το dynamic dns τι σας λέει;
dynamic dns
μειονέκτημα: πρέπει να ανοίξεις πόρτες στο adsl modem
μειονέκτημα: από τις ανοιχτές πόρτες θα προσπαθούν να μπουν και άλλοι
πλεονέκτημα: εκτός από το να ανοίξεις πόρτες δεν έχεις να κάνεις τίποτα άλλο
Πριν ~2 χρόνια είχα γράψει ένα python script για τη λύση χωρίς
dynamic dns. Σε ένα pc έπαιζε σταθερά επί πολλούς μήνες. Here it is
(απαιτεί το pexpet[1]):
#! /usr/bin/python
# This program allows someone else to access the ssh daemon (or any
other TCP service)
# running on your PC even if it is behind a firewall
# THAT SOMEONE ELSE CAN DO NASTY THINGS WITH YOUR PC - you've been warned
# see 'Usage' below (or run it without parameters) for more info
#
#
# # This is how I install it in my friends (I paste the commands
bellow in pastebin.com for them):
# SERVER=x.y.z
# ls ~/.ssh/known_hosts > /dev/null && grep -v $SERVER
~/.ssh/known_hosts > /tmp/foo3029 && cat /tmp/foo3029 >
~/.ssh/known_hosts && rm -f /tmp/foo3029 && echo "OK 1"
# wget -q -O pexpect.py www.enlogic.gr/other/pexpect.py && wget -q
-O remote.py www.enlogic.gr/other/remote.py && echo "OK 2"
# PORT=ssh_port_of_the_server
# USER=user_name
# PASWD=the_password
# kill -9 `ps ax | grep ssh.*$USER@$SERVER | grep -v grep | cut -d\ -f1`
# python remote.py 22225 $SERVER $PORT "" $USER $PASWD 22 2
#
# and if there is any problem I replace 2 with 3
#
# # and some ubuntu/debian tips:
# # ...to install both the ssh client and the ssh server
# sudo apt-get install ssh
# # ...to install only the ssh client
# sudo apt-get install openssh-client
import pexpect,time,sys,re,commands
#=============================CONFIGURATION================================
# various timeouts
ConnectTimeout=20
NormalTimeout=5
ResponseTimeOut=0.5
#===========================================================================
def debug(s,level=2):
global Verbosity
if level<=Verbosity:
print "***INFO : %s"%(s)
def errmsg(s):
sys.stderr.write( "***ERROR: %s\n"%(s) )
def wait(t,msg):
debug(msg)
time.sleep(t)
# todo: maybe kill leftover ssh connections to the remotehost that may
block this port forwarding
# e.g. take the output of "ps ax" and find lines with
"%s:localhost:%s"%(MhFreePort,FhSshdPort)
# these are processes you MOST LIKELY must kill
def main():
global Verbosity
if len(sys.argv)<>9 and len(sys.argv)<>1:
print "ERROR: not enough parameters (run me with no parameters
to get help on usage)"
print len(sys.argv)
return
if len(sys.argv)==1:
print """Usage:
%s MasterHost MhSshdPort Fh2MhSshOptions MhUserName MhPassword
MhFreePort FhSshdPort Verbosity
This program allows someone else to ssh to your PC even if it is
behind a firewall
Here is a typical case:
You have a host behind a firewall that allows NO incoming
connection (Firewalled Host -- FH)
and you have a Master Host (MH) from where you want to connect to
the Firewalled Host
and the Master Host CAN ACCEPT SSH CONNECTIONS
You arange for this script to be running in FH and you can connect
from MH by issuing
this command:
ssh -p MhFreePort user at localhost
You should have a user with a dummy shell setup in MH just to
accept the ssh connection.
Here is a bash script for the dummy shell. This shell prints a
line containing the magic
word 'quit' that this script expects to recieve whenever you type anything:
#!/bin/bash
while read BUFFER; do
echo "echo type quit[ENTER] to quit"
if [ "$BUFFER" = "quit" ]; then break; fi
done
So in MH create a user and set his shell to be the bash script above.
(here is an example from my /etc/passwd
remote:x:520:520::/home/remote:/opt/dummyshell.sh
)
This script strives to keep an open ssh connection from FH to MH.
The Firewalled Host should run ssh listening to localhost:FhSshdPort
On Master Host, TCP Port locahost:MhFreePort should by free (not
bind to something else)
LIST OF PARAMETERS IN ORDER OF APEARENCE
----------------------------------------
(regarding master host)
MhFreePort (picking a random port from 30000-65000 is usualy OK)
(regarding the ssh conection from FH 2 MH)
MasterHost
MhSshdPort (typicaly 22)
Fh2MhSshOptions
MhUserName
MhPassword
(regarding free host)
FhSshdPort (typicaly 22)
(verbosity see bellow for info)
Verbosity
MORE DETAILS
------------
Regarding the verbosity option:
0=only errors
1=errors and some important messages (started/connected/disconnected)
2=most debug messages (i.e. everything except row output from
ssh session)
3=all messages
"""%(sys.argv[0]).split("/")[-1]
return
else:
try:
# regarding master host
MhFreePort=int(sys.argv[1])
# regarding the ssh conection from FH --> MH
MasterHost=sys.argv[2]
MhSshdPort=int(sys.argv[3])
Fh2MhSshOptions=sys.argv[4]
MhUserName=sys.argv[5]
MhPassword=sys.argv[6]
# regarding free host
FhSshdPort=int(sys.argv[7])
# verbosity:
Verbosity=int(sys.argv[8])
except:
errmsg("Invalid value in parameter")
# build the ssh command
sshcmd="ssh -p %s -o'RSAAuthentication=no'
-o'PubkeyAuthentication=no' %s -R %s:localhost:%s
%s@%s"%(MhSshdPort,Fh2MhSshOptions,MhFreePort,FhSshdPort,MhUserName,MasterHost)
# start an endless loop of ssh connection attempts
while 1:
debug("Trying to connect with command: "+sshcmd)
# first try to spawn an ssh command
try:
child = pexpect.spawn (sshcmd)
if Verbosity>=3: child.logfile = sys.stdout
except KeyboardInterrupt:
debug("ABORTING due to KeyboardInterrupt")
break
except:
errmsg("failed to spawn ssh")
wait(5,"waiting before retrying")
else:
debug("ssh started (but we're not yet connected)",1)
# ssh spawned, wait for MhPassword
try:
i = child.expect(['assword:', 'yes/no', 'Offending key
in'],ConnectTimeout)
except KeyboardInterrupt:
debug("ABORTING due to KeyboardInterrupt")
break
except:
errmsg("failed expecting Password or accept key")
else:
if i==0:
debug("sending Password")
child.sendline(MhPassword)
elif i==1:
debug("sending a 'yes' answer")
child.sendline("yes")
debug("sending Password")
child.expect("assword:", NormalTimeout)
child.sendline(MhPassword)
elif i==2:
errmsg("Please fix your known_hosts file to get
rid of the following error: \n\n%s" % child.before)
break
# MhPassword sent, wait for prompt
try:
i = child.expect(['Last login'],NormalTimeout)
except KeyboardInterrupt:
debug("ABORTING due to KeyboardInterrupt")
break
except:
errmsg("failed expecting 'last login' prompt")
else:
# all done, start an endless ping
debug("Connected to Firewalled Host",1)
while child.isalive()==1:
child.sendline('ping')
debug("sent command")
# expect a standard response
ExpectedResponse='quit'
try:
child.expect(ExpectedResponse,ResponseTimeOut)
response=child.after
except KeyboardInterrupt:
debug("ABORTING due to KeyboardInterrupt")
break
except:
response=0
if response==ExpectedResponse:
debug("got proper answer")
wait(10,"waiting 10secs before next ping")
elif response==0:
errmsg("Ping timed out (no response from
remote machine)")
break
else:
errmsg("bad response from remote
machine:%s"%(response))
break
# either a bad response or a time out
# close the connection if needed
if child.isalive():
debug("ABORTING SESSION (stoping ssh)",1)
child.close()
else:
debug("ABORTING SESSION (ssh process has terminated)",1)
# wait before retrying to connect
wait(10,"Waiting 10secs before retrying ssh")
errmsg("Terminated")
main()
____________
[1] Pexpect is a Python module for spawning child applications and
controlling them automatically...
More information about the Linux-greek-users
mailing list