简体   繁体   中英

can't upload file using ftplib over ssh-tunnel

I'm trying to upload a file using ftplib over an sshtunnel. I can login successfully to the remote end ftp server over this tunnel, but the program times out when trying to send the file.

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()

I can certanly connect and login:

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'

... but a time out rises when trying to upload the file ...

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

any hint?

thanks!

So the thing is I was missing tunneling the data port of FTP. In order to avoid creating a second tunnel, I just used sftp instead.

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)

With the previous I can upload a file to a remote SFTP server over an SSH tunnel. Yes, is not FTP, but it worked for me.

If FTP is the only possible way, then a second ssh tunnel for the data channel will be needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM