本网站相关文章:

What is ftp?

ftp

FTP(File Transfer Portocol)文本传输协议, 用于在网络上进行文件传输的一套标准协议, 使用 C/S 模式, 处于 TCP/IP 五层协议的应用层.注意, FTP 关注于文件传送, 而其他如 NFS 则关注于文件访问.

工作模式

FTP 有两种模式用于实现 C/S 之间的通信和文件传输, 分别为:

  • 主动模式(PORT): 客户端为控制流发起端, 服务器为数据流发起端, 同时打开并监听一个端口
  • 被动模式(Passive): 客户端为控制流和数据流的发起端, 服务器仅创建一个监控随机端口的进程

主动模式: 主动模式, 被动模式: 被动模式

为何提出被动模式?
在主动模式中存在一个 BUG, 其中 Server 需要主动连接客户端随机端口, 一般而言 C/S 之间存在防火墙,此时服务器主动连接客户端的某一个端口需要Client进行额外的配置, 这样不符合一个产品的易用性.所以提出了被动模式, 在 Server 限定可以随机连接的端口范围, 生成随机端口并告知 Client, 由 Client 连接随机端口, Server被动被连接, 开始数据流.

目标和缺点

FTP 在提出时希望实现的目的:

  • 文件(程序, 数据)的共享
  • 鼓励间接/隐式的使用远程计算机
  • 向用户屏蔽不同主机中各种文件存储系统(File system)的细节
  • 可靠和高效的传输数据

当然, 万事并非十全十美, 由于使用场景以及设计框架的局限性, FTP 在安全性以及小文件传输方面有一定的不足之处:

  • 密码和文件内容都是明文传输, 不安全
  • 控制流和数据流的分离, 控制流闲置过长可能被置为超时, 大量数据的传输可能会发生错误
  • 在传输数量极多的小文件时, 性能不佳

What is vsftp?

Introduction

vsftp–Very Secure FTP Daemon, 一个为类 UNIX 系统开发的轻量, 安全, 稳定的 FTP服务器端, 注意,它是 FTP 的服务器端, 并不包括 Client.

vsftp 功能:

  • 使用 SSH/TLS 来保护 FTP
  • 使用 Standalone or inetd 两种工作方式
  • 限制用户登录, 限制连接数, 限制 chroot
  • 允许上传, 本地用户登录, 匿名用户登录
  • 限制传输带宽
  • 支持 IPV6
  • 支持虚拟用户, 虚拟路径

其中 vsftp 的性能可以参考官网: vsftp performance

Working

vsftp 有两种启动以及工作方式:

  • standalone–独立守护进程工作方式
  • xinetd–系统守护进程方式

其中standalone一次启动, 并一直驻留在内存中, 不断的监听数据流和控制流端口, 其优点:

  • 快速的响应命令以及数据
  • 适合大量访问的 FTP 服务器
  • 便于 PAM 验证

相比standalone高并发但是耗费系统大量资源, inetd工作方式下的 ftp 仅仅在外部连接请求到达时才会启动 FTP 进程, 所以不适合于大量连接的应用场景. 类似某一个工作岗位, 在客流量很小的时候常常招聘兼职人员, 相反则必须招聘专业全职人员.

Install

Ubuntu

Standalone

1
2
3
4
5
6
7
8
9
10
11
12
# 安装
sudo apt-get install vsftpd
# 卸载
sudo aptitude purge vsftpd
# 修复卸载报错并彻底卸载
sudo sh -x /var/lib/dpkg/info/vsftpd.postrm remove
sudo aptitude purge vsftpd
# 启动
sudo service vsftpd start
sudo systemctl restart vsftpd
# 端口查看
sudo netstat -npltu | grep 21

配置文件所在地: /etc/vsftpd.conf 该文件中记录了 ftp 启动日志所在地以及其他关键信息匿名用户根路径: /srv/ftp

Xinetd Daemon

