vsftpd 2.3.5+ 版本拒绝在可写 chroot 下运行,即使设置 allow_writeable_chroot=YES;根本原因是用户 shell 必须存在于 /etc/shells 中且 check_shell=YES 生效,否则直接报错 500 OOPS。

vsftpd 启动失败,报错 500 OOPS: vsftpd: refusing to run,且日志里明确提到 allow_writeable_chroot=YES —— 这不是配置错了,而是 vsftpd 2.3.5+ 版本起的强制安全限制:它拒绝在可写根目录(chroot)下运行,哪怕你显式设置了 allow_writeable_chroot=YES。
为什么 allow_writeable_chroot=YES 不起作用?
从 vsftpd 2.3.5 开始,该选项仅在满足特定条件时才生效:
– 必须使用 pam_shells 检查用户 shell(即 check_shell=YES,默认开启);
– 用户的 shell 必须存在于 /etc/shells 中;
– 即使设了 allow_writeable_chroot=YES,如果用户 shell 不合法,vsftpd 仍会直接拒绝启动,并抛出那个 OOPS 错误。
常见诱因是:你把用户 shell 改成了 /bin/false 或 /sbin/nologin,但没把它们加进 /etc/shells。
怎么快速验证并修复?
按顺序检查以下三点:
- 运行
grep $(getent passwd your_ftp_user | cut -d: -f7) /etc/shells,确认用户 shell 是否在白名单中; - 如果不在,用
echo "/bin/false" | sudo tee -a /etc/shells补上(根据实际 shell 调整); - 确保配置文件中没有拼写错误:
allow_writeable_chroot=YES(注意是=YES,不是=yes或=on); - 重启服务:
sudo systemctl restart vsftpd,再看journalctl -u vsftpd -n 20是否还有refusing to run。
替代方案:不依赖 allow_writeable_chroot
如果你无法或不愿修改 /etc/shells,更稳妥的做法是让 chroot 目录本身不可写(符合 vsftpd 默认安全策略):
- 保持
allow_writeable_chroot=NO(或直接删掉这行); - 将用户主目录设为不可写:
chmod a-w /home/ftpuser; - 在内部建一个可写子目录,比如
/home/ftpuser/upload,并chmod 775 /home/ftpuser/upload; - 通过
local_root=/home/ftpuser和权限控制实现功能隔离。
最常被忽略的是 /etc/shells 同步问题——改完 vsftpd 配置却忘了同步 shell 白名单,导致整个服务卡在启动阶段。这个检查点比反复调参数更值得优先做。










