对 python的 ftp 模块 探坑之旅

image.png

python 自带一个ftp 模块 ftplib
一般常用的都可以搞定,
一般直接使用它的 FTP(),如果 ssl 加密啥的就用 FTP_TLS()

具体的,参考

https://docs.python.org/2/library/ftplib.html
https://www.cnblogs.com/kaituorensheng/p/4480512.html

ftp登陆连接
from ftplib import FTP            #加载ftp模块
ftp=FTP()                         #设置变量
ftp.set_debuglevel(2)             #打开调试级别2,显示详细信息
ftp.connect("IP","port")          #连接的ftp sever和端口
ftp.login("user","password")      #连接的用户名,密码
print ftp.getwelcome()            #打印出欢迎信息
ftp.cmd("xxx/xxx")                #进入远程目录
bufsize=1024                      #设置的缓冲区大小
filename="filename.txt"           #需要下载的文件
file_handle=open(filename,"wb").write #以写模式在本地打开文件
ftp.retrbinaly("RETR filename.txt",file_handle,bufsize) #接收服务器上文件并写入本地文件
ftp.set_debuglevel(0)             #关闭调试模式
ftp.quit()                        #退出ftp
 
ftp相关命令操作
ftp.cwd(pathname)                 #设置FTP当前操作的路径
ftp.dir()                         #显示目录下所有目录信息
ftp.nlst()                        #获取目录下的文件
ftp.mkd(pathname)                 #新建远程目录
ftp.pwd()                         #返回当前所在位置
ftp.rmd(dirname)                  #删除远程目录
ftp.delete(filename)              #删除远程文件
ftp.rename(fromname, toname)#将fromname修改名称为toname。
ftp.storbinaly("STOR filename.txt",file_handel,bufsize)  #上传目标文件
ftp.retrbinary("RETR filename.txt",file_handel,bufsize)  #下载FTP文件

BUT
这次超级失败的是,我一直没有连接成功,坑实在太多,我一个人根本不够填

运维也不愿意花时间帮我解决这个小问题,我自己吭哧半天还不如人间 filiza 或者命令行 连得快,现在可以看一段实例

from ftplib import FTP
from ftplib import FTP_TLS
#from ftplib import resp
host='ftps.baidu.com'
port='21'
user='zhuzh***'
pwd='zzg**t.2'
ip='117.43.165.150'
files = []
#实名用户 加密登录
ftps = FTP_TLS(host)
ftps.set_debuglevel(2)
ftps.auth()

ftps.login(user,pwd)
ftps.makepasv()
ftps.sendcmd('pbsz 0')
ftps.set_pasv(True)

ftps.prot_p()

files = ftps.nlst()
for f in files:
    print(f)

按照正常的套路其实以上是可以正常运行,然鹅儿一直失败,


425 Security: Bad IP connecting
其实是
主要是需要在/etc/vsftpd/vsftpd.conf文件中添加如下一行:

pasv_promiscuous=YES

service vsftpd restart

pasv_promiscuous选项参数说明:
此选项激活时,将关闭PASV模式的安全检查。该检查确保数据连接和控制连接是来自同一个IP地址。小心打开此选项。此选项唯一合理的用法是存在于由安全隧道方案构成的组织中。默认值为NO。
合理的用法是:在一些安全隧道配置环境下,或者更好地支持FXP时(才启用它)。

但是程序里做不到,也修改不了服务器配置文件

后来思路变了,参考
https://stackoverflow.com/questions/44057732/connecting-to-explicit-ftp-over-tls-in-python?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

The problem is that the server is returning the wrong IP address inside the response to the PASV command. This is typical for servers in some internal network behind some firewall. In this case 10.19.1.137 is returned, which is an IP address usable in local networks only.

This is a broken setup of the FTP server. But unfortunately such broken setup is common so many clients work around it by ignoring the given IP address in the response and using instead the IP address of the control connection. ftplib has no support for such workaround. But one can monkey patch it to provide such support:

我理解大致意思就是 ftp 好像对内网识别不是很友好 ,需要借助sock 来打辅助

下面的这段代码简直就是雪中送炭

from ftplib import FTP_TLS

# replace original makepasv function with one which always returns
# the peerhost of the control connections as peerhost for the data
# connection
_old_makepasv = FTP_TLS.makepasv
def _new_makepasv(self):
    host,port = _old_makepasv(self)
    host = self.sock.getpeername()[0]
    return host,port
FTP_TLS.makepasv = _new_makepasv

ftp = FTP_TLS(ipAddress)
ftp.login(...)
ftp.nlst()

最后尝试 后非常好用,我的大半天都奉献在这里了,好心酸

from ftplib import FTP
from ftplib import FTP_TLS
#from ftplib import resp
host='ftps.baidu.com'
port='21'
user='zhu**g'
pwd='zz***mt.2'
ip='117.48.195.150'
files = []
_old_makepasv = FTP_TLS.makepasv
def _new_makepasv(self):
    host,port = _old_makepasv(self)
    host = self.sock.getpeername()[0]
    return host,port
FTP_TLS.makepasv = _new_makepasv

#实名用户 加密登录
ftps = FTP_TLS(host)
ftps.set_debuglevel(2)
ftps.auth()

ftps.login(user,pwd)
ftps.makepasv()
ftps.sendcmd('pbsz 0')
ftps.set_pasv(True)
ftps.prot_p()

files = ftps.nlst()
for f in files:
    print(f)

FTP Illegal PORT command

500 Illegal PORT command的问题(FTP主被动模式)

Python ftplib timing out

你可能感兴趣的:(对 python的 ftp 模块 探坑之旅)