Super Daemon 方式

  • 编辑 vsftpd.conf, 设置: listen=NO
  • 安装 xinetd: sudo apt-get install xinetd
  • 配置 xinetd, 编辑/etc/xinetd.conf文件
  • 启动 xinetd 服务或者重启

其中 xinetd.conf 配置:

1
2
3
4
5
6
7
8
9
10
11
service ftp
{
socket_type = stream
wait = no
user = root
server = /usr/sbin/vsftpd
log_on_success += DURATION USERID
log_on_failure += USERID
nice = 10
disable = no
}

重启:

1
2
3
4
# 先关闭standalone
sudo service vsftpd stop
# 启动xinetd
sudo service xinetd start

查看进程是否启动: sudo netstat -npltu | grep 21

Mac

Mac 安装 vsftp 命令:

1
2
3
4
5
6
7
8
9
# 安装
brew install vsftpd
# 启动
sudo brew services start vsftpd
sudo vsftpd
# 安装ftp等网络工具命令包
brew install inetutils
# 端口查看
netstat -ant |grep "*.21"

配置文件所在地: /usr/local/etc/vsftpd.conf

Configure vsftp?

通用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# StandAlone模式就是该服务拥有自己的守护进程支持
listen=YES
# 如果不支持请关闭该设置,可以再启动之时查看sudo systemctl status vsftpd
listen_ipv6=YES
# 若为YES,则强迫FTP-DATA的数据传送使用port 20,默认YES
connect_from_port_20=<YES/NO>
# 开启日志
xferlog_enable=YES
# 日志路径
xferlog_file=/var/log/vsftpd.log
# 支持WUFTP的日志文件格式
xferlog_std_format=YES
# ftp登录语
ftpd_banner=unlessbamboo's ftp ^_^
# 本地用户可以访问
local_enable=YES
# 设置是否支持虚拟用户帐号访问
guest_enable=<YES/NO>
# 上传文件
write_enable=YES
# 建立新目录和文件的umask
local_umask=022
# 设置本地用户最大的传输速率,单位为bytes/sec,值为0表示不限制
local_max_rate=<n>
# 设置本地用户登陆后的目录,默认为本地用户的主目录
local_root=<file>
# 当chroot_local_user=NO, chroot_list_enable=YES,只有filename文件指定的用户可执行chroot
chroot_list_file=<filename>
# 禁止用户登出ftp目录
chroot_list_enable=NO
# 禁止使用ls -R命令
ls_recurse_enable=NO
# 使用本地时间
use_localtime=YES
# 禁止上传文件更改宿主
chown_uploads=NO
# 异步传输
async_abor_enable=YES
# Ascii传输支持
ascii_upload_enable=YES
ascii_download_enable=YES

匿名配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 匿名访问 开启
anonymous_enable=YES
# 设置匿名用户的最大传输速率,单位为B/s,值为0表示不限制
anon_max_rate=<n>
# 是否开放匿名用户的浏览权限
anon_world_readable_only=<YES/NO>
# 允许匿名用户上传
anon_upload_enable=YES
# 允许匿名用户创建目录
anon_mkdir_write_enable=YES
# 设置是否允许匿名用户其他的写权限(对开放重命名, 删除文件等权限, 须设置, 否则没法续传)
anon_other_write_enable=<YES/NO>
# 匿名用户创建目录
dirmessage_enable=YES
# 注解:匿名用户就是ftp,所以想要匿名用户可写,必须文件夹权限设置为ftp

其中对于匿名用户的权限配置:

  • 匿名用户根路径: /srv/ftp
  • 匿名用户根目录权限: 不允许写
  • 对于上传文件, 须创建单独的目录, sudo chmod -R 777 /srv/ftp/upload

Chroot 配置

功能: 限制登录用户访问其他目录, 在登录之后当前用户根目录变为/

