vsftpd 的配置与使用

2021-11-02 1862点热度 1人点赞

在 Linux 上制作 FTP,是绕不开 vsftpd 的。而 vsftpd 的配置文件异常复杂,所以记录。


1 、 vsftpd

Very Secure FTP Daemon 缩写 VSFTPD ,表示 非常安全的文件传输协议守护进程
(其实 FTP 的配置和管理就有许多不安全)

安装 vsftpd 也很简单

apt install vsftpd

默认 Ubuntu 20 安装的是 vsftpd version 3.0.3 版本,其中系统进程使用的是 /etc/vsftpd.conf 配置文件

如果需要查看具体的服务启动进程,可以通过 vsftpdwho 命令来查看

root@localhost:~# vsftpdwho
USER PID STIME CMD
root 8899 08:00 /usr/sbin/vsftpd /etc/vsftpd.conf

FTP 的 监听 默认端口是 21
FTP 的 主动传输 默认端口是 20
FTP 的 被动传输 默认端口是

1.1 、 FTP 的 主动传输和被动传输 区别

FTP 有两种工作状态,主动传输和被动传输 [ 链接 ]

主动传输
1 、客户端 访问 服务端 21 端口
2 、服务端 21 端口 回应 客户端访问请求
3 、--客户端 请求 服务端 提供数据-- 客户端开放 X 端口
4 、服务端 20 端口 主动 请求 客户端 X 端口并推送数据

主动传输前提条件
1 、客户端必须是公网可访问,端口映射匹配齐全
2 、服务端必须允许 20 端口 主动访问第三方终端
3 、服务端必须允许 21 端口 被第三方终端访问

被动传输
1 、客户端 访问 服务端 21 端口
2 、服务端 21 端口 回应 客户端访问请求
3 、--客户端 请求 服务端 提供数据-- 客户端准备链接服务端 Y 端口
4 、服务端 Y 端口 监听 并摆放文件数据(被动)
5 、客户端 访问 服务端 Y 端口 拉取文件数据

被动传输前提条件
1 、服务端必须允许 Y 端口组 被第三方终端访问
2 、服务端必须允许 21 端口 被第三方终端访问

总结一下
主动传输是主动推数据,需要对方存在服务端身份(公网可达)(NAT 环境难以使用)
被动传输是等待拉数据,对方的身份不限制,但额外要开很多端口


2 、 vsftpd 的配置

默认的 vsftpd 配置文件如下,足以启动一个普通的 只读 FTP 服务(仅限 IPV6)[ 链接 ]
参数 主动传输+被动传输 使用系统用户登录 禁止匿名用户 允许虚拟用户 调度文件夹欢迎信息 不支持 FTPS

listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
ssl_enable=NO

而就常用的需求来说,我们只需要一个简单的配置
参数 主动传输+被动传输 限定被动传输端口 30000-30010 使用系统用户登录 可读可写 限定家目录 禁止匿名用户 隐藏文件所有者 隐藏服务器点目录 限制传输速度 1MB/s

listen=YES
listen_ipv6=NO
listen_port=21
ftp_data_port=20
connect_from_port_20=YES
pasv_enable=YES
pasv_min_port=30000
pasv_max_port=30010
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=NO
chroot_local_user=YES
chroot_list_enable=NO
local_root=/opt/ftp/$USER
user_sub_token=$USER
passwd_chroot_enable=YES
allow_writeable_chroot=YES
user_config_dir=/etc/vsftpd_user_conf
use_localtime=YES
xferlog_enable=YES
xferlog_std_format=NO
vsftpd_log_file=/var/log/vsftpd.log
secure_chroot_dir=/var/run/vsftpd/empty
pam_service_name=vsftpd
force_dot_files=YES
hide_ids=YES
mkdir /etc/vsftpd_user_conf
useradd -s /bin/false -d /opt/ftp/user01 user01
echo user01:user01 | chpasswd

mkdir -p /opt/ftp/user01
chown user01:root /opt/ftp/user01
touch /opt/ftp/user01/successfully_connected.txt
mkdir -p /opt/ftp/user01/upload
chown user01:user01 /opt/ftp/user01/upload

touch /etc/vsftpd_user_conf/user01
echo "local_root=/opt/ftp/user01" >> /etc/vsftpd_user_conf/user01
echo "local_max_rate=104857600" >> /etc/vsftpd_user_conf/user01

2.1 、 IPV4 和 IPV6 监听

