python实现FTP服务器服务的方法


Posted in Python onApril 11, 2017

FTP服务的主动模式和被动模式

在开始之前,先聊一下FTP的主动模式和被动模式,两者的区别 , 用两张图来表示可能会更加清晰一些:

主动模式:

python实现FTP服务器服务的方法

主动模式工作过程:

1. 客户端以随机非特权端口N,就是大于1024的端口,对server端21端口发起连接

2. 客户端开始监听 N+1端口;

3. 服务端会主动以20端口连接到客户端的N+1端口。

主动模式的优点:

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

主动模式的缺点:

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

被动模式:

python实现FTP服务器服务的方法

被动模式工作过程:

1. 客户端以随机非特权端口连接服务端的21端口

2. 服务端开启一个非特权端口为被动端口,并返回给客户端

3. 客户端以非特权端口+1的端口主动连接服务端的被动端口

被动模式缺点:

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

被动模式的优点:对客户端网络环境没有要求

了解了FTP之后,开始使用python来实现FTP服务

准备工作

本次使用python版本:python 3.4.3

安装模块 pyftpdlib

pip3 install pyftpdlib

创建代码文件 FtpServer.py

代码

实现简单的本地验证

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

#实例化虚拟用户,这是FTP验证首要条件
authorizer = DummyAuthorizer()

#添加用户权限和路径,括号内的参数是(用户名, 密码, 用户目录, 权限)
authorizer.add_user('user', '12345', '/home/', perm='elradfmw')

#添加匿名用户 只需要路径
authorizer.add_anonymous('/home/huangxm')

#初始化ftp句柄
handler = FTPHandler
handler.authorizer = authorizer

#监听ip 和 端口,因为linux里非root用户无法使用21端口,所以我使用了2121端口
server = FTPServer(('192.168.0.108', 2121), handler)

#开始服务
server.serve_forever()

开启服务

$python FtpServer.py

测试一下:

python实现FTP服务器服务的方法

输入个错误密码试试:

python实现FTP服务器服务的方法

验证不通过,无法登录 。

但这似乎是主动模式的FTP ,如何实现被动模式呢?

通过以下代码添加被动端口:

handler.passive_ports = range(2000,2333)

完整代码:

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

#实例化虚拟用户,这是FTP验证首要条件
authorizer = DummyAuthorizer()

#添加用户权限和路径,括号内的参数是(用户名, 密码, 用户目录, 权限)
authorizer.add_user('user', '12345', '/home/', perm='elradfmw')

#添加匿名用户 只需要路径
authorizer.add_anonymous('/home/huangxm')

#初始化ftp句柄
handler = FTPHandler
handler.authorizer = authorizer

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

#监听ip 和 端口
server = FTPServer(('192.168.0.108', 2121), handler)

#开始服务
server.serve_forever()

开启服务,可以看到被动端口的信息:

$ python FtpServer.py 
[I 2017-01-11 15:18:37] >>> starting FTP server on 192.168.0.108:2121, pid=46296 <<<
[I 2017-01-11 15:18:37] concurrency model: async
[I 2017-01-11 15:18:37] masquerade (NAT) address: None
[I 2017-01-11 15:18:37] passive ports: 2000->2332

FTP用户管理:

通过上面的实践,FTP服务器已经可以正常工作了,但是如果需要很多个FTP用户呢,怎么办呢? 每个用户都写一遍吗?

其实我们可以定义一个用户文件user.py

#用户名   密码    权限     目录
# root   12345   elradfmwM  /home
huangxm   12345   elradfmwM  /home

然后遍历该文件,将不以#开头的行加入到user_list列表中

完整代码:

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


def get_user(userfile):
  #定义一个用户列表
  user_list = []
  with open(userfile) as f:
    for line in f:
      print(len(line.split()))
      if not line.startswith('#') and line:
        if len(line.split()) == 4: 
          user_list.append(line.split())
        else:
          print("user.conf配置错误")
  return user_list

#实例化虚拟用户,这是FTP验证首要条件
authorizer = DummyAuthorizer()