1
2
3
4
5
6
7
8
9
10
11
# 限制所有用户
chroot_local_user=YES
# 开放所有用户,限制特定用户
chroot_local_user=NO
chroot_list_enable=YES
# 用户列表文件: read1, read2, read3
chroot_list_file=/etc/vsftpd.chroot_list
# 限制所有,开放特定用户
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list

真实用户

对于真实用户登录 FTP 服务器, 此时需要先创建用户, 之后才能登录:

1
2
3
4
5
6
7
8
9
10
# 在服务器上创建
sudo adduser ftptest
# 更改用户目录
sudo mkdir /home/ftptest/ftp
sudo chown nobody:nogroup /home/ftptest/ftp
sudo chmod a-w /home/ftptest/ftp
sudo mkdir /home/ftptest/ftp/files
sudo chown ftptest:ftptest /home/ftptest/ftp/files
# 在客户端上登录
ftp://ftptest:passwd@unusebamboo

配置:

1
2
user_sub_token=$USER
local_root=/home/$USER/ftp

虚拟用户

虚拟用户的使用场景, 对于如下目录结构:

1
2
3
4
5
/home/vsftpd/
- dbzh1/
- dbzh2/
- dbzh3/
# 其中dbzh1为只读, dbzh2为只读, dbzh3拥有所有权限

希望创建 3 个虚拟用户: db1, db2, db3分别对上述三个目录进行相应权限设置.
a) 设置虚拟用户数据库
文件内容格式 loguser.txt:

1
2
user_id
passwd

创建的文件内容如下:

1
2
3
4
5
6
bamboo-read
bambooread123
bamboo-write
bamboowrite123
bamboo
bamboo123

生成数据库

1
2
3
sudo apt-get install db-util
sudo db_load -T -t hash -f /home/vsftpd/loguser.txt /etc/vsftpd_login.db
sudo chmod 600 /etc/vsftpd_login.db

配置 PAM, /etc/pam.d/vsftpd配置:

1
2
auth sufficient pam_userdb.so db=/etc/vsftpd_login
account sufficient pam_userdb.so db=/etc/vsftpd_login

/etc/vsftpd.conf更改配置: pam_service_name=vsftpd

b) 虚拟用户创建相应的目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建目录
sudo mkdir /etc/vsftpd_user_conf
cd /etc/vsftpd_user_conf
sudo touch bamboo-read bamboo-write bamboo
# 设置目录权限
sudo mkdir bamboo-write bamboo-read bamboo-any
# 主目录权限
sudo chown a-w /home/vsftpd
# 避免安全漏洞,限制chroot权限
sudo chown a-w /home/vsftpd/bamboo*
# 创建上传与下载目录
sudo mkdir upload download
sudo usermod -G vsftpd bamboo
sudo chown vsftpd:bamboo download upload

c) 虚拟用户配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 只读配置bamboo-read
local_root=/home/vsftpd/bamboo-read
# 读写配置(不能有任何空格,否则500错误)
write_enable=YES
anon_world_readable_only=NO
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
local_root=/home/vsftpd/bamboo
# 是否启用chroot_list_file配置的文件
chroot_list_enable=YES
# 默认为/etc/vsftpd.chroot_list,填入账户名称
chroot_list_file=/etc/vsftpd.chroot_list
# YES:用户不能切换到主目录之外的目录,除了chroot_list_file中的用户
# NO:能够切换,除了chroot_list_file中的用户
chroot_local_user=YES

其他配置

生成私钥

1
sudo openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

软链接目录

ftp 服务器不支持软链接目录, 如果需要支持外接目录, 可以使用 mount 挂在另外一个目录, 该 mount 目录对于 vsftpd 而言是一个正常文件系统目录, 可以被 vsftp 正常使用.

1
2
# 其中/opt/need_link_dir为待挂载目录, /data/ftp_dir为FTP中的目录
mount --bind /opt/need_link_dir /data/ftp_dir

访问拒绝

