FTP 介绍

FTP是File Transfer Protocol的缩写,译为文件传输协议,是基于CS结构的应用层协议。其主要作用是在网络上的两台计算机之间传输文件。

FTP 工作模式

FTP的传输层使用的是TCP协议,采用双端口的工作模式,即数据传输的过程中会开启两个通道,命令通道和数据通道。

  • 命令通道用于服务器和客户端之间交互指令的传输。固定使用21端口

  • 数据通道用于用于实际的文件传输,包括上传和下载文件等,使用的端口不固定。


通道隔离的作用:

1、 隔离作用:将命令(控制信息)和数据流隔离,FTP确保了命令传输的简洁性和效率。即使在大量数据传输时,也可以无干扰地发送控制信息。

2、 信息加密:分开命令和数据流,可以在不同通道上应用不同的安全措施

FTP 数据通道端口

如果是服务器主动向客户端发起连接(主动模式),服务端数据通道用20端口,客户端随机

如果是服务器被动接受客户端的连接请求(被动模式),服务端和客户端都使用随机端口


FTP主动模式和被动模式的区别:

这两种模式在使用和功能上是一样的,主要区别在于建立数据连接的方式和使用的端口。

  • 在主动模式下,服务器尝试从FTP数据端口(通常是20)连接到客户端打开的随机端口。如果客户端的防火墙没有为这个入站连接配置规则,那么连接尝试可能会被防火墙拒绝。

  • 在被动模式下,客户端尝试连接到服务器打开的随机端口。如果服务器的防火墙没有允许入站连接到这个端口,或者客户端的防火墙阻止了出站连接,那么数据连接也可能失败。


一般使用的是被动模式,因为客户端的大多数防火墙默认允许出站流量,即出去的流量是不加限制的。所以大多数现代FTP客户端会默认使用被动模式,这样与各种网络配置的兼容性更好。


但是如果服务端开启了防火墙,通过连接跟踪功能可以确保FTP的数据通道能够在防火墙受限的环境中正常工作,连接追踪功能是Linux防火墙Netfilter的一个功能,它可以跟踪所有通过防火墙的连接的状态。(一般情况下为了方便都是直接将服务端防火墙给关了的)

FTP 工作流程

1、 服务端开启对应守护进程,监听21/tcp端口

2、 客户端发起连接请求,通过21端口连接到服务器。建立命令通道,命令通道用于传输和通信相关的一些指令。

3、 建立数据通道:如果是主动模式,服务端数据通道使用20端口,客户端随机。如果是被动模式,双方都使用随机端口

4、 两个通道建立后,进行数据的传输。

搭建FTP服务

在Linux操作系统上搭建FTP服务端一般使用vsftpd 这个工具,它具有速度快、稳定性好,单机可支持15k并发量的特点。

在windwos上搭建的话可以用FileZilla Server这个工具。

vsftp官网:https://security.appspot.com/vsftpd.html

FileZilla官网:https://filezilla-project.org/

1、安装vsftpd

一般直接通过软件管理工具,例如yum、apt等直接安装就可以了,也可以去官网下载源码包进行编译安装;

例如:ubuntu安装vsftpd

sudo apt install vsftpd

2、基本配置修改

使用软件包安装的vsftpd,配置文件一般位于/etc/vsftpd.conf或者/etc/vsftpd/vsftpd.conf,编辑配置文件即可完成相关功能的配置;

端口监听

vsftpd服务端默认监听21端口,可以通过 listen_port 修改默认监听的端口

例如:将端口改为2121

listen_port=2121

主动模式数据通道的端口是20,是通过 connect_from_port_20=YES 选项指定的,如果需要修改主动模式的端口,可以将 connect_from_port_20 设置为NO,然后通过 ftp_data_port 选项进行指定。

例如:将主动模式下数据通道端口修改为200

connect_from_port_20=NOftp_data_port=200

被动模式时,可以指定数据通道的端口范围,通过 pasv_min_port 指定下限值,通过 pasv_max_por 指定上限值

例如:将被动模式下服务端的数据通道端口指定为6000-6010这个范围

pasv_min_port=6000pasv_max_port=6010

时间配置

vsftpd默认使用的是默认使用的是格林尼治时间,所以如果要使用本地时间的话,需要将 use_localtime 设置为YES。

use_localtime=YES

用户禁锢

当客户端连接到服务端时,未使用禁锢功能时,用户能够访问其家目录之外的其他文件系统目录。

因为用户登录到FTP服务器后起始目录(FTP根目录)通常是用户的家目录,可以将其限制在这个目录内,不能访问它的上级目录。

可以通过 chroot_local_user 选项禁锢用户,此时该目录就是用户能见到的根目录。

chroot_local_user=YES

说明:

