您当前的位置:首页 > 计算机 > 编程开发 > Python

python实现FTP服务器

时间:09-14来源:作者:点击数:

基础知识

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

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

FTP主动模式

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

然后开放N+1号端口进行监听,并向服务器发出PORTN+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进行监听,然后用PORTP命令通知客户端,自己的数据端口是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()
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门