在 ftp 服务器搭建完成, 在服务器本机上可以通过命令ftp -p ip1可以正常访问, 但是通过其他机器时报错refused, 基本上都是因为防火墙的问题, 需要通过防火墙开启 21/22 端口, 例如ubuntu 20.04环境:

1
2
3
4
5
6
7
8
9
10
# 1. ufw查看, 此时已经设置了ftp相关端口, 但仍然无法使用ftp
ufw status
ufw allow 20,21,990/tcp

# 2. 通过firewalld或者iptables进行了配置, 此时就需要额外开启
ufw disable
firewall-cmd --add-service=ftp --permanent

# 注意, 每次改动需要重新加载配置
firewall-cmd --reload

Ftp Client

  1. FileZilla 客户端, 具有较为完善的客户端功能, 并且相比客户端更为稳定, 同时具备 Unix/Window 版本.
    注意, 如果需要在 FileZilla 使用匿名用户, 必须选择登录类型为正常, 输入anonymous即可.
  2. Mac Findler, Mac 下: 前往–>服务器–>ftp:username@hostname
    PS: 在 MAC 之间使用 AirDrop 是最为方便快捷的传输方式, 当然, 限于局域网
  3. 命令行: 使用各种命令进行控制流操作, 从而传输数据

Example

Simple Anonymous in Mac

在 Mac 下配置一个简单的 vsftpd 服务器, 尽可能不变动原有的配置文件, 支持匿名用户

  • chroot directory 目录, 默认/usr/share/empty
  • 增加其他配置, 如是否可写, PAM 服务支持虚拟用户等
  • 重启 vsftpd 服务
  • 通过ftp 127.0.0.1命令, 匿名用户anonmouse来登录 ftp

新增配置

1
2
3
4
5
6
7
8
9
10
11
pam_service_name=ftpd
# anonymous
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anonymous_enable=YES
write_enable=YES
local_umask=022
anon_upload_enable=YES
anon_mkdir_write_enable=YES
# 增加匿名用户根目录
anon_root=/Users/bifeng/Documents/ftp/

整个过程非常简单, 没有配置额外的用户, 仅仅支持匿名用户的下载操作.

Simple Anonymous in Ubuntu

在 ubuntu 上安装 vsftpd 之后, 会默认创建ftp用户, 相应的用户主目录以及配置如下/etc/passwd:

1
ftp:x:112:119:ftp daemon,,,:/srv/ftp:/bin/false

其中 ftp 用户默认就是匿名用户, 故 FTP 开启匿名登录之后, 主目录就是/srv/ftp. 新增或者更改
配置:

1
2
3
4
5
6
7
8
9
# 开启匿名登录
anonymous_enable=YES
# 允许匿名上传文件
write_enable=YES
anon_mkdir_write_enable=YES
anon_upload_enable=YES
# 设置本地用户上传文件掩码以及虚拟用户上传文件掩码
local_umask=022
anon_umask=022

/srv/ftp根目录下创建上传和下载目录, 因为根目录不允许进行写操作:

1
2
3
4
5
cd /srv/ftp & mkdir upload & mkdir download
# 设置匿名用户以及其他用户可写
chown ftp:ftp upload && chmod 775 upload
# 设置匿名用户以及其他用户可读
chown ftp:ftp download && chmod 664 download

重启 vsftpd 服务: service vsftpd restart
这里稍微介绍一下 umask 的计算公式, 其中默认情况下目录权限–777, 文件–666, 此时如果 umask 和
创建的目录或者文件关系:

umask 值 创建文件权限 创建目录权限
022 rw-rw-rw- -> rw-r–r– == 644 rwxrwxrwx -> rwxr-xr-x =755
033 rw-rw-rw- -> rw-r–r– == 644 rwxrwxrwx -> rwxr–r– =744
055 rw-rw-rw- -> rw–w–w- == 622 rwxrwxrwx -> rwx-w–w- =722

注意, 需要转为二进制之后, 进行相应运算: binary(666) & ~(binary(umask))

引用