chroot_local_user是一个全局配置,针对所有用户生效(虚拟用户、本地用户和匿名用户)

指定数据目录

用户登录到FTP服务器后起始目录是该用户的家目录,可以通过 local_root 指定用户的起始目录,用户登录FTP服务器后(刚开始还是在用户家目录),会切换到local_root指定的目录。

local_root=/data

如果要更改匿名用户登录FTP服务器后默认所在的数据目录,通过 anon_root 可以实现。

anon_root=/data

根目录写权限

使用chroot环境时,默认不允许将用户chroot到可写目录,因为如果用户被限制在一个可写的chroot目录中,可能会利用某些权限提升漏洞来获得对整个系统的访问权。

如果用户具有登录进来所在的目录的写权限,那么就会现在客户端无法登录的情况,这个时候通过 allow_writeable_chroot 选项可以解决这个问题。

说明: 这个配置通常用于本地非匿名用户,对匿名用户不生效。因为如果匿名用户可以写入自己的chroot目录,他们可能会上传恶意文件,或者以其他方式改变服务器的文件系统,从而危害服务器的安全。

allow_writeable_chroot=YES

子配置文件指定

如果把所有的配置都放在vsftpd的主配值文件里面,可能会导致配置太过于臃肿,且在一些特殊情况下,例如不同的虚拟用户授予不同的权限,这个时候就需要指定子配置文件了。

  • ser_config_dir:指定存放子配置文件的位置,会默认加载该目录中以.conf结尾的配置文件

日志设置

如果想要vsftpd的日志输出更详细,可以通过以下选项来进行配置。

  • xferlog_file:可以指定一个自定义的日志文件路径,日志文件默认位置通常是/var/log/vsftpd.log

  • xferlog_enable:是否启用文件传输日志,这会记录所有的上传和下载,一般设置为YES

  • xferlog_std_format:如果设置为NO,vsftpd将使用详细日志格式而不是标准的xferlog格式。这提供了更多的详细信息,包括每个FTP命令的日志记录

  • log_ftp_protocol:启用此选项将记录每个FTP会话的详细对话,这包括客户端和服务器之间的所有交互,一般设置为YES

匿名用户模式

匿名用户模式是一种特殊的访问方式,允许用户在没有个人账户的情况下登录到FTP服务器。这通常是为了公共文件共享而设置的。

可以通过这些选项来配置启用匿名用户和匿名用户的相关权限:


启用匿名用户:

  • anonymous_enable:是否启用匿名用户模式,YES表示启用

  • no_anon_password:是否要求匿名用户输入密码。YES表示不用输入密码,但是客户端软件可能仍会提示输入密码,设置为YES后可以输入任何内容(或者留空),因为服务器已经被配置为不验证匿名用户的密码。


匿名用户权限配置:

因为匿名用户在FTP服务中通常受到特别的管理和限制,主要是因为安全考虑。由于匿名用户不需要身份验证即可访问FTP服务,因此需要对他们的权限进行严格控制。所以配置选项较多且严格。

  • write_enable:是否让所有用户拥有删除、上传、修改等权限。此选项针对所有用户生效,但是如果匿名用户只开启了这个选项,照样没权限,因为vsftpd对匿名用户的权限管控很严格,所以还需要一些其它选项辅助才行。

  • anon_upload_enable: 控制匿名用户是否可以上传文件。通常设置为YES

  • anon_umask:控制匿名用户上传文件后,文件的umask,通常设置为022.

  • anon_mkdir_write_enable: 控制匿名用户是否可以创建新目录。通常设置为YES

  • anon_other_write_enable: 控制匿名用户是否可以进行其他写操作,如删除和重命名文件。通常设置为YES

  • anon_world_readable_only: 控制匿名用户只能下载全局可读的文件,通常设置为NO,表示不是仅可读的文件也能下载。

本地用户模式

本地用户模式指的是允许系统上的本地用户使用他们的系统用户名和密码通过FTP登录。

启用本地用户:

  • local_enable:是否允许客户端使用ftp服务器上的系统用户进行登录

本地用户权限:

  • write_enable:允许用户对ftp服务端的数据进行操作。相对于匿名用户模式,本地模式的权限配置就简单很多了。直接通过 write_enable 选项就可以开启修改服务端数据的权限了。

用户映射模式

用户映射一般是都将多个虚拟用户映射为一个本地系统用户。这样使得FTP用户与系统用户不直接关联,增强了安全性,并且可以给不通的虚拟用户设置不同的权限。


虚拟用户:

指的是在操作系统层面不存在的用户账号,这些用户在 /etc/passwd 文件中找不到,虚拟用户只存在于为它们创建的特定服务中,它们有自己的认证机制和权限设置,与系统用户完全独立。


FTP中的虚拟用户:

