无法在ssh-tunnel上使用ftplib上传文件

时间:2019-12-14 22:17:30

标签: python ftp ssh-tunnel

我正在尝试通过sshtunnel使用ftplib上传文件。我可以通过此隧道成功登录到远程ftp服务器,但是在尝试发送文件时程序超时。

import paramiko
from sshtunnel import SSHTunnelForwarder
from ftplib import FTP

USER               = ["userSSH","passSSH"]
SSHPORT            = 22
SSHIP              = "A.B.C.D"
ROUTER_FTP_PORT    = 21
REMOTE_FTP         = "W.X.Y.Z"

fserver = SSHTunnelForwarder( (SSHIP, SSHPORT), 
    ssh_username        = USER[0], 
    ssh_password        = USER[1], 
    remote_bind_address = (REMOTE_FTP, ROUTER_FTP_PORT), )

fserver.start()
fport = fserver.local_bind_port

ftp = FTP()
ftp.connect("127.0.0.1",fport)
ftp.login("ftpUser","ftpPass")
file = open('lucas.cfg','rb')
ftp.storbinary('STOR lucas.cfg',file)
file.close()

我可以安全地连接并登录:

In [8]: ftp.connect("127.0.0.1",fport)
Out[8]: '220 FTP server ready'

In [9]: ftp.login("ftpUser","ftpPass")
Out[9]: '230 User logged in'

...但是尝试上传文件时超时...

In [19]: ftp.storbinary('STOR lucas.cfg',file)
---------------------------------------------------------------------------
TimeoutError                              Traceback (most recent call last)
<ipython-input-19-0af0cb3b5ebf> in <module>()
----> 1 ftp.storbinary('STOR lucas.cfg',file)

/usr/lib/python3.6/ftplib.py in storbinary(self, cmd, fp, blocksize, callback, rest)
    502         """
    503         self.voidcmd('TYPE I')
--> 504         with self.transfercmd(cmd, rest) as conn:
    505             while 1:
    506                 buf = fp.read(blocksize)

/usr/lib/python3.6/ftplib.py in transfercmd(self, cmd, rest)
    397     def transfercmd(self, cmd, rest=None):
    398         """Like ntransfercmd() but returns only the socket."""
--> 399         return self.ntransfercmd(cmd, rest)[0]
    400 
    401     def login(self, user = '', passwd = '', acct = ''):

/usr/lib/python3.6/ftplib.py in ntransfercmd(self, cmd, rest)
    359             host, port = self.makepasv()
    360             conn = socket.create_connection((host, port), self.timeout,
--> 361                                             source_address=self.source_address)
    362             try:
    363                 if rest is not None:

/usr/lib/python3.6/socket.py in create_connection(address, timeout, source_address)
    722 
    723     if err is not None:
--> 724         raise err
    725     else:
    726         raise error("getaddrinfo returns an empty list")

/usr/lib/python3.6/socket.py in create_connection(address, timeout, source_address)
    711             if source_address:
    712                 sock.bind(source_address)
--> 713             sock.connect(sa)
    714             # Break explicitly a reference cycle
    715             err = None

TimeoutError: [Errno 110] Connection timed out

有任何提示吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

所以问题是我没有在FTP的数据端口上建立隧道。为了避免创建第二条隧道,我只使用了sftp。

server = SSHTunnelForwarder( (SSHIP, SSHPORT), 
    ssh_username        = USER[0], 
    ssh_password        = USER[1], 
    remote_bind_address = (REMOTE_SFTP, ROUTER_SFTP_PORT), )

server.start()
sftpPort = server.local_bind_port

transport = paramiko.Transport(("127.0.0.1",sftpPort))
transport.connect(None,username,password)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put(fileLocal,fileRemote)

使用前一个,我可以通过SSH隧道将文件上传到远程SFTP服务器。是的,不是FTP,但是对我有用。

如果FTP是唯一可行的方法,则需要用于数据通道的第二条ssh隧道。