跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

vsftpd + Apache 共享目录:从零到生产环境部署指南

本文记录了在 Ubuntu 24.04 系统上部署 vsftpd 服务,并与 Apache 共享同一文件目录的完整过程。内容涵盖基础安装、用户管理、FTPS 加密配置、IPv6 支持以及 PAM 认证问题的排查与解决,适合需要快速搭建“通过 FTP 上传、通过网页展示”的文件共享服务。

一、需求背景与方案选型

1.1 核心需求

  • 通过 FTP 上传文件到服务器的 /var/www/files 目录
  • 该目录同时作为 Apache 的网站目录,通过网页展示文件列表
  • 传输过程需要加密(FTPS)
  • 支持 IPv4 和 IPv6 双栈访问
  • 只需一个 FTP 用户,暂不需要多用户隔离

1.2 方案选型

考虑因素选择
部署方式直接在 Ubuntu 系统安装,避免 Docker 带来的端口映射和权限复杂性
用户类型系统本地用户(ftpuser),使用 /sbin/nologin 作为登录 shell
加密方式显式 FTPS(FTP over TLS),端口 21
IP 支持双栈(IPv4 + IPv6)
权限方案用户组共享:ftpuser 与 www-data 加入同一组,实现权限共享

二、环境准备与软件安装

2.1 安装 vsftpd 和 OpenSSL

sudo apt update
sudo apt install vsftpd openssl -y

安装完成后,系统会自动创建一个名为 ftp 的系统用户,这个用户是 vsftpd 服务的运行者,与你后续创建的 FTP 登录用户无关。

2.2 准备目标目录

sudo mkdir -p /var/www/files

三、用户与权限设计(核心)

3.1 创建 FTP 登录用户

使用 -M 参数不创建家目录,-s /sbin/nologin 禁止 SSH 登录:

sudo useradd -M -s /sbin/nologin ftpuser
sudo passwd ftpuser

注意:/etc/passwd 中的 /home/ftpuser 只是一个配置记录,不代表该目录真实存在。FTP 用户的实际工作目录由 vsftpd 的 local_root 或 chroot 决定。

3.2 建立用户组共享机制

将 ftpuser 和 www-data 加入同一个组 webgroup,实现目录权限共享:

sudo groupadd webgroup
sudo usermod -aG webgroup ftpuser
sudo usermod -aG webgroup www-data

3.3 设置目录权限(含 setgid)

# 目录属主为 ftpuser,属组为 webgroup
sudo chown -R ftpuser:webgroup /var/www/files

# 权限 775:属主和组可读写执行,其他人只读执行
sudo chmod 775 /var/www/files

# setgid:让新建文件自动继承 webgroup
sudo chmod g+s /var/www/files

setgid 的作用:确保 ftpuser 上传的新文件属组自动继承为 webgroup,这样 www-data 就能通过组权限读写这些文件,无需手动修改权限。

四、SSL 证书配置

使用 Let’s Encrypt 受信任证书(如果已有证书,直接复用):

# 证书路径(假设域名为 ftp.tanglinux.com)
rsa_cert_file=/etc/letsencrypt/live/ftp.tanglinux.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/ftp.tanglinux.com/privkey.pem

Let’s Encrypt 证书会自动续期,vsftpd 无需重启即可使用新证书。

备用方案:如果没有域名,可使用自签名证书:

sudo mkdir -p /etc/ssl/vsftpd
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/vsftpd/vsftpd.key \
  -out /etc/ssl/vsftpd/vsftpd.crt \
  -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=MyCompany/CN=ftp.tanglinux.com"
sudo chmod 600 /etc/ssl/vsftpd/vsftpd.key

五、vsftpd 核心配置

5.1 配置文件 /etc/vsftpd.conf

# ===== 基本运行设置 =====
listen=NO
listen_ipv6=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=002
utf8_filesystem=YES

# ===== 用户隔离 =====
chroot_local_user=YES
allow_writeable_chroot=YES

# ===== 被动模式(双栈支持)=====
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=40010
# 如果域名同时解析 IPv4 和 IPv6,可以使用域名
pasv_address=ftp.tanglinux.com
pasv_addr_resolve=YES

# ===== SSL/TLS 加密 =====
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
rsa_cert_file=/etc/letsencrypt/live/ftp.tanglinux.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/ftp.tanglinux.com/privkey.pem
ssl_ciphers=HIGH

# ===== 日志 =====
xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log
log_ftp_protocol=YES

5.2 关键配置说明

配置项作用说明
listen=NO; listen_ipv6=YES启用 IPv6 监听同时接受 IPv4 和 IPv6 连接
local_umask=002新文件权限掩码配合 webgroup 组权限,确保新文件组可写
chroot_local_user=YES锁定用户在家目录防止越权访问系统其他目录
pasv_address=域名被动模式地址域名同时解析 IPv4 和 IPv6 时,双栈均可工作
force_local_*_ssl=YES强制加密禁止明文传输,确保安全

六、PAM 认证配置(关键)

这是整个部署过程中最容易出错的环节。vsftpd 默认的 PAM 配置使用 @include common-session,而 common-session 中包含 pam_systemd.so,该模块对 /sbin/nologin 用户会创建 systemd 用户会话失败,导致 vsftpd 返回 530 Login incorrect。

6.1 问题现象

  • 用户名存在,密码正确
  • TLS 握手成功
  • 返回 530 Login incorrect

6.2 根本原因

/etc/pam.d/common-session 中的 pam_systemd.so 对 /sbin/nologin 用户处理失败,导致整个 PAM 认证栈失败。

6.3 解决方案

将 /etc/pam.d/vsftpd 修改为以下内容:

auth    required        pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
auth    required        pam_unix.so shadow
account required        pam_unix.so
session required        pam_unix.so