#添加用户权限和路径,括号内的参数是(用户名, 密码, 用户目录, 权限)
#authorizer.add_user('user', '12345', '/home/', perm='elradfmw')
user_list = get_user('/home/huangxm/test_py/FtpServer/user.conf')
for user in user_list:
  name, passwd, permit, homedir = user
  try:
    authorizer.add_user(name, passwd, homedir, perm=permit)
  except Exception as e:
    print(e)

#添加匿名用户 只需要路径
authorizer.add_anonymous('/home/huangxm')

#初始化ftp句柄
handler = FTPHandler
handler.authorizer = authorizer

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

#监听ip 和 端口
server = FTPServer(('192.168.0.108', 2121), handler)

#开始服务
server.serve_forever()

到这里,FTP 服务已经完成了。

规范一下代码

首先创建conf目录,存放settings.py和user.py

目录结构(cache里面的不用管):

python实现FTP服务器服务的方法

setting.py

ip = '0.0.0.0'

port = '2121'

#上传速度 300kb/s
max_upload = 300 * 1024

#下载速度 300kb/s
max_download = 300 * 1024

#最大连接数
max_cons = 150

#最多IP数
max_per_ip = 10

#被动端口范围,注意被动端口数量要比最大IP数多,否则可能出现无法连接的情况
passive_ports = (2000, 2200)

#是否开启匿名访问 on|off
enable_anonymous = 'off'
#匿名用户目录
anonymous_path = '/home/huangxm'

#是否开启日志 on|off
enable_logging = 'off'
#日志文件
loging_name = 'pyftp.log'

#欢迎信息
welcome_msg = 'Welcome to my ftp'

user.py

#用户名   密码    权限     目录
#root   12345   elradfmwM  /home/
huangxm   12345   elradfmwM  /home/
test    12345   elradfmwM  /home/huangxm

FtpServer.py

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler, ThrottledDTPHandler
from pyftpdlib.servers import FTPServer
from conf import settings
import logging


def get_user(userfile):
  #定义一个用户列表
  user_list = []
  with open(userfile) as f:
    for line in f:
      if not line.startswith('#') and line:
        if len(line.split()) == 4: 
          user_list.append(line.split())
        else:
          print("user.conf配置错误")
  return user_list

def ftp_server():
  #实例化虚拟用户,这是FTP验证首要条件
  authorizer = DummyAuthorizer()
  
  #添加用户权限和路径,括号内的参数是(用户名, 密码, 用户目录, 权限)
  #authorizer.add_user('user', '12345', '/home/', perm='elradfmw')
  user_list = get_user('conf/user.py')
  for user in user_list:
    name, passwd, permit, homedir = user
    try:
      authorizer.add_user(name, passwd, homedir, perm=permit)
    except Exception as e:
      print(e)

  #添加匿名用户 只需要路径
  if settings.enable_anonymous == 'on':
    authorizer.add_anonymous(settings.anonymous_path)
  
  #下载上传速度设置
  dtp_handler = ThrottledDTPHandler
  dtp_handler.read_limit = settings.max_download
  dtp_handler.write_limit = settings.max_upload

  #初始化ftp句柄
  handler = FTPHandler
  handler.authorizer = authorizer

  #日志记录
  if settings.enable_logging == 'on':
    logging.basicConfig(filename=settings.loging_name, level=logging.INFO)

  #欢迎信息
  handler.banner = settings.welcome_msg
  

  #添加被动端口范围
  handler.passive_ports = range(settings.passive_ports[0], settings.passive_ports[1])

  #监听ip 和 端口
  server = FTPServer((settings.ip, settings.port), handler)
  
  #最大连接数
  server.max_cons = settings.max_cons
  server.max_cons_per_ip = settings.max_per_ip
  
  #开始服务
  print('开始服务')
  server.serve_forever()

if __name__ == "__main__":
  ftp_server()

最后,说一下权限问题

读权限 :

e 改变文件目录
l 列出文件
r 从服务器接收文件

写权限 :

a 文件上传
d 删除文件
f 文件重命名
m 创建文件
w 写权限
M 文件传输模式(通过FTP设置文件权限 )

M 示例:

python实现FTP服务器服务的方法