因为 vsftpd 实在太老了,它并不能支持 IPV4 和 IPV6 双栈同时监听,所以你只能一次仅监听一个。 [ 链接 ]
也就意味着你必须得启动两个 VSFTPD 服务。

vsftpd_ipv4.conf

listen=YES
listen_ipv6=NO
listen_address=192.168.1.100
vsftpd_ipv6.conf

listen=NO
listen_ipv6=YES
listen_address6=fec0:128::1

而对于服务端口的监听,VSFTPD 有两组参数。
定注意服务器/客户端 双向 防火墙 和 端口 相关的问题

# FTP 服务端口
listen_port=21
# 主动传输部分
ftp_data_port=20
connect_from_port_20=YES
# 被动传输部分(默认开启被动传输,端口号不限制使用)
pasv_enable=YES
pasv_min_port=30000
pasv_max_port=30010

# 被动传输回复的文件监听服务器地址(特殊情况使用,默认源进源出)
#pasv_address=192.168.1.100
# pasv_address 是否使用域名地址
#pasv_addr_resolve=NO
# 被动传输的安全检查是否停用(防止第三方拖拽数据文件,默认关闭)
#pasv_promiscuous=NO
# 服务器 最大连接数,单 IP 最大连接数
max_clients=0
max_per_ip=0
# 服务器 建立连接超时时间、主动传输连接超时时间,数据传输超时时间,无操作会话超时时间
accept_timeout=60
connect_timeout=60
data_connection_timeout=120
idle_session_timeout=300

2.3 、服务器信息

# 启用 所有用户 的 增删改 权限 (rw-) (含匿名用户)
write_enable=YES
# 启用 所有用户 的 文件下载 权限 (含匿名用户)
download_enable=YES
# 文件时间 叠加 服务器时区 (默认 GMT 时区 +00)
use_localtime=YES
# 服务器登录欢迎信息(采用 字符串方案 或者 文件方案)
ftpd_banner=Welcome to blah FTP service.
#banner_file=/etc/vsftpd/banner
# 服务器 子目录访问欢迎信息(采用寻找指定文件方案)
#dirmessage_enable=YES
#message_file=.message
# 服务器 切换传输模式 二进制 / ASCII ,默认二进制=NO
ascii_download_enable=NO
ascii_upload_enable=NO
# 服务器 连接会话是否分拆为不同线程(默认为 No)
setproctitle_enable=NO
# 服务器 连接后可使用的 命令 列表
#cmds_allowed=PASV,RETR,QUIT
#cmds_denied=

# 例如只能上传
#cmds_allowed=FEAT,REST,CWD,LIST,MDTM,MKD,NLST,PASS,PASV,PORT,PWD,QUIT,RMD,SIZE,STOR,TYPE,USER,ACCT,APPE,CDUP,HELP,MODE,NOOP,REIN,STAT,STOU,STRU,SYST
# 启用 服务器日志 标准文件日志
xferlog_enable=YES
xferlog_std_format=NO
vsftpd_log_file=/var/log/vsftpd.log

# 采用 xfer 格式记录服务器文件日志
xferlog_enable=YES
xferlog_std_format=YES
xferlog_file=/var/log/xferlog

# 记录所有详细访问日志 (更多日志需要 Debug)
log_ftp_protocol=YES

2.3 、用户 与 虚拟用户

当使用本地用户时,需要额外创建本地用户

root@localhost:~# useradd -s /bin/false -d /home/user01 user01 
root@localhost:~# cat /etc/passwd | grep user01
user01:x:1000:1000:user01,,,:/home/user01:/bin/false

如果涉及到 虚拟用户 ,建议参考该文章 [ ]
通常不建议使用虚拟用户,一方面难以管理权限,一方面还需要 htpasswd 进行配置

# 启用 服务器本地用户列表 登录 FTP
local_enable=YES
# 配置 本地用户登录的家目录(注意配置影响范围)
#local_root=/home/ftpuser
# 配置 用户 上传文件的 umask (建议本地用户 022 默认 077 )
local_umask=022
# 匿名用户 开放登录许可,建议关闭 (anonymous / ftp)
anonymous_enable=NO
# 匿名用户 是否需要登录密码
no_anon_password=NO
# 匿名用户 的用户名
ftp_username=ftp
# 匿名用户 的家目录(默认权限 755,root:ftp,不可使用 777 权限)
anon_root=/srv/ftp

# 匿名用户 是否允许创建新目录
anon_mkdir_write_enable=NO
# 匿名用户 是否允许重命名和删除目录
anon_other_write_enable=NO

