17 KiB
FTP (File Transfer Protocol)
FTP(File Transfer Protocol)是用于在计算机网络中进行文件传输的协议。它使用客户端-服务器模式,允许文件在客户端和服务器之间上传或下载。FTP 服务通常用于在不同主机间传输大容量文件,特别是在网络环境中需要频繁进行文件交换时。
FTP 运行在 OSI 模型的应用层,并利用传输协议 TCP 在不同的主机之间提供可靠的数据传输。并且在文件传输中 FTP 还支持断点续传功能,可以大幅度减少 CPU 网络带宽的开销。
工作原理
FTP 使用客户端与服务器之间的通信来传输文件。它通过两条连接来工作:一条用于命令传输(控制连接),另一条用于数据传输(数据连接)。
相关端口
控制连接端口:21
- 功能:FTP 的控制连接使用端口 21。这条连接用于客户端与服务器之间交换命令和响应。当你在 FTP 客户端中输入命令(例如
LIST
、RETR
、STOR
)时,这些命令是通过端口 21 发送的。 - 数据流向:控制连接是全双工的,客户端和服务器都可以发送消息,但所有数据传输操作(如文件上传、下载)都不会通过控制连接进行。
数据连接端口:20
- 功能:端口 20 在 FTP 协议中用于数据传输连接,特别是在 主动模式(PORT 模式)下。它用于通过数据连接传输实际的文件数据。
- 数据流向:当 FTP 客户端在主动模式下与服务器建立连接时,服务器通过端口 20 向客户端的指定端口发起数据连接。这条连接用于传输文件内容。
FTP 工作模式
FTP 支持两种不同的模式:主动模式(PORT)和被动模式(PASV)。
主动模式(Active Mode)
在主动模式下,客户端向服务器发起连接请求,服务器在数据传输时主动连接客户端。具体来说,客户端使用端口 21 与服务器建立控制连接,而数据连接则由服务器从端口 20 发起到客户端的指定端口。
连接过程
-
建立控制连接:客户端通过任意端口(例如随机的高端口,通常是 1024 以上的端口)向服务器的 端口 21 发起连接,建立 控制连接。这个连接用于发送 FTP 命令和接收响应。例如:客户端使用端口 1025,连接到服务器的端口 21(控制连接)。
-
客户端发送命令:客户端通过控制连接发送 FTP 命令(如
USER
、PASS
、LIST
等),请求服务器执行操作。 -
客户端告诉服务器监听的端口:当客户端希望传输文件时,它会告诉服务器自己希望通过哪个端口进行数据传输。这是通过 PORT 命令 完成的。客户端指定了一个端口(例如 1026)供服务器使用。
-
服务器发起数据连接:服务器收到客户端的 PORT 命令 后,会使用 端口 20 连接到客户端指定的端口(例如 1026)。这条连接用于传输数据,如文件内容或目录列表。
-
数据传输:当服务器与客户端的指定端口建立数据连接后,数据传输就开始了。文件会通过这个数据连接进行传输。
-
断开数据连接:数据传输完成后,数据连接会关闭,控制连接保持打开,直到用户结束会话(通过
QUIT
命令)。
优缺点
优点:服务器主动发起数据连接,因此客户端无需配置其防火墙以允许入站连接。
缺点:如果客户端位于 NAT 或防火墙后面,客户端很难接受来自服务器的入站连接。由于 NAT 会改变客户端的 IP 地址和端口,服务器可能无法正确连接到客户端。
被动模式(Passive Mode)
在被动模式下,服务器不会主动连接客户端,而是客户端主动与服务器建立数据连接。服务器会提供一个端口范围,客户端可以通过控制连接(端口 21)请求服务器提供一个可用端口,客户端再通过这个端口与服务器建立数据连接。
连接过程
- 建立控制连接:客户端首先向服务器的 端口 21 发起连接,建立控制连接。这个过程和主动模式相同。
- 客户端请求服务器进入被动模式:客户端发送 PASV 命令,请求服务器进入被动模式。此时,服务器会选择一个高端口(通常在 1024 以上),并向客户端返回该端口的信息。例如,服务器可能返回
227 Entering Passive Mode (192,168,1,2 120,232)
,这意味着服务器的 IP 地址是192.168.1.2
,并且它希望客户端连接到端口29832
。 - 客户端连接到服务器的被动端口:客户端接收到服务器返回的 IP 地址和端口信息后,会从任意端口连接到服务器提供的被动端口(例如 29832)。这条连接用于文件数据的传输。
- 数据传输:一旦数据连接建立,客户端和服务器就可以通过该连接传输文件数据或目录列表。
- 断开数据连接:数据传输完成后,数据连接会关闭。控制连接仍然保持打开,直到用户结束会话(通过
QUIT
命令)。
优缺点
优点:被动模式解决了客户端处于 NAT 或防火墙后面时的问题,因为客户端只需要发起对服务器的外向连接,不需要接受来自服务器的入站连接。
缺点:服务器需要预先开放一个端口范围,并且在某些情况下,如果服务器的防火墙配置不当,仍然可能会遇到问题。
FTP 常用服务软件
许多操作系统和第三方软件都提供 FTP 服务的实现。常见的 FTP 服务器软件有:
- vsftpd(Very Secure FTP Daemon):在 Linux 上广泛使用的高安全性 FTP 服务器。
- ProFTPD:功能丰富的 FTP 服务,支持多种认证机制。
- Pure-FTPd:简单易用的 FTP 服务器,适用于 Unix/Linux 系统。
- FileZilla Server:在 Windows 上使用的开源 FTP 服务器。
Vsftpd
相关介绍
- 软件包:vsftpd
- 服务类型:由Systemd启动的守护进程
- 配置单元:
/usr/lib/systemd/system/vsftpd.service
- 守护进程:
/usr/sbin/vsftpd
- 端口:
21(ftp)
,20(ftp‐data)
- 主配置文件:
/etc/vsftpd/vsftpd.conf
- 用户访问控制配置文件:
/etc/vsftpd/ftpusers /etc/vsftpd/user_list
- 日志文件:
/etc/logrotate.d/vsftpd
配置文件参数
参数 | 作用 |
---|---|
listen=NO | 是否以独立运行的方式监听服务 |
listen_address=ip地址 | 设置要监听的IP地址 |
listen_port=21 | 设置FTP服务的监听端口 |
download_enable=YES | 是否允许下载文件 |
userlist_enable=YES | 设置用户列表为"允许" |
userlist_deny=YES | 设置用户列表为"禁止" |
max_clients=0 | 最大客户端连接数,0为不限制 |
max_per_ip=0 | 同一IP地址的最大连接数,0为不限制 |
anonymous_enable=YES | 是否允许匿名用户访问 |
anon_upload_enable=YES | 是否允许匿名用户上传文件 |
anon_umask | 匿名用户上传文件的umask |
anon_root=/var/ftp | 匿名用户的ftp根目录 |
anon_mkdir_write_enable=YES | 是否允许匿名用户创建目录 |
anon_other_write_enable=YES | 是否开放匿名用户的其他写入权限(重命名、删除等) |
anon_max_rate=0 | 匿名用户的最大传输速率,0为不限制 |
local_enable=yes | 是否允许本地用户登录 |
local_umask=022 | 本地用户上传文件的umask值 |
local_root=/vat/ftp | 本地用户的ftp根目录 |
chroot_local_user=YES | 是否将用户权限禁锢在ftp目录,以确保安全 |
local_max_rate=0 | 本地用户的最大传输速率,0为不限制 |
基本操作
- 安装vsftpd软件
[root@localhost ~]# yum -y install vsftpd
- 准备共享分发的文件
[root@localhost ~]# touch /var/ftp/test.txt # /var/ftp/ 是默认的共享目录
[root@localhost ~]# echo "hello ftp server" > /var/ftp/test.txt
- 配置文件中开启匿名用户登录
[root@localhost ~]# vim /etc/vsftpd/vsftpd.conf
......
anonymous_enable=YES
......
- 启动服务
[root@localhost ~]# systemctl start vsftpd
[root@localhost ~]# systemctl enable vsftpd
- 关闭防火墙
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
到此,我们的FTP服务端就部署完成了。接下来我们应该通过一些客户端软件来连接到服务端上,进行文件的传输。
客户端工具
Linux
- 第一种
[root@localhost ~]# ftp 192.168.88.10
Connected to 192.168.88.10 (192.168.88.10).
220 (vsFTPd 3.0.5)
Name (192.168.88.10:root): anonymous # 匿名用户anonymous
331 Please specify the password.
Password: # 直接回车
230 Login successful. # 看到successful说明连接成功
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
# 退出的话,执行exit命令
- 第二种
[root@localhost ~]# lftp 192.168.88.10 # 默认使用匿名账户登录
lftp 192.168.88.10:~> ls
drwxr-xr-x 2 0 0 6 Nov 06 17:49 pub
-rw-r--r-- 1 0 0 17 Jan 04 01:39 test.txt
区别:
- ftp 工具是一定要输入用户名称和密码的,登录成功或者失败会给出提示。
- lftp 不会直接给出登录成功或者失败的提示,需要输入 ls 工具才可以发现是否连接成功,优点在于连接更加方便
注意:
FTP 有个名单列表。里面会有一些用户名。配合配置文件中的 userlist配置,如果是userlist_enable=YES 表示允许该名单的用户登录(白名单),反之,如果是 userlist_deny=YES 表示拒绝名单里的用户登录(黑名单)。
[root@localhost ~]# cat /etc/vsftpd/user_list
# vsftpd userlist
# If userlist_deny=NO, only allow users in this file
# If userlist_deny=YES (default), never allow users in this file, and
# do not even prompt for a password.
# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers
# for users that are denied.
root
bin
...
Windows
第一种:
可以在资源管理器或者运行窗口中输入 ftp://192.168.88.10
去连接到 ftp 服务器,如果我们想连接共享目录下面的具体某个目录,比如默认存在的pub目录,我们可以通过 ftp://192.168.88.10/pub
这样的方式来连接。

