zoukankan      html  css  js  c++  java
  • python实现FTP服务器

    基础知识

    FTP只通过TCP连接,FTP不同于其他服务的是它使用了两个端口, 一个数据端口和一个命令端口(或称为控制端口)。

    通常21端口是命令端口,20端口是数据端口。当混入主动/被动模式的概念时,数据端口就有可能不是20了

    FTP主动模式

    在主动模式下,FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,

    然后开放N+1号端口进行监听,并向服务器发出PORT N+1命令。

    服务器接收到命令后,会用其本地的FTP数据端口(通常是20)来连接客户端指定的端口N+1,进行数据传输。

    • FTP服务器命令(21)端口接受客户端任意端口(客户端初始连接)
    • FTP服务器命令(21)端口到客户端端口(>1023)(服务器响应客户端命令)
    • FTP服务器数据(20)端口到客户端端口(>1023)(服务器初始化数据连接到客户端数据端口)
    • FTP服务器数据(20)端口接受客户端端口(>1023)(客户端发送ACK包到服务器的数据端口)

    主动模式的优点:

    服务端配置简单,利于服务器安全管理,服务器只需要开放21端口

    主动模式的缺点:

    如果客户端开启了防火墙,或客户端处于内网(NAT网关之后), 那么服务器对客户端端口发起的连接可能会失败

    FTP被动模式

    在被动模式下,FTP库户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,同时会开启N+1号端口。

    然后向服务器发送PASV命令,通知服务器自己处于被动模式。

    服务器收到命令后,会开放一个大于1024的端口P进行监听,然后用PORT P命令通知客户端,自己的数据端口是P。

    客户端收到命令后,会通过N+1号端口连接服务器的端口P,然后在两个端口之间进行数据传输

    • FTP服务器命令(21)端口接受客户端任意端口(客户端初始连接)
    • FTP服务器命令(21)端口到客户端端口(>1023)(服务器响应客户端命令)
    • FTP服务器数据端口(>1023)接受客户端端口(>1023)(客户端初始化数据连接到服务器指定的任意端口)
    • FTP服务器数据端口(>1023)到客户端端口(>1023)(服务器发送ACK响应和数据到客户端的数据端口)

    被动模式缺点:

    服务器配置管理稍显复杂,不利于安全,服务器需要开放随机高位端口以便客户端可以连接,因此大多数FTP服务软件都可以手动配置被动端口的范围

    被动模式的优点:

    对客户端网络环境没有要求

    总结

    主动FTP:
         命令连接:客户端 >1023端口 -> 服务器 21端口
         数据连接:客户端 >1023端口 <- 服务器 20端口 

      被动FTP:
         命令连接:客户端 >1023端口 -> 服务器 21端口
         数据连接:客户端 >1023端口 -> 服务器 >1023端口 

    使用python来实现FTP服务

    安装模块 pyftpdlib

    pip3 install pyftpdlib
    

    教程

    http://pyftpdlib.readthedocs.io/en/latest/tutorial.html

    源码

    https://github.com/giampaolo/pyftpdlib

    使用:

    from pyftpdlib.authorizers import DummyAuthorizer
    from pyftpdlib.handlers import FTPHandler
    from pyftpdlib.servers import FTPServer
    
    # 新建一个用户组
    authorizer = DummyAuthorizer()
    # 将用户名,密码,指定目录,权限 添加到里面
    authorizer.add_user("fan", "root", "E:/", perm="elr")  # adfmw
    # 这个是添加匿名用户,任何人都可以访问,如果去掉的话,需要输入用户名和密码,可以自己尝试
    authorizer.add_anonymous("E:/")
    
    handler = FTPHandler
    handler.authorizer = authorizer
    # 开启服务器
    server = FTPServer(("127.0.0.1", 21), handler)
    server.serve_forever()
    

    然后将程序运行起来,接下来看一下效果,在浏览器上ftp://localhost/

    用户权限

    读取权限:
    
    "e" =更改目录(CWD,CDUP命令)
    
    "l" =列表文件(LIST,NLST,STAT,MLSD,MLST,SIZE命令)
    
    "r" =从服务器检索文件(RETR命令)
    
    写入权限:
    
    "a" =将数据追加到现有文件(APPE命令)
    
    "d" =删除文件或目录(DELE,RMD命令)
    
    "f" =重命名文件或目录(RNFR,RNTO命令)
    
    "m" =创建目录(MKD命令)
    
    "w" =将文件存储到服务器(STOR,STOU命令)
    
    "M"=更改文件模式/权限(SITE CHMOD命令)
    
    "T"=更改文件修改时间(SITE MFMT命令)
    

    开启被动端口模式

    #添加被动端口范围
    handler.passive_ports = range(8300, 8500)
    

    demo  

    from pyftpdlib.authorizers import DummyAuthorizer
    from pyftpdlib.handlers import FTPHandler
    from pyftpdlib.servers import FTPServer
    
    # 新建一个用户组
    authorizer = DummyAuthorizer()
    # 将用户名,密码,指定目录,权限 添加到里面
    authorizer.add_user("test", "1234", "E:/", perm="elradfmw")  # adfmw
    # 这个是添加匿名用户,任何人都可以访问,如果去掉的话,需要输入用户名和密码,可以自己尝试
    authorizer.add_anonymous("E:/")
    
    handler = FTPHandler
    handler.authorizer = authorizer
    
    #添加被动端口范围
    handler.passive_ports = range(8300, 8500)
    
    # 开启服务器
    server = FTPServer(("127.0.0.1", 2121), handler)
    server.serve_forever()

    -----------输出-----------------

    [I 2018-08-06 15:37:16] >>> starting FTP server on 127.0.0.1:2121, pid=8564 <<<
    [I 2018-08-06 15:37:16] concurrency model: async
    [I 2018-08-06 15:37:16] masquerade (NAT) address: None
    [I 2018-08-06 15:37:16] passive ports: 8300->8499
    [I 2018-08-06 15:37:32] 127.0.0.1:54898-[] FTP session opened (connect)

     

    读取用户列表,建立FTP

    #-----------user.ini------
    
    [alex]
    password=123
    perm=elradfmwM
    home=D:/
    
    [egon]
    password=123456
    perm=elradfmwM
    home=D:/
    
    
    #------------ftpdemo
    
    from pyftpdlib.authorizers import DummyAuthorizer
    from pyftpdlib.handlers import FTPHandler, ThrottledDTPHandler
    from pyftpdlib.servers import FTPServer
    import configparser
    import logging
    
    IP = '127.0.0.1'
    
    PORT = '2121'
    
    # 上传速度  100kb/s
    MAX_UPLOAD = 100 * 1024
    
    # 下载速度 100kb/s
    MAX_DOWNLOAD = 100 * 1024
    
    # 最大连接数
    MAX_CONS = 100
    
    # 最多IP数
    MAX_PER_IP = 10
    
    # 被动端口范围,注意被动端口数量要比最大IP数多,否则可能出现无法连接的情况
    PASSIVE_PORTS = (8300, 8500)
    
    # 是否开启匿名访问 on|off
    ENABLE_ANONYMOUS = 'off'
    
    # 匿名用户目录
    ANONYMOUS_PATH = 'E:/DEVTOOL/'
    
    
    # 日志文件
    LOGING_NAME = 'pyftp.log'
    
    # 欢迎信息
    WELCOME_MSG = 'Welcome to my ftp'
    
    # 新建一个用户组
    authorizer = DummyAuthorizer()
    
    # 读取用户配置
    config = configparser.ConfigParser()
    config.read('user.ini')
    user_list = config.sections()
    for user in user_list:
        passwd = config[user]["password"]
        perm = config[user]["perm"]
        home_dir = config[user]["home"]
        # 将用户名,密码,指定目录,权限 添加到里面
        authorizer.add_user(user, passwd, homedir=home_dir, perm=perm)
    
    # 添加匿名用户 只需要路径
    if ENABLE_ANONYMOUS == 'on':
        authorizer.add_anonymous(ANONYMOUS_PATH)
    
    # 下载上传速度设置
    dtp_handler = ThrottledDTPHandler
    dtp_handler.read_limit = MAX_DOWNLOAD
    dtp_handler.write_limit = MAX_UPLOAD
    
    # 初始化ftp句柄
    handler = FTPHandler
    handler.authorizer = authorizer
    
    # 添加被动端口范围
    handler.passive_ports = range(PASSIVE_PORTS[0], PASSIVE_PORTS[1])
    
    
    # 欢迎信息
    handler.banner = WELCOME_MSG
    
    # 监听ip 和 端口
    server = FTPServer((IP, PORT), handler)
    
    # 最大连接数
    server.max_cons = MAX_CONS
    server.max_cons_per_ip = MAX_PER_IP
    
    # 开始服务
    print('FTP开始服务 ', (IP, PORT))
    server.serve_forever()

     参考网站:

    https://www.cnblogs.com/huangxm/p/6274645.html

      

  • 相关阅读:
    20175322 周弋鸿 2018-2019-2 《Java程序设计》第八周学习总结
    2018-2019-2-20175303 实验二 《Java开发环境的熟悉》实验报告
    20175322 《Java程序设计》第七周学习总结
    20175322 《Java程序设计》第六周学习总结
    2018-2019-2 20175322实验一《Java开发环境的熟悉》实验报告
    20175322《Java程序设计》第五周学习总结
    《Java程序设计》第四周学习总结
    《Java程序设计》第三周学习总结
    《Java程序设计》第二周学习总结
    第一周学习总结
  • 原文地址:https://www.cnblogs.com/xiao-apple36/p/9415237.html
Copyright © 2011-2022 走看看