一般是存在一个Berkeley DB文件文件中,然后编写对应的 PAM 规则来实现身份验证(因为FTP支持PAMA插件),这样在客户端进行登录的时候就能验证用户的身份,从而执行下一步操作。


Berkeley DB文件:

这是一个键值对数据库文件,通常包含用户名和加密后的密码。它是由管理员预先创建好的,用于存储虚拟用户的认证信息。奇数行是账号,偶数行是密码。


启用虚拟用户模式:

  • local_enable:虚拟用户可以理解为是一种特殊的系统用户,所以需要开启 local_enable=YES选项。

  • guest_enable:所有非匿名登录的用户都会被当作虚拟用户,然后映射为guest_username 指定的系统用户。

  • guest_username:指定将虚拟用户映射为某个系统用户


虚拟用户权限配置:

如果是配置为和系统用户一样的权限:

  • virtual_use_local_privs:启用这个选项,虚拟用户就可以拥有和系统用户一样的操作权限

官网文档说了,没有启用virtual_use_local_privs,虚拟用户将默认具有与匿名用户相同的权限,这就是为什么用匿名用户的配置可以实现虚拟用户的配原因。

  • anon_upload_enable

  • anon_mkdir_write_enable

  • anon_other_write_enable=yes

  • anon_world_readable_only=NO

匿名用户配置流程

(1)创建数据目录

默认情况下,vsftpd中的匿名用户有两个,anonymous和ftp。匿名用户登录FTP服务器时,他们的起始目录通常是由特定的匿名FTP用户的家目录决定的。大多数Linux发行版中,这个目录是/var/ftp或/srv/ftp,具体是多少可以通过 getent passwd ftp 查看

getent passwd ftp

如果需要更改初始的数据目录,通过 anon_root 选项可以修改,在匿名用户登陆后(登录时也会先进入默认的起始目录)将尝试更改的目录。

# 创建数据目录sudo mkdir -p /ftp_data/anon_data# 更改文件权限chown root:root /ftp_datashmod 755  /ftp_datachown ftp:ftp /ftp_data/anon_data

说明:

对匿名用户来说,默认是不允许对家目录拥有写权限的,虽然有一个 allow_writeable_chroot=YES 选项,但是这个选项对匿名用户不生效。所以如果要让匿名用户操作服务端数据,一种做法就是在指定的数据目录下再创建一个目录,客户的数据存放在数据目录的子目录中。

(2)修改配置文件

配置匿名用户的时候,改这些配置就行了,其它保持默认即可。

sudo vim /etc/vsftpd.conf# 开启匿名用户登录anonymous_enable=YESno_anon_password=YES# 匿名用户权限配置 这里是给了所有权限write_enable=YESanon_upload_enable=YESanon_umask=022anon_mkdir_write_enable=YESanon_other_write_enable=YESanon_world_readable_only=YES# 数据目录设置anon_root=/ftp_datachroot_local_user=YESallow_writeable_chroot=YES# 日志设置 显示详细的日志信息xferlog_enable=YESxferlog_std_format=NOlog_ftp_protocol=YES# 连接设置(同一个局域网内不用设置)# 接受从任何IP地址发起的被动模式数据连接,即使该IP地址与发起FTP控制连接的IP地址不同。(负载均衡情况有用)pasv_promiscuous=YES# 指定了被动模式下vsftpd告诉FTP客户端的外部IP地址。,客户端需要用它来建立数据连接(如果服务器处于NAT后面需要指定为公网IP地址)pasv_address=47.104.130.81

说明:

当客户端位于负载均衡器后面时,控制连接(即FTP命令)可能通过一个IP地址来建立,而数据连接(用于传输文件)可能来自另一个IP地址。默认情况下,vsftpd出于安全考虑要求数据连接必须来自与控制连接相同的IP地址。如果启用了负载均衡,这个默认行为会导致数据连接被拒绝,因为IP地址不匹配。设置pasv_promiscuous=YES可以使vsftpd接受来自任何IP地址的数据连接,从而解决了这个问题。


如果FTP服务器位于NAT(网络地址转换)设备后面,那么服务器上的FTP服务可能无法正确知道自己的公网IP地址。在被动模式下,服务器需要告诉客户端一个公网IP地址来建立数据连接。如果没有设置pasv_address,服务器可能会错误地发送它的私有(内网)IP地址,客户端在互联网上是无法使用这个地址的。通过设置pasv_address为服务器的公网IP地址,您确保了客户端接收到正确的信息,从而可以成功建立数据连接。

(3)重启服务生效

sudo systemctl restart vsftpd.service

系统用户配置流程

(1)创建用于登录FTP服务器的系统用户并且指定数据目录

useradd -m -s /usr/bin/rbash  -d /data/ ftpadminpasswd ftpadmin