# 匿名用户 是否允许上传文件
anon_upload_enable=NO
# 匿名用户 上传文件的所有者
chown_username=NO
# 匿名用户 是否允许更改上传文件所有者
chown_uploads=NO
# 匿名用户 上传文件的 umask (建议 077 )
anon_umask=077

# 匿名用户 登录时 是否需要输入 Email 地址 校验(附 Email 地址列表)
#deny_email_enable=YES
#banned_email_file=/etc/vsftpd/banner_emails

还可以对个别用户专门配置一些服务器参数,如 listen_address / local_max_rate 等

# 用户专属配置参数文件夹
user_config_dir=/etc/vsftpd_user_conf

# 用户专属配置文件 对应 user01 用户,样板如下
root@localhost:~# cat /etc/vsftpd_user_conf/user01

listen_address=192.168.1.110
local_max_rate=104857600

2.4 、用户 的 chroot 管控

强烈建议管控 用户的家目录,推荐方案为全局限制

# 对所有用户均配置 chroot 管控(限定在本地用户的家目录中)
chroot_local_user=YES
chroot_list_enable=NO

# 可以使用 user_sub_token 传递变量进行管理,例如
local_root=/opt/ftp/$USER
user_sub_token=$USER
# chroot 黑名单(仅限制部分用户)
chroot_local_user=NO
chroot_list_enable=YES
# chroot 白名单(仅取消限制部分用户)
chroot_local_user=YES
chroot_list_enable=YES

对应的 chroot_list 文件,均采用一行一个

user01
user02

限定前 / => /
限定后 / => /home/user01

而我们需要定义用户的家目录时,需要补充一个参数

# 家目录调度 /etc/passwd 中的目录,默认认为所有的本地用户家目录均在 /home 下
passwd_chroot_enable=YES

额外还有一个参数,此安全目录是 vsftpd 的绑定目录,限制未知用户的未知权限,默认不给任何权限(也不该给)

secure_chroot_dir=/var/run/vsftpd/empty

2.5 、 FTP 登录管制模式

# 用户登录黑名单
userlist_deny=YES
userlist_file=/etc/vsftpd.denied_users
# 用户登录白名单
userlist_deny=YES
userlist_enable=YES
userlist_file=/etc/vsftpd.allowed_users

对应的 userlist_file 文件,均采用一行一个用户的方式进行管理。

user01
user02

还可以通过主机地址的方式管控

tcp_wrappers=YES

此时 VSFTPD 会检查 /etc/hosts.allow 和 /etc/hosts.deny 两个文件,进而形成简易防火墙。


2.6 、 FTP SSL/TLS 配置

# 启用 安全传输 方式访问 (FTPS)
ssl_enable=YES
# 匿名用户是否允许使用 安全传输 保障
allow_anon_ssl=NO
# 对登录和数据传输都进行加密
force_local_logins_ssl=YES
force_local_data_ssl=YES
# 隐式 SSL 开启
implicit_ssl=YES
# FTPS 服务端口(SSL/TLS)
listen_port=990
# 启用 TLS 加密方式,禁用不安全 SSLv2/v3 加密方式
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
# 服务器 预设 SSL 证书路径
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

2.7 、 FTP 限速

FTP 是可以进行限速的,单位为 B/s,默认是不限速的。

# 限制所有本地用户最高下载速度为 1MB/s
local_max_rate=1048576
# 限制匿名用户最高下载速度为 300KB/s
anon_max_rate=307200

也可以针对个别用户限速,方式为创建单用户配置文件,里面增加服务端参数,限定在该用户下启用(参考 2.3 节)


2.8 、安全参数

# 允许 chroot 根目录可写入
allow_writeable_chroot=YES
# 允许 在 PAM 文件不存在时,检查 /etc/shells 确认用户可以登录
check_shell=YES
# 隐藏 ./ 和 ../ 目录
force_dot_files=YES
# 隐藏 文件所有者信息
hide_idss=YES

3 、常见问题

3.1 、 FTP 语言格式编码

在访问 FTP 时,我们可能会涉及到 中文/日文/韩文 等 Unicode 字符,而查看他们的时候会出现乱码问题

这是因为 GB2312 / UTF8 等字符编码导致的问题,同样的 Samba Windows 文件共享早就做好了兼容

而想解决这个问题,首要情况就是 修改客户端的字符编码为 UTF8

