pyftpdlib 搭建FTP服务器

学会socket之后,就可以使用应用层的协议了,比如FTP,HTTP等,不过一般这些应用层都会有现成的模块,学不学socket都无所谓,这是python的方便之处。这里搭建FTP服务器使用的就是pyftpdlib。这个模块使用起来非常简单。

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
import os


def main():
    # Instantiate a dummy authorizer for managing 'virtual' users
    authorizer = DummyAuthorizer()

    # Define a new user having full r/w permissions and a read-only
    # anonymous user
    authorizer.add_user('user', '12345', '.', perm='elradfmwM')
    authorizer.add_anonymous("F:/")

    # Instantiate FTP handler class
    handler = FTPHandler
    handler.authorizer = authorizer

    # Define a customized banner (string returned when client connects)
    handler.banner = "pyftpdlib based ftpd ready."

    # Specify a masquerade address and the range of ports to use for
    # passive connections.  Decomment in case you're behind a NAT.
    #handler.masquerade_address = '151.25.42.11'
    #handler.passive_ports = range(60000, 65535)

    # Instantiate FTP server class and listen on 0.0.0.0:2121
    address = ('127.0.0.1', 2121)
    server = FTPServer(address, handler)

    # set a limit for connections
    server.max_cons = 256
    server.max_cons_per_ip = 5

    # start ftp server
    server.serve_forever()

if __name__ == '__main__':
    main()

使用上述代码即可搭建一个匿名的ftp服务器,在浏览器窗口输入 ftp:\\localhost:2121即可看到文件目录。

支持的功能

  1. 基本的匿名ftp服务器
  2. log功能
  3. 用户加密(可以使用电脑的用户名和密码)
  4. TLS/SSL传输加密
  5. 并发连接
  6. 带宽限制
    上述这些功能的详细介绍可以在turorail找到

命令行使用

简单的FTP服务器在安装这个模块后,可以使用命令行开启:

python -m pyftpdlib -i 192.168.20.195 -p 8021 -d E: -w

上面命令的意思是开启一个FTP服务器,目录为E盘,并且可以写入文件(-w)。为了更方便的上传下载文件,推荐使用FileZilla,而不是浏览器。

更多内容

参考pyftpdlib's document

为了方便操作,重写了一个脚本,自动打开服务,并复制地址到粘贴板

import subprocess
import re
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
import sys
import os
import ctypes
import pyperclip


def getIp():
    args = [r"powershell", r"(ipconfig | findstr IPv4)"]
    ip = subprocess.run(args, stdout=subprocess.PIPE)
    ipString = ip.stdout.decode("gb2312")

    reip = re.compile(r'(?<![\.\d])(?:\d{1,3}\.){3}\d{1,3}(?![\.\d])')
    counter = 0
    ipList = []
    for ip0 in reip.findall(ipString):
        ipList.append(ip0)
        print("ip%d : %s" % (counter, ip0))
        counter += 1

    return ipList[0]


def setFtpServer(ip, path):
    authorizer = DummyAuthorizer()
    authorizer.add_user('user', '12345', '.', perm='elradfmwM')
    authorizer.add_anonymous(path)
    handler = FTPHandler
    handler.authorizer = authorizer
    handler.banner = "pyftpdlib based ftpd ready."
    address = (ip, 21)
    server = FTPServer(address, handler)
    server.max_cons = 256
    server.max_cons_per_ip = 5
    server.serve_forever()


STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11
STD_ERROR_HANDLE = -12

# 字体颜色定义 ,关键在于颜色编码,由2位十六进制组成,分别取0~f,前一位指的是背景色,后一位指的是字体色
# 由于该函数的限制,应该是只有这16种,可以前景色与背景色组合。也可以几种颜色通过或运算组合,组合后还是在这16种颜色中

# Windows CMD命令行 字体颜色定义 text colors
FOREGROUND_BLACK = 0x00  # black.
FOREGROUND_DARKBLUE = 0x01  # dark blue.
FOREGROUND_DARKGREEN = 0x02  # dark green.
FOREGROUND_DARKSKYBLUE = 0x03  # dark skyblue.
FOREGROUND_DARKRED = 0x04  # dark red.
FOREGROUND_DARKPINK = 0x05  # dark pink.
FOREGROUND_DARKYELLOW = 0x06  # dark yellow.
FOREGROUND_DARKWHITE = 0x07  # dark white.
FOREGROUND_DARKGRAY = 0x08  # dark gray.
FOREGROUND_BLUE = 0x09  # blue.
FOREGROUND_GREEN = 0x0a  # green.
FOREGROUND_SKYBLUE = 0x0b  # skyblue.
FOREGROUND_RED = 0x0c  # red.
FOREGROUND_PINK = 0x0d  # pink.
FOREGROUND_YELLOW = 0x0e  # yellow.
FOREGROUND_WHITE = 0x0f  # white.


# Windows CMD命令行 背景颜色定义 background colors
BACKGROUND_BLUE = 0x10  # dark blue.
BACKGROUND_GREEN = 0x20  # dark green.
BACKGROUND_DARKSKYBLUE = 0x30  # dark skyblue.
BACKGROUND_DARKRED = 0x40  # dark red.
BACKGROUND_DARKPINK = 0x50  # dark pink.
BACKGROUND_DARKYELLOW = 0x60  # dark yellow.
BACKGROUND_DARKWHITE = 0x70  # dark white.
BACKGROUND_DARKGRAY = 0x80  # dark gray.
BACKGROUND_BLUE = 0x90  # blue.
BACKGROUND_GREEN = 0xa0  # green.
BACKGROUND_SKYBLUE = 0xb0  # skyblue.
BACKGROUND_RED = 0xc0  # red.
BACKGROUND_PINK = 0xd0  # pink.
BACKGROUND_YELLOW = 0xe0  # yellow.
BACKGROUND_WHITE = 0xf0  # white.


# get handle
std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)


def set_cmd_text_color(color, handle=std_out_handle):
    Bool = ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
    return Bool

# reset white


def resetColor():
    set_cmd_text_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)


# 绿色
# green
def printGreen(mess):
    set_cmd_text_color(FOREGROUND_GREEN)
    sys.stdout.write(mess)
    resetColor()


if __name__ == "__main__":
    path = os.getcwd()

    if len(sys.argv) == 2:
        path = sys.argv[1]

    ip = getIp()

    set_cmd_text_color(FOREGROUND_GREEN)
    print("you have shared %s" % path)
    print(r"you can visit ftp://%s now" % ip)
    print("address has copy to you clipboard")
    resetColor()
    pyperclip.copy("ftp://" + ip)
    setFtpServer(ip, path)

posted @ 2017-05-25 11:24  Weyne  阅读(675)  评论(0编辑  收藏