☰
Linux 配置 FTP 服务器实现文件上传下载
2026/9/29 12:39:04 网站建设 项目流程

前言

vsftpd(Very Secure FTP Daemon)是 Linux 上最主流的 FTP 服务端,特点是轻量、稳定、安全性好。适合这些场景:

  • 给外包/客户开个账号传文件
  • 老设备、老系统只支持 FTP
  • 内网快速搭个文件中转站

先说句实在话:FTP 是明文协议,账号密码和数据在网上裸奔。除非有历史包袱,否则新项目建议直接用 SFTP(基于 SSH,零配置成本)或 FTPS。本文最后会讲怎么给 vsftpd 加上 TLS 加密。

环境:Rocky Linux 8 / CentOS 7(Ubuntu 差异已标注)


一、安装

# Rocky / CentOS dnf install -y vsftpd # Ubuntu / Debian # apt install -y vsftpd vsftpd -v # 确认版本,后面有些配置项和版本相关

先备份配置,这步别省:

cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.bak

注意路径差异:CentOS 系在/etc/vsftpd/,Ubuntu 是/etc/vsftpd.conf(没有子目录)。


二、创建 FTP 用户

# -d 指定家目录,-s 指定不可登录的 shell(安全) useradd -d /data/ftp/ftpuser -s /sbin/nologin ftpuser # 设置系统密码 passwd ftpuser # 目录准备 mkdir -p /data/ftp/ftpuser chown -R ftpuser:ftpuser /data/ftp/ftpuser chmod 755 /data/ftp/ftpuser

为什么要-s /sbin/nologin?FTP 用户只需要能传文件,不需要能 SSH 登录服务器。给它/sbin/nologin能有效降低被爆破后的危害。但要注意:某些发行版需要把 shell 加入/etc/shells,详见 6.2。


三、配置 vsftpd.conf

完整配置如下(同样给精简可用的版本):

# ========== 基本设置 ========== # 禁止匿名登录(重要!默认可能是 YES) anonymous_enable=NO # 允许本地用户登录 local_enable=YES # 允许写操作(上传、删除、改名都靠它) write_enable=YES # 本地用户上传文件的权限掩码,022 = 755 local_umask=022 # ========== 目录与日志 ========== dirmessage_enable=YES xferlog_enable=YES xferlog_std_format=YES connect_from_port_20=YES # 以独立模式运行并监听 listen=YES listen_ipv6=NO # PAM 认证模块 pam_service_name=vsftpd userlist_enable=YES # ========== 禁锢用户在家目录 ========== # 用户登录后只能在自家目录,无法 cd 到上级 chroot_local_user=YES allow_writeable_chroot=YES # ========== 被动模式(NAT/防火墙环境必配)========== pasv_enable=YES pasv_min_port=30000 pasv_max_port=30100 # 公网访问时必填,填服务器的公网 IP # pasv_address=203.0.113.10

核心参数说明

参数说明
anonymous_enable=NO必改项。默认开启匿名访问,等于谁都能传文件
write_enable=YES不开这个,用户只能下载不能上传
chroot_local_user=YES把用户锁在自家目录,防止翻看服务器其他文件
allow_writeable_chroot=YES关键项,见 6.1,不加会直接报错登不上
pasv_min_port/pasv_max_port被动模式端口范围,防火墙要放行这一段
pasv_address服务器在 NAT 后面时,必须填公网 IP

四、启动服务与防火墙

systemctl enable --now vsftpd systemctl status vsftpd

防火墙:

firewall-cmd --permanent --add-service=ftp firewall-cmd --permanent --add-port=30000-30100/tcp firewall-cmd --reload

为什么还要加端口范围?FTP 有两种模式:

  • 主动模式(Active):服务端主动连客户端。客户端在 NAT 后面时基本用不了。
  • 被动模式(Passive):客户端连服务端的随机高端口。现代客户端默认都是被动模式,所以必须放行pasv_min_port~pasv_max_port。

SELinux:

getenforce setsebool -P ftpd_full_access on # 允许 vsftpd 读写用户家目录

五、验证测试

5.1 服务端自测

ftp localhost # 输入用户名密码,能登录就说明基本 OK

5.2 Linux 客户端测试

# 方式一:ftp 命令 ftp 192.168.1.10 # 方式二:lftp(更好用,支持被动模式切换) dnf install -y lftp lftp -u ftpuser,密码 192.168.1.10

5.3 curl 测试(适合脚本化验证)

# 下载 curl -u ftpuser:密码 ftp://192.168.1.10/test.txt # 上传 curl -u ftpuser:密码 -T local.txt ftp://192.168.1.10/ # 列目录 curl -u ftpuser:密码 ftp://192.168.1.10/

注意:curl 默认走主动模式,在某些网络环境下会失败。加上--ftp-pasv强制被动模式再试:

curl --ftp-pasv -u ftpuser:密码 ftp://192.168.1.10/

如果加了这个参数就好了,说明是主动/被动模式搞错了,不是服务端问题。

5.4 用 FileZilla 等图形工具

连接时把「传输模式」设为被动,字符集设为UTF-8,中文文件名才不会乱码。


六、常见问题排查(重点)

6.1500 OOPS: vsftpd: refusing to run with writable root inside chroot()

这是配chroot_local_user=YES后最经典的错误。