有许许多多终端的 FTP 客户端工具过于老旧,直接用着 Windows 我行我素的 GB2312 编码,进而导致用户上传的文件,在服务端出现 文件名存在 / \ ? 等严格禁止的特殊字符。这不仅导致文件无法通过 FTP 删除,严重还会导致管理混乱。(例如 菱形问号 � 这种无法识别的特殊内容)

而另一个问题是 例如 FileZilla 等 并不老旧的 FTP 客户端工具,默认配置的字符集是 自动检测,然后导致的结果依然等同于老旧客户端,因为 FTP 服务端 默认不会给客户端发送 服务端的字符编码 这个信息

而 vsftpd 对此额外增加了一个选项,限制上传的文件字符编码问题,即 服务端强制 UTF8

utf8_filesystem=YES

增加该选项后,服务端会强制告诉客户端,服务器为 UTF8 服务器,请按照该编码上传

但是依然挡不住老旧客户端上传 中文文件名。(毕竟 FTP 是二进制数据上传,然后再进行改名操作)

可能最后的杀手锏就是 限定服务器字符编码格式 和 服务器磁盘字符编码格式,可以参考下方的强制 UTF8 方案
(注意修改服务器的字符编码和服务器磁盘的字符编码需要非常慎重,通常存在文件后绝不考虑更改)

cat /etc/fstab

# <file system> <mount point>    <type>  <options>                 <dump>  <pass>
  /dev/sda1     /ftpserver/Data  vfat    rw,exec,utf8,umask=0000   0       0

而一个乱码文件,经常会出现 rm 都删除不掉,ls 能看到,但是你根本输入不出乱码字符,所以也无法自动填充文件名,只能用 inode 的方式去删除

find -inum 12345678 -exec rm -rf {} \;

具体操作如下

root@localhost:~# touch delete.txt

root@localhost:~# ls -al -i
12345601 drwxr-xr-x 2 root root 43 11 月  2 08:00 .
12345611 dr--r--r-- 3 root root 56 11 月  2 08:00 ..
82345652 -rw-r--r-- 1 root root  0 11 月  2 08:00 delete.txt
82345651 -rw-r--r-- 1 root root  0 11 月  2 08:00 example.txt

root@localhost:~# find -inum 82345652 -exec rm -rf {} \;

root@localhost:~# ls -ali
12345601 drwxr-xr-x 2 root root 25 11 月  2 08:14 .
12345611 dr--r--r-- 3 root root 56 11 月  2 08:00 ..
82345652 -rw-r--r-- 1 root root  0 11 月  2 08:00 example.txt

3.2 、 Chroot 家目录可写问题

问题现象:500 OOPS: vsftpd: refusing to run with writable root inside chroot()

主要来源于安全防护部分,防止有用户对家目录根的特殊文件 (例如 .bashrc ) 的修改进而形成安全漏洞

对于确定不会存在 Shell 的用户,可以使用 allow_writeable_chroot 参数进行许可

allow_writeable_chroot=YES

或者在家目录根下禁止用户写入 ,用户后期不能自行在家目录下创建目录和文件。

chmod a-w /home/user01

还可以在家目录根下额外创建其他可写入文件夹给用户使用,同样用户不能自行在家目录下创建目录和文件。


3.3 、 Shell 问题

问题现象 530 Login incorrect.(非 /bin/sh /bin/bash 用户登录)

主要问题是 VSFTPD 存在默认认证方案 /etc/pam.d/vsftpd

pam_service_name=vsftpd

此认证方案中存在两个部分,第一部分是禁止系统用户登录,第二部分是检查用户 Shell 是否可用

auth    required        pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
auth    required        pam_shells.so

后者是导致此问题的主要原因,解决办法有两种

第一种,对 /etc/pam.d/vsftpd 中 pam_shells.so 所属行进行注释操作。(推荐)

第二种,将 /bin/false 添加到 /etc/shells(可能有其他问题)

题外话:FTP 与 本地用户 Shell [ 链接 ]
/bin/false 作为登录 shell 会直接返回终止,无输出。
/bin/nologin 作为登录 shell 会直接返回终止,输出提醒 “禁止登陆”
/etc/shells 记录系统中所有可登录用的 Shell ,不在此清单都认为是无效 shell(无权登录)


4 、参考链接

vsftpd 配置文件详解 [ 链接 ]

Linux 下 vsFTP 配置全方案 (限制用户/端口/速度/空间) [ 链接 ]

配置 vsftpd 的遇到的坑及搭建虚拟账户 [ 链接 ]

配置 ftp 服务器只能上传不能进行其他操作 [ 链接 ]

StarryVoid

Have a good time