修改说明:

原始配置修改后配置变化
@include common-accountaccount required pam_unix.so直接调用,去除 pam_systemd.so 干扰
@include common-sessionsession required pam_unix.so直接调用,去除 pam_systemd.so 干扰
@include common-authauth required pam_unix.so shadow直接调用,流程更清晰

执行修改命令:

sudo tee /etc/pam.d/vsftpd << 'EOF'
auth    required        pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
auth    required        pam_unix.so shadow
account required        pam_unix.so
session required        pam_unix.so
EOF
sudo systemctl restart vsftpd

注意:如果 PAM 配置中仍有 auth required pam_shells.so,也需要注释掉或删除,因为 /sbin/nologin 不在 /etc/shells 白名单中。

七、防火墙与端口放行

# 放行控制端口和被动模式端口范围
sudo ufw allow 21/tcp
sudo ufw allow 40000:40010/tcp
sudo ufw reload

云服务器注意:还需在云服务商控制台的安全组中放行上述端口(TCP 协议)。

八、Apache 目录列表配置

开启 Apache 的 mod_autoindex 功能,使 /var/www/files 目录在网页上显示文件列表。

8.1 开启目录列表

# /etc/apache2/apache2.conf 或站点配置
<Directory "/var/www/files">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

8.2 重启 Apache

sudo systemctl restart apache2

九、连接测试

使用支持 FTPS 的客户端(如 FileZilla)连接:

连接参数值
协议FTP over TLS (explicit encryption)
主机ftp.tanglinux.com(或 IP)
端口21
用户名ftpuser
密码你设置的密码

成功连接后,上传一个测试文件,访问 http://你的域名/ 或 http://你的IP/ 确认 Apache 目录列表正常显示。

十、常见问题与解决方法

问题解决方案
530 Login incorrect(密码正确)检查 PAM 配置,确保去掉了 pam_systemd.so 干扰
能登录但无法列出目录检查被动模式端口 40000-40010 是否在防火墙和安全组中放行
上传文件后 Apache 无法写入确认 setgid 生效(ls -ld /var/www/files 显示 drwxrwsr-x)
IPv6 连接失败确认 listen_ipv6=YES,且域名正确解析 AAAA 记录
自签名证书警告正常现象,接受即可;生产环境建议使用 Let’s Encrypt
vsftpd 启动失败sudo journalctl -u vsftpd -n 20 查看详细错误

十一、经验总结

在整个部署过程中,有几个关键点值得特别关注:

1. PAM 配置是最大陷阱

vsftpd 默认的 PAM 配置使用 @include common-session,会引入 pam_systemd.so。对于使用 /sbin/nologin 的 FTP 用户,pam_systemd.so 会尝试创建 systemd 用户会话并失败,导致 530 Login incorrect。解决方案是直接使用 pam_unix.so,去除系统默认的 common-session 引用。

2. IPv6 和被动模式的配合

pasv_address 可以设置域名,只要域名同时解析 A 和 AAAA 记录,vsftpd 会根据客户端的地址族返回对应的 IP 地址,实现双栈支持。

3. 文件权限的协作

通过 webgroup 组 + setgid + local_umask=002 的组合,确保 vsftpd 上传的文件 Apache 可以读写,无需手动干预。

4. 证书管理

Let’s Encrypt 证书的自动续期机制对 vsftpd 友好,续期后无需重启服务。

十二、最终配置清单

配置项状态路径/内容
vsftpd 安装✅vsftpd openssl
FTP 用户✅ftpuser,shell 为 /sbin/nologin
共享组✅webgroup(包含 ftpuser 和 www-data)
目录权限✅775,setgid,属主 ftpuser:webgroup
vsftpd.conf✅双栈 + FTPS + 被动模式
PAM 配置✅直接调用 pam_unix.so,去除 common-session
SSL 证书✅Let’s Encrypt 或自签名
防火墙✅放行 21/tcp 和 40000-40010/tcp
Apache 目录列表✅Options Indexes

十三、验证结果

部署完成后,通过 FileZilla 连接成功:

状态: 连接建立,等待欢迎消息...
响应: 220 (vsFTPd 3.0.5)
命令: AUTH TLS
响应: 234 Proceed with negotiation.
状态: 初始化 TLS 中...
状态: TLS 连接已建立。
命令: USER ftpuser
响应: 331 Please specify the password.
命令: PASS ********
响应: 230 Login successful.
状态: 已登录
状态: 读取目录列表...
命令: PWD
响应: 257 "/" is the current directory
状态: 列出"/"的目录成功

至此,vsftpd + Apache 共享目录服务部署完成,支持 IPv4/IPv6 双栈和 FTPS 加密传输。

作者

老丹

关注我
其他文章
上一个

mbed TLS 深度解析:为嵌入式系统而生的安全通信库

下一个

vsftpd.conf 完整配置项清单

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • Ubuntu 防火墙迁移指南:从 UFW 到 firewalld 的完整实践 2026年9月12日
  • Nano 编辑器完全操作指南:从入门到熟练 2026年9月12日
  • SSCG:让自签名证书不再“危险”的生成工具 2026年9月12日
  • Ubuntu Samba 服务安装与配置完全指南 2026年9月12日
  • 从零开始:用 Docker 部署 Jellyfin 并启用英特尔核显硬件加速 2026年9月11日

文章分类

  • C/C++开发 (22)
  • Docker容器 (5)
  • Linux工具包 (17)
  • Linux服务配置 (50)
  • Linux系统 (16)
  • OpenWrt路由 (3)
  • Shell脚本 (3)
  • 代码管理 (1)
  • 安防技术 (4)
  • 数据安全 (36)
  • 未分类 (1)
  • 网络协议 (25)
  • 计算机理论 (23)
  • 音视频技术 (5)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号