美文网首页
2020-02-22 搭建FTP服务器与客户端

2020-02-22 搭建FTP服务器与客户端

作者: 阿丧小威 | 来源:发表于2020-02-23 01:01 被阅读0次

    1. 搭建FTP服务器

    FTP(File Transfer Protocol,文件传输协议)运行在TCP协议上,使用两个端口,即数据端口和命令端口,也称控制端口。默认情况下,20是数据端口,21是命令端口。
    FTP有两种传输模式:主动模式和被动模式。
    (1)主动模式:客户端首先从任意的非特殊端口n(大于1023的端口,也是客户端的命令端口)连接FTP服务器的命令端口(默认是21),向服务发出命令PORT n+1,告诉服务器自己使用n+1端口作为数据端口进行数据传输,然后在n+1端口监听。服务器收到PORT n+1后向客户端返回一个'ACK',然后服务器从它自己的数据端口(20)到客户端先前指定的数据端口(n+1端口)的连接,最后客户端向服务器返回一个'ACK',过程结束。

    ftp的主动模式

    (2)被动模式:为了解决服务器发起到客户的连接问题,人们开发了被动FTP,或者叫作PASV,当客户端通知服务器处于被动模式时才启用。在被动模式FTP中,命令连接和数据连接都由客户端发起。当开启一个FTP连接时,客户端打开两个任意的非特权本地端口(大于1023)。第一个端口连接服务器的21端口,但与主动方式的FTP不同,客户端不会提交PORT命令并允许服务器来回连接数据端口,而是提交PASV命令。这样做的结果是服务器会开启一个任意的非特权端口,并发送PORT P命令给客户端,然后客户端发起从本地端口N+1到服务器的端口P的连接用来传送数据。

    ftp的被动模式

    总结:主动方式对FTP服务器的管理有利,但对客户端的管理不利。因为FTP服务器企图与客户端的高位随机端口建立连接,而这个端口很有可能被客户端的防火墙阻塞掉。被动方式对FTP客户端的管理有利,但对服务器端的管理不利。因为客户端要与服务器端建立两个连接,其中一个连到一个高位随机端口,而这个端口很有可能被服务器端的防火墙阻塞掉。
    使用Python搭建一个FTP服务器需要pyftpdlib模块,安装非常简单:

    pip install pyftpdlib
    

    (1)快速搭建一个简单的FTP服务器。执行:

    python -m pyftpdlib -p 21
    

    即可在执行命令所在的目录下建立一个端口为21的供下载文件的FTP服务器,注意Linux系统需要root用户才能使用默认端口21,windows系统中目录文件名可能是乱码,原因是pyftpdlib内部使用utf8,而windows使用gbk,参照下面的步骤可解决windows系统的乱码问题。
    首先,找到pyftpdlib源文件所在的目录。

    [root@localhost ~]# python3
    Python 3.6.5 (default, Jun 29 2019, 14:06:04) 
    [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import pyftpdlib
    >>> pyftpdlib.__path__
    ['/usr/local/python3.6.5/lib/python3.6/site-packages/pyftpdlib']
    

    其次,在目录pyftpdlib源文件所在的目录找到文件filesystems.py和handlers.py,先备份。

    [root@localhost ~]# cd /usr/local/python3.6.5/lib/python3.6/site-packages/pyftpdlib
    [root@localhost pyftpdlib]# ls
    authorizers.py  filesystems.py  __init__.py  log.py       prefork.py   servers.py
    _compat.py      handlers.py     ioloop.py    __main__.py  __pycache__  test
    

    再次,打开filesystems.py,找到

    yield line.encode('utf8, self.cmd_channel.unicode_errors)
    

    共有两处,修改'utf8'为'gbk',保存退出。
    打开handlers.py,找到

    return bytes.decode('utf8', self.unicode_errors)
    

    修改utf8为gbk,保存退出。
    最后,验证乱码已解决。
    (2)搭建一个具有访问权限,可配置相关信息的FTP服务器(ftpserver.py)。

    from pyftpdlib.authorizers import DummyAuthorizer
    from pyftpdlib.handlers import FTPHandler,ThrottledDTPHandler
    from pyftpdlib.servers import FTPServer
    from pyftpdlib.log import LogFormatter
    import logging
    
    
    #记录日志,默认情况下日志仅输出到屏幕(终端),这里既输出到屏幕又输出到文件,方便日志查看
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    ch = logging.StreamHandler()
    fh = logging.FileHandler(filename='myftpserver.log',encoding='utf-8')   #默认的方式是追加到文件
    ch.setFormatter(LogFormatter())
    fh.setFormatter(LogFormatter())
    logger.addHandler(ch)   #将日志输出至屏幕
    logger.addHandler(fh)   #将日志输出至文件
    
    
    # 实例化虚拟用户,这是FTP验证首要条件
    authorizer = DummyAuthorizer()
    # 添加用户权限和路径,括号内的参数是(用户名、密码、用户目录、权限),可以为不同的用户添加不同的目录和权限
    authorizer.add_user("user", "12345", "/ftp", perm="elradfmw")
    # 添加匿名用户,只需要路径
    authorizer.add_anonymous("/ftp")
    
    # 初始化ftp句柄
    handler = FTPHandler
    handler.authorizer = authorizer
    
    # 添加被动端口范围
    handler.passive_ports = range(2000,2333)
    
    # 下载上传速度
    dtp_handler = ThrottledDTPHandler
    dtp_handler.read_limit = 300 * 1024 #300kb/s
    dtp_handler.write_limit  300 * 1024 #300kb/s
    handler.dtp_handler = dtp_handler
    
    # 监听ip和端口,linux里需要root用户
    server = FTPServer(("0.0.0.0", 21), handler)
    
    # 最大连接数
    server.max_cons = 150
    server.max_cons_per_ip = 15
    
    # 开始服务,自带日志打印信息
    server.serve_forever()
    

    执行python ftpserver.py

    [root@localhost ~]# python3 ftpserver.py 
    [I 2020-02-22 17:03:23] concurrency model: async
    [I 2020-02-22 17:03:23] masquerade (NAT) address: None
    [I 2020-02-22 17:03:23] passive ports: 2000->2332
    [I 2020-02-22 17:03:23] >>> starting FTP server on 0.0.0.0:21, pid=7716 <<<
    

    同时该目录下也会生成一个myftpserver.log文件,文件内容与屏幕上的信息一致。
    下面我们登录该FTP并列出目录进行测试:

    C:\Users\willi>ftp 192.168.9.43
    连接到 192.168.9.43。
    220 pyftpdlib 1.5.6 ready.
    530 Log in with USER and PASS first.
    用户(192.168.9.43:(none)): user
    331 Username ok, send password.
    密码:
    230 Login successful.
    ftp> dir
    200 Active data connection established.
    125 Data connection already open. Transfer starting.
    226 Transfer complete.
    ftp> dir
    200 Active data connection established.
    125 Data connection already open. Transfer starting.
    drwxr-xr-x   2 root     root            6 Feb 22 09:19 test
    226 Transfer complete.
    ftp: 收到 64 字节,用时 0.00秒 32.00千字节/秒。
    ftp>
    

    对应服务器的打印信息:

    [root@localhost ~]# python3 ftpserver.py 
    [I 2020-02-22 17:03:23] concurrency model: async
    [I 2020-02-22 17:03:23] masquerade (NAT) address: None
    [I 2020-02-22 17:03:23] passive ports: 2000->2332
    [I 2020-02-22 17:03:23] >>> starting FTP server on 0.0.0.0:21, pid=7716 <<<
    [I 2020-02-22 17:18:40] 192.168.9.206:8439-[] FTP session opened (connect)
    [I 2020-02-22 17:18:48] 192.168.9.206:8439-[user] USER 'user' logged in.
    [I 2020-02-22 17:24:25] 192.168.9.206:8439-[user] Control connection timed out.
    [I 2020-02-22 17:24:25] 192.168.9.206:8439-[user] FTP session closed (disconnect).
    

    至此,一个FTP服务器已经搭建完成,可以修改ftpserver.py来满足自己的需求。
    用户权限的代码及说明:

    image.png image.png

    2. 编写FTP客户端程序

    在实际应用中可能经常访问FTP服务器来上传或下载文件,Python也可以替我们做这些。

    # -*- coding: utf-8 -*-
    # !/usr/local/bin/python
    # Time: 2020/2/22 22:22:22
    # Description:
    # File Name: ftpclient.py
    
    from ftplib import FTP
    #登录FTP
    ftp = FTP('localhost', user='user', passwd='12345')
    #设置编码方式,由于在windows系统,设置编码为gbk
    ftp.encoding = 'gbk'
    # 切换目录
    ftp.cwd('test')
    #列出文件夹的内容
    ftp.retrlines('LIST')   # ftp.dir()
    #下载文件 note.txt
    ftp.retrbinary('RETR note.txt', open('note.txt', 'wb').write)
    #上传文件 ftpserver.py
    ftp.storbinary('STOR ftpserver.py', open('ftpserver.py', 'rb'))
    #查看目录下的文件详情
    for f in ftp.mlsd(path='/test'):
        print(f)
    

    运行结果如下:

    [root@localhost ~]# python3 ftpclient.py 
    -rw-r--r--   1 root     root            0 Feb 22 16:58 note.txt
    ('note.txt', {'modify': '20200222165853', 'perm': 'radfw', 'size': '0', 'type': 'file', 'unique': 'fd00gf155'})
    ('ftpserver.py', {'modify': '20200222165941', 'perm': 'radfw', 'size': '1681', 'type': 'file', 'unique': 'fd00gf156'})
    

    注意:操作前需要先进入/ftp目录创建对应的目录和文件。

    相关文章

      网友评论

          本文标题:2020-02-22 搭建FTP服务器与客户端

          本文链接:https://www.haomeiwen.com/subject/vxmcqhtx.html