我正在尝试使用django连接到远程mysql数据库 该文档指定首先需要打开SSH隧道才能连接到数据库 是否有一个python库可以在设置某些设置时打开SSH隧道?
答案 0 :(得分:7)
答案 1 :(得分:5)
这是Python3的代码片段(但你应该可以毫不费力地将它改装成Python2)。它在一个单独的线程中运行SSH隧道;然后主线程通过SSH隧道获取网络流量。
在此示例中,ssh隧道将本地端口2222转发到localhost上的端口80。主要活动包括运行
curl http://localhost:2222
即,从端口2222获取网页。
类SshTunnel初始化为4个参数,本地和远程端口,远程用户和远程主机。它只是以下列方式启动SSH:
ssh -N -L localport:remotehost:remoteport remoteuser@remotehost
为了完成这项工作,您需要为remoteuser @ remotehost提供无密码登录(通过远程服务器上已知的〜/ .ssh / id_rsa.pub)。 这样运行的ssh隧道在一个线程上;主要任务必须是另一个。 ssh隧道线程被标记为守护进程,因此一旦主活动终止,它将自动停止。
我没有提供完整的MySQL连接示例,因为它应该是不言自明的。一旦SshTunnel设置了本地TCP端口,您就可以连接到它 - 无论是通过MySQL客户端,卷曲还是其他任何东西。
import subprocess
import time
import threading
class SshTunnel(threading.Thread):
def __init__(self, localport, remoteport, remoteuser, remotehost):
threading.Thread.__init__(self)
self.localport = localport # Local port to listen to
self.remoteport = remoteport # Remote port on remotehost
self.remoteuser = remoteuser # Remote user on remotehost
self.remotehost = remotehost # What host do we send traffic to
self.daemon = True # So that thread will exit when
# main non-daemon thread finishes
def run(self):
if subprocess.call([
'ssh', '-N',
'-L', str(self.localport) + ':' + self.remotehost + ':' + str(self.remoteport),
self.remoteuser + '@' + self.remotehost ]):
raise Exception ('ssh tunnel setup failed')
if __name__ == '__main__':
tunnel = SshTunnel(2222, 80, 'karel', 'localhost')
tunnel.start()
time.sleep(1)
subprocess.call(['curl', 'http://localhost:2222'])
答案 2 :(得分:3)
尝试使用sshtunnel package。
这很简单:
pip install sshtunnel
python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost
披露:我是此软件包的作者和维护者。
答案 3 :(得分:2)
这是一个可以放入代码的小课程:
import subprocess
import random
import tempfile
class SSHTunnel:
def __init__(self, host, user, port, key, remote_port):
self.host = host
self.user = user
self.port = port
self.key = key
self.remote_port = remote_port
# Get a temporary file name
tmpfile = tempfile.NamedTemporaryFile()
tmpfile.close()
self.socket = tmpfile.name
self.local_port = random.randint(10000, 65535)
self.local_host = '127.0.0.1'
self.open = False
def start(self):
exit_status = subprocess.call(['ssh', '-MfN',
'-S', self.socket,
'-i', self.key,
'-p', self.port,
'-l', self.user,
'-L', '{}:{}:{}'.format(self.local_port, self.local_host, self.remote_port),
'-o', 'ExitOnForwardFailure=True',
self.host
])
if exit_status != 0:
raise Exception('SSH tunnel failed with status: {}'.format(exit_status))
if self.send_control_command('check') != 0:
raise Exception('SSH tunnel failed to check')
self.open = True
def stop(self):
if self.open:
if self.send_control_command('exit') != 0:
raise Exception('SSH tunnel failed to exit')
self.open = False
def send_control_command(self, cmd):
return subprocess.check_call(['ssh', '-S', self.socket, '-O', cmd, '-l', self.user, self.host])
def __enter__(self):
self.start()
return self
def __exit__(self, type, value, traceback):
self.stop()
以下是您可以使用它的方法,例如MySQL(通常是端口3306):
with SSHTunnel('database.server.com', 'you', '22', '/path/to/private_key', '3306') as tunnel:
print "Connected on port {} at {}".format(tunnel.local_port, tunnel.local_host)
答案 4 :(得分:0)
我建议您尝试使用pyngrok
之类的程序来为您管理ngrok
隧道吗?完全公开,我是它的开发者。 SSH示例here和Django示例here,但是就像安装pyngrok
一样简单:
pip install pyngrok
并使用它:
from pyngrok import ngrok
# <NgrokTunnel: "tcp://0.tcp.ngrok.io:12345" -> "localhost:22">
ssh_tunnel = ngrok.connect(22, "tcp")
或者公开您的MySQL数据库:
# <NgrokTunnel: "tcp://0.tcp.ngrok.io:12346" -> "localhost:3306">
mysql_tunnel = ngrok.connect(3306, "tcp")
或者公开给Django开发服务器:
# <NgrokTunnel: "http://<public_sub>.ngrok.io" -> "http://localhost:8000">
http_tunnel = ngrok.connect(8000)