本地转发代码forward.py
#!/usr/bin/env python
import os
import socket
import select
import SocketServer
import sys
import paramiko
def verbose(s):
print s
class ForwardServer (SocketServer.ThreadingTCPServer):
daemon_threads = True
allow_reuse_address = True
class Handler (SocketServer.BaseRequestHandler):
def handle(self):
try:
chan = self.ssh_transport.open_channel('direct-tcpip',
(self.chain_host, self.chain_port),
self.request.getpeername())
except Exception, e:
verbose('Incoming request to %s:%d failed: %s' % (self.chain_host,
self.chain_port,
repr(e)))
return
if chan is None:
verbose('Incoming request to %s:%d was rejected by the SSH server.' %
(self.chain_host, self.chain_port))
return
verbose('Connected! Tunnel open %r -> %r -> %r' % (self.request.getpeername(),
chan.getpeername(), (self.chain_host, self.chain_port)))
try:
while True:
r, w, x = select.select([self.request, chan], [], [])
if self.request in r:
data = self.request.recv(1024)
if len(data) == 0:
break
chan.send(data)
if chan in r:
data = chan.recv(1024)
if len(data) == 0:
break
self.request.send(data)
except Exception as e:
verbose('Forward request to %s:%d was failed.' %
(self.chain_host, self.chain_port))
verbose('Tunnel closed from %r' % (self.request.getpeername(),))
chan.close()
self.request.close()
forwardServer=None;
def forward_tunnel(local_port, remote_host, remote_port, transport):
class SubHander (Handler):
chain_host = remote_host
chain_port = remote_port
ssh_transport = transport
global forwardServer
forwardServer=ForwardServer(('', local_port), SubHander);
forwardServer.serve_forever();
def stopForward():
if forwardServer:
forwardServer.shutdown();
def forward(local_port,ssh_host,ssh_port,username,password,remote_host,remote_port):
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
try:
client.connect(ssh_host, ssh_port, username,password)
except Exception, e:
print '*** Failed to connect to %s:%d: %r' % (ssh_host, ssh_port, e)
sys.exit(1)
verbose('Now forwarding port %d to %s:%d ...' % (local_port, remote_host, remote_port))
try:
forward_tunnel(local_port, remote_host, remote_port, client.get_transport())
except KeyboardInterrupt:
print 'C-c: Port forwarding stopped.'
sys.exit(0)
if __name__ == '__main__':
forward(3306,"ssh.company.com",22,"admin","pwd","172.24.23.21",3306)
先启动转发服务。
通过代理连接数据库服务器 test.py:
conn=MySQLdb.connect(host="127.0.0.1", port=3306, user="user", passwd="pwd", db="db",
connect_timeout=1000, charset="GBK")
cur=conn.cursor()
cur.execute("""select * from temp limit 5""");
for c in cursor:
print c
cur.close();
conn.close()
注意,这里是先向本地3306发送数据,本地转发服务接收到数据后会转发给SSHD服务,SSHD服务会帮我们将数据转发到目标服务器,得到响应后再原路返回。