美文网首页
py-FTP服务器之四:ftp主程序

py-FTP服务器之四:ftp主程序

作者: 奇奇乌布里 | 来源:发表于2020-05-02 00:03 被阅读0次

    关于pyftpdlib建立 FTP服务器的详细内容:
    py-FTP服务器之一:虚拟运行环境
    py-FTP服务器之二:用户配置文件
    py-FTP服务器之三:启用SSL连接
    py-FTP服务器之四:ftp主程序
    py-FTP服务器之五:其他

    • 主程序是ftp.py
    • ftp.py同级要有一个rootftp文件夹, 作为根目录, ftp上传来的文件全部丢里面

    关于是否启用SSL加密和多进程的代码

    # 是否启用ssl加密和多进程模式
    USE_SSL = False  # 是否启用ftps加密传输,通过修改单独的文件设置,默认是不用ssl
    if 'ssl' in argv:
        USE_SSL = True  # 如果要启用ssl,运行时要加参数 ssl
    if 'mul' in argv:
        USE_MULTIPLE_PROCESS = True  # 开启多进程模式, 运行时要增加参数 mul
    

    注意: 在启动程序时需要在后面加参数, 比如要启用ssl, 则应当输入python ftp.py ssl, 如果还要开启多进程, 则应输入python ftp.py ssl mul

    MD5验证函数

    这个函数是在官方给的基础上做了一些简化.

    # 验证用户密码hash后是否与原来的一样,照着官方文档写的,修改了一点
    class DummyMD5Authorizer(DummyAuthorizer):
        def validate_authentication(self, username, password, handler):
            hash = md5(password.encode('utf-8')).hexdigest()  # 与md5USerPassword.py上的算法一致
            try:
                if self.user_table[username]['pwd'] != hash:
                    raise KeyError
            except KeyError:
                raise AuthenticationFailed
    

    从文本文件加载用户信息

    # 读取用户权限文件,向虚拟用户管理器添加用户
    def add_user(authorizer):
    
        # 用户权限文件
        userfile = 'userMD5.txt'  # 文件格式如下(md5加密后的文件,运行md5UserPassword.py后自动生成)
        '''
            # 备注文字(用tab间隔开来)
            username    md5(password)    path    perm
            username    md5(password)    path    perm
            username    md5(password)    path    perm
        '''
    
        # 用户列表
        user_list = []
        split_str = '\t'
    
        # 从userMD5.txt读取用户信息
        with open(userfile) as f:
            for line in f:
                line = line.replace('\n', '')  # 去掉最后的\n
                if not line.startswith('#') and line:  # #后面是备注
                    if len(line.split(split_str)) == 4:  # 用户名/密码/路径/权限
                        user_list.append(line.split(split_str))
                    else:
                        print("userMD5.txt配置错误: %s" % line)
    
        # 添加用户
        for user in user_list:
            authorizer.add_user(user[0], user[1], './rootftp' + user[2], perm=user[3], msg_login="欢迎光临", msg_quit="欢迎下次光临")
            print('[%s\t---\t%s\t%s]' % (user[0], user[3], user[2]))
    
        # 返回虚拟用户管理器
        return authorizer
    

    被动模式PASV

    • 如果有电脑在局域网中要连接外网的FTP, 则建议使用被动模式PASV进行连接
    • 设置一个假的IP地址, 确定一个被动模式端口的范围(默认设置为这个, 服务器的最后5000多个端口号)
    # 被动模式配置
        # Specify a masquerade address and the range of ports to use for
        # passive connections.  Decomment in case you're behind a NAT.
        # 设置假IP地址发回给ftp客户端,设置被动模式的端口区间(最大65535)
        handler.masquerade_address = '151.25.42.11'  # ftp服务器的伪IP地址
        handler.passive_ports = range(60000, 65535)  # 被动模式下的随机端口
    

    完整代码ftp.py

    # coding:utf-8
    from pyftpdlib.servers import FTPServer, MultiprocessFTPServer
    from pyftpdlib.authorizers import DummyAuthorizer, AuthenticationFailed
    from hashlib import md5
    from pyftpdlib.handlers import FTPHandler
    from pyftpdlib.handlers import TLS_FTPHandler  # TLS_FTPHandler需要pip安装pyopenssl
    from sys import argv  # 用来读取启动py文件时的命令行参数
    
    
    # 是否启用ssl加密
    USE_SSL = False  # 是否启用ftps加密传输,通过修改单独的文件设置,默认是不用ssl
    if 'ssl' in argv:
        USE_SSL = True  # 如果要启用ssl,运行时要加参数 ssl
    if 'mul' in argv:
        USE_MULTIPLE_PROCESS = True  # 开启多进程模式
    
    
    # 验证用户密码hash后是否与原来的一样,照着官方文档写的,修改了一点
    class DummyMD5Authorizer(DummyAuthorizer):
        def validate_authentication(self, username, password, handler):
            hash = md5(password.encode('utf-8')).hexdigest()  # 与md5USerPassword.py上的算法一致
            try:
                if self.user_table[username]['pwd'] != hash:
                    raise KeyError
            except KeyError:
                raise AuthenticationFailed
    
    
    # 读取用户权限文件,向虚拟用户管理器添加用户
    def add_user(authorizer):
    
        # 用户权限文件
        userfile = 'userMD5.txt'  # 文件格式如下(md5加密后的文件,运行md5UserPassword.py后自动生成)
        '''
            # 备注文字(用tab间隔开来)
            username    md5(password)    path    perm
            username    md5(password)    path    perm
            username    md5(password)    path    perm
        '''
    
        # 用户列表
        user_list = []
        split_str = '\t'
    
        # 从userMD5.txt读取用户信息
        with open(userfile) as f:
            for line in f:
                line = line.replace('\n', '')  # 去掉最后的\n
                if not line.startswith('#') and line:  # #后面是备注
                    if len(line.split(split_str)) == 4:  # 用户名/密码/路径/权限
                        user_list.append(line.split(split_str))
                    else:
                        print("userMD5.txt配置错误: %s" % line)
    
        # 添加用户
        for user in user_list:
            authorizer.add_user(user[0], user[1], './rootftp' + user[2], perm=user[3], msg_login="欢迎光临", msg_quit="欢迎下次光临")
            print('[%s\t---\t%s\t%s]' % (user[0], user[3], user[2]))
    
        # 返回虚拟用户管理器
        return authorizer
    
    
    #
    def main():
        # 用户验证
        # Instantiate a dummy authorizer for managing 'virtual' users 创建虚拟用户管理器
        # authorizer = DummyAuthorizer()
        authorizer = DummyMD5Authorizer()  # 因为要验证hash值,所以改成这个了类了,官方写的, 这个类继承自DummyAuthorizer类
    
        # Define a new user having full r/w permissions and a read-only anonymous user
        # 读取userMD5.txt文件,绑定 用户-权限
        authorizer = add_user(authorizer)  # 写成了一个函数add_user()来自动读取userMD5.txt
        # authorizer.add_anonymous(os.getcwd())  # 匿名用户,关闭
    
        # ftp主控制器
        # Instantiate FTP handler class
        # 绑定FTP控制器
        if not USE_SSL:
            handler = FTPHandler  # ftp传输
        if USE_SSL:
            handler = TLS_FTPHandler  # ftps传输 = ftp + ssl
        handler.authorizer = authorizer  # 绑定用户管理器
    
        # ssl加密
        if USE_SSL:
            handler.certfile = 'crt_key.pem'  # 此处需要插入自签名证书文件base64编码的pem
            # requires SSL for both control and data channel
            # 启用ssl加密传输
            # handler.tls_control_required = True  # 控制连接启用ssl加密
            handler.tls_data_required = True  # 数据连接启用ssl加密
    
        # 锦上添花
        # Define a customized banner (string returned when client connects)
        # 定义ftp客户端[连接成功欢迎词]
        handler.banner = "欢迎你我尊贵的客人莅临指导"
    
        # 被动模式配置
        # Specify a masquerade address and the range of ports to use for
        # passive connections.  Decomment in case you're behind a NAT.
        # 设置假IP地址发回给ftp客户端,设置被动模式的端口区间(最大65535)
        handler.masquerade_address = '151.25.42.11'  # ftp服务器的伪IP地址
        handler.passive_ports = range(60000, 65535)  # 被动模式下的随机端口
    
        # ip限制及端口设定
        # Instantiate FTP server class and listen on 0.0.0.0:8081
        # 设置不限制IP地址访问,端口8081,使用TCP端口8081
        address = ('0.0.0.0', 8081)  # ip限制及连接端口(需要在安全组里放通这个端口)
        # 多进程模式是否开启
        if USE_MULTIPLE_PROCESS:
            server = MultiprocessFTPServer(address, handler)
        else:
            server = FTPServer(address, handler)
    
        # 最大连接数限制
        # set a limit for connections
        # 设置最大连接数,和相同IP地址的最大同时连接数
        server.max_cons = 50
        server.max_cons_per_ip = 20
    
        # 万事俱备,只欠东风
        # start ftp server
        # 启动ftp服务器
        server.serve_forever()
    
    
    # 启动
    if __name__ == '__main__':
        main()
    
    

    启动

    启动命令: python ftp.py ssl mul
    后台运行: nohup python ftp.py >> log 2>&1 &

    相关文章

      网友评论

          本文标题:py-FTP服务器之四:ftp主程序

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