Linux 搭建FTP服务
FTP 介绍
FTP是File Transfer Protocol的缩写,译为文件传输协议,是基于CS结构的应用层协议。其主要作用是在网络上的两台计算机之间传输文件。
FTP传输层使用的是TCP协议,它有一个很大的特点是采用双端口的工作模式,即客户端和服务端的通信是通过两个通道进行的
-
命令通道用于服务器和客户端之间交互指令的传输。固定使用21端口
-
数据通道用于用于实际的文件传输,包括上传和下载文件等,使用的端口不固定。
FTP采双通道模式有以下原因:
1、 隔离作用:将命令(控制信息)和数据流隔离,FTP确保了命令传输的简洁性和效率。即使在大量数据传输时,也可以无干扰地发送控制信息。
2、 信息加密:分开命令和数据流,可以在不同通道上应用不同的安全措施
FTP服务端的命令通道端口默认为21/tcp,但是数据通道的端口不固定,在不同的工作模式下有所不同。
1、主动模式:即服务器主动向客户端发起连接,服务端数据通道用20端口,客户端的端口随机
2、被动模式:即客户端主动发起连接请求,服务端被动接受客户端的连接请求,此时双方都是使用随机端口
FTP为什么要分为主动模式和被动模式,猜测可能是为了兼容更多的使用场景吧。但是两种模式在使用和功能上是一样的,主要区别在于建立数据连接的方式和使用的端口。
1、主动模式:服务端的20端口会连接客户端的随机端口,如果客户端开启了防火墙就会导致连接拒绝;
2、被动模式:被动模式是客户端主动发起连接,一般情况下防火墙都是不限制出去的流量的,主要服务端配置了合适的策略,那么不会导致连接失败的。这也是为什么大多数现代FTP客户端会默认使用被动模式,这样与各种网络配置的兼容性更好。
说明:
FTP服务端有两种方法解决被动模式下客户端访问本机随机端口,一种是通过连接追踪功能,还有一种直接把防火墙关了,就不会有这个问题了。
FTP的工作流程大体上时这样的,简单来说就是先建立命令通道再建立数据通道。
1、 服务端开启对应守护进程,监听21/tcp端口
2、 客户端发起连接请求,通过21端口连接到服务器。建立命令通道,命令通道用于传输和通信相关的一些指令。
3、 建立数据通道:如果是主动模式,服务端数据通道使用20端口,客户端随机。如果是被动模式,双方都使用随机端口
4、 两个通道建立后,进行数据的传输。
在Linux主机上,一般通过vsftpd这个软件来搭建FTP服务端,因为vsftpd具有速度快、稳定性好,单机就可支持15K并发量的特点。
vsftp官网:https://security.appspot.com/vsftpd.html
在windows主机上,一般可以用FileZilla Server这个工具搭建FTP服务端,因为它的配置很简单,搭建很容易。
FileZilla官网:https://filezilla-project.org/
安装vsftpd,一般通过软件管理工具进行安装即可,例如yum、apt等。也可以去官网下载源码进行编译安装。
例如:ubuntu安装vsftpd
sudo apt install vsftpd
vsftpd 配置项说明
配置文件
使用软件管理工具安装的vsftpd,主配置文件一般位于/etc/vsftpd.conf或者/etc/vsftpd/vsftpd.conf,编辑配置文件即可完成相关功能的配置;
vsftpd中也有子配置文件,但是默认是需要自己指定的,通过 user_config_dir 选项可以指定存放子配置文件的位置。这样服务加载时会默认读取该目录中的子配置文件
例如;指定自配文件存放位置为/etc/vsftpd.d
user_config_dir=/etc/vsftpd.d
说明:
使用软件管理工具安装vsftpd后,会自动创建一个名为vsftpd的service文件,将服务交由systemd管理
如果vsftpd的服务启动失败,直接手动执行systemd服务文件中的ExecStart指定的命令是一种排查问题的有效方法。这样做可以直接在命令行中看到vsftpd进程的输出,包括任何导致启动失败的错误信息。
root@ubuntu:~# systemctl cat vsftpd.service
# /lib/systemd/system/vsftpd.service
[Unit]
Description=vsftpd FTP server
After=network.target
[Service]
Type=simple
ExecStart=/usr/sbin/vsftpd /etc/vsftpd.conf
ExecReload=/bin/kill -HUP $MAINPID
ExecStartPre=-/bin/mkdir -p /var/run/vsftpd/empty
[Install]
WantedBy=multi-user.target
端口修改
服务端默认监听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=NO
ftp_data_port=200
被动模式下,服务端数据通道默认端口范围时没有限制的,但是可以指定数据通道的端口范围,通过 pasv_min_port 指定下限值,通过 pasv_max_por 指定上限值
例如:将被动模式下服务端的数据通道端口指定为6000-6010这个范围
pasv_min_port=6000
pasv_max_port=6010
时间配置
vsftpd默认使用的是默认使用的是格林尼治时间,所以如果要使用本地时间的话,需要将 use_localtime 设置为YES。
use_localtime=YES
说明: 格里尼治时间约等于世界标准时间,本地时间 = 世界标准时间 + 时区差 例如:北京时间 = 世界标准时间 + 8
用户禁锢
当客户端连接到服务端时,后起始目录(FTP根目录)通常是用户的家目录,FTP一般默认用户能够访问其家目录之外的其他文件系统目录。为了安全考虑,可以将其限制在这个目录内,不能访问它的上级目录,此时该目录就是用户能见到的根目录。
可以通过 chroot_local_user 选项实现,这个选项是针对所有用户生效的,不管是匿名用户还是系统用户。
chroot_local_user=YES
更改数据目录
用户登录到FTP服务器后起始目录是该用户的家目录,但是在某些情况下我们可能想更改其所在目录,这个时候可以通过 local_root 指定用户登录到FTP服务器后切换到local_root指定的目录。但是这个选项对匿名用户没效,匿名用户要使用 anon_root 才可以实现。
这里需要注意一点是:用户在登录FTP服务器后再切换到的这个指定目录,所以刚开始连接到服务端时,用户还是会进入其家目录然后再切换到指定目录。如果这个时候用户的家目录不存在就会报错,连接不上服务端。
例如:将用户的数据目录更改到/data目录
local_root=/data
例如:更改匿名用户的数据目录为/data
anon_root=/data
根目录写权限
我们在使用 chroot_local_user 将用户禁锢到某个目录时,此时默认是不允许用户对该目录具备写权限的,因为可能会利用某些权限提升漏洞来获得对整个系统的访问权。
如果此时用户拥有对该目录,也就是该用户的根目录拥有写权限,没法正常连接到服务端,此时有种简便方法就是通过 allow_writeable_chroot 选项解决。但是该选项对匿名用户不生效,即这个配置通常用于本地非匿名用户。因为如果匿名用户可以写入自己的chroot目录,他们可能会上传恶意文件,或者以其他方式改变服务器的文件系统,从而危害服务器的安全。
allow_writeable_chroot=YES
说明: 匿名用户要解决这个问题,一种方法就是将该目录的写权限给取消,但是此时匿名用户没有了修改服务端数据的能力,还有种方法就是再该目录下再创建一个带写权限的目录,这样就能再这个子目录里面进行相关数据的操作了。
日志设置
如果想要vsftpd的日志输出更详细,可以通过以下选项来进行配置。
-
xferlog_file:可以指定一个自定义的日志文件路径,日志文件默认位置通常是/var/log/vsftpd.log
-
xferlog_enable:是否启用文件传输日志,这会记录所有的上传和下载,一般设置为YES
-
xferlog_std_format:如果设置为NO,vsftpd将使用详细日志格式而不是标准的xferlog格式。这提供了更多的详细信息,包括每个FTP命令的日志记录
-
log_ftp_protocol:启用此选项将记录每个FTP会话的详细对话,这包括客户端和服务器之间的所有交互,一般设置为YES
连接设置
pasv_promiscuous: 默认为NO,此时要求数据通道(用于传输文件)和命令通道(用于发送FTP命令)需要来自同一个IP地址。
具体是这样的,FTP支持数据通道两种模式,主动模式(POST)和被动模式(PASV),被动模式是客户端主动连接服务端的一个随机端口,然后建立起数据通道。如果pasv_promiscuous为NO,就会检查数据通道的IP地址是否和命令通道一样的,如果不一样就报错,不允许数据传输。设置为YES后,就算不一样也允许传输。这种情况很容易出现在客户都安是负载均衡的情况,所以如果客户都安是负载均衡,可以将这个选项设置为YES,但是安全性也会降低。
pasv_address: 这个选项是用来指定,被动模式下客户端要连接的服务端的IP地址,默认是FTP服务器在被动模式下会自动使用其主机地址,但是如果FTP服务器位于NAT后面,客户都安无法访问这个地址。此时使用该选项指定为公网IP地址或路由器地址,这样客户都安才能正常建立连接。
说明: 如果是在同一个局域网内,没必要加这两个参数。
黑白名单配置
黑名单:位于指定列表中的用户不能方位FTP服务器,白名单:位于指定列表中的用户才可以访问FTP服务器。
例如:我将FTP配置为系统用户模式,但是我又希望所有的系统用户都能访问FTP服务器,这个时候就可以采用白名单来实现。vsftpd中有以下几个选项可以实现黑白名单。
-
userlist_enable:默认是NO,设置为YES表示只有userlist_file中指定的用户可以登录
-
userlist_file:用于指定存放相关用户的文件,里面只需要加用户名就行了
-
userlist_deny:默认是YES,表示userlist_file中指定的用户不能登录ftp服务器
匿名用户模式
匿名用户模式是一种特殊的访问方式,允许用户在没有个人账户的情况下登录到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 选项的情况下,这个时候虚拟用户将默认具有与匿名用户相同的权限,这就是为什么用匿名用户的配置可以实现虚拟用户的配原因。
方法三:这种情况就是通过 ser_config_dir 选项定义子配置文件,给每个虚拟用户定义不同的权限。
官网文档说了,没有启用virtual_use_local_privs,和匿名用户相同的权限,这就是可以通过匿名用户选项可以配置虚拟用户权限的原因
FTP 匿名用户配置流程
(1)安装服务
sudo apt install vsftpd -y
(2)创建数据目录
默认情况下,vsftpd中的匿名用户有两个,anonymous和ftp。匿名用户登录FTP服务器时,他们的起始目录通常是由特定的匿名FTP用户的家目录决定的。
可以通过 gentent 工具查看该用户的家目录在哪儿,一般大多数Linux发行版中,这个目录是/var/ftp或/srv/ftp。大多数情况下都是将数据存放在一个指定的目录中,所以这里需要单独创建数据目录。
例如:查看ftp的家目录
getent passwd ftp
例如:创建数据目录为/ftp_data,指定数据存放的位置在/ftp_data/anon_data
# 创建数据目录
sudo mkdir -p /ftp_data/anon_data
# 更改文件权限
chown root:root /ftp_data
shmod 755 /ftp_data
chown ftp:ftp /ftp_data/anon_data
说明:
对匿名用户来说,默认是不允许对家目录拥有写权限的,虽然有一个 allow_writeable_chroot=YES 选项,但是这个选项对匿名用户不生效。所以如果要让匿名用户操作服务端数据,一种做法就是在指定的数据目录下再创建一个目录,客户的数据存放在数据目录的子目录中。
(3)服务配置
编辑配置文件,修改以下配置即可,权限配置的时候可以给根据实际情况给予权限,我这里给了所有权限。
sudo vim /etc/vsftpd.conf
# 开启匿名用户登录
anonymous_enable=YES
no_anon_password=YES
# 匿名用户权限配置
write_enable=YES
anon_upload_enable=YES
anon_umask=022
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
anon_world_readable_only=YES
# 数据目录设置
anon_root=/ftp_data
chroot_local_user=YES
allow_writeable_chroot=YES
# 连接设置(同一个局域网内不用设置)
pasv_promiscuous=YES
pasv_address=47.104.130.81
# 日志设置 用于显示详细的日志信息
xferlog_enable=YES
xferlog_std_format=NO
log_ftp_protocol=YES
(4)重启服务
sudo systemctl restart vsftpd.service
FTP 系统用户配置流程
(1)安装服务
sudo apt insall vsftpd -y
(2)创建用户
如果不想使用默认的家目录作为数据目录,可以在创建系统用户的时候就指定数据目录为家目录。
useradd -m -s /usr/bin/rbash -d /data/ ftpadmin
# 设置密码
passwd ftpadmin
说明: 为了加强安全性,防止给予用户完整的shell访问权限可能会带来安全问题。所以为用户指定登录shell为rbash,即限制性的bash shell,限制用户能够运行的命令。
(3)配置修改
相较于匿名用户的权限配置,本地用户的权限配置就简单很多了。直接通过 write_enable 选项就可以开启修改服务端数据的权限了。
sudo vim /etc/vsftpd.conf
# 启用系统用户模式
local_enable=YES
# 权限配置
write_enable=YES
# 指定数据目录
local_root=/data
chroot_local_user=YES
allow_writeable_chroot=YES
# 日志配置
xferlog_enable=YES
xferlog_std_format=NO
log_ftp_protocol=YES
# 连接配置(局域网内不用管)
pasv_promiscuous=YES
pasv_address=47.104.130.81
# 登录名单配置
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd.user_list
(4)创建名单
创建 userlist_file 指定的文件。里面存放允许登录的用户名
sudo vim /etc/vsftpd.user_list
ftpadmin
(5)重启服务
systemctl restart vsftpd.service
FTP 虚拟用户配置流程
(1)服务安装
sudo apt install vsftpd -y
(2)创建用户
useradd -r -m -d /ftp_data -s /sbin/nologin ftpuser
(3)生成Berkeley DB 数据库文件
先创建一个文本文件,奇数行是用户名,偶数行是密码。后通过 db-util 工具包 提供的 db_load 工具实现Berkeley DB 数据库文件。
# 编辑文本文件
sudo vim ~/vusers
tom
Abc123
bob
123456
alice
redhat
# 生成DB文件
sudo db_load -T -t hash -f ~/vusers /etc/vsftpd/vusers.db
(4)PAM规则编写
vsftpd支持PAM插件,当用户尝试登录FTP服务时,vsftpd会通过PAM调用 pam_userdb.so 模块。后者会检查用户提供的用户名和密码是否与 /etc/vsftpd/vusers 数据库中的记录匹配。如果认证成功,用户将被允许登录。
在安装vsftpd的时候,在/etc/pam.d目录下生成了一个默认的规则文件vsftpd,可以直接基于这个文件添加验证规则。
# 加入以下内容
sudo vim /etc/pam.d/vsftpd
auth required pam_userdb.so db=/etc/vsftpd/vusers
account required pam_userdb.so db=/etc/vsftpd/vusers
说明:
因为我们的数据库文件中只指定了用户名和密码:
auth部分(auth required pam_userdb.so db=/etc/vsftpd/vusers): 这个配置主要负责验证用户提供的密码是否正确。会根据用户输入的用户名去指定的数据库(如/etc/vsftpd/vusers)中查找对应的记录,并核对密码是否匹配
account部分(account required pam_userdb.so db=/etc/vsftpd/vusers): 作用主要就是验证提供的账号是否存在于数据库中。会根据用户输入的用户名去指定的数据库(如/etc/vsftpd/vusers)中查找对应的记录
(5)修改配置
咱们上面也说了,指定虚拟用户权限有三种常用的方式,即和匿名用户同权限、和系统用户同权限,还有不同虚拟用户不同权限。
基础配置部分:
sudo vim /etc/vsftpd.conf
# 启用匿名用户模式
local_enable=YES
guest_enable=YES
# 指定映射的用户
guest_username=ftpuser
# 日志配置
xferlog_enable=YES
xferlog_std_format=NO
log_ftp_protocol=YES
# 连接配置(局域网内不用管)
pasv_promiscuous=YES
pasv_address=47.104.130.81
# 指定用于验证的PAM规则文件,不用加全路径,会默认到/etc/pam.d下找
pam_service_name=vsftpd
权限配置部分:
方式一:和系统用户同权限
# 虚拟用户拥有和系统用户同样的权限
write_enable=YES
local_umask=022
virtual_use_local_privs=YES
# 数据目录指定
local_root=/ftp_data
chroot_local_user=YES
allow_writeable_chroot=YES
方式二:和匿名用户同权限,
virtual_use_local_privs为NO就会和匿名用户同权限,此时可以用匿名用户的相关配置来配置虚拟用户权限,因为virtual_use_local_privs默认为NO,所以不加这个配置即可。
# 权限配置 这里是全部权限
write_enable=YES
local_umask=022
anon_upload_enable=yes
anon_mkdir_write_enable=yes
anon_other_write_enable=yes
anon_world_readable_only=NO
# 数据目录指定
local_root=/ftp_data
chroot_local_user=YES
allow_writeable_chroot=YES
方式三:不同虚拟用户之间拥有不同的权限
这个时候要通过ser_config_dir 选项指定子配置文件的存放位置,然后在这个目录里面创建子配置文件,vsftpd有一个规定:使用了user_config_dir指令来指定一个用户配置文件夹,那么每个用户的子配置文件应该与其用户名相同
例如:给tom单独配置权限
1)主配置文件配置
sudo vim /etc/vsftpd.conf
# 启用匿名用户模式
local_enable=YES
guest_enable=YES
# 指定映射的用户
guest_username=ftpuser
# 日志配置
xferlog_enable=YES
xferlog_std_format=NO
log_ftp_protocol=YES
# 连接配置(局域网内不用管)
pasv_promiscuous=YES
pasv_address=47.104.130.81
# 指定用于验证的PAM规则文件,不用加全路径,会默认到/etc/pam.d下找
pam_service_name=vsftpd
# 指定子配置文件目录
user_config_dir=/etc/vsftpd.d
2)创建子配置文件
# 一定要和用户名同名,后面要别加后缀这些
sudo vim /etc/vsftpd.d/tom
# 配置相关权限
write_enable=YES
local_umask=022
anon_upload_enable=yes
anon_mkdir_write_enable=yes
anon_other_write_enable=yes
anon_world_readable_only=NO
# 数据目录指定
local_root=/ftp_data
chroot_local_user=YES
allow_writeable_chroot=YES
(6)重启服务即可
systemctl restart vsftpd.service
FTP 客户端工具
Linux 命令行工具
ftp:安装vsftpd的时候就默认自带的可以命令行工具,
# 不指定默认是21端口
ftp server_host [port]
ftp相关命令介绍:
连接到ftp服务端后,使用help命令就可以列出相关操作指令了。
!:执行本地shell命令。
dir:列出远程目录的详细内容。
mdelete:删除多个文件。
mdir:列出多个远程目录的内容。
mget:下载多个文件。
mput:上传多个文件。
ascii:设置传输模式为ASCII(文本文件)。
binary:设置传输模式为二进制(非文本文件,如图片、视频)。
bye / quit / exit / close / disconnect:退出FTP会话。
cd:改变远程目录。
lcd:改变本地计算机上的“当前工作目录”
delete:删除远程文件。
get:下载文件。
put:上传文件。
pwd:显示当前远程目录。
help / ?:显示帮助信息。
ls:列出远程目录的内容。
mkdir:创建远程目录。
rmdir:删除远程目录。
rename:重命名远程文件或目录。
status:显示当前状态。
user:登录使用不同的用户名。
passive:切换到被动模式。
open:连接到FTP服务器。
prompt:切换批量传输命令的交互模式。
wget:wget也支持ftp协议(主要用于下载操作)
# 使用用户名user和密码pass下载位于根目录的file.zip
wget ftp://user:password@ftp.example.com/file.zip
windows 图形工具
FileZilla:非常流行的免费FTP客户端,支持FTP、FTPS和SFTP,界面友好,功能齐全。 下载链接:https://filezilla-project.org/download.php?type=client
WinSCP:主要用于安全文件传输的免费客户端,支持SFTP、SCP和FTP。 下载链接:https://winscp.net/eng/index.php