为了加强安全性,防止给予用户完整的shell访问权限可能会带来安全问题。所以为用户指定登录shell为rbash,即限制性的bash shell,限制用户能够运行的命令。

(2)修改配置文件
相较于匿名用户的权限配置,本地用户的权限配置就简单很多了。直接通过 write_enable 选项就可以开启修改服务端数据的权限了。

sudo vim /etc/vsftpd.conf# 启用系统用户模式local_enable=YES# 权限配置write_enable=YES# 指定数据目录local_root=/datachroot_local_user=YESallow_writeable_chroot=YES# 连接配置(局域网内不用管)pasv_promiscuous=YESpasv_address=47.104.130.81# 日志配置xferlog_enable=YESxferlog_std_format=NOlog_ftp_protocol=YES# 登录名单配置# user_list中的用户允许登录userlist_enable=YES# 指定哪些用户可以登录服务端userlist_file=/etc/vsftpd.user_list# 如为YES,表示禁止列表中的用户访问FTP服务器userlist_deny=NO

(3)创建允许连接的名单

sudo vim /etc/vsftpd.user_listftpadmin

(4)重启服务

systemctl restart vsftpd.service

虚拟用户配置流程

(1)创建用户

useradd -r -m -d /ftp_data  -s /sbin/nologin ftpuser

(2)生成生成Berkeley DB 数据库文件

先创建一个文本文件,奇数行是用户名,偶数行是密码。然后通过db-util工具包提供的db_load工具实现Berkeley DB 数据库文件。

# 编辑文本文件sudo vim ~/vuserstomAbc123bob123456aliceredhat# 生成DB文件sudo db_load -T -t hash -f ~/vusers   /etc/vsftpd/vusers.db

(3)编写PAM规则文件

vsftpd支持PAM插件,当用户尝试登录FTP服务时,vsftpd会通过PAM调用pam_userdb.so模块。后者会检查用户提供的用户名和密码是否与/etc/vsftpd/vusers数据库中的记录匹配。如果认证成功,用户将被允许登录。
在安装vsftpd的时候,在/etc/pam.d目录下生成了一个默认的规则文件vsftpd,可以直接基于这个文件添加验证规则。

sudo vim /etc/pam.d/vsftpdauth    required        pam_userdb.so   db=/etc/vsftpd/vusersaccount required        pam_userdb.so   db=/etc/vsftpd/vusers

(4)修改配置

将若干个虚拟用户映射为一个系统用户,且虚拟用户拥有系统用户的权限配置方法:

sudo vim /etc/vsftpd.conf# 虚拟用户可以理解为是一种特殊的系统用户,所以需要开启 local_enable=YES选项。local_enable=YESguest_enable=YES# 指定映射的用户guest_username=ftpuser# 开启权限write_enable=YESlocal_umask=022# 虚拟用户拥有和系统用户同样的权限virtual_use_local_privs=YES# 数据目录管理local_root=/ftp_datachroot_local_user=YESallow_writeable_chroot=YES# 指定用于验证的PAM规则文件,不用加全路径,会默认到/etc/pam.d下找pam_service_name=vsftpd

(5)重启服务

sudo systemctl restart vsftpd.service

虚拟用户权限细致化管理:

根据官方配置文档我们可知,当 virtual_use_local_privs=NO 时(默认就是NO),虚拟用户将使用与匿名用户相同的权限,也就是可以通过匿名用户的一些权限配置选项来配置虚拟用户的权限。


所以如果不想给虚拟用户系统用户的所有权限,可以通过匿名用户的相关配置来指定权限。

例如:给虚拟用户配置所有权限

sudo vim /etc/vsftpd.conf# 虚拟用户可以理解为是一种特殊的系统用户,所以需要开启 local_enable=YES选项。local_enable=YESguest_enable=YES# 指定映射的用户guest_username=ftpuser# 开启权限write_enable=YESlocal_umask=022anon_upload_enable=yesanon_mkdir_write_enable=yesanon_other_write_enable=yesanon_world_readable_only=NO# 连接设置(同一个局域网内不用设置)# 接受从任何IP地址发起的被动模式数据连接,即使该IP地址与发起FTP控制连接的IP地址不同。(负载均衡情况有用)pasv_promiscuous=YES# 指定了被动模式下vsftpd告诉FTP客户端的外部IP地址。,客户端需要用它来建立数据连接(如果服务器处于NAT后面需要指定为公网IP地址)pasv_address=47.104.130.81# 日志设置 显示详细的日志信息xferlog_enable=YESxferlog_std_format=NOlog_ftp_protocol=YES# 数据目录管理local_root=/ftp_datachroot_local_user=YESallow_writeable_chroot=YES# 指定用于验证的PAM规则文件,不用加全路径,会默认到/etc/pam.d下找pam_service_name=vsftpd