原因:你把用户禁锢在家目录了,但家目录本身是可写的。用户如果能写自己的"根目录",就能通过上传.ssh之类的目录实现越权,所以 vsftpd 拒绝启动。

解法一(推荐):确认 vsftpd 版本 ≥ 3.0,加上

allow_writeable_chroot=YES

解法二(更安全,不依赖配置项):把家目录设成不可写,另建子目录给用户写:

chmod 755 /data/ftp/ftpuser mkdir /data/ftp/ftpuser/upload chown ftpuser:ftpuser /data/ftp/ftpuser/upload

这样用户能进家目录(只读),但要写东西得进upload子目录。安全性比解法一好。

版本坑:allow_writeable_chroot在 vsftpd 3.0.2 曾被移除,3.0.3 又加回来了。如果你加了这行还报unknown option,说明版本不对,只能用解法二。

6.2530 Login incorrect

这个错误信息很笼统,原因有好几个,按下面顺序排查:

① shell 不在/etc/shells里

grep nologin /etc/shells

如果没输出,说明/sbin/nologin没被列为合法 shell,PAM 会拒绝。加上:

echo /sbin/nologin >> /etc/shells

② 用户被列入了黑名单

cat /etc/vsftpd/ftpusers # 这个文件里的用户一律禁止 FTP 登录 cat /etc/vsftpd/user_list # 配合 userlist_enable=YES,默认是黑名单

root默认就在这两个文件里,这是故意的,不要删。你自己的用户如果也在里面,删掉对应行。

③ PAM 配置问题

检查/etc/pam.d/vsftpd,确认pam_shells.so和pam_listfile.so没有误伤。

④ 密码本身错了

先确认能su - ftpuser切换成功,排除密码问题。

6.3 能登录能列目录,但上传失败

检查这三点:

grep write_enable /etc/vsftpd/vsftpd.conf # 是不是 NO ls -ld /data/ftp/ftpuser # 目录属主对不对 getsebool ftpd_full_access # SELinux 放行了吗

文件系统权限和 SELinux 都要过,和 NFS 一样是两层校验。

6.4 被动模式连不上(能登录但列不出目录 / 一直卡住)

症状:能连上、能认证,但执行ls就卡住或超时。

原因:被动模式的数据端口被防火墙拦了。

# 确认配置生效 grep pasv /etc/vsftpd/vsftpd.conf # 确认防火墙放行了整个范围 firewall-cmd --list-all | grep -A2 ports

如果服务器在云上(阿里云/腾讯云),别忘了安全组也要放行 30000-30100。这是最容易被忽略的一层。

用抓包定位到底卡在哪:

tcpdump -i any -n port 21 or portrange 30000-30100

6.5 中文文件名乱码

确认客户端用UTF-8编码连接。FileZilla 里:站点管理器 → 字符集 → 强制 UTF-8。

vsftpd 本身在较新版本默认就是 UTF-8,老版本可能需要:

utf8_filesystem=YES

七、进阶:给 FTP 加上 TLS 加密(FTPS)

既然 FTP 是明文的,生产环境强烈建议启用 TLS。

① 生成自签证书(内网够用;公网建议买正式证书)

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ -keyout /etc/vsftpd/vsftpd.key \ -out /etc/vsftpd/vsftpd.crt \ -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=192.168.1.10" chmod 600 /etc/vsftpd/vsftpd.key

② 配置中追加

ssl_enable=YES allow_anon_ssl=NO force_local_data_ssl=YES force_local_logins_ssl=YES ssl_tlsv1_2=YES ssl_tlsv1_1=NO ssl_tlsv1=NO ssl_sslv2=NO ssl_sslv3=NO rsa_cert_file=/etc/vsftpd/vsftpd.crt rsa_private_key_file=/etc/vsftpd/vsftpd.key require_ssl_reuse=NO ssl_ciphers=HIGH

重启:

systemctl restart vsftpd

客户端就要用FTPS(不是 SFTP)连接,并且因为是自签证书,需要选择"信任该证书"。

require_ssl_reuse=NO这行建议加上。某些客户端(尤其是 FileZilla)在 TLS 会话复用上和 vsftpd 有兼容性问题,不加这个可能连不上。


八、安全加固清单

措施做法
禁用匿名anonymous_enable=NO
禁锢目录chroot_local_user=YES+ 不可写家目录
限制登录用user_list白名单,只放需要的用户
禁用 root保持/etc/vsftpd/ftpusers里有 root
加密传输启用 TLS(第七节)
限制来源防火墙 + 云安全组限制源 IP
防爆破配合 fail2ban 监控/var/log/secure
被动端口收窄pasv_min_port/pasv_max_port范围开小一点

九、总结

环节关键点
用户useradd -s /sbin/nologin,shell 要进/etc/shells
核心配置anonymous_enable=NO、write_enable=YES、chroot_local_user=YES
chroot 报错allow_writeable_chroot=YES或改用手法更稳的"不可写家目录 + 子目录"
防火墙放行 ftp +被动端口范围(云服务器还要配安全组)
SELinuxsetsebool -P ftpd_full_access on
排错卡在列目录 = 被动模式端口没通;530 = shell/黑名单/PAM

最后再提醒一次:FTP 明文传输,新项目优先考虑 SFTP。如果必须用 FTP,请务必按第七节把 TLS 打开。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询