到服务器上查看一下权限:

python实现FTP服务器服务的方法

可以看到权限已经被修改了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python编写检测数据库SA用户的方法
Jul 11 Python
在Python中使用itertools模块中的组合函数的教程
Apr 13 Python
深入理解python中的atexit模块
Mar 07 Python
Python网络爬虫神器PyQuery的基本使用教程
Feb 03 Python
Django后台获取前端post上传的文件方法
May 28 Python
Python使用wget实现下载网络文件功能示例
May 31 Python
对django layer弹窗组件的使用详解
Aug 31 Python
详解Django CAS 解决方案
Oct 30 Python
Python图像阈值化处理及算法比对实例解析
Jun 19 Python
Python collections模块的使用方法
Oct 09 Python
Python获取android设备cpu和内存占用情况
Nov 15 Python
python机器学习Github已达8.9Kstars模型解释器LIME
Nov 23 Python
python读写json文件的简单实现
Apr 11 #Python
Python实现Mysql数据库连接池实例详解
Apr 11 #Python
详解Python中类的定义与使用
Apr 11 #Python
python获取指定时间差的时间实例详解
Apr 11 #Python
一个基于flask的web应用诞生 组织结构调整(7)
Apr 11 #Python
一个基于flask的web应用诞生 记录用户账户登录状态(6)
Apr 11 #Python
一个基于flask的web应用诞生 用户注册功能开发(5)
Apr 11 #Python
You might like
php include类文件超时问题处理
2015/02/06 PHP
php+ajax+json 详解及实例代码
2016/12/12 PHP
PHP 使用二进制保存用户状态的实例
2018/01/29 PHP
PHP获取MySQL执行sql语句的查询时间方法
2018/08/21 PHP
ThinkPHP5+UEditor图片上传到阿里云对象存储OSS功能示例
2019/08/05 PHP
基于jQuery替换table中的内容并显示进度条的代码
2011/08/02 Javascript
JQuery伸缩导航练习示例
2013/11/13 Javascript
浅析JavaScript中的同名标识符优先级
2013/12/06 Javascript
利用jQuery的动画函数animate实现豌豆发射效果
2016/08/28 Javascript
jQuery删除节点用法示例(remove方法)
2016/09/08 Javascript
AngularJS实现网站换肤实例
2021/02/19 Javascript
layui点击导航栏刷新tab页的示例代码
2018/08/14 Javascript
vue中进入详情页记住滚动位置的方法(keep-alive)
2018/09/21 Javascript
layer.open的自适应及居中及子页面标题的修改方法
2019/09/05 Javascript
[50:27]Secret vs VG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python基础教程之元组操作使用详解
2014/03/25 Python
Python实现爬虫抓取与读写、追加到excel文件操作示例
2018/06/27 Python
PyQt5重写QComboBox的鼠标点击事件方法
2019/06/25 Python
使用Python自动生成HTML的方法示例
2019/08/06 Python
Django 后台获取文件列表 InMemoryUploadedFile的例子
2019/08/07 Python
Django admin model 汉化显示文字的实现方法
2019/08/12 Python
使用OpenCV circle函数图像上画圆的示例代码
2019/12/27 Python
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
采用专利算法搜索最廉价的机票:CheapAir
2016/09/10 全球购物
Lulu & Georgia官方网站:购买地毯、家具、抱枕、壁纸、床上用品等
2018/03/19 全球购物
美国玩具公司:U.S.Toy
2018/05/19 全球购物
Schecker荷兰:狗狗用品和配件
2019/06/06 全球购物
"引用"与多态的关系
2013/02/01 面试题
委托证明书
2014/09/17 职场文书
市委常委班子党的群众路线教育实践活动整改措施
2014/10/02 职场文书
村主任“四风”问题个人整改措施
2014/10/04 职场文书
入党积极分子培养联系人意见
2015/08/12 职场文书
导游词之南昌滕王阁
2019/11/29 职场文书
Golang 正则匹配效率详解
2021/04/25 Golang
Mysql分析设计表主键为何不用uuid
2022/03/31 MySQL
基于Python实现射击小游戏的制作
2022/04/06 Python