第二种:
可以打开 cmd 窗口,在 cmd 中通过 ftp 192.168.88.10
访问即可,跟 Linux 中使用 ftp 工具连接时的操作一致。

主被动模式配置
主动模式
在主动模式下,客户端告诉服务器使用哪个端口进行数据传输,服务器通过主动连接客户端的指定端口进行数据传输。
修改 vsftpd
配置文件
# 主动模式配置
connect_from_port_20=YES
被动模式
在被动模式下,服务器告诉客户端使用哪个端口传输数据,客户端会主动连接到这些端口。被动模式更适合穿越防火墙的网络环境。
修改vsftpd
配置文件,添加以下内容
# 被动模式配置
pasv_enable=YES
pasv_min_port=30000
pasv_max_port=31000 # 随机端口范围(但是会有些许误差)
主被动切换测试
通过user01或者anonymous用户从客户端连接上来以后,通过passive切换主被动模式
[root@localhost ~]# ftp 192.168.88.10
Connected to 192.168.88.10 (192.168.88.10).
220 (vsFTPd 3.0.5)
Name (192.168.88.10:root): user01
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> dir
227 Entering Passive Mode (192,168,88,10,120,145). # 默认是被动模式,192,168,88,10,120,145 这里表示随机端口
150 Here comes the directory listing.
226 Directory send OK.
ftp> passive # 通过passive切换主被动
Passive mode off.
ftp> dir
200 PORT command successful. Consider using PASV. # 主动模式使用20做为数据端口,所以没有提示端口
150 Here comes the directory listing.
226 Directory send OK.
ftp>
案例分析01
自定义匿名用户访问目录,能够上传和下载文件
服务端配置
# 准备匿名用户访问的目录和文件
[root@server ~]# mkdir /share/pub && chmod 777 /share/pub && chown ftp:ftp /share/pub
[root@server ~]# echo "anonymous Test download..." > download.txt
# 修改相关配置
[root@server ~]# echo "anon_root=/share" >> /etc/vsftpd/vsftpd.conf
[root@server ~]# echo "anon_upload_enable=YES" >> /etc/vsftpd/vsftpd.conf
[root@server ~]# systemctl restart vsftpd.service
客户端测试验证
[root@client ~]# echo "anonymous Test upload..." > upload.txt
# 访问、上传和下载测试
[root@client ~]# lftp 172.16.175.129
lftp 172.16.175.129:~> cd pub
cd 成功, 当前目录=/pub
lftp 172.16.175.129:/pub> ls
lftp 172.16.175.129:/pub> get download.txt
lftp 172.16.175.129:/pub> put upload.txt
案例分析02
使用本地用户成功登录以后,默认的访问目录为该用户的家目录
服务端配置
# 确保local_enable是否开启
[root@server share]# grep 'local_enable' /etc/vsftpd/vsftpd.conf
local_enable=YES
# 新建用户和测试文件
[root@server ~]# useradd user01
[root@server ~]# echo 123 | passwd --stdin user01
[root@server ~]# su - user01
[user01@server ~]$ echo "user01 Test download..." > download.txt
客户端测试验证
[root@client ~]# echo "user01 Test upload..." > upload.txt
# 访问,上传和下载测试
[root@client ~]# ftp lftp -u user01 172.16.175.129
密码:
lftp user01@172.16.175.129:~> ls
-rw-r--r-- 1 1000 1000 13 Jul 08 17:41 download.txt
lftp user01@172.16.175.129:~> get download.txt
13 bytes transferred
lftp user01@172.16.175.129:~> put upload.txt
2686 bytes transferred
案例分析03
虚拟用户访问控制:虚拟用户为 eagleslab001 和 eagleslab002,服务端本地代理用户为 vuser;eagleslab001 默认访问 /home/vsftpd/eagleslab01
且能够创建/删除/上传/下载文件,eagleslab002 不做额外配置。
服务端配置
# 创建用于进行FTP认证的用户数据库,其中奇数行为用户名,偶数行为密码
[root@server ~]$ cat << EOF > /etc/vsftpd/vuser.list
eagleslab001
00123456
eagleslab002
00234567
EOF
# HASH哈希工具(db_load):将明文信息转为密文
[root@localhost ~]# yum install -y libdb-utils
[root@localhost ~]# db_load -T -t hash -f /etc/vsftpd/vuser.list /etc/vsftpd/vuser.db
# 查看文件描述以及修改权限 & 删除明文信息
[root@localhost ~]# file /etc/vsftpd/vuser.db
/etc/vsftpd/vuser.db: Berkeley DB (Hash, version 9, native byte-order)
[root@localhost ~]# chmod 600 /etc/vsftpd/vuser.db
[root@localhost ~]# rm -rf vuser.list
# 创建虚拟用户的本地代理用户 & 用户目录
[root@localhost ~]# useradd -d /home/vsftpd -s /sbin/nologin vuser
[root@localhost ~]# mkdir -p /home/vsftpd/{eagleslab001,eagleslab002}
[root@localhost ~]# chmod -Rf 755 /home/vsftpd/
# 新建用于虚拟用户认证的PAM文件
[root@localhost ~]# cat << EOF > /etc/pam.d/vsftpd_vuser
auth required pam_userdb.so db=/etc/vsftpd/vuser
account required pam_userdb.so db=/etc/vsftpd/vuser
EOF
# 更新配置文件
[root@localhost ~]# cat << EOF >> /etc/vsftpd/vsftpd.conf
pam_service_name=vsftpd_vuser
userlist_enable=YES
guest_enable=YES
guest_username=vuser
allow_writeable_chroot=YES
chroot_local_user=YES
user_config_dir=/etc/vsftpd/conf.d
EOF
# 针对 eagleslabl001 设置不同权限
[root@localhost ~]# cat << EOF > /etc/vsftpd/conf.d/eagleslab001
local_root=/home/vsftpd/eagleslab001
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
EOF
# 重启服务
[root@localhost ~]# systemctl restart vsftpd
# 准备一些测试文件
[user01@server ~]$ echo "eagleslab001 Test download..." > /home/vsftpd/eagleslab001/download001.txt
[user01@server ~]$ echo "eagleslab002 Test download..." > /home/vsftpd/eagleslab002/download002.txt
客户端测试验证
# eagleslab001
[root@client ~]# lftp -u eagleslab001,00123456 172.16.175.129
...
# eagleslab002 put: 访问失败: 550 Permission denied.
[root@client ~]# lftp -u eagleslab002,00234567 172.16.175.129