vsftpd 的配置与使用

2021-11-02 59点热度 0人点赞 0条评论

在 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 命令来查看

[email protected]:~# 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、用户 与 虚拟用户

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

[email protected]:~# useradd -s /bin/false -d /home/user01 user01 
[email protected]:~# 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 用户,样板如下
[email protected]:~# 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 {} \;

具体操作如下

[email protected]:~# touch delete.txt

[email protected]:~# 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

[email protected]:~# find -inum 82345652 -exec rm -rf {} \;

[email protected]:~# 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 的遇到的坑及搭建虚拟账户 [ 链接 ]

StarryVoid

Have a good time